diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a319af4a1..c6bff9647 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,3 +27,8 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage.lcov flags: unittests + - name: Run deno test for /x/dhkemSecp256k1HkdfSha256 + working-directory: ./x/dhkemSecp256k1HkdfSha256 + run: | + deno fmt --check + deno task test diff --git a/.github/workflows/ci_browser.yml b/.github/workflows/ci_browser.yml index 87dad734b..cf04bf9a4 100644 --- a/.github/workflows/ci_browser.yml +++ b/.github/workflows/ci_browser.yml @@ -24,6 +24,14 @@ jobs: npm install -g esbuild deno task dnt deno task minify > test/pages/src/hpke.js + mkdir test/pages/dhkemSecp256k1HkdfSha256 + cp -rf x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/pages/* test/pages/dhkemSecp256k1HkdfSha256 + deno task minify > test/pages/dhkemSecp256k1HkdfSha256/src/hpke.js + - working-directory: ./x/dhkemSecp256k1HkdfSha256 + run: | + deno task dnt + cp npm/esm/*.js ../../test/pages/dhkemSecp256k1HkdfSha256/src/ + cp -rf npm/esm/src ../../test/pages/dhkemSecp256k1HkdfSha256/src/ - uses: peaceiris/actions-gh-pages@v3 with: deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} @@ -41,3 +49,5 @@ jobs: npm ci npx playwright install --with-deps npx playwright test + - working-directory: ./x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers + run: npm install && npx playwright install && npx playwright test diff --git a/.github/workflows/ci_bun.yml b/.github/workflows/ci_bun.yml index 07d50d01a..227160f6d 100644 --- a/.github/workflows/ci_bun.yml +++ b/.github/workflows/ci_bun.yml @@ -24,6 +24,11 @@ jobs: npm install -g esbuild deno task dnt deno task minify > test/bun/src/hpke.js + deno task minify > x/dhkemSecp256k1HkdfSha256/test/runtimes/hpke.js + - working-directory: ./x/dhkemSecp256k1HkdfSha256/ + run: | + deno task dnt + deno task minify > test/runtimes/hpke-dhkemSecp256k1HkdfSha256.js - uses: antongolub/action-setup-bun@v1 with: bun-version: 0.4 @@ -32,4 +37,10 @@ jobs: run: | nohup bun src/index.js & sleep 3 - deno test hpke.spec.ts --allow-net --allow-env \ No newline at end of file + deno test hpke.spec.ts --allow-net --allow-env + - name: Run test for dhkemSecp256k1HkdfSha256 + working-directory: ./x/dhkemSecp256k1HkdfSha256/test/runtimes/bun + run: | + nohup bun src/index.js & + sleep 3 + deno test hpke-dhkemSecp256k1HkdfSha256.spec.ts --allow-net \ No newline at end of file diff --git a/.github/workflows/ci_cfw.yml b/.github/workflows/ci_cfw.yml index 38f25d94b..457d73c40 100644 --- a/.github/workflows/ci_cfw.yml +++ b/.github/workflows/ci_cfw.yml @@ -24,6 +24,10 @@ jobs: npm install -g esbuild deno task dnt deno task minify > test/wrangler/src/hpke.js + deno task minify > x/dhkemSecp256k1HkdfSha256/test/runtimes/hpke.js + - working-directory: ./x/dhkemSecp256k1HkdfSha256/ + run: | + deno bundle mod.ts test/runtimes/hpke-dhkemSecp256k1HkdfSha256.js - name: Run test working-directory: ./test/wrangler run: | @@ -31,3 +35,10 @@ jobs: nohup npm start & sleep 3 deno test hpke.spec.ts --allow-net --allow-env + - name: Run test for dhkemSecp256k1HkdfSha256 + working-directory: ./x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare + run: | + npm install + nohup npm start & + sleep 3 + deno test hpke-dhkemSecp256k1HkdfSha256.spec.ts --allow-net diff --git a/.github/workflows/ci_node.yml b/.github/workflows/ci_node.yml index 8d443a380..f697e0c4e 100644 --- a/.github/workflows/ci_node.yml +++ b/.github/workflows/ci_node.yml @@ -27,3 +27,8 @@ jobs: npm install -g esbuild deno task dnt deno task minify > ./npm/hpke.min.js + - name: Run dnt & minify for /x/dhkemSecp256k1HkdfSha256 + working-directory: ./x/dhkemSecp256k1HkdfSha256 + run: | + deno task dnt + deno task minify > ./npm/hpke-dhkemSecp256k1.min.js diff --git a/deno.json b/deno.json index 6ef31e85e..33bb2a28c 100644 --- a/deno.json +++ b/deno.json @@ -15,6 +15,7 @@ "test/" ], "exclude": [ + "x", "samples/node/node_modules", "samples/ts-node/node_modules", "test/bun", @@ -25,6 +26,7 @@ "lint": { "include": ["mod.ts", "samples/", "src/", "test/"], "exclude": [ + "x", "samples/node/node_modules", "samples/ts-node/node_modules", "test/bun", diff --git a/dnt.ts b/dnt.ts index 8f30e8d63..d7ed83412 100644 --- a/dnt.ts +++ b/dnt.ts @@ -1,6 +1,7 @@ import { build, emptyDir } from "dnt"; await emptyDir("./npm"); +await emptyDir("./x/dhkemSecp256k1HkdfSha256/npm"); await build({ entryPoints: ["./mod.ts"], diff --git a/src/cipherSuite.ts b/src/cipherSuite.ts index efb7bb555..a47df4bef 100644 --- a/src/cipherSuite.ts +++ b/src/cipherSuite.ts @@ -29,7 +29,6 @@ import { DhkemP256HkdfSha256, DhkemP384HkdfSha384, DhkemP521HkdfSha512, - DhkemSecp256K1HkdfSha256, DhkemX25519HkdfSha256, DhkemX448HkdfSha512, } from "./kems/dhkem.ts"; @@ -88,16 +87,16 @@ export class CipherSuite { case KemId.DhkemP521HkdfSha512: this._kem = new DhkemP521HkdfSha512(); break; - case KemId.DhkemSecp256K1HkdfSha256: - this._kem = new DhkemSecp256K1HkdfSha256(); - break; case KemId.DhkemX25519HkdfSha256: this._kem = new DhkemX25519HkdfSha256(); break; - default: - // case KemId.DhkemX448HkdfSha512: + case KemId.DhkemX448HkdfSha512: this._kem = new DhkemX448HkdfSha512(); break; + default: + throw new errors.InvalidParamError( + `The KEM (${params.kem}) cannot be specified by KemId. Use submodule for the KEM`, + ); } } this.kem = this._kem.id; diff --git a/src/identifiers.ts b/src/identifiers.ts index f597b91e3..fbcc51b54 100644 --- a/src/identifiers.ts +++ b/src/identifiers.ts @@ -22,8 +22,10 @@ export const Kem = { DhkemP384HkdfSha384: 0x0011, /** DHKEM (P-521, HKDF-SHA512). */ DhkemP521HkdfSha512: 0x0012, - /** DHKEM (secp256k1, HKDF-SHA256). EXPERIMENTAL. The KEM id can be changed in the standardization process. */ + /** DHKEM (secp256k1, HKDF-SHA256). EXPERIMENTAL/DEPRECATED. The KEM id can be changed in the standardization process. */ DhkemSecp256K1HkdfSha256: 0x0013, + /** DHKEM (secp256k1, HKDF-SHA256). EXPERIMENTAL. The KEM id can be changed in the standardization process. */ + DhkemSecp256k1HkdfSha256: 0x0013, /** DHKEM (X25519, HKDF-SHA256) */ DhkemX25519HkdfSha256: 0x0020, /** DHKEM (X448, HKDF-SHA512) */ diff --git a/src/kems/dhkem.ts b/src/kems/dhkem.ts index 50787608e..c1e1123fa 100644 --- a/src/kems/dhkem.ts +++ b/src/kems/dhkem.ts @@ -6,7 +6,6 @@ import type { RecipientContextParams } from "../interfaces/recipientContextParam import { Algorithm } from "../algorithm.ts"; import { Ec } from "./dhkemPrimitives/ec.ts"; -import { Secp256K1 } from "./dhkemPrimitives/secp256k1.ts"; import { X25519 } from "./dhkemPrimitives/x25519.ts"; import { X448 } from "./dhkemPrimitives/x448.ts"; import { KemId } from "../identifiers.ts"; @@ -250,20 +249,6 @@ export class DhkemP521HkdfSha512 extends Dhkem implements KemInterface { } } -export class DhkemSecp256K1HkdfSha256 extends Dhkem implements KemInterface { - public readonly id: KemId = KemId.DhkemSecp256K1HkdfSha256; - public readonly secretSize: number = 32; - public readonly encSize: number = 65; - public readonly publicKeySize: number = 65; - public readonly privateKeySize: number = 32; - - constructor() { - const kdf = new HkdfSha256(); - const prim = new Secp256K1(kdf); - super(prim, kdf); - } -} - export class DhkemX25519HkdfSha256 extends Dhkem { public readonly id: KemId = KemId.DhkemX25519HkdfSha256; public readonly secretSize: number = 32; diff --git a/test/bun/hpke.spec.ts b/test/bun/hpke.spec.ts index 62c5c9c85..5c043f223 100644 --- a/test/bun/hpke.spec.ts +++ b/test/bun/hpke.spec.ts @@ -41,18 +41,18 @@ describe("Cloudflare Workers", () => { }); }); - describe("GET /test?kem=0x0013", () => { - it("should return ok", async () => { - for (const kdf of ["0x0001", "0x0002", "0x0003"]) { - for (const aead of ["0x0001", "0x0002", "0x0003"]) { - const res = await fetch( - `http://localhost:3000/test?kem=0x0013&kdf=${kdf}&aead=${aead}`, - ); - assertEquals("ok", await res.text()); - } - } - }); - }); + // describe("GET /test?kem=0x0013", () => { + // it("should return ok", async () => { + // for (const kdf of ["0x0001", "0x0002", "0x0003"]) { + // for (const aead of ["0x0001", "0x0002", "0x0003"]) { + // const res = await fetch( + // `http://localhost:3000/test?kem=0x0013&kdf=${kdf}&aead=${aead}`, + // ); + // assertEquals("ok", await res.text()); + // } + // } + // }); + // }); describe("GET /test?kem=0x0020", () => { it("should return ok", async () => { diff --git a/test/cipherSuite.test.ts b/test/cipherSuite.test.ts index 25e579bd2..b749bf874 100644 --- a/test/cipherSuite.test.ts +++ b/test/cipherSuite.test.ts @@ -1,4 +1,4 @@ -import { assertEquals, assertRejects } from "testing/asserts.ts"; +import { assertEquals, assertRejects, assertThrows } from "testing/asserts.ts"; import { describe, it } from "testing/bdd.ts"; @@ -170,26 +170,19 @@ describe("CipherSuite", () => { }); }); - describe("constructor with DhkemP256HkdfSha256/HkdfSha256/ExportOnly", () => { - it("should have ciphersuites", async () => { - const suite: CipherSuite = new CipherSuite({ - kem: KemId.DhkemSecp256K1HkdfSha256, - kdf: KdfId.HkdfSha256, - aead: AeadId.ExportOnly, - }); - const kem = await suite.kemContext(); - assertEquals(kem.secretSize, 32); - assertEquals(kem.encSize, 65); - assertEquals(kem.publicKeySize, 65); - assertEquals(kem.privateKeySize, 32); - + describe("constructor with DhkemSecp256KHkdfSha256/HkdfSha256/ExportOnly", () => { + it("should throw InvalidParamError", async () => { // assert - assertEquals(suite.kem, KemId.DhkemSecp256K1HkdfSha256); - assertEquals(suite.kem, 0x0013); - assertEquals(suite.kdf, KdfId.HkdfSha256); - assertEquals(suite.kdf, 0x0001); - assertEquals(suite.aead, AeadId.ExportOnly); - assertEquals(suite.aead, 0xFFFF); + await assertThrows( + () => + new CipherSuite({ + kem: KemId.DhkemSecp256k1HkdfSha256, + kdf: KdfId.HkdfSha256, + aead: AeadId.ExportOnly, + }), + errors.InvalidParamError, + "The KEM (19) cannot be specified by KemId. Use submodule for the KEM", + ); }); }); @@ -667,39 +660,6 @@ describe("CipherSuite", () => { }); }); - describe("A README example of Base mode (KemId.DhkemSecp256K1HkdfSha256/KdfId.HkdfSha256)", () => { - it("should work normally", async () => { - // setup - const suite = new CipherSuite({ - kem: KemId.DhkemSecp256K1HkdfSha256, - kdf: KdfId.HkdfSha256, - aead: AeadId.Aes128Gcm, - }); - - const rkp = await suite.generateKeyPair(); - - const sender = await suite.createSenderContext({ - recipientPublicKey: rkp.publicKey, - }); - - const recipient = await suite.createRecipientContext({ - recipientKey: rkp, - enc: sender.enc, - }); - - // encrypt - const ct = await sender.seal( - new TextEncoder().encode("my-secret-message"), - ); - - // decrypt - const pt = await recipient.open(ct); - - // assert - assertEquals(new TextDecoder().decode(pt), "my-secret-message"); - }); - }); - describe("A README example of Base mode (KemId.DhkemX448HkdfSha256/KdfId.HkdfSha512)", () => { it("should work normally with ids", async () => { // setup diff --git a/test/cipherSuiteBackwardCompat.test.ts b/test/cipherSuiteBackwardCompat.test.ts index b3793e642..649b036c3 100644 --- a/test/cipherSuiteBackwardCompat.test.ts +++ b/test/cipherSuiteBackwardCompat.test.ts @@ -1,4 +1,4 @@ -import { assertEquals, assertRejects } from "testing/asserts.ts"; +import { assertEquals, assertRejects, assertThrows } from "testing/asserts.ts"; import { describe, it } from "testing/bdd.ts"; @@ -158,26 +158,19 @@ describe("CipherSuite(backward-compat)", () => { }); }); - describe("constructor with DhkemP256HkdfSha256/HkdfSha256/ExportOnly", () => { - it("should have ciphersuites", async () => { - const suite: CipherSuite = new CipherSuite({ - kem: Kem.DhkemSecp256K1HkdfSha256, - kdf: Kdf.HkdfSha256, - aead: Aead.ExportOnly, - }); - const kem = await suite.kemContext(); - assertEquals(kem.secretSize, 32); - assertEquals(kem.encSize, 65); - assertEquals(kem.publicKeySize, 65); - assertEquals(kem.privateKeySize, 32); - + describe("constructor with DhkemSecp256KHkdfSha256/HkdfSha256/ExportOnly", () => { + it("should throw InvalidParamError", async () => { // assert - assertEquals(suite.kem, Kem.DhkemSecp256K1HkdfSha256); - assertEquals(suite.kem, 0x0013); - assertEquals(suite.kdf, Kdf.HkdfSha256); - assertEquals(suite.kdf, 0x0001); - assertEquals(suite.aead, Aead.ExportOnly); - assertEquals(suite.aead, 0xFFFF); + await assertThrows( + () => + new CipherSuite({ + kem: Kem.DhkemSecp256K1HkdfSha256, + kdf: Kdf.HkdfSha256, + aead: Aead.ExportOnly, + }), + errors.InvalidParamError, + "The KEM (19) cannot be specified by KemId. Use submodule for the KEM", + ); }); }); @@ -525,39 +518,6 @@ describe("CipherSuite(backward-compat)", () => { }); }); - describe("A README example of Base mode (Kem.DhkemSecp256K1HkdfSha256/Kdf.HkdfSha256)", () => { - it("should work normally", async () => { - // setup - const suite = new CipherSuite({ - kem: Kem.DhkemSecp256K1HkdfSha256, - kdf: Kdf.HkdfSha256, - aead: Aead.Aes128Gcm, - }); - - const rkp = await suite.generateKeyPair(); - - const sender = await suite.createSenderContext({ - recipientPublicKey: rkp.publicKey, - }); - - const recipient = await suite.createRecipientContext({ - recipientKey: rkp, - enc: sender.enc, - }); - - // encrypt - const ct = await sender.seal( - new TextEncoder().encode("my-secret-message"), - ); - - // decrypt - const pt = await recipient.open(ct); - - // assert - assertEquals(new TextDecoder().decode(pt), "my-secret-message"); - }); - }); - describe("A README example of Base mode (Kem.DhkemX448HkdfSha256/Kdf.HkdfSha512)", () => { it("should work normally", async () => { // setup diff --git a/test/kemContext.test.ts b/test/kemContext.test.ts index c91d05871..c88ac989e 100644 --- a/test/kemContext.test.ts +++ b/test/kemContext.test.ts @@ -7,7 +7,6 @@ import { DhkemP256HkdfSha256, DhkemP384HkdfSha384, DhkemP521HkdfSha512, - DhkemSecp256K1HkdfSha256, DhkemX25519HkdfSha256, DhkemX448HkdfSha512, } from "../src/kems/dhkem.ts"; @@ -16,8 +15,6 @@ import { loadCrypto, loadSubtleCrypto } from "../src/webCrypto.ts"; import * as errors from "../src/errors.ts"; -import { hexStringToBytes } from "./utils.ts"; - describe("constructor", () => { describe("with valid parameters", () => { it("should return a proper instance", async () => { @@ -55,15 +52,6 @@ describe("constructor", () => { assertEquals(dhkemP521.publicKeySize, 133); assertEquals(dhkemP521.privateKeySize, 64); - const dhkemSecp256K1 = new DhkemSecp256K1HkdfSha256(); - dhkemSecp256K1.init(api); - assertEquals(typeof dhkemP256, "object"); - assertEquals(dhkemSecp256K1.id, KemId.DhkemSecp256K1HkdfSha256); - assertEquals(dhkemSecp256K1.secretSize, 32); - assertEquals(dhkemSecp256K1.encSize, 65); - assertEquals(dhkemSecp256K1.publicKeySize, 65); - assertEquals(dhkemSecp256K1.privateKeySize, 32); - const dhkemX25519 = new DhkemX25519HkdfSha256(); dhkemX25519.init(api); assertEquals(typeof dhkemX25519, "object"); @@ -150,27 +138,6 @@ describe("generateKeyPair", () => { assertEquals(kp.privateKey.usages[0], "deriveBits"); }); - it("should return a proper instance with DhkemSecp256K1HkdfSha256", async () => { - const api = await loadSubtleCrypto(); - - // assert - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - const kp = await kemContext.generateKeyPair(); - assertEquals(kp.publicKey.type, "public"); - assertEquals(kp.publicKey.extractable, true); - assertEquals(kp.publicKey.algorithm.name, "ECDH"); - // assertEquals(kp.publicKey.algorithm.namedCurve, "secp256k1"); - assertEquals(kp.publicKey.usages.length, 0); - // assertEquals(kp.publicKey.usages[0], "deriveBits"); - assertEquals(kp.privateKey.type, "private"); - assertEquals(kp.privateKey.extractable, true); - assertEquals(kp.privateKey.algorithm.name, "ECDH"); - // assertEquals(kp.privateKey.algorithm.namedCurve, "secp256k1"); - assertEquals(kp.privateKey.usages.length, 1); - assertEquals(kp.privateKey.usages[0], "deriveBits"); - }); - it("should return a proper instance with DhkemX25519HkdfSha256", async () => { const api = await loadSubtleCrypto(); @@ -308,29 +275,6 @@ describe("deriveKeyPair", () => { assertEquals(kp.privateKey.usages[0], "deriveBits"); }); - it("should return a proper instance with DhkemSecp256K1HkdfSha256", async () => { - const api = await loadSubtleCrypto(); - const cryptoApi = await loadCrypto(); - - // assert - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - const ikm = new Uint8Array(32); - cryptoApi.getRandomValues(ikm); - const kp = await kemContext.deriveKeyPair(ikm.buffer); - assertEquals(kp.publicKey.type, "public"); - assertEquals(kp.publicKey.extractable, true); - assertEquals(kp.publicKey.algorithm.name, "ECDH"); - // assertEquals(kp.publicKey.algorithm.namedCurve, "secp256k1"); - assertEquals(kp.publicKey.usages.length, 0); - // assertEquals(kp.publicKey.usages[0], "deriveBits"); - assertEquals(kp.privateKey.type, "private"); - assertEquals(kp.privateKey.extractable, true); - assertEquals(kp.privateKey.algorithm.name, "ECDH"); - // assertEquals(kp.privateKey.algorithm.namedCurve, "secp256k1"); - assertEquals(kp.privateKey.usages.length, 1); - assertEquals(kp.privateKey.usages[0], "deriveBits"); - }); it("should return a proper instance with DhkemX25519HkdfSha256", async () => { const api = await loadSubtleCrypto(); const cryptoApi = await loadCrypto(); @@ -450,23 +394,6 @@ describe("serialize/deserializePublicKey", () => { assertEquals(pubKey.usages.length, 0); }); - it("should return a proper instance with DhkemSecp256K1HkdfSha256", async () => { - const api = await loadSubtleCrypto(); - - // assert - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - const kp = await kemContext.generateKeyPair(); - const bPubKey = await kemContext.serializePublicKey(kp.publicKey); - const pubKey = await kemContext.deserializePublicKey(bPubKey); - assertEquals(pubKey.type, "public"); - assertEquals(pubKey.extractable, true); - assertEquals(pubKey.algorithm.name, "ECDH"); - // assertEquals(pubKey.algorithm.namedCurve, "secp256k1"); - assertEquals(pubKey.usages.length, 0); - // assertEquals(pubKey.usages[0], "deriveBits"); - }); - it("should return a proper instance with DhkemX25519HkdfSha256", async () => { const api = await loadSubtleCrypto(); @@ -741,37 +668,6 @@ describe("importKey", () => { // assert assertEquals(privKey.usages.length, 0); }); - - it("should return a valid private key for DhkemSecp256K1HkdfSha256 from raw key", async () => { - const api = await loadSubtleCrypto(); - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - - const cryptoApi = await loadCrypto(); - const rawKey = new Uint8Array(32); - cryptoApi.getRandomValues(rawKey); - const privKey = await kemContext.importKey("raw", rawKey, false); - - // assert - assertEquals(privKey.usages.length, 1); - assertEquals(privKey.usages[0], "deriveBits"); - }); - - it("should return a valid public key for DhkemSecp256K1HkdfSha256 from raw key", async () => { - const api = await loadSubtleCrypto(); - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - - const cryptoApi = await loadCrypto(); - const rawKey = new Uint8Array(33); - rawKey[0] = hexStringToBytes("04")[0]; - cryptoApi.getRandomValues(rawKey); - const privKey = await kemContext.importKey("raw", rawKey, true); - - // assert - assertEquals(privKey.usages.length, 0); - // assertEquals(privKey.usages[0], "deriveBits"); - }); }); describe("with invalid parameters", () => { @@ -1206,37 +1102,5 @@ describe("importKey", () => { errors.DeserializeError, ); }); - - it("should throw DeserializeError with invalid DhkemSecp256K1HkdfSha256 private key", async () => { - const api = await loadSubtleCrypto(); - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - - const cryptoApi = await loadCrypto(); - const rawKey = new Uint8Array(33); - cryptoApi.getRandomValues(rawKey); - - // assert - await assertRejects( - () => kemContext.importKey("raw", rawKey, false), - errors.DeserializeError, - ); - }); - - it("should throw DeserializeError with invalid DhkemSecp256K1HkdfSha256 public key", async () => { - const api = await loadSubtleCrypto(); - const kemContext = new DhkemSecp256K1HkdfSha256(); - kemContext.init(api); - - const cryptoApi = await loadCrypto(); - const rawKey = new Uint8Array(32); - cryptoApi.getRandomValues(rawKey); - - // assert - await assertRejects( - () => kemContext.importKey("raw", rawKey, true), - errors.DeserializeError, - ); - }); }); }); diff --git a/test/pages/index.html b/test/pages/index.html index d377b9562..030be424a 100644 --- a/test/pages/index.html +++ b/test/pages/index.html @@ -7,7 +7,7 @@ Kem.DhkemP256HkdfSha256, Kem.DhkemP384HkdfSha384, Kem.DhkemP521HkdfSha512, - Kem.DhkemSecp256K1HkdfSha256, + // Kem.DhkemSecp256K1HkdfSha256, Kem.DhkemX25519HkdfSha256, Kem.DhkemX448HkdfSha512, ]; diff --git a/test/playwright/hpke.spec.ts b/test/playwright/hpke.spec.ts index afa1bae8c..03eba0b77 100644 --- a/test/playwright/hpke.spec.ts +++ b/test/playwright/hpke.spec.ts @@ -4,6 +4,6 @@ test("basic test", async ({ page }) => { await page.goto("https://dajiaji.github.io/hpke-js/"); await page.click("text=run"); await page.waitForTimeout(5000); - await expect(page.locator("id=pass")).toHaveText("54"); + await expect(page.locator("id=pass")).toHaveText("45"); await expect(page.locator("id=fail")).toHaveText("0"); }); diff --git a/test/wrangler/hpke.spec.ts b/test/wrangler/hpke.spec.ts index 2c793a892..ccf7be025 100644 --- a/test/wrangler/hpke.spec.ts +++ b/test/wrangler/hpke.spec.ts @@ -41,18 +41,18 @@ describe("Cloudflare Workers", () => { }); }); - describe("GET /test?kem=0x0013", () => { - it("should return ok", async () => { - for (const kdf of ["0x0001", "0x0002", "0x0003"]) { - for (const aead of ["0x0001", "0x0002", "0x0003"]) { - const res = await fetch( - `http://localhost:8787/test?kem=0x0013&kdf=${kdf}&aead=${aead}`, - ); - assertEquals("ok", await res.text()); - } - } - }); - }); + // describe("GET /test?kem=0x0013", () => { + // it("should return ok", async () => { + // for (const kdf of ["0x0001", "0x0002", "0x0003"]) { + // for (const aead of ["0x0001", "0x0002", "0x0003"]) { + // const res = await fetch( + // `http://localhost:8787/test?kem=0x0013&kdf=${kdf}&aead=${aead}`, + // ); + // assertEquals("ok", await res.text()); + // } + // } + // }); + // }); describe("GET /test?kem=0x0020", () => { it("should return ok", async () => { diff --git a/x/dhkemSecp256k1HkdfSha256/README.md b/x/dhkemSecp256k1HkdfSha256/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/x/dhkemSecp256k1HkdfSha256/deno.json b/x/dhkemSecp256k1HkdfSha256/deno.json new file mode 100644 index 000000000..e51640cae --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/deno.json @@ -0,0 +1,26 @@ +{ + "imports": { + "testing/": "https://deno.land/std@0.191.0/testing/", + "dnt": "https://deno.land/x/dnt@0.37.0/mod.ts" + }, + "fmt": { + "include": [ + "deno.json", + "dnt.ts", + "mod.ts", + "src/", + "test/" + ], + "exclude": [] + }, + "lint": { + "include": ["mod.ts", "src/", "test/"], + "exclude": [] + }, + "tasks": { + "test": "deno fmt && deno lint && deno test test -A --fail-fast --doc --coverage=coverage --parallel --allow-read", + "cov": "deno coverage ./coverage --lcov --exclude='test'", + "dnt": "deno run -A dnt.ts $(git describe --tags $(git rev-list --tags --max-count=1))", + "minify": "esbuild npm/esm/mod.js --bundle --format=esm --minify" + } +} diff --git a/x/dhkemSecp256k1HkdfSha256/deno.lock b/x/dhkemSecp256k1HkdfSha256/deno.lock new file mode 100644 index 000000000..745a35fe0 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/deno.lock @@ -0,0 +1,160 @@ +{ + "version": "2", + "remote": { + "https://deno.land/std@0.140.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", + "https://deno.land/std@0.140.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49", + "https://deno.land/std@0.140.0/bytes/bytes_list.ts": "67eb118e0b7891d2f389dad4add35856f4ad5faab46318ff99653456c23b025d", + "https://deno.land/std@0.140.0/bytes/equals.ts": "fc16dff2090cced02497f16483de123dfa91e591029f985029193dfaa9d894c9", + "https://deno.land/std@0.140.0/bytes/mod.ts": "763f97d33051cc3f28af1a688dfe2830841192a9fea0cbaa55f927b49d49d0bf", + "https://deno.land/std@0.140.0/fmt/colors.ts": "30455035d6d728394781c10755351742dd731e3db6771b1843f9b9e490104d37", + "https://deno.land/std@0.140.0/fs/_util.ts": "0fb24eb4bfebc2c194fb1afdb42b9c3dda12e368f43e8f2321f84fc77d42cb0f", + "https://deno.land/std@0.140.0/fs/ensure_dir.ts": "9dc109c27df4098b9fc12d949612ae5c9c7169507660dcf9ad90631833209d9d", + "https://deno.land/std@0.140.0/hash/sha256.ts": "803846c7a5a8a5a97f31defeb37d72f519086c880837129934f5d6f72102a8e8", + "https://deno.land/std@0.140.0/io/buffer.ts": "bd0c4bf53db4b4be916ca5963e454bddfd3fcd45039041ea161dbf826817822b", + "https://deno.land/std@0.140.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.140.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.140.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b", + "https://deno.land/std@0.140.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.140.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", + "https://deno.land/std@0.140.0/path/mod.ts": "d3e68d0abb393fb0bf94a6d07c46ec31dc755b544b13144dee931d8d5f06a52d", + "https://deno.land/std@0.140.0/path/posix.ts": "293cdaec3ecccec0a9cc2b534302dfe308adb6f10861fa183275d6695faace44", + "https://deno.land/std@0.140.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.140.0/path/win32.ts": "31811536855e19ba37a999cd8d1b62078235548d67902ece4aa6b814596dd757", + "https://deno.land/std@0.140.0/streams/conversion.ts": "712585bfa0172a97fb68dd46e784ae8ad59d11b88079d6a4ab098ff42e697d21", + "https://deno.land/std@0.181.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", + "https://deno.land/std@0.181.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", + "https://deno.land/std@0.181.0/fs/_util.ts": "65381f341af1ff7f40198cee15c20f59951ac26e51ddc651c5293e24f9ce6f32", + "https://deno.land/std@0.181.0/fs/ensure_dir.ts": "dc64c4c75c64721d4e3fb681f1382f803ff3d2868f08563ff923fdd20d071c40", + "https://deno.land/std@0.181.0/fs/expand_glob.ts": "e4f56259a0a70fe23f05215b00de3ac5e6ba46646ab2a06ebbe9b010f81c972a", + "https://deno.land/std@0.181.0/fs/walk.ts": "ea95ffa6500c1eda6b365be488c056edc7c883a1db41ef46ec3bf057b1c0fe32", + "https://deno.land/std@0.181.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", + "https://deno.land/std@0.181.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", + "https://deno.land/std@0.181.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0", + "https://deno.land/std@0.181.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", + "https://deno.land/std@0.181.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", + "https://deno.land/std@0.181.0/path/mod.ts": "bf718f19a4fdd545aee1b06409ca0805bd1b68ecf876605ce632e932fe54510c", + "https://deno.land/std@0.181.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d", + "https://deno.land/std@0.181.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", + "https://deno.land/std@0.181.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba", + "https://deno.land/std@0.182.0/_util/asserts.ts": "178dfc49a464aee693a7e285567b3d0b555dc805ff490505a8aae34f9cfb1462", + "https://deno.land/std@0.182.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", + "https://deno.land/std@0.182.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e", + "https://deno.land/std@0.182.0/fs/_util.ts": "65381f341af1ff7f40198cee15c20f59951ac26e51ddc651c5293e24f9ce6f32", + "https://deno.land/std@0.182.0/fs/empty_dir.ts": "c3d2da4c7352fab1cf144a1ecfef58090769e8af633678e0f3fabaef98594688", + "https://deno.land/std@0.182.0/fs/expand_glob.ts": "e4f56259a0a70fe23f05215b00de3ac5e6ba46646ab2a06ebbe9b010f81c972a", + "https://deno.land/std@0.182.0/fs/walk.ts": "920be35a7376db6c0b5b1caf1486fb962925e38c9825f90367f8f26b5e5d0897", + "https://deno.land/std@0.182.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", + "https://deno.land/std@0.182.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", + "https://deno.land/std@0.182.0/path/_util.ts": "d7abb1e0dea065f427b89156e28cdeb32b045870acdf865833ba808a73b576d0", + "https://deno.land/std@0.182.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", + "https://deno.land/std@0.182.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", + "https://deno.land/std@0.182.0/path/mod.ts": "bf718f19a4fdd545aee1b06409ca0805bd1b68ecf876605ce632e932fe54510c", + "https://deno.land/std@0.182.0/path/posix.ts": "8b7c67ac338714b30c816079303d0285dd24af6b284f7ad63da5b27372a2c94d", + "https://deno.land/std@0.182.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", + "https://deno.land/std@0.182.0/path/win32.ts": "d186344e5583bcbf8b18af416d13d82b35a317116e6460a5a3953508c3de5bba", + "https://deno.land/std@0.191.0/fmt/colors.ts": "d67e3cd9f472535241a8e410d33423980bec45047e343577554d3356e1f0ef4e", + "https://deno.land/std@0.191.0/testing/_diff.ts": "1a3c044aedf77647d6cac86b798c6417603361b66b54c53331b312caeb447aea", + "https://deno.land/std@0.191.0/testing/_format.ts": "a69126e8a469009adf4cf2a50af889aca364c349797e63174884a52ff75cf4c7", + "https://deno.land/std@0.191.0/testing/_test_suite.ts": "30f018feeb3835f12ab198d8a518f9089b1bcb2e8c838a8b615ab10d5005465c", + "https://deno.land/std@0.191.0/testing/asserts.ts": "e16d98b4d73ffc4ed498d717307a12500ae4f2cbe668f1a215632d19fcffc22f", + "https://deno.land/std@0.191.0/testing/bdd.ts": "59f7f7503066d66a12e50ace81bfffae5b735b6be1208f5684b630ae6b4de1d0", + "https://deno.land/x/code_block_writer@12.0.0/mod.ts": "2c3448060e47c9d08604c8f40dee34343f553f33edcdfebbf648442be33205e5", + "https://deno.land/x/code_block_writer@12.0.0/utils/string_utils.ts": "60cb4ec8bd335bf241ef785ccec51e809d576ff8e8d29da43d2273b69ce2a6ff", + "https://deno.land/x/deno_cache@0.4.1/auth_tokens.ts": "5fee7e9155e78cedf3f6ff3efacffdb76ac1a76c86978658d9066d4fb0f7326e", + "https://deno.land/x/deno_cache@0.4.1/cache.ts": "51f72f4299411193d780faac8c09d4e8cbee951f541121ef75fcc0e94e64c195", + "https://deno.land/x/deno_cache@0.4.1/deno_dir.ts": "f2a9044ce8c7fe1109004cda6be96bf98b08f478ce77e7a07f866eff1bdd933f", + "https://deno.land/x/deno_cache@0.4.1/deps.ts": "8974097d6c17e65d9a82d39377ae8af7d94d74c25c0cbb5855d2920e063f2343", + "https://deno.land/x/deno_cache@0.4.1/dirs.ts": "d2fa473ef490a74f2dcb5abb4b9ab92a48d2b5b6320875df2dee64851fa64aa9", + "https://deno.land/x/deno_cache@0.4.1/disk_cache.ts": "1f3f5232cba4c56412d93bdb324c624e95d5dd179d0578d2121e3ccdf55539f9", + "https://deno.land/x/deno_cache@0.4.1/file_fetcher.ts": "07a6c5f8fd94bf50a116278cc6012b4921c70d2251d98ce1c9f3c352135c39f7", + "https://deno.land/x/deno_cache@0.4.1/http_cache.ts": "f632e0d6ec4a5d61ae3987737a72caf5fcdb93670d21032ddb78df41131360cd", + "https://deno.land/x/deno_cache@0.4.1/mod.ts": "ef1cda9235a93b89cb175fe648372fc0f785add2a43aa29126567a05e3e36195", + "https://deno.land/x/deno_cache@0.4.1/util.ts": "8cb686526f4be5205b92c819ca2ce82220aa0a8dd3613ef0913f6dc269dbbcfe", + "https://deno.land/x/dir@1.5.1/data_local_dir/mod.ts": "91eb1c4bfadfbeda30171007bac6d85aadacd43224a5ed721bbe56bc64e9eb66", + "https://deno.land/x/dnt@0.37.0/lib/compiler.ts": "209ad2e1b294f93f87ec02ade9a0821f942d2e524104552d0aa8ff87021050a5", + "https://deno.land/x/dnt@0.37.0/lib/compiler_transforms.ts": "cbb1fd5948f5ced1aa5c5aed9e45134e2357ce1e7220924c1d7bded30dcd0dd0", + "https://deno.land/x/dnt@0.37.0/lib/mod.deps.ts": "30367fc68bcd2acf3b7020cf5cdd26f817f7ac9ac35c4bfb6c4551475f91bc3e", + "https://deno.land/x/dnt@0.37.0/lib/npm_ignore.ts": "b430caa1905b65ae89b119d84857b3ccc3cb783a53fc083d1970e442f791721d", + "https://deno.land/x/dnt@0.37.0/lib/package_json.ts": "61f35b06e374ed39ca776d29d67df4be7ee809d0bca29a8239687556c6d027c2", + "https://deno.land/x/dnt@0.37.0/lib/pkg/dnt_wasm.generated.js": "65514d733c044bb394e4765321e33b73c490b20f86563293b5665d7a7b185153", + "https://deno.land/x/dnt@0.37.0/lib/pkg/snippets/dnt-wasm-a15ef721fa5290c5/helpers.js": "a6b95adc943a68d513fe8ed9ec7d260ac466b7a4bced4e942f733e494bb9f1be", + "https://deno.land/x/dnt@0.37.0/lib/shims.ts": "df1bd4d9a196dca4b2d512b1564fff64ac6c945189a273d706391f87f210d7e6", + "https://deno.land/x/dnt@0.37.0/lib/test_runner/get_test_runner_code.ts": "4dc7a73a13b027341c0688df2b29a4ef102f287c126f134c33f69f0339b46968", + "https://deno.land/x/dnt@0.37.0/lib/test_runner/test_runner.ts": "4d0da0500ec427d5f390d9a8d42fb882fbeccc92c92d66b6f2e758606dbd40e6", + "https://deno.land/x/dnt@0.37.0/lib/transform.deps.ts": "e42f2bdef46d098453bdba19261a67cf90b583f5d868f7fe83113c1380d9b85c", + "https://deno.land/x/dnt@0.37.0/lib/types.ts": "b8e228b2fac44c2ae902fbb73b1689f6ab889915bd66486c8a85c0c24255f5fb", + "https://deno.land/x/dnt@0.37.0/lib/utils.ts": "878b7ac7003a10c16e6061aa49dbef9b42bd43174853ebffc9b67ea47eeb11d8", + "https://deno.land/x/dnt@0.37.0/mod.ts": "37d0c784371cf1750f30203a95de2555ba4c1aa89d826024f14c038f87e0f344", + "https://deno.land/x/dnt@0.37.0/transform.ts": "1b127c5f22699c8ab2545b98aeca38c4e5c21405b0f5342ea17e9c46280ed277", + "https://deno.land/x/hpke@0.21.0/mod.ts": "b9e7d697ea421173b8534c79f878cb4b58fefe54a86d0562c0fced64a9561503", + "https://deno.land/x/hpke@0.21.0/src/aeads/aesGcm.ts": "7b69653031fe910301235de8327603a92cfa2a055542c7f7f22d151aba47c735", + "https://deno.land/x/hpke@0.21.0/src/aeads/chacha20Poly1305.ts": "e2d47b6ceedc5da8459b3b5c9928238a8b74e4a6e48b0f979a387a396d7b704a", + "https://deno.land/x/hpke@0.21.0/src/aeads/exportOnly.ts": "6103460a4b426596338c39d66aea20a0b6be65791c03df25372c2e9f6afb55c6", + "https://deno.land/x/hpke@0.21.0/src/algorithm.ts": "3ecda38db36b958877d0ca6ea577bd4c8edbfab18d5eff4d908bf91f5ebb48a1", + "https://deno.land/x/hpke@0.21.0/src/cipherSuite.ts": "ba3a339d8665f6b1da9f985e4145a02d1850128430b02f1c6034f0e10958d251", + "https://deno.land/x/hpke@0.21.0/src/consts.ts": "98cf8b1a4cd370964208cb292bafa196c5722fbb900d486112a0c206a77f2252", + "https://deno.land/x/hpke@0.21.0/src/encryptionContext.ts": "2589d10de7e941089ff199c40fbb4d73c9e6bff6e7076f5cc7c9e4885f6a79e7", + "https://deno.land/x/hpke@0.21.0/src/errors.ts": "05822bd1d483cd1fdf515b26398f8c270b8561fa94dc818f6bc3c7031415ccf0", + "https://deno.land/x/hpke@0.21.0/src/exporterContext.ts": "86c5aa30996cec1af43d3ce06d95a8a89ddb555ce2c61f1616661bd3fef4529b", + "https://deno.land/x/hpke@0.21.0/src/identifiers.ts": "f04543410b4332f372f831aff730ad93bd5eb36ffe81c18b11e2c2705d410c29", + "https://deno.land/x/hpke@0.21.0/src/interfaces/aeadInterface.ts": "0c5e11e27c7d5cfbc22df3ee8f6ae81e06bfbbe543554e0ab16f9456b96c33e8", + "https://deno.land/x/hpke@0.21.0/src/interfaces/aeadKey.ts": "3f070a3630f812feef2b775e17144115a66077c2d5b7060af3eb25f068b001d2", + "https://deno.land/x/hpke@0.21.0/src/interfaces/aeadParams.ts": "c541e24d11f2ceef2830dd3aba28c316a884bdc02ac0e9c66d95bc2a23b92292", + "https://deno.land/x/hpke@0.21.0/src/interfaces/cipherSuiteParams.ts": "b1580711d88420dbd16ce9e5f9cac0aedde809630de3b9f908e6040dff60a9de", + "https://deno.land/x/hpke@0.21.0/src/interfaces/encapsulator.ts": "6a81362683e1eb9f7406bb974b6b7bd5554bc6c93eed3ab3e955a9dda9beca48", + "https://deno.land/x/hpke@0.21.0/src/interfaces/encryptionContextInterface.ts": "329c1ee876540713351a5eb77888c48a7296388293a0d320b757e252a08fc328", + "https://deno.land/x/hpke@0.21.0/src/interfaces/exporter.ts": "6667607ba48f02ec447f143d1e0050adbe11cd7857c8dce3670dd5a8a9298e91", + "https://deno.land/x/hpke@0.21.0/src/interfaces/kdfInterface.ts": "b8b683981ef7e8f8c083a442a2a8ba7ae23c6aa4403714031202f3f50e6dafdd", + "https://deno.land/x/hpke@0.21.0/src/interfaces/kemInterface.ts": "d8c7448020108e7a07c9b6a7f5cb06913f8a624411846ae64918057c3a77cb22", + "https://deno.land/x/hpke@0.21.0/src/interfaces/kemPrimitives.ts": "17349098c1e496e628a9fb39ba70c20c8a3e8a385e73b70ab535f83bc7902be1", + "https://deno.land/x/hpke@0.21.0/src/interfaces/keyInfo.ts": "8cc05de2a7e0c446913393c3a340eda323bc6338bf2152d9aa648c2d47712546", + "https://deno.land/x/hpke@0.21.0/src/interfaces/keyScheduleParams.ts": "e0a698815eb123c914de499de71bde80a79b4488e6ce681fbb394037ba2a9645", + "https://deno.land/x/hpke@0.21.0/src/interfaces/preSharedKey.ts": "98543f61362b5f77675f4f5f13af4efdf58183c3c309f539d6c6c9cb62124090", + "https://deno.land/x/hpke@0.21.0/src/interfaces/recipientContextParams.ts": "02194c133714506d12524c7828ff80464e089534ac8c1a08eb1e7913c6f24ce2", + "https://deno.land/x/hpke@0.21.0/src/interfaces/responses.ts": "35d2bf77ab4d32cfe90bf96d3a61bf92a10a3979e90be74f64965da019c46531", + "https://deno.land/x/hpke@0.21.0/src/interfaces/senderContextParams.ts": "f57ffc17222e79d87c4f7730fb826c0ba6860c5ace1d06aeddde29c5618f362e", + "https://deno.land/x/hpke@0.21.0/src/kdfs/hkdf.ts": "24a8c0edfc41fe5c2d96b270c5ebda8fcbc5f3844ab1ff73eb655bdfd71d1ac2", + "https://deno.land/x/hpke@0.21.0/src/kems/dhkem.ts": "894bbe4e4cc481057a4528b44b6b29096d83314c3bd89f57bee768faee5e8e4f", + "https://deno.land/x/hpke@0.21.0/src/kems/dhkemPrimitives/ec.ts": "57eee1dd96ad7a48de8cc69d20918c956a397a8d597c0b6ee0e68b85970f473e", + "https://deno.land/x/hpke@0.21.0/src/kems/dhkemPrimitives/secp256k1.ts": "74be448865e2800a18ba70419758713c417bf74de66f3d344387317f4cb39072", + "https://deno.land/x/hpke@0.21.0/src/kems/dhkemPrimitives/x25519.ts": "1b211e210df98252cb45c45028f77772a0962d3ae403ee48e1160b8620e92438", + "https://deno.land/x/hpke@0.21.0/src/kems/dhkemPrimitives/x448.ts": "bf17c0ccb58abe9efa12d38ed7ad494eea89d1cd55739a3648ed055f45d1f59a", + "https://deno.land/x/hpke@0.21.0/src/recipientContext.ts": "228ba51bc52df0387617a3f471d43b3ec4f7b6d142c0f7f395d282a09f6ceae9", + "https://deno.land/x/hpke@0.21.0/src/senderContext.ts": "e4a4381b9dfbae61309c5ed4fe92db973df57b704c6d200afe8bfc4a3e845e47", + "https://deno.land/x/hpke@0.21.0/src/utils/bignum.ts": "2e8749a21cde3ec81e4d353ec001732d60c22d56a717f83bec4c9ddf8227f75c", + "https://deno.land/x/hpke@0.21.0/src/utils/misc.ts": "9ec825918998d8df2593571b722d9e4344081152ef9f68012431226960bb2dfd", + "https://deno.land/x/hpke@0.21.0/src/webCrypto.ts": "60296a8b402f93a6622b57d140299fe524c3bce334dbf46a23a37b2c520f6f89", + "https://deno.land/x/hpke@0.21.0/src/xCryptoKey.ts": "93355b8422f3477b62e2d048ec0c766ccd6c36bfe0649345f092239a984edc2d", + "https://deno.land/x/ts_morph@18.0.0/bootstrap/mod.ts": "b53aad517f106c4079971fcd4a81ab79fadc40b50061a3ab2b741a09119d51e9", + "https://deno.land/x/ts_morph@18.0.0/bootstrap/ts_morph_bootstrap.js": "6645ac03c5e6687dfa8c78109dc5df0250b811ecb3aea2d97c504c35e8401c06", + "https://deno.land/x/ts_morph@18.0.0/common/DenoRuntime.ts": "6a7180f0c6e90dcf23ccffc86aa8271c20b1c4f34c570588d08a45880b7e172d", + "https://deno.land/x/ts_morph@18.0.0/common/mod.ts": "01985d2ee7da8d1caee318a9d07664774fbee4e31602bc2bb6bb62c3489555ed", + "https://deno.land/x/ts_morph@18.0.0/common/ts_morph_common.js": "845671ca951073400ce142f8acefa2d39ea9a51e29ca80928642f3f8cf2b7700", + "https://deno.land/x/ts_morph@18.0.0/common/typescript.js": "d5c598b6a2db2202d0428fca5fd79fc9a301a71880831a805d778797d2413c59", + "https://deno.land/x/wasmbuild@0.13.0/cache.ts": "89eea5f3ce6035a1164b3e655c95f21300498920575ade23161421f5b01967f4", + "https://deno.land/x/wasmbuild@0.13.0/loader.ts": "d98d195a715f823151cbc8baa3f32127337628379a02d9eb2a3c5902dbccfc02" + }, + "npm": { + "specifiers": { + "@noble/ciphers@0.1.4": "@noble/ciphers@0.1.4", + "@noble/curves@1.1.0": "@noble/curves@1.1.0", + "@noble/hashes@1.3.1": "@noble/hashes@1.3.1" + }, + "packages": { + "@noble/ciphers@0.1.4": { + "integrity": "sha512-d3ZR8vGSpy3v/nllS+bD/OMN5UZqusWiQqkyj7AwzTnhXFH72pF5oB4Ach6DQ50g5kXxC28LdaYBEpsyv9KOUQ==", + "dependencies": {} + }, + "@noble/curves@1.1.0": { + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "@noble/hashes@1.3.1" + } + }, + "@noble/hashes@1.3.1": { + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "dependencies": {} + } + } + } +} diff --git a/x/dhkemSecp256k1HkdfSha256/dnt.ts b/x/dhkemSecp256k1HkdfSha256/dnt.ts new file mode 100644 index 000000000..012719733 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/dnt.ts @@ -0,0 +1,59 @@ +import { build, emptyDir } from "dnt"; + +await emptyDir("./npm"); + +await build({ + entryPoints: ["./mod.ts"], + outDir: "./npm", + typeCheck: false, + test: true, + declaration: true, + scriptModule: "umd", + importMap: "./deno.json", + compilerOptions: { + lib: ["es2021", "dom"], + }, + shims: { + deno: "dev", + }, + package: { + name: "@hpke-js/dhkemSecp256k1HkdfSha256", + version: Deno.args[0], + description: + "A Hybrid Public Key Encryption (HPKE) module extension for secp256k1 curve", + repository: { + type: "git", + url: "git+https://github.com/dajiaji/hpke-js.git", + }, + homepage: "https://github.com/dajiaji/hpke-js#readme", + license: "MIT", + main: "./script/mod.js", + types: "./types/mod.d.ts", + exports: { + ".": { + "import": "./esm/mod.js", + "require": "./script/mod.js", + }, + "./package.json": "./package.json", + }, + keywords: [ + "hpke", + "rfc9180", + "hkdf", + "dh", + "security", + "encryption", + ], + engines: { + "node": ">=16.0.0", + }, + author: "Ajitomi Daisuke", + bugs: { + url: "https://github.com/dajiaji/hpke-js/issues", + }, + }, +}); + +// post build steps +Deno.copyFileSync("../../LICENSE", "npm/LICENSE"); +Deno.copyFileSync("README.md", "npm/README.md"); diff --git a/x/dhkemSecp256k1HkdfSha256/mod.ts b/x/dhkemSecp256k1HkdfSha256/mod.ts new file mode 100644 index 000000000..3b21062ae --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/mod.ts @@ -0,0 +1 @@ +export { DhkemSecp256k1HkdfSha256 } from "./src/dhkemSecp256k1HkdfSha256.ts"; diff --git a/src/kems/dhkemPrimitives/secp256k1.ts b/x/dhkemSecp256k1HkdfSha256/src/dhkemSecp256k1HkdfSha256.ts similarity index 76% rename from src/kems/dhkemPrimitives/secp256k1.ts rename to x/dhkemSecp256k1HkdfSha256/src/dhkemSecp256k1HkdfSha256.ts index 09a29e789..b9d565566 100644 --- a/src/kems/dhkemPrimitives/secp256k1.ts +++ b/x/dhkemSecp256k1HkdfSha256/src/dhkemSecp256k1HkdfSha256.ts @@ -1,16 +1,20 @@ import { secp256k1 } from "npm:@noble/curves@1.1.0/secp256k1"; -import type { KemPrimitives } from "../../interfaces/kemPrimitives.ts"; -import type { KdfInterface } from "../../interfaces/kdfInterface.ts"; +import type { KemPrimitives } from "../../../src/interfaces/kemPrimitives.ts"; +import type { KdfInterface } from "../../../src/interfaces/kdfInterface.ts"; +import type { KemInterface } from "../../../src/interfaces/kemInterface.ts"; -import { Algorithm } from "../../algorithm.ts"; -import { XCryptoKey } from "../../xCryptoKey.ts"; +import { Algorithm } from "../../../src/algorithm.ts"; +import { KemId } from "../../../src/identifiers.ts"; +import { XCryptoKey } from "../../../src/xCryptoKey.ts"; +import { HkdfSha256 } from "../../../src/kdfs/hkdf.ts"; +import { Dhkem } from "../../../src/kems/dhkem.ts"; -import * as consts from "../../consts.ts"; +import * as consts from "../../../src/consts.ts"; const ALG_NAME = "ECDH"; -export class Secp256K1 extends Algorithm implements KemPrimitives { +class Secp256k1 extends Algorithm implements KemPrimitives { private _hkdf: KdfInterface; private _nPk: number; private _nSk: number; @@ -126,3 +130,17 @@ export class Secp256K1 extends Algorithm implements KemPrimitives { }); } } + +export class DhkemSecp256k1HkdfSha256 extends Dhkem implements KemInterface { + public readonly id: KemId = KemId.DhkemSecp256K1HkdfSha256; + public readonly secretSize: number = 32; + public readonly encSize: number = 65; + public readonly publicKeySize: number = 65; + public readonly privateKeySize: number = 32; + + constructor() { + const kdf = new HkdfSha256(); + const prim = new Secp256k1(kdf); + super(prim, kdf); + } +} diff --git a/x/dhkemSecp256k1HkdfSha256/test/dhkemSecp256k1HkdfSha256.test.ts b/x/dhkemSecp256k1HkdfSha256/test/dhkemSecp256k1HkdfSha256.test.ts new file mode 100644 index 000000000..2901426e1 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/dhkemSecp256k1HkdfSha256.test.ts @@ -0,0 +1,279 @@ +import { assertEquals, assertRejects } from "testing/asserts.ts"; +import { describe, it } from "testing/bdd.ts"; + +import { + AeadId, + CipherSuite, + KdfId, + KemId, +} from "https://deno.land/x/hpke/mod.ts"; + +import { DhkemSecp256k1HkdfSha256 } from "../src/dhkemSecp256k1HkdfSha256.ts"; + +const isBrowser = () => typeof window !== "undefined"; + +const isCloudflareWorkers = () => typeof caches !== "undefined"; + +function hexStringToBytes(v: string): Uint8Array { + if (v.length === 0) { + return new Uint8Array([]); + } + const res = v.match(/[\da-f]{2}/gi); + if (res == null) { + throw new Error("hexStringToBytes: not hex string"); + } + return new Uint8Array(res.map(function (h) { + return parseInt(h, 16); + })); +} + +async function loadCrypto(): Promise { + if (isBrowser() || isCloudflareWorkers()) { + if (globalThis.crypto !== undefined) { + return globalThis.crypto; + } + // jsdom + } + + try { + const { webcrypto } = await import("crypto"); // node:crypto + return (webcrypto as unknown as Crypto); + } catch (_e: unknown) { + throw new Error("Web Cryptograph API not supported"); + } +} + +async function loadSubtleCrypto(): Promise { + if (isBrowser() || isCloudflareWorkers()) { + if (globalThis.crypto !== undefined) { + return globalThis.crypto.subtle; + } + // jsdom + } + + try { + const { webcrypto } = await import("crypto"); // node:crypto + return (webcrypto as unknown as Crypto).subtle; + } catch (_e: unknown) { + throw new Error("Web Cryptograph API not supported"); + } +} + +describe("DhkemP256k1Hkdf256", () => { + describe("with valid parameters", () => { + it("should have a correct KEM object", async () => { + const api = await loadSubtleCrypto(); + + // assert + const dhkemSecp256k1 = new DhkemSecp256k1HkdfSha256(); + dhkemSecp256k1.init(api); + assertEquals(typeof dhkemSecp256k1, "object"); + assertEquals(dhkemSecp256k1.id, KemId.DhkemSecp256K1HkdfSha256); + assertEquals(dhkemSecp256k1.secretSize, 32); + assertEquals(dhkemSecp256k1.encSize, 65); + assertEquals(dhkemSecp256k1.publicKeySize, 65); + assertEquals(dhkemSecp256k1.privateKeySize, 32); + }); + }); +}); + +describe("generateKeyPair", () => { + describe("with valid parameters", () => { + it("should return a proper instance", async () => { + const api = await loadSubtleCrypto(); + + // assert + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + const kp = await kemContext.generateKeyPair(); + assertEquals(kp.publicKey.type, "public"); + assertEquals(kp.publicKey.extractable, true); + assertEquals(kp.publicKey.algorithm.name, "ECDH"); + // assertEquals(kp.publicKey.algorithm.namedCurve, "secp256k1"); + assertEquals(kp.publicKey.usages.length, 0); + // assertEquals(kp.publicKey.usages[0], "deriveBits"); + assertEquals(kp.privateKey.type, "private"); + assertEquals(kp.privateKey.extractable, true); + assertEquals(kp.privateKey.algorithm.name, "ECDH"); + // assertEquals(kp.privateKey.algorithm.namedCurve, "secp256k1"); + assertEquals(kp.privateKey.usages.length, 1); + assertEquals(kp.privateKey.usages[0], "deriveBits"); + }); + }); +}); + +describe("deriveKeyPair", () => { + describe("with valid parameters", () => { + it("should return a proper instance", async () => { + const api = await loadSubtleCrypto(); + const cryptoApi = await loadCrypto(); + + // assert + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + const ikm = new Uint8Array(32); + cryptoApi.getRandomValues(ikm); + const kp = await kemContext.deriveKeyPair(ikm.buffer); + assertEquals(kp.publicKey.type, "public"); + assertEquals(kp.publicKey.extractable, true); + assertEquals(kp.publicKey.algorithm.name, "ECDH"); + // assertEquals(kp.publicKey.algorithm.namedCurve, "secp256k1"); + assertEquals(kp.publicKey.usages.length, 0); + // assertEquals(kp.publicKey.usages[0], "deriveBits"); + assertEquals(kp.privateKey.type, "private"); + assertEquals(kp.privateKey.extractable, true); + assertEquals(kp.privateKey.algorithm.name, "ECDH"); + // assertEquals(kp.privateKey.algorithm.namedCurve, "secp256k1"); + assertEquals(kp.privateKey.usages.length, 1); + assertEquals(kp.privateKey.usages[0], "deriveBits"); + }); + }); +}); + +describe("serialize/deserializePublicKey", () => { + describe("with valid parameters", () => { + it("should return a proper instance with DhkemSecp256k1HkdfSha256", async () => { + const api = await loadSubtleCrypto(); + + // assert + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + const kp = await kemContext.generateKeyPair(); + const bPubKey = await kemContext.serializePublicKey(kp.publicKey); + const pubKey = await kemContext.deserializePublicKey(bPubKey); + assertEquals(pubKey.type, "public"); + assertEquals(pubKey.extractable, true); + assertEquals(pubKey.algorithm.name, "ECDH"); + // assertEquals(pubKey.algorithm.namedCurve, "secp256k1"); + assertEquals(pubKey.usages.length, 0); + // assertEquals(pubKey.usages[0], "deriveBits"); + }); + }); +}); + +describe("importKey", () => { + describe("with valid parameters", () => { + it("should return a valid private key for DhkemSecp256k1HkdfSha256 from raw key", async () => { + const api = await loadSubtleCrypto(); + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + + const cryptoApi = await loadCrypto(); + const rawKey = new Uint8Array(32); + cryptoApi.getRandomValues(rawKey); + const privKey = await kemContext.importKey("raw", rawKey, false); + + // assert + assertEquals(privKey.usages.length, 1); + assertEquals(privKey.usages[0], "deriveBits"); + }); + + it("should return a valid public key for DhkemSecp256k1HkdfSha256 from raw key", async () => { + const api = await loadSubtleCrypto(); + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + + const cryptoApi = await loadCrypto(); + const rawKey = new Uint8Array(33); + rawKey[0] = hexStringToBytes("04")[0]; + cryptoApi.getRandomValues(rawKey); + const privKey = await kemContext.importKey("raw", rawKey, true); + + // assert + assertEquals(privKey.usages.length, 0); + // assertEquals(privKey.usages[0], "deriveBits"); + }); + }); + + describe("with invalid parameters", () => { + it("should throw DeserializeError with invalid DhkemSecp256k1HkdfSha256 private key", async () => { + const api = await loadSubtleCrypto(); + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + + const cryptoApi = await loadCrypto(); + const rawKey = new Uint8Array(33); + cryptoApi.getRandomValues(rawKey); + + // assert + await assertRejects( + () => kemContext.importKey("raw", rawKey, false), + Error, + ); + }); + + it("should throw DeserializeError with invalid DhkemSecp256k1HkdfSha256 public key", async () => { + const api = await loadSubtleCrypto(); + const kemContext = new DhkemSecp256k1HkdfSha256(); + kemContext.init(api); + + const cryptoApi = await loadCrypto(); + const rawKey = new Uint8Array(32); + cryptoApi.getRandomValues(rawKey); + + // assert + await assertRejects( + () => kemContext.importKey("raw", rawKey, true), + Error, + ); + }); + }); +}); + +describe("CipherSuite", () => { + describe("constructor with DhkemP256HkdfSha256/HkdfSha256/Aes128Gcm", () => { + it("should have a correct ciphersuite", async () => { + const suite: CipherSuite = new CipherSuite({ + kem: new DhkemSecp256k1HkdfSha256(), + kdf: KdfId.HkdfSha256, + aead: AeadId.ExportOnly, + }); + const kem = await suite.kemContext(); + assertEquals(kem.secretSize, 32); + assertEquals(kem.encSize, 65); + assertEquals(kem.publicKeySize, 65); + assertEquals(kem.privateKeySize, 32); + + // assert + assertEquals(suite.kem, KemId.DhkemSecp256K1HkdfSha256); + assertEquals(suite.kem, 0x0013); + assertEquals(suite.kdf, KdfId.HkdfSha256); + assertEquals(suite.kdf, 0x0001); + assertEquals(suite.aead, AeadId.ExportOnly); + assertEquals(suite.aead, 0xFFFF); + }); + }); + + describe("A README example of Base mode (DhkemSecp256k1HkdfSha256/KdfId.HkdfSha256)", () => { + it("should work normally", async () => { + // setup + const suite = new CipherSuite({ + kem: new DhkemSecp256k1HkdfSha256(), + kdf: KdfId.HkdfSha256, + aead: AeadId.Aes128Gcm, + }); + + const rkp = await suite.generateKeyPair(); + + const sender = await suite.createSenderContext({ + recipientPublicKey: rkp.publicKey, + }); + + const recipient = await suite.createRecipientContext({ + recipientKey: rkp, + enc: sender.enc, + }); + + // encrypt + const ct = await sender.seal( + new TextEncoder().encode("my-secret-message"), + ); + + // decrypt + const pt = await recipient.open(ct); + + // assert + assertEquals(new TextDecoder().decode(pt), "my-secret-message"); + }); + }); +}); diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/dhkemSecp256k1HkdfSha256.spec.ts b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/dhkemSecp256k1HkdfSha256.spec.ts new file mode 100644 index 000000000..a1c14b661 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/dhkemSecp256k1HkdfSha256.spec.ts @@ -0,0 +1,9 @@ +import { expect, test } from "@playwright/test"; + +test("basic test", async ({ page }) => { + await page.goto("https://dajiaji.github.io/hpke-js/dhkemSecp256k1HkdfSha256"); + await page.click("text=run"); + await page.waitForTimeout(5000); + await expect(page.locator("id=pass")).toHaveText("9"); + await expect(page.locator("id=fail")).toHaveText("0"); +}); diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/package.json b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/package.json new file mode 100644 index 000000000..22ec1425b --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@playwright/test": "^1.36.1" + } +} diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/pages/index.html b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/pages/index.html new file mode 100644 index 000000000..32c8c9d53 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/pages/index.html @@ -0,0 +1,87 @@ + + hpke-js test + + + +

