@hpke/dhkem-x448
Advanced tools
Comparing version 1.0.4 to 1.1.0
@@ -1,9 +0,5 @@ | ||
export declare class AlgorithmBase { | ||
export declare class NativeAlgorithm { | ||
protected _api: SubtleCrypto | undefined; | ||
constructor(); | ||
protected _setup(): Promise<void>; | ||
} | ||
export declare class Algorithm extends AlgorithmBase { | ||
constructor(); | ||
init(api: SubtleCrypto): void; | ||
protected checkInit(): void; | ||
} |
@@ -1,2 +0,20 @@ | ||
export class AlgorithmBase { | ||
import { NotSupportedError } from "./errors.js"; | ||
import { isBrowser, isCloudflareWorkers } from "./utils/misc.js"; | ||
async function loadSubtleCrypto() { | ||
if (isBrowser() || isCloudflareWorkers()) { | ||
if (globalThis.crypto !== undefined) { | ||
return globalThis.crypto.subtle; | ||
} | ||
// jsdom | ||
} | ||
try { | ||
// @ts-ignore: to ignore "crypto" | ||
const { webcrypto } = await import("crypto"); // node:crypto | ||
return webcrypto.subtle; | ||
} | ||
catch (e) { | ||
throw new NotSupportedError(e); | ||
} | ||
} | ||
export class NativeAlgorithm { | ||
constructor() { | ||
@@ -10,15 +28,8 @@ Object.defineProperty(this, "_api", { | ||
} | ||
} | ||
export class Algorithm extends AlgorithmBase { | ||
constructor() { | ||
super(); | ||
} | ||
init(api) { | ||
this._api = api; | ||
} | ||
checkInit() { | ||
if (this._api === undefined) { | ||
throw new Error("Not initialized. Call init()"); | ||
async _setup() { | ||
if (this._api !== undefined) { | ||
return; | ||
} | ||
this._api = await loadSubtleCrypto(); | ||
} | ||
} |
@@ -20,2 +20,3 @@ /** | ||
export declare const Kem: { | ||
readonly NotAssigned: 0; | ||
readonly DhkemP256HkdfSha256: 16; | ||
@@ -38,2 +39,3 @@ readonly DhkemP384HkdfSha384: 17; | ||
export declare const KemId: { | ||
readonly NotAssigned: 0; | ||
readonly DhkemP256HkdfSha256: 16; | ||
@@ -40,0 +42,0 @@ readonly DhkemP384HkdfSha384: 17; |
@@ -16,2 +16,3 @@ /** | ||
export const Kem = { | ||
NotAssigned: 0x0000, | ||
DhkemP256HkdfSha256: 0x0010, | ||
@@ -18,0 +19,0 @@ DhkemP384HkdfSha384: 0x0011, |
@@ -19,22 +19,23 @@ import type { RecipientContextParams } from "./recipientContextParams.js"; | ||
/** | ||
* Generates a key pair. | ||
* Serializes a public key as CryptoKey to a byte string of length `Npk`. | ||
* | ||
* If the error occurred, throws {@link NotSupportedError}. | ||
* If the error occurred, throws {@link SerializeError}. | ||
* | ||
* @returns A key pair generated. | ||
* @throws {@link NotSupportedError} | ||
* @param key A CryptoKey. | ||
* @returns A key as bytes. | ||
* @throws {@link SerializeError} | ||
*/ | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
/** | ||
* Derives a key pair from the byte string ikm. | ||
* Deserializes a public key as a byte string of length `Npk` to CryptoKey. | ||
* | ||
* If the error occurred, throws {@link DeriveKeyPairError}. | ||
* If the error occurred, throws {@link DeserializeError}. | ||
* | ||
* @param ikm An input keying material. | ||
* @returns A key pair derived. | ||
* @throws {@link DeriveKeyPairError} | ||
* @param key A key as bytes. | ||
* @returns A CryptoKey. | ||
* @throws {@link DeserializeError} | ||
*/ | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
/** | ||
* Serializes a public key as CryptoKey to a byte string of length `Npk`. | ||
* Serializes a private key as CryptoKey to a byte string of length `Nsk`. | ||
* | ||
@@ -47,5 +48,5 @@ * If the error occurred, throws {@link SerializeError}. | ||
*/ | ||
serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
/** | ||
* Deserializes a public key as a byte string of length `Npk` to CryptoKey. | ||
* Deserializes a private key as a byte string of length `Nsk` to CryptoKey. | ||
* | ||
@@ -58,3 +59,3 @@ * If the error occurred, throws {@link DeserializeError}. | ||
*/ | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
deserializePrivateKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
/** | ||
@@ -80,2 +81,21 @@ * Imports a public or private key and converts to a {@link CryptoKey}. | ||
/** | ||
* Generates a key pair. | ||
* | ||
* If the error occurred, throws {@link NotSupportedError}. | ||
* | ||
* @returns A key pair generated. | ||
* @throws {@link NotSupportedError} | ||
*/ | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
/** | ||
* Derives a key pair from the byte string ikm. | ||
* | ||
* If the error occurred, throws {@link DeriveKeyPairError}. | ||
* | ||
* @param ikm An input keying material. | ||
* @returns A key pair derived. | ||
* @throws {@link DeriveKeyPairError} | ||
*/ | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
/** | ||
* Generates an ephemeral, fixed-length symmetric key and | ||
@@ -82,0 +102,0 @@ * a fixed-length encapsulation of the key that can be decapsulated |
import type { KdfInterface } from "../interfaces/kdfInterface.js"; | ||
import { AlgorithmBase } from "../algorithm.js"; | ||
import { NativeAlgorithm } from "../algorithm.js"; | ||
import { KdfId } from "../identifiers.js"; | ||
export declare class KdfAlgorithm extends AlgorithmBase { | ||
protected _suiteId: Uint8Array; | ||
constructor(); | ||
init(suiteId: Uint8Array): void; | ||
protected checkInit(): void; | ||
} | ||
export declare class HkdfNative extends KdfAlgorithm implements KdfInterface { | ||
export declare class HkdfNative extends NativeAlgorithm implements KdfInterface { | ||
readonly id: KdfId; | ||
readonly hashSize: number; | ||
protected _suiteId: Uint8Array; | ||
protected readonly algHash: HmacKeyGenParams; | ||
constructor(); | ||
init(suiteId: Uint8Array): void; | ||
buildLabeledIkm(label: Uint8Array, ikm: Uint8Array): Uint8Array; | ||
@@ -22,3 +18,3 @@ buildLabeledInfo(label: Uint8Array, info: Uint8Array, len: number): Uint8Array; | ||
labeledExpand(prk: ArrayBuffer, label: Uint8Array, info: Uint8Array, len: number): Promise<ArrayBuffer>; | ||
protected setup(): Promise<void>; | ||
protected _checkInit(): void; | ||
} | ||
@@ -25,0 +21,0 @@ export declare class HkdfSha256Native extends HkdfNative { |
@@ -1,4 +0,3 @@ | ||
import { AlgorithmBase } from "../algorithm.js"; | ||
import { NativeAlgorithm } from "../algorithm.js"; | ||
import { KdfId } from "../identifiers.js"; | ||
import { loadSubtleCrypto } from "../webCrypto.js"; | ||
import * as consts from "../consts.js"; | ||
@@ -8,24 +7,5 @@ import * as errors from "../errors.js"; | ||
const HPKE_VERSION = new Uint8Array([72, 80, 75, 69, 45, 118, 49]); | ||
export class KdfAlgorithm extends AlgorithmBase { | ||
export class HkdfNative extends NativeAlgorithm { | ||
constructor() { | ||
super(); | ||
Object.defineProperty(this, "_suiteId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: consts.EMPTY | ||
}); | ||
} | ||
init(suiteId) { | ||
this._suiteId = suiteId; | ||
} | ||
checkInit() { | ||
if (this._suiteId === consts.EMPTY) { | ||
throw new Error("Not initialized. Call init()"); | ||
} | ||
} | ||
} | ||
export class HkdfNative extends KdfAlgorithm { | ||
constructor() { | ||
super(); | ||
Object.defineProperty(this, "id", { | ||
@@ -43,2 +23,8 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(this, "_suiteId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: consts.EMPTY | ||
}); | ||
Object.defineProperty(this, "algHash", { | ||
@@ -55,4 +41,7 @@ enumerable: true, | ||
} | ||
init(suiteId) { | ||
this._suiteId = suiteId; | ||
} | ||
buildLabeledIkm(label, ikm) { | ||
this.checkInit(); | ||
this._checkInit(); | ||
const ret = new Uint8Array(7 + this._suiteId.byteLength + label.byteLength + ikm.byteLength); | ||
@@ -66,3 +55,3 @@ ret.set(HPKE_VERSION, 0); | ||
buildLabeledInfo(label, info, len) { | ||
this.checkInit(); | ||
this._checkInit(); | ||
const ret = new Uint8Array(9 + this._suiteId.byteLength + label.byteLength + info.byteLength); | ||
@@ -77,3 +66,3 @@ ret.set(new Uint8Array([0, len]), 0); | ||
async extract(salt, ikm) { | ||
await this.setup(); | ||
await this._setup(); | ||
if (salt.byteLength === 0) { | ||
@@ -91,3 +80,3 @@ salt = new ArrayBuffer(this.hashSize); | ||
async expand(prk, info, len) { | ||
await this.setup(); | ||
await this._setup(); | ||
const key = await this._api.importKey("raw", prk, this.algHash, false, [ | ||
@@ -123,3 +112,3 @@ "sign", | ||
async extractAndExpand(salt, ikm, info, len) { | ||
await this.setup(); | ||
await this._setup(); | ||
const baseKey = await this._api.importKey("raw", ikm, "HKDF", false, ["deriveBits"]); | ||
@@ -139,7 +128,6 @@ return await this._api.deriveBits({ | ||
} | ||
async setup() { | ||
if (this._api !== undefined) { | ||
return; | ||
_checkInit() { | ||
if (this._suiteId === consts.EMPTY) { | ||
throw new Error("Not initialized. Call init()"); | ||
} | ||
this._api = await loadSubtleCrypto(); | ||
} | ||
@@ -146,0 +134,0 @@ } |
@@ -8,3 +8,3 @@ // @ts-ignore: for "npm:" | ||
async extract(salt, ikm) { | ||
await this.setup(); | ||
await this._setup(); | ||
if (salt.byteLength === 0) { | ||
@@ -11,0 +11,0 @@ salt = new ArrayBuffer(this.hashSize); |
import type { KdfInterface } from "../interfaces/kdfInterface.js"; | ||
import type { KemInterface } from "../interfaces/kemInterface.js"; | ||
import type { KemPrimitives } from "../interfaces/kemPrimitives.js"; | ||
import type { DhkemPrimitives } from "../interfaces/dhkemPrimitives.js"; | ||
import type { SenderContextParams } from "../interfaces/senderContextParams.js"; | ||
import type { RecipientContextParams } from "../interfaces/recipientContextParams.js"; | ||
import { Algorithm } from "../algorithm.js"; | ||
import { KemId } from "../identifiers.js"; | ||
export declare class Dhkem extends Algorithm implements KemInterface { | ||
export declare class Dhkem implements KemInterface { | ||
readonly id: KemId; | ||
@@ -14,10 +13,12 @@ readonly secretSize: number; | ||
readonly privateKeySize: number; | ||
protected _prim: KemPrimitives; | ||
protected _prim: DhkemPrimitives; | ||
protected _kdf: KdfInterface; | ||
constructor(prim: KemPrimitives, kdf: KdfInterface); | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
constructor(id: KemId, prim: DhkemPrimitives, kdf: KdfInterface); | ||
serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
deserializePrivateKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
importKey(format: "raw" | "jwk", key: ArrayBuffer | JsonWebKey, isPublic?: boolean): Promise<CryptoKey>; | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
encap(params: SenderContextParams): Promise<{ | ||
@@ -28,4 +29,3 @@ sharedSecret: ArrayBuffer; | ||
decap(params: RecipientContextParams): Promise<ArrayBuffer>; | ||
private _setup; | ||
private _generateSharedSecret; | ||
} |
@@ -1,5 +0,2 @@ | ||
import { Algorithm } from "../algorithm.js"; | ||
import { KemId } from "../identifiers.js"; | ||
import { loadSubtleCrypto } from "../webCrypto.js"; | ||
import { concat, concat3, i2Osp, isCryptoKeyPair } from "../utils/misc.js"; | ||
import { i2Osp, isCryptoKeyPair } from "../utils/misc.js"; | ||
import { EMPTY, INPUT_LENGTH_LIMIT } from "../consts.js"; | ||
@@ -12,20 +9,22 @@ import * as errors from "../errors.js"; | ||
// b"shared_secret" | ||
// deno-fmt-ignore | ||
const LABEL_SHARED_SECRET = new Uint8Array([ | ||
115, | ||
104, | ||
97, | ||
114, | ||
101, | ||
100, | ||
95, | ||
115, | ||
101, | ||
99, | ||
114, | ||
101, | ||
116, | ||
115, 104, 97, 114, 101, 100, 95, 115, 101, 99, | ||
114, 101, 116, | ||
]); | ||
export class Dhkem extends Algorithm { | ||
constructor(prim, kdf) { | ||
super(); | ||
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) { | ||
const ret = new Uint8Array(a.length + b.length + c.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
ret.set(c, a.length + b.length); | ||
return ret; | ||
} | ||
export class Dhkem { | ||
constructor(id, prim, kdf) { | ||
Object.defineProperty(this, "id", { | ||
@@ -35,3 +34,3 @@ enumerable: true, | ||
writable: true, | ||
value: KemId.DhkemP256HkdfSha256 | ||
value: void 0 | ||
}); | ||
@@ -74,13 +73,26 @@ Object.defineProperty(this, "secretSize", { | ||
}); | ||
this.id = id; | ||
this._prim = prim; | ||
this._kdf = kdf; | ||
const suiteId = new Uint8Array(SUITE_ID_HEADER_KEM); | ||
suiteId.set(i2Osp(this.id, 2), 3); | ||
this._kdf.init(suiteId); | ||
} | ||
async serializePublicKey(key) { | ||
return await this._prim.serializePublicKey(key); | ||
} | ||
async deserializePublicKey(key) { | ||
return await this._prim.deserializePublicKey(key); | ||
} | ||
async serializePrivateKey(key) { | ||
return await this._prim.serializePrivateKey(key); | ||
} | ||
async deserializePrivateKey(key) { | ||
return await this._prim.deserializePrivateKey(key); | ||
} | ||
async importKey(format, key, isPublic = true) { | ||
return await this._prim.importKey(format, key, isPublic); | ||
} | ||
async generateKeyPair() { | ||
await this._setup(); | ||
try { | ||
return await this._prim.generateKeyPair(); | ||
} | ||
catch (e) { | ||
throw new errors.NotSupportedError(e); | ||
} | ||
return await this._prim.generateKeyPair(); | ||
} | ||
@@ -91,45 +103,11 @@ async deriveKeyPair(ikm) { | ||
} | ||
await this._setup(); | ||
try { | ||
return await this._prim.deriveKeyPair(ikm); | ||
} | ||
catch (e) { | ||
throw new errors.DeriveKeyPairError(e); | ||
} | ||
return await this._prim.deriveKeyPair(ikm); | ||
} | ||
async serializePublicKey(key) { | ||
await this._setup(); | ||
try { | ||
return await this._prim.serializePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
async deserializePublicKey(key) { | ||
await this._setup(); | ||
try { | ||
return await this._prim.deserializePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async importKey(format, key, isPublic = true) { | ||
await this._setup(); | ||
try { | ||
return await this._prim.importKey(format, key, isPublic); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async encap(params) { | ||
await this._setup(); | ||
const ke = params.nonEphemeralKeyPair === undefined | ||
? await this.generateKeyPair() | ||
: params.nonEphemeralKeyPair; | ||
const enc = await this._prim.serializePublicKey(ke.publicKey); | ||
const pkrm = await this._prim.serializePublicKey(params.recipientPublicKey); | ||
try { | ||
const ke = params.nonEphemeralKeyPair === undefined | ||
? await this.generateKeyPair() | ||
: params.nonEphemeralKeyPair; | ||
const enc = await this._prim.serializePublicKey(ke.publicKey); | ||
const pkrm = await this._prim.serializePublicKey(params.recipientPublicKey); | ||
let dh; | ||
@@ -169,18 +147,11 @@ if (params.senderKey === undefined) { | ||
async decap(params) { | ||
let pke; | ||
await this._setup(); | ||
const pke = await this._prim.deserializePublicKey(params.enc); | ||
const skr = isCryptoKeyPair(params.recipientKey) | ||
? params.recipientKey.privateKey | ||
: params.recipientKey; | ||
const pkr = isCryptoKeyPair(params.recipientKey) | ||
? params.recipientKey.publicKey | ||
: await this._prim.derivePublicKey(params.recipientKey); | ||
const pkrm = await this._prim.serializePublicKey(pkr); | ||
try { | ||
pke = await this._prim.deserializePublicKey(params.enc); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
try { | ||
const skr = isCryptoKeyPair(params.recipientKey) | ||
? params.recipientKey.privateKey | ||
: params.recipientKey; | ||
const pkr = isCryptoKeyPair(params.recipientKey) | ||
? params.recipientKey.publicKey | ||
: await this._prim.derivePublicKey(params.recipientKey); | ||
const pkrm = await this._prim.serializePublicKey(pkr); | ||
let dh; | ||
@@ -212,13 +183,2 @@ if (params.senderPublicKey === undefined) { | ||
} | ||
async _setup() { | ||
if (this._api !== undefined) { | ||
return; | ||
} | ||
const api = await loadSubtleCrypto(); | ||
const suiteId = new Uint8Array(SUITE_ID_HEADER_KEM); | ||
suiteId.set(i2Osp(this.id, 2), 3); | ||
this._prim.init(api); | ||
this._kdf.init(suiteId); | ||
super.init(api); | ||
} | ||
async _generateSharedSecret(dh, kemContext) { | ||
@@ -225,0 +185,0 @@ const labeledIkm = this._kdf.buildLabeledIkm(LABEL_EAE_PRK, dh); |
@@ -1,5 +0,4 @@ | ||
import type { KemPrimitives } from "../../interfaces/kemPrimitives.js"; | ||
import type { DhkemPrimitives } from "../../interfaces/dhkemPrimitives.js"; | ||
import type { KdfInterface } from "../../interfaces/kdfInterface.js"; | ||
import { Algorithm } from "../../algorithm.js"; | ||
export declare class X448 extends Algorithm implements KemPrimitives { | ||
export declare class X448 implements DhkemPrimitives { | ||
private _hkdf; | ||
@@ -11,9 +10,11 @@ private _nPk; | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
deserializePrivateKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
importKey(format: "raw" | "jwk", key: ArrayBuffer | JsonWebKey, isPublic: boolean): Promise<CryptoKey>; | ||
derivePublicKey(key: CryptoKey): Promise<CryptoKey>; | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
derivePublicKey(key: CryptoKey): Promise<CryptoKey>; | ||
dh(sk: CryptoKey, pk: CryptoKey): Promise<ArrayBuffer>; | ||
private _serializePublicKey; | ||
private _deserializePublicKey; | ||
private _serializePrivateKey; | ||
private _importRawKey; | ||
@@ -20,0 +21,0 @@ private _importJWK; |
// @ts-ignore: for "npm:" | ||
import { ed448, x448 } from "@noble/curves/ed448"; | ||
import { Algorithm } from "../../algorithm.js"; | ||
import { KEM_USAGES, LABEL_DKP_PRK, LABEL_SK, } from "../../interfaces/kemPrimitives.js"; | ||
import { XCryptoKey } from "../../xCryptoKey.js"; | ||
import * as consts from "../../consts.js"; | ||
import * as errors from "../../errors.js"; | ||
import { KEM_USAGES, LABEL_DKP_PRK, LABEL_SK, } from "../../interfaces/dhkemPrimitives.js"; | ||
import { base64UrlToBytes } from "../../utils/misc.js"; | ||
import { XCryptoKey } from "../../xCryptoKey.js"; | ||
const ALG_NAME = "X448"; | ||
export class X448 extends Algorithm { | ||
export class X448 { | ||
constructor(hkdf) { | ||
super(); | ||
Object.defineProperty(this, "_hkdf", { | ||
@@ -35,37 +34,88 @@ enumerable: true, | ||
async serializePublicKey(key) { | ||
return await this._serializePublicKey(key); | ||
try { | ||
return await this._serializePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
async deserializePublicKey(key) { | ||
return await this._deserializePublicKey(key); | ||
try { | ||
return await this._importRawKey(key, true); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async serializePrivateKey(key) { | ||
try { | ||
return await this._serializePrivateKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
async deserializePrivateKey(key) { | ||
try { | ||
return await this._importRawKey(key, false); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async importKey(format, key, isPublic) { | ||
if (format === "raw") { | ||
return await this._importRawKey(key, isPublic); | ||
try { | ||
if (format === "raw") { | ||
return await this._importRawKey(key, isPublic); | ||
} | ||
// jwk | ||
if (key instanceof ArrayBuffer) { | ||
throw new Error("Invalid jwk key format"); | ||
} | ||
return await this._importJWK(key, isPublic); | ||
} | ||
// jwk | ||
if (key instanceof ArrayBuffer) { | ||
throw new Error("Invalid jwk key format"); | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
return await this._importJWK(key, isPublic); | ||
} | ||
async derivePublicKey(key) { | ||
return await this._derivePublicKey(key); | ||
} | ||
async generateKeyPair() { | ||
const rawSk = ed448.utils.randomPrivateKey(); | ||
const sk = new XCryptoKey(ALG_NAME, rawSk, "private", KEM_USAGES); | ||
const pk = await this.derivePublicKey(sk); | ||
return { publicKey: pk, privateKey: sk }; | ||
try { | ||
const rawSk = ed448.utils.randomPrivateKey(); | ||
const sk = new XCryptoKey(ALG_NAME, rawSk, "private", KEM_USAGES); | ||
const pk = await this.derivePublicKey(sk); | ||
return { publicKey: pk, privateKey: sk }; | ||
} | ||
catch (e) { | ||
throw new errors.NotSupportedError(e); | ||
} | ||
} | ||
async deriveKeyPair(ikm) { | ||
const dkpPrk = await this._hkdf.labeledExtract(consts.EMPTY, LABEL_DKP_PRK, new Uint8Array(ikm)); | ||
const rawSk = await this._hkdf.labeledExpand(dkpPrk, LABEL_SK, consts.EMPTY, this._nSk); | ||
const sk = new XCryptoKey(ALG_NAME, new Uint8Array(rawSk), "private", KEM_USAGES); | ||
return { | ||
privateKey: sk, | ||
publicKey: await this.derivePublicKey(sk), | ||
}; | ||
try { | ||
const dkpPrk = await this._hkdf.labeledExtract(consts.EMPTY, LABEL_DKP_PRK, new Uint8Array(ikm)); | ||
const rawSk = await this._hkdf.labeledExpand(dkpPrk, LABEL_SK, consts.EMPTY, this._nSk); | ||
const sk = new XCryptoKey(ALG_NAME, new Uint8Array(rawSk), "private", KEM_USAGES); | ||
return { | ||
privateKey: sk, | ||
publicKey: await this.derivePublicKey(sk), | ||
}; | ||
} | ||
catch (e) { | ||
throw new errors.DeriveKeyPairError(e); | ||
} | ||
} | ||
async derivePublicKey(key) { | ||
try { | ||
return await this._derivePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async dh(sk, pk) { | ||
return await this._dh(sk, pk); | ||
try { | ||
return await this._dh(sk, pk); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
@@ -77,10 +127,5 @@ _serializePublicKey(k) { | ||
} | ||
_deserializePublicKey(k) { | ||
return new Promise((resolve, reject) => { | ||
if (k.byteLength !== this._nPk) { | ||
reject(new Error("Invalid public key for the ciphersuite")); | ||
} | ||
else { | ||
resolve(new XCryptoKey(ALG_NAME, new Uint8Array(k), "public")); | ||
} | ||
_serializePrivateKey(k) { | ||
return new Promise((resolve) => { | ||
resolve(k.key.buffer); | ||
}); | ||
@@ -91,6 +136,7 @@ } | ||
if (isPublic && key.byteLength !== this._nPk) { | ||
reject(new Error("Invalid public key for the ciphersuite")); | ||
reject(new Error("Invalid length of the key")); | ||
} | ||
if (!isPublic && key.byteLength !== this._nSk) { | ||
reject(new Error("Invalid private key for the ciphersuite")); | ||
if (!isPublic && | ||
(key.byteLength !== this._nSk && key.byteLength !== this._nSk + 1)) { | ||
reject(new Error("Invalid length of the key")); | ||
} | ||
@@ -126,5 +172,10 @@ resolve(new XCryptoKey(ALG_NAME, new Uint8Array(key), isPublic ? "public" : "private", isPublic ? [] : KEM_USAGES)); | ||
_derivePublicKey(k) { | ||
return new Promise((resolve) => { | ||
const pk = x448.getPublicKey(k.key); | ||
resolve(new XCryptoKey(ALG_NAME, pk, "public")); | ||
return new Promise((resolve, reject) => { | ||
try { | ||
const pk = x448.getPublicKey(k.key); | ||
resolve(new XCryptoKey(ALG_NAME, pk, "public")); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
@@ -131,0 +182,0 @@ } |
@@ -28,4 +28,3 @@ import { KemId } from "../identifiers.js"; | ||
const kdf = new HkdfSha512(); | ||
const prim = new X448(kdf); | ||
super(prim, kdf); | ||
super(KemId.DhkemX448HkdfSha512, new X448(kdf), kdf); | ||
Object.defineProperty(this, "id", { | ||
@@ -32,0 +31,0 @@ enumerable: true, |
@@ -22,24 +22,4 @@ /** | ||
/** | ||
* Executes XOR of two byte strings. | ||
*/ | ||
export declare function xor(a: Uint8Array, b: Uint8Array): Uint8Array; | ||
/** | ||
* Concatenates two Uint8Arrays. | ||
*/ | ||
export declare function concat(a: Uint8Array, b: Uint8Array): Uint8Array; | ||
/** | ||
* Concatenates three Uint8Arrays. | ||
*/ | ||
export declare function concat3(a: Uint8Array, b: Uint8Array, c: Uint8Array): Uint8Array; | ||
/** | ||
* Converts hex string to bytes. | ||
*/ | ||
export declare function hexToBytes(v: string): Uint8Array; | ||
/** | ||
* Converts bytes to hex string. | ||
*/ | ||
export declare function bytesToHex(v: Uint8Array): string; | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
*/ | ||
export declare function base64UrlToBytes(v: string): Uint8Array; |
@@ -39,55 +39,2 @@ import * as dntShim from "../../_dnt.shims.js"; | ||
/** | ||
* Executes XOR of two byte strings. | ||
*/ | ||
export function xor(a, b) { | ||
if (a.byteLength !== b.byteLength) { | ||
throw new Error("xor: different length inputs"); | ||
} | ||
const buf = new Uint8Array(a.byteLength); | ||
for (let i = 0; i < a.byteLength; i++) { | ||
buf[i] = a[i] ^ b[i]; | ||
} | ||
return buf; | ||
} | ||
/** | ||
* 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; | ||
} | ||
/** | ||
* Concatenates three Uint8Arrays. | ||
*/ | ||
export function concat3(a, b, c) { | ||
const ret = new Uint8Array(a.length + b.length + c.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
ret.set(c, a.length + b.length); | ||
return ret; | ||
} | ||
/** | ||
* Converts hex string to bytes. | ||
*/ | ||
export function hexToBytes(v) { | ||
if (v.length === 0) { | ||
return new Uint8Array([]); | ||
} | ||
const res = v.match(/[\da-f]{2}/gi); | ||
if (res == null) { | ||
throw new Error("hexToBytes: not hex string"); | ||
} | ||
return new Uint8Array(res.map(function (h) { | ||
return parseInt(h, 16); | ||
})); | ||
} | ||
/** | ||
* Converts bytes to hex string. | ||
*/ | ||
export function bytesToHex(v) { | ||
return [...v].map((x) => x.toString(16).padStart(2, "0")).join(""); | ||
} | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
@@ -94,0 +41,0 @@ */ |
@@ -6,3 +6,3 @@ { | ||
"name": "@hpke/dhkem-x448", | ||
"version": "1.0.4", | ||
"version": "1.1.0", | ||
"description": "A Hybrid Public Key Encryption (HPKE) module extension for X448", | ||
@@ -9,0 +9,0 @@ "repository": { |
@@ -34,4 +34,4 @@ <h1 align="center">@hpke/dhkem-x448</h1> | ||
<script type="module"> | ||
import * as hpke from "https://esm.sh/@hpke/core@1.0.4"; | ||
import * as x448 from "https://esm.sh/@hpke/dhkem-x448@1.0.4"; | ||
import * as hpke from "https://esm.sh/@hpke/core@1.1.0"; | ||
import * as x448 from "https://esm.sh/@hpke/dhkem-x448@1.1.0"; | ||
// ... | ||
@@ -53,4 +53,4 @@ </script> | ||
<script type="module"> | ||
import * as hpke from "https://unpkg.com/@hpke/core@1.0.4/esm/mod.js"; | ||
import * as x448 from "https://unpkg.com/@hpke/dhkem-x448@1.0.4/esm/mod.js"; | ||
import * as hpke from "https://unpkg.com/@hpke/core@1.1.0/esm/mod.js"; | ||
import * as x448 from "https://unpkg.com/@hpke/dhkem-x448@1.1.0/esm/mod.js"; | ||
// ... | ||
@@ -80,4 +80,4 @@ </script> | ||
// use a specific version | ||
import * as hpke from "https://deno.land/x/hpke@1.0.4/core/mod.ts"; | ||
import * as x448 from "https://deno.land/x/hpke@1.0.4/x/dhkem-x448/mod.ts"; | ||
import * as hpke from "https://deno.land/x/hpke@1.1.0/core/mod.ts"; | ||
import * as x448 from "https://deno.land/x/hpke@1.1.0/x/dhkem-x448/mod.ts"; | ||
@@ -110,4 +110,4 @@ // use the latest stable version | ||
<script type="module"> | ||
import { KdfId, AeadId, CipherSuite } from "https://esm.sh/@hpke/core@1.0.4"; | ||
import { DhkemX448HkdfSha512 } from "https://esm.sh/@hpke/dhkem-x448@1.0.4"; | ||
import { KdfId, AeadId, CipherSuite } from "https://esm.sh/@hpke/core@1.1.0"; | ||
import { DhkemX448HkdfSha512 } from "https://esm.sh/@hpke/dhkem-x448@1.1.0"; | ||
@@ -199,4 +199,4 @@ globalThis.doHpke = async () => { | ||
```js | ||
import { KdfId, AeadId, CipherSuite } from "https://deno.land/x/hpke@1.0.4/core/mod.ts"; | ||
import { DhkemX448HkdfSha512 } from "https://deno.land/x/hpke@1.0.4/x/dhkem-x448/mod.ts"; | ||
import { KdfId, AeadId, CipherSuite } from "https://deno.land/x/hpke@1.1.0/core/mod.ts"; | ||
import { DhkemX448HkdfSha512 } from "https://deno.land/x/hpke@1.1.0/x/dhkem-x448/mod.ts"; | ||
@@ -203,0 +203,0 @@ async function doHpke() { |
@@ -1,9 +0,5 @@ | ||
export declare class AlgorithmBase { | ||
export declare class NativeAlgorithm { | ||
protected _api: SubtleCrypto | undefined; | ||
constructor(); | ||
protected _setup(): Promise<void>; | ||
} | ||
export declare class Algorithm extends AlgorithmBase { | ||
constructor(); | ||
init(api: SubtleCrypto): void; | ||
protected checkInit(): void; | ||
} |
@@ -0,1 +1,24 @@ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
(function (factory) { | ||
@@ -7,9 +30,28 @@ if (typeof module === "object" && typeof module.exports === "object") { | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports"], factory); | ||
define(["require", "exports", "./errors.js", "./utils/misc.js"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
var __syncRequire = typeof module === "object" && typeof module.exports === "object"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Algorithm = exports.AlgorithmBase = void 0; | ||
class AlgorithmBase { | ||
exports.NativeAlgorithm = void 0; | ||
const errors_js_1 = require("./errors.js"); | ||
const misc_js_1 = require("./utils/misc.js"); | ||
async function loadSubtleCrypto() { | ||
if ((0, misc_js_1.isBrowser)() || (0, misc_js_1.isCloudflareWorkers)()) { | ||
if (globalThis.crypto !== undefined) { | ||
return globalThis.crypto.subtle; | ||
} | ||
// jsdom | ||
} | ||
try { | ||
// @ts-ignore: to ignore "crypto" | ||
const { webcrypto } = await (__syncRequire ? Promise.resolve().then(() => __importStar(require("crypto"))) : new Promise((resolve_1, reject_1) => { require(["crypto"], resolve_1, reject_1); }).then(__importStar)); // node:crypto | ||
return webcrypto.subtle; | ||
} | ||
catch (e) { | ||
throw new errors_js_1.NotSupportedError(e); | ||
} | ||
} | ||
class NativeAlgorithm { | ||
constructor() { | ||
@@ -23,18 +65,10 @@ Object.defineProperty(this, "_api", { | ||
} | ||
} | ||
exports.AlgorithmBase = AlgorithmBase; | ||
class Algorithm extends AlgorithmBase { | ||
constructor() { | ||
super(); | ||
} | ||
init(api) { | ||
this._api = api; | ||
} | ||
checkInit() { | ||
if (this._api === undefined) { | ||
throw new Error("Not initialized. Call init()"); | ||
async _setup() { | ||
if (this._api !== undefined) { | ||
return; | ||
} | ||
this._api = await loadSubtleCrypto(); | ||
} | ||
} | ||
exports.Algorithm = Algorithm; | ||
exports.NativeAlgorithm = NativeAlgorithm; | ||
}); |
@@ -20,2 +20,3 @@ /** | ||
export declare const Kem: { | ||
readonly NotAssigned: 0; | ||
readonly DhkemP256HkdfSha256: 16; | ||
@@ -38,2 +39,3 @@ readonly DhkemP384HkdfSha384: 17; | ||
export declare const KemId: { | ||
readonly NotAssigned: 0; | ||
readonly DhkemP256HkdfSha256: 16; | ||
@@ -40,0 +42,0 @@ readonly DhkemP384HkdfSha384: 17; |
@@ -28,2 +28,3 @@ (function (factory) { | ||
exports.Kem = { | ||
NotAssigned: 0x0000, | ||
DhkemP256HkdfSha256: 0x0010, | ||
@@ -30,0 +31,0 @@ DhkemP384HkdfSha384: 0x0011, |
@@ -19,22 +19,23 @@ import type { RecipientContextParams } from "./recipientContextParams.js"; | ||
/** | ||
* Generates a key pair. | ||
* Serializes a public key as CryptoKey to a byte string of length `Npk`. | ||
* | ||
* If the error occurred, throws {@link NotSupportedError}. | ||
* If the error occurred, throws {@link SerializeError}. | ||
* | ||
* @returns A key pair generated. | ||
* @throws {@link NotSupportedError} | ||
* @param key A CryptoKey. | ||
* @returns A key as bytes. | ||
* @throws {@link SerializeError} | ||
*/ | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
/** | ||
* Derives a key pair from the byte string ikm. | ||
* Deserializes a public key as a byte string of length `Npk` to CryptoKey. | ||
* | ||
* If the error occurred, throws {@link DeriveKeyPairError}. | ||
* If the error occurred, throws {@link DeserializeError}. | ||
* | ||
* @param ikm An input keying material. | ||
* @returns A key pair derived. | ||
* @throws {@link DeriveKeyPairError} | ||
* @param key A key as bytes. | ||
* @returns A CryptoKey. | ||
* @throws {@link DeserializeError} | ||
*/ | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
/** | ||
* Serializes a public key as CryptoKey to a byte string of length `Npk`. | ||
* Serializes a private key as CryptoKey to a byte string of length `Nsk`. | ||
* | ||
@@ -47,5 +48,5 @@ * If the error occurred, throws {@link SerializeError}. | ||
*/ | ||
serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
/** | ||
* Deserializes a public key as a byte string of length `Npk` to CryptoKey. | ||
* Deserializes a private key as a byte string of length `Nsk` to CryptoKey. | ||
* | ||
@@ -58,3 +59,3 @@ * If the error occurred, throws {@link DeserializeError}. | ||
*/ | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
deserializePrivateKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
/** | ||
@@ -80,2 +81,21 @@ * Imports a public or private key and converts to a {@link CryptoKey}. | ||
/** | ||
* Generates a key pair. | ||
* | ||
* If the error occurred, throws {@link NotSupportedError}. | ||
* | ||
* @returns A key pair generated. | ||
* @throws {@link NotSupportedError} | ||
*/ | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
/** | ||
* Derives a key pair from the byte string ikm. | ||
* | ||
* If the error occurred, throws {@link DeriveKeyPairError}. | ||
* | ||
* @param ikm An input keying material. | ||
* @returns A key pair derived. | ||
* @throws {@link DeriveKeyPairError} | ||
*/ | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
/** | ||
* Generates an ephemeral, fixed-length symmetric key and | ||
@@ -82,0 +102,0 @@ * a fixed-length encapsulation of the key that can be decapsulated |
import type { KdfInterface } from "../interfaces/kdfInterface.js"; | ||
import { AlgorithmBase } from "../algorithm.js"; | ||
import { NativeAlgorithm } from "../algorithm.js"; | ||
import { KdfId } from "../identifiers.js"; | ||
export declare class KdfAlgorithm extends AlgorithmBase { | ||
protected _suiteId: Uint8Array; | ||
constructor(); | ||
init(suiteId: Uint8Array): void; | ||
protected checkInit(): void; | ||
} | ||
export declare class HkdfNative extends KdfAlgorithm implements KdfInterface { | ||
export declare class HkdfNative extends NativeAlgorithm implements KdfInterface { | ||
readonly id: KdfId; | ||
readonly hashSize: number; | ||
protected _suiteId: Uint8Array; | ||
protected readonly algHash: HmacKeyGenParams; | ||
constructor(); | ||
init(suiteId: Uint8Array): void; | ||
buildLabeledIkm(label: Uint8Array, ikm: Uint8Array): Uint8Array; | ||
@@ -22,3 +18,3 @@ buildLabeledInfo(label: Uint8Array, info: Uint8Array, len: number): Uint8Array; | ||
labeledExpand(prk: ArrayBuffer, label: Uint8Array, info: Uint8Array, len: number): Promise<ArrayBuffer>; | ||
protected setup(): Promise<void>; | ||
protected _checkInit(): void; | ||
} | ||
@@ -25,0 +21,0 @@ export declare class HkdfSha256Native extends HkdfNative { |
@@ -30,3 +30,3 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "../algorithm.js", "../identifiers.js", "../webCrypto.js", "../consts.js", "../errors.js"], factory); | ||
define(["require", "exports", "../algorithm.js", "../identifiers.js", "../consts.js", "../errors.js"], factory); | ||
} | ||
@@ -36,6 +36,5 @@ })(function (require, exports) { | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.HkdfSha512Native = exports.HkdfSha384Native = exports.HkdfSha256Native = exports.HkdfNative = exports.KdfAlgorithm = void 0; | ||
exports.HkdfSha512Native = exports.HkdfSha384Native = exports.HkdfSha256Native = exports.HkdfNative = void 0; | ||
const algorithm_js_1 = require("../algorithm.js"); | ||
const identifiers_js_1 = require("../identifiers.js"); | ||
const webCrypto_js_1 = require("../webCrypto.js"); | ||
const consts = __importStar(require("../consts.js")); | ||
@@ -45,25 +44,5 @@ const errors = __importStar(require("../errors.js")); | ||
const HPKE_VERSION = new Uint8Array([72, 80, 75, 69, 45, 118, 49]); | ||
class KdfAlgorithm extends algorithm_js_1.AlgorithmBase { | ||
class HkdfNative extends algorithm_js_1.NativeAlgorithm { | ||
constructor() { | ||
super(); | ||
Object.defineProperty(this, "_suiteId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: consts.EMPTY | ||
}); | ||
} | ||
init(suiteId) { | ||
this._suiteId = suiteId; | ||
} | ||
checkInit() { | ||
if (this._suiteId === consts.EMPTY) { | ||
throw new Error("Not initialized. Call init()"); | ||
} | ||
} | ||
} | ||
exports.KdfAlgorithm = KdfAlgorithm; | ||
class HkdfNative extends KdfAlgorithm { | ||
constructor() { | ||
super(); | ||
Object.defineProperty(this, "id", { | ||
@@ -81,2 +60,8 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(this, "_suiteId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: consts.EMPTY | ||
}); | ||
Object.defineProperty(this, "algHash", { | ||
@@ -93,4 +78,7 @@ enumerable: true, | ||
} | ||
init(suiteId) { | ||
this._suiteId = suiteId; | ||
} | ||
buildLabeledIkm(label, ikm) { | ||
this.checkInit(); | ||
this._checkInit(); | ||
const ret = new Uint8Array(7 + this._suiteId.byteLength + label.byteLength + ikm.byteLength); | ||
@@ -104,3 +92,3 @@ ret.set(HPKE_VERSION, 0); | ||
buildLabeledInfo(label, info, len) { | ||
this.checkInit(); | ||
this._checkInit(); | ||
const ret = new Uint8Array(9 + this._suiteId.byteLength + label.byteLength + info.byteLength); | ||
@@ -115,3 +103,3 @@ ret.set(new Uint8Array([0, len]), 0); | ||
async extract(salt, ikm) { | ||
await this.setup(); | ||
await this._setup(); | ||
if (salt.byteLength === 0) { | ||
@@ -129,3 +117,3 @@ salt = new ArrayBuffer(this.hashSize); | ||
async expand(prk, info, len) { | ||
await this.setup(); | ||
await this._setup(); | ||
const key = await this._api.importKey("raw", prk, this.algHash, false, [ | ||
@@ -161,3 +149,3 @@ "sign", | ||
async extractAndExpand(salt, ikm, info, len) { | ||
await this.setup(); | ||
await this._setup(); | ||
const baseKey = await this._api.importKey("raw", ikm, "HKDF", false, ["deriveBits"]); | ||
@@ -177,7 +165,6 @@ return await this._api.deriveBits({ | ||
} | ||
async setup() { | ||
if (this._api !== undefined) { | ||
return; | ||
_checkInit() { | ||
if (this._suiteId === consts.EMPTY) { | ||
throw new Error("Not initialized. Call init()"); | ||
} | ||
this._api = await (0, webCrypto_js_1.loadSubtleCrypto)(); | ||
} | ||
@@ -184,0 +171,0 @@ } |
@@ -20,3 +20,3 @@ (function (factory) { | ||
async extract(salt, ikm) { | ||
await this.setup(); | ||
await this._setup(); | ||
if (salt.byteLength === 0) { | ||
@@ -23,0 +23,0 @@ salt = new ArrayBuffer(this.hashSize); |
import type { KdfInterface } from "../interfaces/kdfInterface.js"; | ||
import type { KemInterface } from "../interfaces/kemInterface.js"; | ||
import type { KemPrimitives } from "../interfaces/kemPrimitives.js"; | ||
import type { DhkemPrimitives } from "../interfaces/dhkemPrimitives.js"; | ||
import type { SenderContextParams } from "../interfaces/senderContextParams.js"; | ||
import type { RecipientContextParams } from "../interfaces/recipientContextParams.js"; | ||
import { Algorithm } from "../algorithm.js"; | ||
import { KemId } from "../identifiers.js"; | ||
export declare class Dhkem extends Algorithm implements KemInterface { | ||
export declare class Dhkem implements KemInterface { | ||
readonly id: KemId; | ||
@@ -14,10 +13,12 @@ readonly secretSize: number; | ||
readonly privateKeySize: number; | ||
protected _prim: KemPrimitives; | ||
protected _prim: DhkemPrimitives; | ||
protected _kdf: KdfInterface; | ||
constructor(prim: KemPrimitives, kdf: KdfInterface); | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
constructor(id: KemId, prim: DhkemPrimitives, kdf: KdfInterface); | ||
serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
deserializePrivateKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
importKey(format: "raw" | "jwk", key: ArrayBuffer | JsonWebKey, isPublic?: boolean): Promise<CryptoKey>; | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
encap(params: SenderContextParams): Promise<{ | ||
@@ -28,4 +29,3 @@ sharedSecret: ArrayBuffer; | ||
decap(params: RecipientContextParams): Promise<ArrayBuffer>; | ||
private _setup; | ||
private _generateSharedSecret; | ||
} |
@@ -30,3 +30,3 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "../algorithm.js", "../identifiers.js", "../webCrypto.js", "../utils/misc.js", "../consts.js", "../errors.js"], factory); | ||
define(["require", "exports", "../utils/misc.js", "../consts.js", "../errors.js"], factory); | ||
} | ||
@@ -37,5 +37,2 @@ })(function (require, exports) { | ||
exports.Dhkem = void 0; | ||
const algorithm_js_1 = require("../algorithm.js"); | ||
const identifiers_js_1 = require("../identifiers.js"); | ||
const webCrypto_js_1 = require("../webCrypto.js"); | ||
const misc_js_1 = require("../utils/misc.js"); | ||
@@ -49,20 +46,22 @@ const consts_js_1 = require("../consts.js"); | ||
// b"shared_secret" | ||
// deno-fmt-ignore | ||
const LABEL_SHARED_SECRET = new Uint8Array([ | ||
115, | ||
104, | ||
97, | ||
114, | ||
101, | ||
100, | ||
95, | ||
115, | ||
101, | ||
99, | ||
114, | ||
101, | ||
116, | ||
115, 104, 97, 114, 101, 100, 95, 115, 101, 99, | ||
114, 101, 116, | ||
]); | ||
class Dhkem extends algorithm_js_1.Algorithm { | ||
constructor(prim, kdf) { | ||
super(); | ||
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) { | ||
const ret = new Uint8Array(a.length + b.length + c.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
ret.set(c, a.length + b.length); | ||
return ret; | ||
} | ||
class Dhkem { | ||
constructor(id, prim, kdf) { | ||
Object.defineProperty(this, "id", { | ||
@@ -72,3 +71,3 @@ enumerable: true, | ||
writable: true, | ||
value: identifiers_js_1.KemId.DhkemP256HkdfSha256 | ||
value: void 0 | ||
}); | ||
@@ -111,13 +110,26 @@ Object.defineProperty(this, "secretSize", { | ||
}); | ||
this.id = id; | ||
this._prim = prim; | ||
this._kdf = kdf; | ||
const suiteId = new Uint8Array(SUITE_ID_HEADER_KEM); | ||
suiteId.set((0, misc_js_1.i2Osp)(this.id, 2), 3); | ||
this._kdf.init(suiteId); | ||
} | ||
async serializePublicKey(key) { | ||
return await this._prim.serializePublicKey(key); | ||
} | ||
async deserializePublicKey(key) { | ||
return await this._prim.deserializePublicKey(key); | ||
} | ||
async serializePrivateKey(key) { | ||
return await this._prim.serializePrivateKey(key); | ||
} | ||
async deserializePrivateKey(key) { | ||
return await this._prim.deserializePrivateKey(key); | ||
} | ||
async importKey(format, key, isPublic = true) { | ||
return await this._prim.importKey(format, key, isPublic); | ||
} | ||
async generateKeyPair() { | ||
await this._setup(); | ||
try { | ||
return await this._prim.generateKeyPair(); | ||
} | ||
catch (e) { | ||
throw new errors.NotSupportedError(e); | ||
} | ||
return await this._prim.generateKeyPair(); | ||
} | ||
@@ -128,45 +140,11 @@ async deriveKeyPair(ikm) { | ||
} | ||
await this._setup(); | ||
try { | ||
return await this._prim.deriveKeyPair(ikm); | ||
} | ||
catch (e) { | ||
throw new errors.DeriveKeyPairError(e); | ||
} | ||
return await this._prim.deriveKeyPair(ikm); | ||
} | ||
async serializePublicKey(key) { | ||
await this._setup(); | ||
try { | ||
return await this._prim.serializePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
async deserializePublicKey(key) { | ||
await this._setup(); | ||
try { | ||
return await this._prim.deserializePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async importKey(format, key, isPublic = true) { | ||
await this._setup(); | ||
try { | ||
return await this._prim.importKey(format, key, isPublic); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async encap(params) { | ||
await this._setup(); | ||
const ke = params.nonEphemeralKeyPair === undefined | ||
? await this.generateKeyPair() | ||
: params.nonEphemeralKeyPair; | ||
const enc = await this._prim.serializePublicKey(ke.publicKey); | ||
const pkrm = await this._prim.serializePublicKey(params.recipientPublicKey); | ||
try { | ||
const ke = params.nonEphemeralKeyPair === undefined | ||
? await this.generateKeyPair() | ||
: params.nonEphemeralKeyPair; | ||
const enc = await this._prim.serializePublicKey(ke.publicKey); | ||
const pkrm = await this._prim.serializePublicKey(params.recipientPublicKey); | ||
let dh; | ||
@@ -182,7 +160,7 @@ if (params.senderKey === undefined) { | ||
const dh2 = new Uint8Array(await this._prim.dh(sks, params.recipientPublicKey)); | ||
dh = (0, misc_js_1.concat)(dh1, dh2); | ||
dh = concat(dh1, dh2); | ||
} | ||
let kemContext; | ||
if (params.senderKey === undefined) { | ||
kemContext = (0, misc_js_1.concat)(new Uint8Array(enc), new Uint8Array(pkrm)); | ||
kemContext = concat(new Uint8Array(enc), new Uint8Array(pkrm)); | ||
} | ||
@@ -194,3 +172,3 @@ else { | ||
const pksm = await this._prim.serializePublicKey(pks); | ||
kemContext = (0, misc_js_1.concat3)(new Uint8Array(enc), new Uint8Array(pkrm), new Uint8Array(pksm)); | ||
kemContext = concat3(new Uint8Array(enc), new Uint8Array(pkrm), new Uint8Array(pksm)); | ||
} | ||
@@ -208,18 +186,11 @@ const sharedSecret = await this._generateSharedSecret(dh, kemContext); | ||
async decap(params) { | ||
let pke; | ||
await this._setup(); | ||
const pke = await this._prim.deserializePublicKey(params.enc); | ||
const skr = (0, misc_js_1.isCryptoKeyPair)(params.recipientKey) | ||
? params.recipientKey.privateKey | ||
: params.recipientKey; | ||
const pkr = (0, misc_js_1.isCryptoKeyPair)(params.recipientKey) | ||
? params.recipientKey.publicKey | ||
: await this._prim.derivePublicKey(params.recipientKey); | ||
const pkrm = await this._prim.serializePublicKey(pkr); | ||
try { | ||
pke = await this._prim.deserializePublicKey(params.enc); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
try { | ||
const skr = (0, misc_js_1.isCryptoKeyPair)(params.recipientKey) | ||
? params.recipientKey.privateKey | ||
: params.recipientKey; | ||
const pkr = (0, misc_js_1.isCryptoKeyPair)(params.recipientKey) | ||
? params.recipientKey.publicKey | ||
: await this._prim.derivePublicKey(params.recipientKey); | ||
const pkrm = await this._prim.serializePublicKey(pkr); | ||
let dh; | ||
@@ -232,7 +203,7 @@ if (params.senderPublicKey === undefined) { | ||
const dh2 = new Uint8Array(await this._prim.dh(skr, params.senderPublicKey)); | ||
dh = (0, misc_js_1.concat)(dh1, dh2); | ||
dh = concat(dh1, dh2); | ||
} | ||
let kemContext; | ||
if (params.senderPublicKey === undefined) { | ||
kemContext = (0, misc_js_1.concat)(new Uint8Array(params.enc), new Uint8Array(pkrm)); | ||
kemContext = concat(new Uint8Array(params.enc), new Uint8Array(pkrm)); | ||
} | ||
@@ -252,13 +223,2 @@ else { | ||
} | ||
async _setup() { | ||
if (this._api !== undefined) { | ||
return; | ||
} | ||
const api = await (0, webCrypto_js_1.loadSubtleCrypto)(); | ||
const suiteId = new Uint8Array(SUITE_ID_HEADER_KEM); | ||
suiteId.set((0, misc_js_1.i2Osp)(this.id, 2), 3); | ||
this._prim.init(api); | ||
this._kdf.init(suiteId); | ||
super.init(api); | ||
} | ||
async _generateSharedSecret(dh, kemContext) { | ||
@@ -265,0 +225,0 @@ const labeledIkm = this._kdf.buildLabeledIkm(LABEL_EAE_PRK, dh); |
@@ -1,5 +0,4 @@ | ||
import type { KemPrimitives } from "../../interfaces/kemPrimitives.js"; | ||
import type { DhkemPrimitives } from "../../interfaces/dhkemPrimitives.js"; | ||
import type { KdfInterface } from "../../interfaces/kdfInterface.js"; | ||
import { Algorithm } from "../../algorithm.js"; | ||
export declare class X448 extends Algorithm implements KemPrimitives { | ||
export declare class X448 implements DhkemPrimitives { | ||
private _hkdf; | ||
@@ -11,9 +10,11 @@ private _nPk; | ||
deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer>; | ||
deserializePrivateKey(key: ArrayBuffer): Promise<CryptoKey>; | ||
importKey(format: "raw" | "jwk", key: ArrayBuffer | JsonWebKey, isPublic: boolean): Promise<CryptoKey>; | ||
derivePublicKey(key: CryptoKey): Promise<CryptoKey>; | ||
generateKeyPair(): Promise<CryptoKeyPair>; | ||
deriveKeyPair(ikm: ArrayBuffer): Promise<CryptoKeyPair>; | ||
derivePublicKey(key: CryptoKey): Promise<CryptoKey>; | ||
dh(sk: CryptoKey, pk: CryptoKey): Promise<ArrayBuffer>; | ||
private _serializePublicKey; | ||
private _deserializePublicKey; | ||
private _serializePrivateKey; | ||
private _importRawKey; | ||
@@ -20,0 +21,0 @@ private _importJWK; |
@@ -30,3 +30,3 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
else if (typeof define === "function" && define.amd) { | ||
define(["require", "exports", "@noble/curves/ed448", "../../algorithm.js", "../../interfaces/kemPrimitives.js", "../../xCryptoKey.js", "../../consts.js", "../../utils/misc.js"], factory); | ||
define(["require", "exports", "@noble/curves/ed448", "../../consts.js", "../../errors.js", "../../interfaces/dhkemPrimitives.js", "../../utils/misc.js", "../../xCryptoKey.js"], factory); | ||
} | ||
@@ -39,11 +39,10 @@ })(function (require, exports) { | ||
const ed448_1 = require("@noble/curves/ed448"); | ||
const algorithm_js_1 = require("../../algorithm.js"); | ||
const kemPrimitives_js_1 = require("../../interfaces/kemPrimitives.js"); | ||
const xCryptoKey_js_1 = require("../../xCryptoKey.js"); | ||
const consts = __importStar(require("../../consts.js")); | ||
const errors = __importStar(require("../../errors.js")); | ||
const dhkemPrimitives_js_1 = require("../../interfaces/dhkemPrimitives.js"); | ||
const misc_js_1 = require("../../utils/misc.js"); | ||
const xCryptoKey_js_1 = require("../../xCryptoKey.js"); | ||
const ALG_NAME = "X448"; | ||
class X448 extends algorithm_js_1.Algorithm { | ||
class X448 { | ||
constructor(hkdf) { | ||
super(); | ||
Object.defineProperty(this, "_hkdf", { | ||
@@ -72,37 +71,88 @@ enumerable: true, | ||
async serializePublicKey(key) { | ||
return await this._serializePublicKey(key); | ||
try { | ||
return await this._serializePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
async deserializePublicKey(key) { | ||
return await this._deserializePublicKey(key); | ||
try { | ||
return await this._importRawKey(key, true); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async serializePrivateKey(key) { | ||
try { | ||
return await this._serializePrivateKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
async deserializePrivateKey(key) { | ||
try { | ||
return await this._importRawKey(key, false); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async importKey(format, key, isPublic) { | ||
if (format === "raw") { | ||
return await this._importRawKey(key, isPublic); | ||
try { | ||
if (format === "raw") { | ||
return await this._importRawKey(key, isPublic); | ||
} | ||
// jwk | ||
if (key instanceof ArrayBuffer) { | ||
throw new Error("Invalid jwk key format"); | ||
} | ||
return await this._importJWK(key, isPublic); | ||
} | ||
// jwk | ||
if (key instanceof ArrayBuffer) { | ||
throw new Error("Invalid jwk key format"); | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
return await this._importJWK(key, isPublic); | ||
} | ||
async derivePublicKey(key) { | ||
return await this._derivePublicKey(key); | ||
} | ||
async generateKeyPair() { | ||
const rawSk = ed448_1.ed448.utils.randomPrivateKey(); | ||
const sk = new xCryptoKey_js_1.XCryptoKey(ALG_NAME, rawSk, "private", kemPrimitives_js_1.KEM_USAGES); | ||
const pk = await this.derivePublicKey(sk); | ||
return { publicKey: pk, privateKey: sk }; | ||
try { | ||
const rawSk = ed448_1.ed448.utils.randomPrivateKey(); | ||
const sk = new xCryptoKey_js_1.XCryptoKey(ALG_NAME, rawSk, "private", dhkemPrimitives_js_1.KEM_USAGES); | ||
const pk = await this.derivePublicKey(sk); | ||
return { publicKey: pk, privateKey: sk }; | ||
} | ||
catch (e) { | ||
throw new errors.NotSupportedError(e); | ||
} | ||
} | ||
async deriveKeyPair(ikm) { | ||
const dkpPrk = await this._hkdf.labeledExtract(consts.EMPTY, kemPrimitives_js_1.LABEL_DKP_PRK, new Uint8Array(ikm)); | ||
const rawSk = await this._hkdf.labeledExpand(dkpPrk, kemPrimitives_js_1.LABEL_SK, consts.EMPTY, this._nSk); | ||
const sk = new xCryptoKey_js_1.XCryptoKey(ALG_NAME, new Uint8Array(rawSk), "private", kemPrimitives_js_1.KEM_USAGES); | ||
return { | ||
privateKey: sk, | ||
publicKey: await this.derivePublicKey(sk), | ||
}; | ||
try { | ||
const dkpPrk = await this._hkdf.labeledExtract(consts.EMPTY, dhkemPrimitives_js_1.LABEL_DKP_PRK, new Uint8Array(ikm)); | ||
const rawSk = await this._hkdf.labeledExpand(dkpPrk, dhkemPrimitives_js_1.LABEL_SK, consts.EMPTY, this._nSk); | ||
const sk = new xCryptoKey_js_1.XCryptoKey(ALG_NAME, new Uint8Array(rawSk), "private", dhkemPrimitives_js_1.KEM_USAGES); | ||
return { | ||
privateKey: sk, | ||
publicKey: await this.derivePublicKey(sk), | ||
}; | ||
} | ||
catch (e) { | ||
throw new errors.DeriveKeyPairError(e); | ||
} | ||
} | ||
async derivePublicKey(key) { | ||
try { | ||
return await this._derivePublicKey(key); | ||
} | ||
catch (e) { | ||
throw new errors.DeserializeError(e); | ||
} | ||
} | ||
async dh(sk, pk) { | ||
return await this._dh(sk, pk); | ||
try { | ||
return await this._dh(sk, pk); | ||
} | ||
catch (e) { | ||
throw new errors.SerializeError(e); | ||
} | ||
} | ||
@@ -114,10 +164,5 @@ _serializePublicKey(k) { | ||
} | ||
_deserializePublicKey(k) { | ||
return new Promise((resolve, reject) => { | ||
if (k.byteLength !== this._nPk) { | ||
reject(new Error("Invalid public key for the ciphersuite")); | ||
} | ||
else { | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, new Uint8Array(k), "public")); | ||
} | ||
_serializePrivateKey(k) { | ||
return new Promise((resolve) => { | ||
resolve(k.key.buffer); | ||
}); | ||
@@ -128,8 +173,9 @@ } | ||
if (isPublic && key.byteLength !== this._nPk) { | ||
reject(new Error("Invalid public key for the ciphersuite")); | ||
reject(new Error("Invalid length of the key")); | ||
} | ||
if (!isPublic && key.byteLength !== this._nSk) { | ||
reject(new Error("Invalid private key for the ciphersuite")); | ||
if (!isPublic && | ||
(key.byteLength !== this._nSk && key.byteLength !== this._nSk + 1)) { | ||
reject(new Error("Invalid length of the key")); | ||
} | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, new Uint8Array(key), isPublic ? "public" : "private", isPublic ? [] : kemPrimitives_js_1.KEM_USAGES)); | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, new Uint8Array(key), isPublic ? "public" : "private", isPublic ? [] : dhkemPrimitives_js_1.KEM_USAGES)); | ||
}); | ||
@@ -158,3 +204,3 @@ } | ||
} | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, (0, misc_js_1.base64UrlToBytes)(key.d), "private", kemPrimitives_js_1.KEM_USAGES)); | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, (0, misc_js_1.base64UrlToBytes)(key.d), "private", dhkemPrimitives_js_1.KEM_USAGES)); | ||
} | ||
@@ -164,5 +210,10 @@ }); | ||
_derivePublicKey(k) { | ||
return new Promise((resolve) => { | ||
const pk = ed448_1.x448.getPublicKey(k.key); | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, pk, "public")); | ||
return new Promise((resolve, reject) => { | ||
try { | ||
const pk = ed448_1.x448.getPublicKey(k.key); | ||
resolve(new xCryptoKey_js_1.XCryptoKey(ALG_NAME, pk, "public")); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
@@ -169,0 +220,0 @@ } |
@@ -40,4 +40,3 @@ (function (factory) { | ||
const kdf = new hkdfSha512_js_1.HkdfSha512(); | ||
const prim = new x448_js_1.X448(kdf); | ||
super(prim, kdf); | ||
super(identifiers_js_1.KemId.DhkemX448HkdfSha512, new x448_js_1.X448(kdf), kdf); | ||
Object.defineProperty(this, "id", { | ||
@@ -44,0 +43,0 @@ enumerable: true, |
@@ -22,24 +22,4 @@ /** | ||
/** | ||
* Executes XOR of two byte strings. | ||
*/ | ||
export declare function xor(a: Uint8Array, b: Uint8Array): Uint8Array; | ||
/** | ||
* Concatenates two Uint8Arrays. | ||
*/ | ||
export declare function concat(a: Uint8Array, b: Uint8Array): Uint8Array; | ||
/** | ||
* Concatenates three Uint8Arrays. | ||
*/ | ||
export declare function concat3(a: Uint8Array, b: Uint8Array, c: Uint8Array): Uint8Array; | ||
/** | ||
* Converts hex string to bytes. | ||
*/ | ||
export declare function hexToBytes(v: string): Uint8Array; | ||
/** | ||
* Converts bytes to hex string. | ||
*/ | ||
export declare function bytesToHex(v: Uint8Array): string; | ||
/** | ||
* 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.bytesToHex = exports.hexToBytes = exports.concat3 = exports.concat = exports.xor = exports.i2Osp = exports.isCryptoKeyPair = exports.isDeno = exports.isCloudflareWorkers = exports.isBrowser = void 0; | ||
exports.base64UrlToBytes = exports.i2Osp = exports.isCryptoKeyPair = exports.isDeno = exports.isCloudflareWorkers = exports.isBrowser = void 0; | ||
const dntShim = __importStar(require("../../_dnt.shims.js")); | ||
@@ -80,60 +80,2 @@ /** | ||
/** | ||
* Executes XOR of two byte strings. | ||
*/ | ||
function xor(a, b) { | ||
if (a.byteLength !== b.byteLength) { | ||
throw new Error("xor: different length inputs"); | ||
} | ||
const buf = new Uint8Array(a.byteLength); | ||
for (let i = 0; i < a.byteLength; i++) { | ||
buf[i] = a[i] ^ b[i]; | ||
} | ||
return buf; | ||
} | ||
exports.xor = xor; | ||
/** | ||
* 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; | ||
/** | ||
* Concatenates three Uint8Arrays. | ||
*/ | ||
function concat3(a, b, c) { | ||
const ret = new Uint8Array(a.length + b.length + c.length); | ||
ret.set(a, 0); | ||
ret.set(b, a.length); | ||
ret.set(c, a.length + b.length); | ||
return ret; | ||
} | ||
exports.concat3 = concat3; | ||
/** | ||
* Converts hex string to bytes. | ||
*/ | ||
function hexToBytes(v) { | ||
if (v.length === 0) { | ||
return new Uint8Array([]); | ||
} | ||
const res = v.match(/[\da-f]{2}/gi); | ||
if (res == null) { | ||
throw new Error("hexToBytes: not hex string"); | ||
} | ||
return new Uint8Array(res.map(function (h) { | ||
return parseInt(h, 16); | ||
})); | ||
} | ||
exports.hexToBytes = hexToBytes; | ||
/** | ||
* Converts bytes to hex string. | ||
*/ | ||
function bytesToHex(v) { | ||
return [...v].map((x) => x.toString(16).padStart(2, "0")).join(""); | ||
} | ||
exports.bytesToHex = bytesToHex; | ||
/** | ||
* Decodes Base64Url-encoded data. | ||
@@ -140,0 +82,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
1
133327
85
3575