Skip to content

Commit

Permalink
Merge pull request #193 from dajiaji/introduce-aead-interface
Browse files Browse the repository at this point in the history
Add AeadInterface for CipherSuiteParams.
  • Loading branch information
dajiaji authored Jul 23, 2023
2 parents 57377b9 + 9356375 commit b4df9ed
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 140 deletions.
1 change: 1 addition & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export type { AeadInterface } from "./src/interfaces/aeadInterface.ts";
export type { AeadKey } from "./src/interfaces/aeadKey.ts";
export type { CipherSuiteParams } from "./src/interfaces/cipherSuiteParams.ts";
export type { KdfInterface } from "./src/interfaces/kdfInterface.ts";
Expand Down
41 changes: 32 additions & 9 deletions src/aeadKeys/aesGcmKey.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import type { AeadKey } from "../interfaces/aeadKey.ts";
import type { AeadInterface } from "../interfaces/aeadInterface.ts";

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

export class AesGcmKey extends Algorithm implements AeadKey {
export class AesGcmKey implements AeadKey {
public readonly id: AeadId = AeadId.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) {
super();
public constructor(api: SubtleCrypto, key: ArrayBuffer) {
this._api = api;
this._rawKey = key;
}

Expand All @@ -23,7 +24,6 @@ export class AesGcmKey extends Algorithm 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 @@ -33,7 +33,7 @@ export class AesGcmKey extends Algorithm implements AeadKey {
iv: iv,
additionalData: aad,
};
const ct: ArrayBuffer = await (this._api as SubtleCrypto).encrypt(
const ct: ArrayBuffer = await this._api.encrypt(
alg,
this._key,
data,
Expand All @@ -46,7 +46,6 @@ export class AesGcmKey extends Algorithm 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 @@ -56,7 +55,7 @@ export class AesGcmKey extends Algorithm implements AeadKey {
iv: iv,
additionalData: aad,
};
const pt: ArrayBuffer = await (this._api as SubtleCrypto).decrypt(
const pt: ArrayBuffer = await this._api.decrypt(
alg,
this._key,
data,
Expand All @@ -65,7 +64,7 @@ export class AesGcmKey extends Algorithm implements AeadKey {
}

private async importKey(key: ArrayBuffer): Promise<CryptoKey> {
return await (this._api as SubtleCrypto).importKey(
return await this._api.importKey(
"raw",
key,
{ name: "AES-GCM" },
Expand All @@ -88,3 +87,27 @@ export class Aes256GcmKey extends AesGcmKey {
public readonly nonceSize: number = 12;
public readonly tagSize: number = 16;
}

export class Aes128Gcm extends Algorithm implements AeadInterface {
public readonly id: AeadId = AeadId.Aes128Gcm;
public readonly keySize: number = 16;
public readonly nonceSize: number = 12;
public readonly tagSize: number = 16;

public createAeadKey(key: ArrayBuffer): AeadKey {
this.checkInit();
return new Aes128GcmKey(this._api as SubtleCrypto, key);
}
}

export class Aes256Gcm extends Algorithm implements AeadInterface {
public readonly id: AeadId = AeadId.Aes256Gcm;
public readonly keySize: number = 32;
public readonly nonceSize: number = 12;
public readonly tagSize: number = 16;

public createAeadKey(key: ArrayBuffer): AeadKey {
this.checkInit();
return new Aes256GcmKey(this._api as SubtleCrypto, key);
}
}
22 changes: 18 additions & 4 deletions src/aeadKeys/chacha20Poly1305Key.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { chacha20_poly1305 } from "npm:@noble/[email protected]/chacha";

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

import { Algorithm } from "../algorithm.ts";
import { AeadId } from "../identifiers.ts";

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

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

Expand Down Expand Up @@ -62,3 +65,14 @@ export class Chacha20Poly1305Key extends Algorithm implements AeadKey {
});
}
}

export class Chacha20Poly1305 extends Algorithm implements AeadInterface {
public readonly id: AeadId = AeadId.Chacha20Poly1305;
public readonly keySize: number = 32;
public readonly nonceSize: number = 12;
public readonly tagSize: number = 16;

public createAeadKey(key: ArrayBuffer): AeadKey {
return new Chacha20Poly1305Key(this._api as SubtleCrypto, key);
}
}
20 changes: 20 additions & 0 deletions src/aeadKeys/exportOnly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { AeadKey } from "../interfaces/aeadKey.ts";
import type { AeadInterface } from "../interfaces/aeadInterface.ts";

import { Algorithm } from "../algorithm.ts";
import { AeadId } from "../identifiers.ts";

import { NotSupportedError } from "../errors.ts";

export class ExportOnly extends Algorithm implements AeadInterface {
public readonly id: AeadId = AeadId.ExportOnly;
public readonly keySize: number = 0;
public readonly nonceSize: number = 0;
public readonly tagSize: number = 0;

public createAeadKey(_key: ArrayBuffer): AeadKey {
throw new NotSupportedError(
"createAeadKey() is not supported on ExportOnly",
);
}
}
122 changes: 59 additions & 63 deletions src/cipherSuite.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { AeadKey } from "./interfaces/aeadKey.ts";
import type { AeadInterface } from "./interfaces/aeadInterface.ts";
import type { AeadParams } from "./interfaces/aeadParams.ts";
import type { CipherSuiteParams } from "./interfaces/cipherSuiteParams.ts";
import type { KdfInterface } from "./interfaces/kdfInterface.ts";
Expand All @@ -16,8 +17,10 @@ import {
RecipientExporterContext,
SenderExporterContext,
} from "./exporterContext.ts";
import { createAeadKey } from "./encryptionContext.ts";
import { AeadId, KdfId, KemId, Mode } from "./identifiers.ts";
import { Aes128Gcm, Aes256Gcm } from "./aeadKeys/aesGcmKey.ts";
import { ExportOnly } from "./aeadKeys/exportOnly.ts";
import { Chacha20Poly1305 } from "./aeadKeys/chacha20Poly1305Key.ts";
import { HkdfSha256, HkdfSha384, HkdfSha512 } from "./kdfs/hkdf.ts";
import { RecipientContext } from "./recipientContext.ts";
import { SenderContext } from "./senderContext.ts";
Expand Down Expand Up @@ -57,16 +60,10 @@ export class CipherSuite {
/** The AEAD id of the cipher suite. */
public readonly aead: AeadId;

/** The length in bytes of an AEAD key (Nk). */
public readonly aeadKeySize: number = 0;
/** The length in bytes of an AEAD nonce (Nn). */
public readonly aeadNonceSize: number = 0;
/** The length in bytes of an AEAD authentication tag (Nt). */
public readonly aeadTagSize: number = 0;

private _api: SubtleCrypto | undefined = undefined;
private _kem: KemInterface;
private _kdf: KdfInterface;
private _aead: AeadInterface;
private _suiteId: Uint8Array;

/**
Expand All @@ -77,6 +74,7 @@ export class CipherSuite {
* @throws {@link InvalidParamError}
*/
constructor(params: CipherSuiteParams) {
// KEM
if (typeof params.kem !== "number") {
this._kem = params.kem;
} else {
Expand All @@ -96,15 +94,15 @@ export class CipherSuite {
case KemId.DhkemX25519HkdfSha256:
this._kem = new DhkemX25519HkdfSha256();
break;
case KemId.DhkemX448HkdfSha512:
default:
// case KemId.DhkemX448HkdfSha512:
this._kem = new DhkemX448HkdfSha512();
break;
default:
throw new errors.InvalidParamError("Invalid KEM id");
}
}
this.kem = this._kem.id;

// KDF
if (typeof params.kdf !== "number") {
this._kdf = params.kdf;
} else {
Expand All @@ -115,37 +113,36 @@ export class CipherSuite {
case KdfId.HkdfSha384:
this._kdf = new HkdfSha384();
break;
case KdfId.HkdfSha512:
default:
// case KdfId.HkdfSha512:
this._kdf = new HkdfSha512();
break;
default:
throw new errors.InvalidParamError("Invalid KDF id");
}
}
this.kdf = this._kdf.id;

switch (params.aead) {
case AeadId.Aes128Gcm:
this.aeadKeySize = 16;
this.aeadNonceSize = 12;
this.aeadTagSize = 16;
break;
case AeadId.Aes256Gcm:
this.aeadKeySize = 32;
this.aeadNonceSize = 12;
this.aeadTagSize = 16;
break;
case AeadId.Chacha20Poly1305:
this.aeadKeySize = 32;
this.aeadNonceSize = 12;
this.aeadTagSize = 16;
break;
case AeadId.ExportOnly:
break;
default:
throw new errors.InvalidParamError("Invalid AEAD id");
// AEAD
if (typeof params.aead !== "number") {
this._aead = params.aead;
} else {
switch (params.aead) {
case AeadId.Aes128Gcm:
this._aead = new Aes128Gcm();
break;
case AeadId.Aes256Gcm:
this._aead = new Aes256Gcm();
break;
case AeadId.Chacha20Poly1305:
this._aead = new Chacha20Poly1305();
break;
default:
// case AeadId.ExportOnly:
this._aead = new ExportOnly();
break;
}
}
this.aead = params.aead;
this.aead = this._aead.id;

this._suiteId = new Uint8Array(consts.SUITE_ID_HEADER_HPKE);
this._suiteId.set(i2Osp(this.kem, 2), 4);
this._suiteId.set(i2Osp(this.kdf, 2), 6);
Expand Down Expand Up @@ -180,26 +177,26 @@ export class CipherSuite {
return this._kem.privateKeySize;
}

// /**
// * The length in bytes of an AEAD key (Nk).
// */
// public get aeadKeySize() {
// return this._aead.keySize;
// }
/**
* The length in bytes of an AEAD key (Nk).
*/
public get aeadKeySize() {
return this._aead.keySize;
}

// /**
// * The length in bytes of an AEAD nonce (Nn).
// */
// public get aeadNonceSize() {
// return this._aead.nonceSize;
// }
/**
* The length in bytes of an AEAD nonce (Nn).
*/
public get aeadNonceSize() {
return this._aead.nonceSize;
}

// /**
// * The length in bytes of an AEAD authentication tag (Nt).
// */
// public get aeadTagSize() {
// return this._aead.tagSize;
// }
/**
* The length in bytes of an AEAD authentication tag (Nt).
*/
public get aeadTagSize() {
return this._aead.tagSize;
}

/**
* Gets a suite-specific KEM context.
Expand Down Expand Up @@ -230,9 +227,7 @@ export class CipherSuite {
*/
public async createAeadKey(key: ArrayBuffer): Promise<AeadKey> {
await this.setup();
const ret = createAeadKey(this.aead, key);
ret.init(this._api as SubtleCrypto);
return ret;
return this._aead.createAeadKey(key);
}

/**
Expand Down Expand Up @@ -392,6 +387,7 @@ export class CipherSuite {
const api = await loadSubtleCrypto();
this._kem.init(api as SubtleCrypto);
this._kdf.init(api as SubtleCrypto, this._suiteId);
this._aead.init(api as SubtleCrypto);
this._api = api;
return;
}
Expand Down Expand Up @@ -463,36 +459,36 @@ export class CipherSuite {
this._kdf.hashSize,
);

if (this.aead === AeadId.ExportOnly) {
return { aead: this.aead, exporterSecret: exporterSecret };
if (this._aead.id === AeadId.ExportOnly) {
return { aead: this._aead, exporterSecret: exporterSecret };
}

const keyInfo = this._kdf.buildLabeledInfo(
consts.LABEL_KEY,
keyScheduleContext,
this.aeadKeySize,
this._aead.keySize,
);
const key = await this._kdf.extractAndExpand(
sharedSecret,
ikm,
keyInfo,
this.aeadKeySize,
this._aead.keySize,
);

const baseNonceInfo = this._kdf.buildLabeledInfo(
consts.LABEL_BASE_NONCE,
keyScheduleContext,
this.aeadNonceSize,
this._aead.nonceSize,
);
const baseNonce = await this._kdf.extractAndExpand(
sharedSecret,
ikm,
baseNonceInfo,
this.aeadNonceSize,
this._aead.nonceSize,
);

return {
aead: this.aead,
aead: this._aead,
exporterSecret: exporterSecret,
key: key,
baseNonce: new Uint8Array(baseNonce),
Expand Down
Loading

0 comments on commit b4df9ed

Please sign in to comment.