hpke-js test

+ +
+ + +
+ +
+ +
+ + + + + + + + + +
pass: -
fail: -
+
+ + diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/pages/src/.gitkeep b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/pages/src/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/playwright.config.ts b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/playwright.config.ts new file mode 100644 index 000000000..ec692f847 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/browsers/playwright.config.ts @@ -0,0 +1,20 @@ +// playwright.config.ts +import { devices, PlaywrightTestConfig } from "@playwright/test"; + +const config: PlaywrightTestConfig = { + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + { + name: "firefox", + use: { ...devices["Desktop Firefox"] }, + }, + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, + }, + ], +}; +export default config; diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/bun/dhkemSecp256k1HkdfSha256.spec.ts b/x/dhkemSecp256k1HkdfSha256/test/runtimes/bun/dhkemSecp256k1HkdfSha256.spec.ts new file mode 100644 index 000000000..cd800a226 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/bun/dhkemSecp256k1HkdfSha256.spec.ts @@ -0,0 +1,17 @@ +import { assertEquals } from "testing/asserts.ts"; +import { describe, it } from "testing/bdd.ts"; + +describe("Cloudflare Workers", () => { + describe("GET /test?kem=0x0013", () => { + it("should return ok", async () => { + for (const kdf of ["0x0001", "0x0002", "0x0003"]) { + for (const aead of ["0x0001", "0x0002", "0x0003"]) { + const res = await fetch( + `http://localhost:3000/test?kem=0x0013&kdf=${kdf}&aead=${aead}`, + ); + assertEquals("ok", await res.text()); + } + } + }); + }); +}); diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/bun/src/index.js b/x/dhkemSecp256k1HkdfSha256/test/runtimes/bun/src/index.js new file mode 100644 index 000000000..dd2889caa --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/bun/src/index.js @@ -0,0 +1,46 @@ +import * as hpke from "./hpke.js"; +import * as secp256k1 from "./hpke-dhkemSecp256k1HkdfSha256.js"; + +export default { + port: 3000, + async fetch(request) { + const url = new URL(request.url); + if (url.pathname !== "/test") { + return new Response("ng: invalid path"); + } + const params = url.searchParams; + const kemStr = params.get("kem"); + const kdfStr = params.get("kdf"); + const aeadStr = params.get("aead"); + if (kemStr === null || kdfStr === null || aeadStr === null) { + return new Response("ng: invalid params"); + } + // const kem = Number.parseInt(kemStr); + const kem = new secp256k1.DhkemSecp256k1HkdfSha256(); + const kdf = Number.parseInt(kdfStr); + const aead = Number.parseInt(aeadStr); + if (Number.isNaN(kem) || Number.isNaN(kdf) || Number.isNaN(aead)) { + return new Response("ng: invalid params"); + } + + try { + const suite = new hpke.CipherSuite({ kem: kem, kdf: kdf, aead: aead }); + const rkp = await suite.generateKeyPair(); + const sender = await suite.createSenderContext({ + recipientPublicKey: rkp.publicKey, + }); + const recipient = await suite.createRecipientContext({ + recipientKey: rkp, + enc: sender.enc, + }); + const ct = await sender.seal(new TextEncoder().encode("hello world!")); + const pt = await recipient.open(ct); + if ("hello world!" !== new TextDecoder().decode(pt)) { + return new Response("ng"); + } + } catch (e) { + return new Response("ng: " + e.message); + } + return new Response("ok"); + }, +}; diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/dhkemSecp256k1HkdfSha256.spec.ts b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/dhkemSecp256k1HkdfSha256.spec.ts new file mode 100644 index 000000000..f71c9a153 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/dhkemSecp256k1HkdfSha256.spec.ts @@ -0,0 +1,17 @@ +import { assertEquals } from "testing/asserts.ts"; +import { describe, it } from "testing/bdd.ts"; + +describe("Cloudflare Workers", () => { + describe("GET /test?kem=0x0013", () => { + it("should return ok", async () => { + for (const kdf of ["0x0001", "0x0002", "0x0003"]) { + for (const aead of ["0x0001", "0x0002", "0x0003"]) { + const res = await fetch( + `http://localhost:8787/test?kem=0x0013&kdf=${kdf}&aead=${aead}`, + ); + assertEquals("ok", await res.text()); + } + } + }); + }); +}); diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/package.json b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/package.json new file mode 100644 index 000000000..18f967de5 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/package.json @@ -0,0 +1,12 @@ +{ + "name": "wrangler", + "version": "0.1.0", + "devDependencies": { + "wrangler": "2.10.0" + }, + "private": true, + "scripts": { + "start": "wrangler dev --local=true", + "deploy": "wrangler publish" + } +} diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/src/index.js b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/src/index.js new file mode 100644 index 000000000..028347408 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/src/index.js @@ -0,0 +1,44 @@ +import * as hpke from "./hpke.js"; + +export default { + async fetch(request) { + const url = new URL(request.url); + if (url.pathname !== "/test") { + return new Response("ng: invalid path"); + } + const params = url.searchParams; + const kemStr = params.get("kem"); + const kdfStr = params.get("kdf"); + const aeadStr = params.get("aead"); + if (kemStr === null || kdfStr === null || aeadStr === null) { + return new Response("ng: invalid params"); + } + // const kem = Number.parseInt(kemStr); + const kem = new secp256k1.DhkemSecp256k1HkdfSha256(); + const kdf = Number.parseInt(kdfStr); + const aead = Number.parseInt(aeadStr); + if (Number.isNaN(kem) || Number.isNaN(kdf) || Number.isNaN(aead)) { + return new Response("ng: invalid params"); + } + + try { + const suite = new hpke.CipherSuite({ kem: kem, kdf: kdf, aead: aead }); + const rkp = await suite.generateKeyPair(); + const sender = await suite.createSenderContext({ + recipientPublicKey: rkp.publicKey, + }); + const recipient = await suite.createRecipientContext({ + recipientKey: rkp, + enc: sender.enc, + }); + const ct = await sender.seal(new TextEncoder().encode("hello world!")); + const pt = await recipient.open(ct); + if ("hello world!" !== new TextDecoder().decode(pt)) { + return new Response("ng"); + } + } catch (e) { + return new Response("ng: " + e.message); + } + return new Response("ok"); + }, +}; diff --git a/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/wrangler.toml b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/wrangler.toml new file mode 100644 index 000000000..ee79b9b87 --- /dev/null +++ b/x/dhkemSecp256k1HkdfSha256/test/runtimes/cloudflare/wrangler.toml @@ -0,0 +1,4 @@ +name = "wrangler" +main = "src/index.js" +compatibility_date = "2022-07-01" +node_compat = true