@hpke/dhkem-secp256k1
Advanced tools
Comparing version 1.2.0 to 1.2.1
@@ -27,2 +27,3 @@ /** | ||
readonly DhkemX448HkdfSha512: 33; | ||
readonly HybridkemX25519Kyber768: 48; | ||
}; | ||
@@ -46,2 +47,3 @@ /** | ||
readonly DhkemX448HkdfSha512: 33; | ||
readonly HybridkemX25519Kyber768: 48; | ||
}; | ||
@@ -48,0 +50,0 @@ /** |
@@ -23,2 +23,3 @@ /** | ||
DhkemX448HkdfSha512: 0x0021, | ||
HybridkemX25519Kyber768: 0x0030, | ||
}; | ||
@@ -25,0 +26,0 @@ /** |
import type { RecipientContextParams } from "./recipientContextParams.js"; | ||
import type { SenderContextParams } from "./senderContextParams.js"; | ||
import { KemId } from "../identifiers.js"; | ||
export declare const SUITE_ID_HEADER_KEM: Uint8Array; | ||
/** | ||
@@ -5,0 +6,0 @@ * The KEM interface. |
@@ -1,1 +0,2 @@ | ||
export {}; | ||
// b"KEM" | ||
export const SUITE_ID_HEADER_KEM = new Uint8Array([75, 69, 77, 0, 0]); |
@@ -11,3 +11,3 @@ import type { KeyScheduleParams } from "./keyScheduleParams.js"; | ||
/** DO NOT USE. FOR DEBUGGING/TESTING PURPOSES ONLY. */ | ||
nonEphemeralKeyPair?: CryptoKeyPair; | ||
ekm?: CryptoKeyPair | ArrayBuffer; | ||
} |
import { EMPTY, INPUT_LENGTH_LIMIT } from "../consts.js"; | ||
import { DecapError, EncapError, InvalidParamError } from "../errors.js"; | ||
import { i2Osp, isCryptoKeyPair } from "../utils/misc.js"; | ||
// b"KEM" | ||
const SUITE_ID_HEADER_KEM = new Uint8Array([75, 69, 77, 0, 0]); | ||
import { SUITE_ID_HEADER_KEM } from "../interfaces/kemInterface.js"; | ||
import { concat, i2Osp, isCryptoKeyPair } from "../utils/misc.js"; | ||
// b"eae_prk" | ||
@@ -14,8 +13,2 @@ const LABEL_EAE_PRK = new Uint8Array([101, 97, 101, 95, 112, 114, 107]); | ||
]); | ||
function concat(a, b) { | ||
const ret = new Uint8Array(a.length + b.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
return ret; | ||
} | ||
function concat3(a, b, c) { | ||
@@ -104,5 +97,14 @@ const ret = new Uint8Array(a.length + b.length + c.length); | ||
async encap(params) { | ||
const ke = params.nonEphemeralKeyPair === undefined | ||
? await this.generateKeyPair() | ||
: params.nonEphemeralKeyPair; | ||
let ke; | ||
if (params.ekm === undefined) { | ||
ke = await this.generateKeyPair(); | ||
} | ||
else if (isCryptoKeyPair(params.ekm)) { | ||
// params.ekm is only used for testing. | ||
ke = params.ekm; | ||
} | ||
else { | ||
// params.ekm is only used for testing. | ||
ke = await this.deriveKeyPair(params.ekm); | ||
} | ||
const enc = await this._prim.serializePublicKey(ke.publicKey); | ||
@@ -109,0 +111,0 @@ const pkrm = await this._prim.serializePublicKey(params.recipientPublicKey); |
@@ -22,4 +22,8 @@ /** | ||
/** | ||
* Concatenates two Uint8Arrays. | ||
*/ | ||
export declare function concat(a: Uint8Array, b: Uint8Array): Uint8Array; | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
*/ | ||
export declare function base64UrlToBytes(v: string): Uint8Array; |
@@ -39,2 +39,11 @@ import * as dntShim from "../../_dnt.shims.js"; | ||
/** | ||
* Concatenates two Uint8Arrays. | ||
*/ | ||
export function concat(a, b) { | ||
const ret = new Uint8Array(a.length + b.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
return ret; | ||
} | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
@@ -41,0 +50,0 @@ */ |
@@ -6,3 +6,3 @@ { | ||
"name": "@hpke/dhkem-secp256k1", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "A Hybrid Public Key Encryption (HPKE) module extension for secp256k1 curve (EXPERIMENTAL)", | ||
@@ -9,0 +9,0 @@ "repository": { |
217
README.md
@@ -12,3 +12,3 @@ <h1 align="center">@hpke/dhkem-secp256k1</h1> | ||
| | ||
[pages(only for the latest ver.)](https://dajiaji.github.io/hpke-js/dhkem-secp256k1/docs/) | ||
[pages (only for the latest ver.)](https://dajiaji.github.io/hpke-js/dhkem-secp256k1/docs/) | ||
@@ -20,5 +20,5 @@ </div> | ||
- [Installation](#installation) | ||
- [Web Browser](#web-browser) | ||
- [Node.js](#nodejs) | ||
- [Deno](#deno) | ||
- [Web Browsers](#web-browsers) | ||
- [Cloudflare Workers](#cloudflare-workers) | ||
@@ -30,6 +30,35 @@ - [Usage](#usage) | ||
### Web Browser | ||
### Node.js | ||
Followings are how to use with typical CDNs. Other CDNs can be used as well. | ||
Using npm: | ||
```sh | ||
npm install @hpke/dhkem-secp256k1 | ||
``` | ||
Using yarn: | ||
```sh | ||
yarn add @hpke/dhkem-secp256k1 | ||
``` | ||
### Deno | ||
Using deno.land: | ||
```js | ||
// use a specific version | ||
import * as hpke from "https://deno.land/x/hpke@1.2.1/core/mod.ts"; | ||
import * as secp256k1 from "https://deno.land/x/hpke@1.2.1/x/dhkem-secp256k1/mod.ts"; | ||
// use the latest stable version | ||
import * as hpke from "https://deno.land/x/hpke/core/mod.ts"; | ||
import * as secp256k1 from "https://deno.land/x/hpke/x/dhkem-secp256k1/mod.ts"; | ||
``` | ||
### Web Browsers | ||
Followings are how to use this module with typical CDNs. Other CDNs can be used | ||
as well. | ||
Using esm.sh: | ||
@@ -40,4 +69,4 @@ | ||
<script type="module"> | ||
import * as hpke from "https://esm.sh/@hpke/core@1.2.0"; | ||
import * as secp256k1 from "https://esm.sh/@hpke/dhkem-secp256k1@1.2.0"; | ||
import * as hpke from "https://esm.sh/@hpke/core@1.2.1"; | ||
import * as secp256k1 from "https://esm.sh/@hpke/dhkem-secp256k1@1.2.1"; | ||
// ... | ||
@@ -59,4 +88,4 @@ </script> | ||
<script type="module"> | ||
import * as hpke from "https://unpkg.com/@hpke/core@1.2.0/esm/mod.js"; | ||
import * as secp256k1 from "https://unpkg.com/@hpke/dhkem-secp256k1@1.2.0/esm/mod.js"; | ||
import * as hpke from "https://unpkg.com/@hpke/core@1.2.1/esm/mod.js"; | ||
import * as secp256k1 from "https://unpkg.com/@hpke/dhkem-secp256k1@1.2.1/esm/mod.js"; | ||
// ... | ||
@@ -66,30 +95,2 @@ </script> | ||
### Node.js | ||
Using npm: | ||
```sh | ||
npm install @hpke/dhkem-secp256k1 | ||
``` | ||
Using yarn: | ||
```sh | ||
yarn add @hpke/dhkem-secp256k1 | ||
``` | ||
### Deno | ||
Using deno.land: | ||
```js | ||
// use a specific version | ||
import * as hpke from "https://deno.land/x/hpke@1.2.0/core/mod.ts"; | ||
import * as secp256k1 from "https://deno.land/x/hpke@1.2.0/x/dhkem-secp256k1/mod.ts"; | ||
// use the latest stable version | ||
import * as hpke from "https://deno.land/x/hpke/core/mod.ts"; | ||
import * as secp256k1 from "https://deno.land/x/hpke/x/dhkem-secp256k1/mod.ts"; | ||
``` | ||
### Cloudflare Workers | ||
@@ -109,51 +110,2 @@ | ||
### Browsers | ||
```html | ||
<html> | ||
<head></head> | ||
<body> | ||
<script type="module"> | ||
import { Aes128Gcm, CipherSuite, HkdfSha256 } from "https://esm.sh/@hpke/core@1.2.0"; | ||
import { DhkemSecp256k1HkdfSha256 } from "https://esm.sh/@hpke/dhkem-secp256k1@1.2.0"; | ||
globalThis.doHpke = async () => { | ||
const suite = new CipherSuite({ | ||
kem: new DhkemSecp256k1HkdfSha256(), | ||
kdf: new HkdfSha256(), | ||
aead: new Aes128Gcm(), | ||
}); | ||
const rkp = await suite.kem.generateKeyPair(); | ||
const sender = await suite.createSenderContext({ | ||
recipientPublicKey: rkp.publicKey | ||
}); | ||
const recipient = await suite.createRecipientContext({ | ||
recipientKey: rkp.privateKey, // rkp (CryptoKeyPair) is also acceptable. | ||
enc: sender.enc, | ||
}); | ||
// encrypt | ||
const ct = await sender.seal(new TextEncoder().encode("hello world!")); | ||
// decrypt | ||
try { | ||
const pt = await recipient.open(ct); | ||
// hello world! | ||
alert(new TextDecoder().decode(pt)); | ||
} catch (err) { | ||
alert("failed to decrypt."); | ||
} | ||
} | ||
</script> | ||
<button type="button" onclick="doHpke()">do HPKE</button> | ||
</body> | ||
</html> | ||
``` | ||
### Node.js | ||
@@ -180,2 +132,5 @@ | ||
// encrypt | ||
const ct = await sender.seal(new TextEncoder().encode("Hello world!")); | ||
const recipient = await suite.createRecipientContext({ | ||
@@ -186,17 +141,14 @@ recipientKey: rkp.privateKey, | ||
// encrypt | ||
const ct = await sender.seal(new TextEncoder().encode("my-secret-message")); | ||
// decrypt | ||
try { | ||
const pt = await recipient.open(ct); | ||
const pt = await recipient.open(ct); | ||
console.log("decrypted: ", new TextDecoder().decode(pt)); | ||
// decrypted: my-secret-message | ||
} catch (err) { | ||
console.log("failed to decrypt."); | ||
} | ||
// Hello world! | ||
console.log(new TextDecoder().decode(pt)); | ||
} | ||
doHpke(); | ||
try { | ||
doHpke(); | ||
} catch (err) { | ||
console.log("failed:", err.message); | ||
} | ||
``` | ||
@@ -207,4 +159,4 @@ | ||
```js | ||
import { Aes256Gcm, CipherSuite, HkdfSha512 } from "https://deno.land/x/hpke@1.2.0/core/mod.ts"; | ||
import { DhkemSecp256k1HkdfSha256 } from "https://deno.land/x/hpke@1.2.0/x/dhkem-secp256k1/mod.ts"; | ||
import { Aes256Gcm, CipherSuite, HkdfSha512 } from "https://deno.land/x/hpke@1.2.1/core/mod.ts"; | ||
import { DhkemSecp256k1HkdfSha256 } from "https://deno.land/x/hpke@1.2.1/x/dhkem-secp256k1/mod.ts"; | ||
@@ -225,2 +177,5 @@ async function doHpke() { | ||
// encrypt | ||
const ct = await sender.seal(new TextEncoder().encode("Hello world!")); | ||
const recipient = await suite.createRecipientContext({ | ||
@@ -231,17 +186,61 @@ recipientKey: rkp.privateKey, | ||
// encrypt | ||
const ct = await sender.seal(new TextEncoder().encode("my-secret-message")); | ||
// decrypt | ||
const pt = await recipient.open(ct); | ||
try { | ||
// decrypt | ||
const pt = await recipient.open(ct); | ||
// Hello world! | ||
console.log(new TextDecoder().decode(pt)); | ||
} | ||
console.log("decrypted: ", new TextDecoder().decode(pt)); | ||
// decrypted: my-secret-message | ||
} catch (_err: unknown) { | ||
console.log("failed to decrypt."); | ||
} | ||
try { | ||
doHpke(); | ||
} catch (_err: unknown) { | ||
console.log("failed."); | ||
} | ||
``` | ||
doHpke(); | ||
### Browsers | ||
```html | ||
<html> | ||
<head></head> | ||
<body> | ||
<script type="module"> | ||
import { Aes128Gcm, CipherSuite, HkdfSha256 } from "https://esm.sh/@hpke/core@1.2.1"; | ||
import { DhkemSecp256k1HkdfSha256 } from "https://esm.sh/@hpke/dhkem-secp256k1@1.2.1"; | ||
globalThis.doHpke = async () => { | ||
try { | ||
const suite = new CipherSuite({ | ||
kem: new DhkemSecp256k1HkdfSha256(), | ||
kdf: new HkdfSha256(), | ||
aead: new Aes128Gcm(), | ||
}); | ||
const rkp = await suite.kem.generateKeyPair(); | ||
const sender = await suite.createSenderContext({ | ||
recipientPublicKey: rkp.publicKey | ||
}); | ||
// encrypt | ||
const ct = await sender.seal(new TextEncoder().encode("Hello world!")); | ||
const recipient = await suite.createRecipientContext({ | ||
recipientKey: rkp.privateKey, // rkp (CryptoKeyPair) is also acceptable. | ||
enc: sender.enc, | ||
}); | ||
// decrypt | ||
const pt = await recipient.open(ct); | ||
// Hello world! | ||
alert(new TextDecoder().decode(pt)); | ||
} catch (err) { | ||
alert("failed:", err.message); | ||
} | ||
} | ||
</script> | ||
<button type="button" onclick="doHpke()">do HPKE</button> | ||
</body> | ||
</html> | ||
``` | ||
@@ -248,0 +247,0 @@ |
@@ -27,2 +27,3 @@ /** | ||
readonly DhkemX448HkdfSha512: 33; | ||
readonly HybridkemX25519Kyber768: 48; | ||
}; | ||
@@ -46,2 +47,3 @@ /** | ||
readonly DhkemX448HkdfSha512: 33; | ||
readonly HybridkemX25519Kyber768: 48; | ||
}; | ||
@@ -48,0 +50,0 @@ /** |
@@ -35,2 +35,3 @@ (function (factory) { | ||
DhkemX448HkdfSha512: 0x0021, | ||
HybridkemX25519Kyber768: 0x0030, | ||
}; | ||
@@ -37,0 +38,0 @@ /** |
import type { RecipientContextParams } from "./recipientContextParams.js"; | ||
import type { SenderContextParams } from "./senderContextParams.js"; | ||
import { KemId } from "../identifiers.js"; | ||
export declare const SUITE_ID_HEADER_KEM: Uint8Array; | ||
/** | ||
@@ -5,0 +6,0 @@ * The KEM interface. |
@@ -12,2 +12,5 @@ (function (factory) { | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SUITE_ID_HEADER_KEM = void 0; | ||
// b"KEM" | ||
exports.SUITE_ID_HEADER_KEM = new Uint8Array([75, 69, 77, 0, 0]); | ||
}); |
@@ -11,3 +11,3 @@ import type { KeyScheduleParams } from "./keyScheduleParams.js"; | ||
/** DO NOT USE. FOR DEBUGGING/TESTING PURPOSES ONLY. */ | ||
nonEphemeralKeyPair?: CryptoKeyPair; | ||
ekm?: CryptoKeyPair | ArrayBuffer; | ||
} |
@@ -7,3 +7,3 @@ (function (factory) { | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "../consts.js", "../errors.js", "../utils/misc.js"], factory); | ||
define(["require", "exports", "../consts.js", "../errors.js", "../interfaces/kemInterface.js", "../utils/misc.js"], factory); | ||
} | ||
@@ -16,5 +16,4 @@ })(function (require, exports) { | ||
const errors_js_1 = require("../errors.js"); | ||
const kemInterface_js_1 = require("../interfaces/kemInterface.js"); | ||
const misc_js_1 = require("../utils/misc.js"); | ||
// b"KEM" | ||
const SUITE_ID_HEADER_KEM = new Uint8Array([75, 69, 77, 0, 0]); | ||
// b"eae_prk" | ||
@@ -28,8 +27,2 @@ const LABEL_EAE_PRK = new Uint8Array([101, 97, 101, 95, 112, 114, 107]); | ||
]); | ||
function concat(a, b) { | ||
const ret = new Uint8Array(a.length + b.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
return ret; | ||
} | ||
function concat3(a, b, c) { | ||
@@ -89,3 +82,3 @@ const ret = new Uint8Array(a.length + b.length + c.length); | ||
this._kdf = kdf; | ||
const suiteId = new Uint8Array(SUITE_ID_HEADER_KEM); | ||
const suiteId = new Uint8Array(kemInterface_js_1.SUITE_ID_HEADER_KEM); | ||
suiteId.set((0, misc_js_1.i2Osp)(this.id, 2), 3); | ||
@@ -119,5 +112,14 @@ this._kdf.init(suiteId); | ||
async encap(params) { | ||
const ke = params.nonEphemeralKeyPair === undefined | ||
? await this.generateKeyPair() | ||
: params.nonEphemeralKeyPair; | ||
let ke; | ||
if (params.ekm === undefined) { | ||
ke = await this.generateKeyPair(); | ||
} | ||
else if ((0, misc_js_1.isCryptoKeyPair)(params.ekm)) { | ||
// params.ekm is only used for testing. | ||
ke = params.ekm; | ||
} | ||
else { | ||
// params.ekm is only used for testing. | ||
ke = await this.deriveKeyPair(params.ekm); | ||
} | ||
const enc = await this._prim.serializePublicKey(ke.publicKey); | ||
@@ -136,7 +138,7 @@ const pkrm = await this._prim.serializePublicKey(params.recipientPublicKey); | ||
const dh2 = new Uint8Array(await this._prim.dh(sks, params.recipientPublicKey)); | ||
dh = concat(dh1, dh2); | ||
dh = (0, misc_js_1.concat)(dh1, dh2); | ||
} | ||
let kemContext; | ||
if (params.senderKey === undefined) { | ||
kemContext = concat(new Uint8Array(enc), new Uint8Array(pkrm)); | ||
kemContext = (0, misc_js_1.concat)(new Uint8Array(enc), new Uint8Array(pkrm)); | ||
} | ||
@@ -177,7 +179,7 @@ else { | ||
const dh2 = new Uint8Array(await this._prim.dh(skr, params.senderPublicKey)); | ||
dh = concat(dh1, dh2); | ||
dh = (0, misc_js_1.concat)(dh1, dh2); | ||
} | ||
let kemContext; | ||
if (params.senderPublicKey === undefined) { | ||
kemContext = concat(new Uint8Array(params.enc), new Uint8Array(pkrm)); | ||
kemContext = (0, misc_js_1.concat)(new Uint8Array(params.enc), new Uint8Array(pkrm)); | ||
} | ||
@@ -184,0 +186,0 @@ else { |
@@ -22,4 +22,8 @@ /** | ||
/** | ||
* Concatenates two Uint8Arrays. | ||
*/ | ||
export declare function concat(a: Uint8Array, b: Uint8Array): Uint8Array; | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
*/ | ||
export declare function base64UrlToBytes(v: string): Uint8Array; |
@@ -35,3 +35,3 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.base64UrlToBytes = exports.i2Osp = exports.isCryptoKeyPair = exports.isDeno = exports.isCloudflareWorkers = exports.isBrowser = void 0; | ||
exports.base64UrlToBytes = exports.concat = exports.i2Osp = exports.isCryptoKeyPair = exports.isDeno = exports.isCloudflareWorkers = exports.isBrowser = void 0; | ||
const dntShim = __importStar(require("../../_dnt.shims.js")); | ||
@@ -80,2 +80,12 @@ /** | ||
/** | ||
* Concatenates two Uint8Arrays. | ||
*/ | ||
function concat(a, b) { | ||
const ret = new Uint8Array(a.length + b.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
return ret; | ||
} | ||
exports.concat = concat; | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
@@ -82,0 +92,0 @@ */ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
130104
3505
240