Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Kem/Kdf/Aead algorithm constructor. #185

Merged
merged 1 commit into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading