Skip to content

Commit

Permalink
Merge pull request #185 from dajiaji/refactor-crypto-api-setting
Browse files Browse the repository at this point in the history
Refactor Kem/Kdf/Aead algorithm constructor.
  • Loading branch information
dajiaji authored Jul 18, 2023
2 parents 09a53bf + dc9b39a commit 593f9bf
Show file tree
Hide file tree
Showing 21 changed files with 394 additions and 194 deletions.
25 changes: 18 additions & 7 deletions src/aeadKeys/aesGcmKey.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import type { AeadKey } from "../interfaces/aeadKey.ts";

import { Algorithm } from "../algorithm.ts";
import { Aead } from "../identifiers.ts";
import * as consts from "../consts.ts";

export class AesGcmKey implements AeadKey {
export class AesGcmKey extends Algorithm implements AeadKey {
public readonly id: Aead = Aead.Aes128Gcm;
public readonly keySize: number = 0;
public readonly nonceSize: number = 0;
public readonly tagSize: number = 0;
private _rawKey: ArrayBuffer;
private _key: CryptoKey | undefined = undefined;
private _api: SubtleCrypto;
// private _api: SubtleCrypto;

public constructor(key: ArrayBuffer, api: SubtleCrypto) {
public constructor(key: ArrayBuffer) {
super();
this._rawKey = key;
this._api = api;
}

public async seal(
iv: ArrayBuffer,
data: ArrayBuffer,
aad: ArrayBuffer,
): Promise<ArrayBuffer> {
this.checkInit();
if (this._key === undefined) {
this._key = await this.importKey(this._rawKey);
(new Uint8Array(this._rawKey)).fill(0);
Expand All @@ -31,7 +33,11 @@ export class AesGcmKey implements AeadKey {
iv: iv,
additionalData: aad,
};
const ct: ArrayBuffer = await this._api.encrypt(alg, this._key, data);
const ct: ArrayBuffer = await (this._api as SubtleCrypto).encrypt(
alg,
this._key,
data,
);
return ct;
}

Expand All @@ -40,6 +46,7 @@ export class AesGcmKey implements AeadKey {
data: ArrayBuffer,
aad: ArrayBuffer,
): Promise<ArrayBuffer> {
this.checkInit();
if (this._key === undefined) {
this._key = await this.importKey(this._rawKey);
(new Uint8Array(this._rawKey)).fill(0);
Expand All @@ -49,12 +56,16 @@ export class AesGcmKey implements AeadKey {
iv: iv,
additionalData: aad,
};
const pt: ArrayBuffer = await this._api.decrypt(alg, this._key, data);
const pt: ArrayBuffer = await (this._api as SubtleCrypto).decrypt(
alg,
this._key,
data,
);
return pt;
}

private async importKey(key: ArrayBuffer): Promise<CryptoKey> {
return await this._api.importKey(
return await (this._api as SubtleCrypto).importKey(
"raw",
key,
{ name: "AES-GCM" },
Expand Down
5 changes: 3 additions & 2 deletions src/aeadKeys/chacha20Poly1305Key.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { chacha20_poly1305 } from "npm:@noble/[email protected]/chacha";

import { Algorithm } from "../algorithm.ts";
import type { AeadKey } from "../interfaces/aeadKey.ts";

import { Aead } from "../identifiers.ts";

export class Chacha20Poly1305Key implements AeadKey {
export class Chacha20Poly1305Key extends Algorithm implements AeadKey {
public readonly id: Aead = Aead.Chacha20Poly1305;
public readonly keySize: number = 32;
public readonly nonceSize: number = 12;
public readonly tagSize: number = 16;
private _key: Uint8Array;

public constructor(key: ArrayBuffer) {
super();
this._key = new Uint8Array(key);
}

Expand Down
36 changes: 36 additions & 0 deletions src/algorithm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as consts from "./consts.ts";

export class AlgorithmBase {
protected _api: SubtleCrypto | undefined = undefined;

constructor() {}

protected checkInit(): void {
if (typeof this._api === "undefined") {
throw new Error("Not initialized. Call init()");
}
}
}

export class Algorithm extends AlgorithmBase {
constructor() {
super();
}

public init(api: SubtleCrypto): void {
this._api = api;
}
}

export class KdfAlgorithm extends AlgorithmBase {
protected _suiteId: Uint8Array = consts.EMPTY;

constructor() {
super();
}

public init(api: SubtleCrypto, suiteId: Uint8Array): void {
this._api = api;
this._suiteId = suiteId;
}
}
37 changes: 27 additions & 10 deletions src/cipherSuite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ export class CipherSuite {
*/
public async createAeadKey(key: ArrayBuffer): Promise<AeadKey> {
await this.setup();
return createAeadKey(this.aead, key, this._api as SubtleCrypto);
const ret = createAeadKey(this.aead, key);
ret.init(this._api as SubtleCrypto);
return ret;
}

/**
Expand Down Expand Up @@ -534,31 +536,46 @@ export class CipherSuite {
}

private createKemContext(): KemInterface {
let ret: KemInterface;
switch (this.kem) {
case Kem.DhkemP256HkdfSha256:
return new DhkemP256HkdfSha256(this._api as SubtleCrypto);
ret = new DhkemP256HkdfSha256();
break;
case Kem.DhkemP384HkdfSha384:
return new DhkemP384HkdfSha384(this._api as SubtleCrypto);
ret = new DhkemP384HkdfSha384();
break;
case Kem.DhkemP521HkdfSha512:
return new DhkemP521HkdfSha512(this._api as SubtleCrypto);
ret = new DhkemP521HkdfSha512();
break;
case Kem.DhkemX25519HkdfSha256:
return new DhkemX25519HkdfSha256(this._api as SubtleCrypto);
ret = new DhkemX25519HkdfSha256();
break;
case Kem.DhkemX448HkdfSha512:
return new DhkemX448HkdfSha512(this._api as SubtleCrypto);
ret = new DhkemX448HkdfSha512();
break;
default:
return new DhkemSecp256K1HkdfSha256(this._api as SubtleCrypto);
ret = new DhkemSecp256K1HkdfSha256();
break;
}
ret.init(this._api as SubtleCrypto);
return ret;
}

private createKdfContext(): KdfInterface {
let ret: KdfInterface;
switch (this.kdf) {
case Kdf.HkdfSha256:
return new HkdfSha256(this._api as SubtleCrypto, this._suiteId);
ret = new HkdfSha256();
break;
case Kdf.HkdfSha384:
return new HkdfSha384(this._api as SubtleCrypto, this._suiteId);
ret = new HkdfSha384();
break;
default:
// case Kdf.HkdfSha512:
return new HkdfSha512(this._api as SubtleCrypto, this._suiteId);
ret = new HkdfSha512();
break;
}
ret.init(this._api as SubtleCrypto, this._suiteId);
return ret;
}
}
11 changes: 6 additions & 5 deletions src/encryptionContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export class EncryptionContext extends ExporterContext {
break;
}

const key = createAeadKey(this._aead, params.key, this._api);
const key = createAeadKey(this._aead, params.key);
key.init(this._api);

this._f = {
key: key,
Expand Down Expand Up @@ -97,7 +98,8 @@ export class EncryptionContext extends ExporterContext {
await this.export(nonceSeed, this._nN),
);
const key = await this.export(keySeed, this._nK);
this._r.key = createAeadKey(this._aead, key, this._api);
this._r.key = createAeadKey(this._aead, key);
this._r.key.init(this._api);
this._r.seq = 0;
} catch (e: unknown) {
this._r.baseNonce = consts.EMPTY;
Expand All @@ -109,13 +111,12 @@ export class EncryptionContext extends ExporterContext {
export function createAeadKey(
aead: Aead,
key: ArrayBuffer,
api: SubtleCrypto,
): AeadKey {
switch (aead) {
case Aead.Aes128Gcm:
return new Aes128GcmKey(key, api);
return new Aes128GcmKey(key);
case Aead.Aes256Gcm:
return new Aes256GcmKey(key, api);
return new Aes256GcmKey(key);
case Aead.Chacha20Poly1305:
return new Chacha20Poly1305Key(key);
default:
Expand Down
8 changes: 3 additions & 5 deletions src/exporterContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ import type { Encapsulator } from "./interfaces/encapsulator.ts";
import type { EncryptionContextInterface } from "./interfaces/encryptionContextInterface.ts";
import type { KdfInterface } from "./interfaces/kdfInterface.ts";

import { WebCrypto } from "./webCrypto.ts";

import * as consts from "./consts.ts";
import * as errors from "./errors.ts";

export class ExporterContext extends WebCrypto
implements EncryptionContextInterface {
export class ExporterContext implements EncryptionContextInterface {
protected _api: SubtleCrypto;
protected readonly exporterSecret: ArrayBuffer;
private _kdf: KdfInterface;

Expand All @@ -17,7 +15,7 @@ export class ExporterContext extends WebCrypto
kdf: KdfInterface,
exporterSecret: ArrayBuffer,
) {
super(api);
this._api = api;
this._kdf = kdf;
this.exporterSecret = exporterSecret;
}
Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/aeadKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export interface AeadKey {
/** The length in bytes of an AEAD authentication tag (Nt). */
readonly tagSize: number;

/**
* Initializes the key by setting the SubtleCrypto.
*/
init(api: SubtleCrypto): void;

/**
* Encrypts data with initial vector and additional authenticated data.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/kdfInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface KdfInterface {
len: number,
): Uint8Array;

init(api: SubtleCrypto, suiteId: Uint8Array): void;

extract(
salt: ArrayBuffer,
ikm: ArrayBuffer,
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/kemInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface KemInterface {
/** The length in bytes of an encoded private key for this KEM (Nsk). */
readonly privateKeySize: number;

init(api: SubtleCrypto): void;

/**
* Generates a key pair.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/kemPrimitives.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export interface KemPrimitives {
init(api: SubtleCrypto): void;

serializePublicKey(key: CryptoKey): Promise<ArrayBuffer>;

deserializePublicKey(key: ArrayBuffer): Promise<CryptoKey>;
Expand Down
Loading

0 comments on commit 593f9bf

Please sign in to comment.