@interop/minimal-cipher 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +220 -0
- package/dist/Cipher.d.ts +210 -0
- package/dist/Cipher.d.ts.map +1 -0
- package/dist/Cipher.js +313 -0
- package/dist/Cipher.js.map +1 -0
- package/dist/DecryptTransformer.d.ts +14 -0
- package/dist/DecryptTransformer.d.ts.map +1 -0
- package/dist/DecryptTransformer.js +125 -0
- package/dist/DecryptTransformer.js.map +1 -0
- package/dist/EncryptTransformer.d.ts +28 -0
- package/dist/EncryptTransformer.d.ts.map +1 -0
- package/dist/EncryptTransformer.js +94 -0
- package/dist/EncryptTransformer.js.map +1 -0
- package/dist/algorithms/a256gcm.d.ts +39 -0
- package/dist/algorithms/a256gcm.d.ts.map +1 -0
- package/dist/algorithms/a256gcm.js +101 -0
- package/dist/algorithms/a256gcm.js.map +1 -0
- package/dist/algorithms/aeskw.d.ts +5 -0
- package/dist/algorithms/aeskw.d.ts.map +1 -0
- package/dist/algorithms/aeskw.js +68 -0
- package/dist/algorithms/aeskw.js.map +1 -0
- package/dist/algorithms/c20p-browser.d.ts +51 -0
- package/dist/algorithms/c20p-browser.d.ts.map +1 -0
- package/dist/algorithms/c20p-browser.js +106 -0
- package/dist/algorithms/c20p-browser.js.map +1 -0
- package/dist/algorithms/c20p.d.ts +51 -0
- package/dist/algorithms/c20p.d.ts.map +1 -0
- package/dist/algorithms/c20p.js +110 -0
- package/dist/algorithms/c20p.js.map +1 -0
- package/dist/algorithms/ecdhkdf.d.ts +24 -0
- package/dist/algorithms/ecdhkdf.d.ts.map +1 -0
- package/dist/algorithms/ecdhkdf.js +76 -0
- package/dist/algorithms/ecdhkdf.js.map +1 -0
- package/dist/algorithms/fips.d.ts +8 -0
- package/dist/algorithms/fips.d.ts.map +1 -0
- package/dist/algorithms/fips.js +8 -0
- package/dist/algorithms/fips.js.map +1 -0
- package/dist/algorithms/p256.d.ts +24 -0
- package/dist/algorithms/p256.d.ts.map +1 -0
- package/dist/algorithms/p256.js +106 -0
- package/dist/algorithms/p256.js.map +1 -0
- package/dist/algorithms/recommended.d.ts +8 -0
- package/dist/algorithms/recommended.d.ts.map +1 -0
- package/dist/algorithms/recommended.js +8 -0
- package/dist/algorithms/recommended.js.map +1 -0
- package/dist/algorithms/x25519-helper-browser.d.ts +7 -0
- package/dist/algorithms/x25519-helper-browser.d.ts.map +1 -0
- package/dist/algorithms/x25519-helper-browser.js +25 -0
- package/dist/algorithms/x25519-helper-browser.js.map +1 -0
- package/dist/algorithms/x25519-helper.d.ts +7 -0
- package/dist/algorithms/x25519-helper.d.ts.map +1 -0
- package/dist/algorithms/x25519-helper.js +51 -0
- package/dist/algorithms/x25519-helper.js.map +1 -0
- package/dist/algorithms/x25519.d.ts +44 -0
- package/dist/algorithms/x25519.d.ts.map +1 -0
- package/dist/algorithms/x25519.js +112 -0
- package/dist/algorithms/x25519.js.map +1 -0
- package/dist/algorithms/xc20p.d.ts +40 -0
- package/dist/algorithms/xc20p.d.ts.map +1 -0
- package/dist/algorithms/xc20p.js +160 -0
- package/dist/algorithms/xc20p.js.map +1 -0
- package/dist/baseX.d.ts +7 -0
- package/dist/baseX.d.ts.map +1 -0
- package/dist/baseX.js +11 -0
- package/dist/baseX.js.map +1 -0
- package/dist/crypto.d.ts +3 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +3 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +119 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +2 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +11 -0
- package/dist/util.js.map +1 -0
- package/package.json +99 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2020 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import crypto from '../crypto.js';
|
|
5
|
+
export const JWE_ENC = 'A256GCM';
|
|
6
|
+
/**
|
|
7
|
+
* Generates a content encryption key (CEK). The 256-bit key is intended to be
|
|
8
|
+
* used as an AES-GCM key.
|
|
9
|
+
*
|
|
10
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
11
|
+
*/
|
|
12
|
+
export async function generateKey() {
|
|
13
|
+
// generate content encryption key
|
|
14
|
+
const key = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 },
|
|
15
|
+
// key must be extractable in order to be wrapped
|
|
16
|
+
true, ['encrypt']);
|
|
17
|
+
return new Uint8Array(await crypto.subtle.exportKey('raw', key));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Encrypts some data. The data will be encrypted using the given 256-bit
|
|
21
|
+
* AES-GCM content encryption key (CEK).
|
|
22
|
+
*
|
|
23
|
+
* @param {object} options - The options to use.
|
|
24
|
+
* @param {Uint8Array} options.data - The data to encrypt.
|
|
25
|
+
* @param {Uint8Array} options.additionalData - Optional additional
|
|
26
|
+
* authentication data.
|
|
27
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
28
|
+
*
|
|
29
|
+
* @returns {Promise<object>} - A Promise that resolves to
|
|
30
|
+
* `{ciphertext, iv, tag}`.
|
|
31
|
+
*/
|
|
32
|
+
export async function encrypt({ data, additionalData, cek }) {
|
|
33
|
+
const cekKey = await _importCek({ cek, usages: ['encrypt'] });
|
|
34
|
+
// NIST Special Publication 800-38D 8.2.2 RGB Construction of IV allows for
|
|
35
|
+
// 96-bit IVs to be randomly generated; should this recommendation change
|
|
36
|
+
// we can pass in a sequence number that can be used in a fixed subfield
|
|
37
|
+
// along with random bytes in another subfield
|
|
38
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
39
|
+
// encrypt data
|
|
40
|
+
const tagBytes = 16;
|
|
41
|
+
const tagLength = tagBytes * 8;
|
|
42
|
+
const encrypted = new Uint8Array(await crypto.subtle.encrypt({
|
|
43
|
+
name: 'AES-GCM',
|
|
44
|
+
iv,
|
|
45
|
+
tagLength,
|
|
46
|
+
additionalData: additionalData
|
|
47
|
+
}, cekKey, data));
|
|
48
|
+
// split ciphertext and tag
|
|
49
|
+
const ciphertext = encrypted.subarray(0, encrypted.length - tagBytes);
|
|
50
|
+
const tag = encrypted.subarray(encrypted.length - tagBytes);
|
|
51
|
+
return {
|
|
52
|
+
ciphertext,
|
|
53
|
+
iv,
|
|
54
|
+
tag
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Decrypts some encrypted data. The data must have been encrypted using
|
|
59
|
+
* the given 256-bit AES-GCM content encryption key.
|
|
60
|
+
*
|
|
61
|
+
* @param {object} options - The options to use.
|
|
62
|
+
* @param {Uint8Array} options.ciphertext - The data to decrypt.
|
|
63
|
+
* @param {Uint8Array} options.iv - The initialization vector.
|
|
64
|
+
* @param {Uint8Array} options.tag - The authentication tag.
|
|
65
|
+
* @param {Uint8Array} options.additionalData - Optional additional
|
|
66
|
+
* authentication data.
|
|
67
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
68
|
+
*
|
|
69
|
+
* @returns {Promise<Uint8Array>} - The decrypted data.
|
|
70
|
+
*/
|
|
71
|
+
export async function decrypt({ ciphertext, iv, tag, additionalData, cek }) {
|
|
72
|
+
if (!(iv instanceof Uint8Array)) {
|
|
73
|
+
throw new Error('Invalid or missing "iv".');
|
|
74
|
+
}
|
|
75
|
+
if (!(ciphertext instanceof Uint8Array)) {
|
|
76
|
+
throw new Error('Invalid or missing "ciphertext".');
|
|
77
|
+
}
|
|
78
|
+
if (!(tag instanceof Uint8Array)) {
|
|
79
|
+
throw new Error('Invalid or missing "tag".');
|
|
80
|
+
}
|
|
81
|
+
const cekKey = await _importCek({ cek, usages: ['decrypt'] });
|
|
82
|
+
// decrypt `ciphertext`
|
|
83
|
+
const encrypted = new Uint8Array(ciphertext.length + tag.length);
|
|
84
|
+
encrypted.set(ciphertext);
|
|
85
|
+
encrypted.set(tag, ciphertext.length);
|
|
86
|
+
const tagLength = tag.length * 8;
|
|
87
|
+
const decrypted = new Uint8Array(await crypto.subtle.decrypt({
|
|
88
|
+
name: 'AES-GCM',
|
|
89
|
+
iv: iv,
|
|
90
|
+
tagLength,
|
|
91
|
+
additionalData: additionalData
|
|
92
|
+
}, cekKey, encrypted));
|
|
93
|
+
return decrypted;
|
|
94
|
+
}
|
|
95
|
+
async function _importCek({ cek, usages }) {
|
|
96
|
+
if (!(cek instanceof Uint8Array)) {
|
|
97
|
+
throw new TypeError('"cek" must be a Uint8Array.');
|
|
98
|
+
}
|
|
99
|
+
return crypto.subtle.importKey('raw', cek, { name: 'AES-GCM', length: 256 }, false, usages);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=a256gcm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a256gcm.js","sourceRoot":"","sources":["../../src/algorithms/a256gcm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aeskw.d.ts","sourceRoot":"","sources":["../../src/algorithms/aeskw.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,IAAI,YAAY,EAAE,MAAM,aAAa,CAAA;AAwFtD,wBAAsB,SAAS,CAAC,EAC9B,OAAO,EACR,EAAE;IACD,OAAO,EAAE,UAAU,CAAA;CACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAUxB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2026 Digital Bazaar, Inc.
|
|
3
|
+
*/
|
|
4
|
+
import { base64url } from '../baseX.js';
|
|
5
|
+
import crypto from '../crypto.js';
|
|
6
|
+
class Kek {
|
|
7
|
+
key;
|
|
8
|
+
algorithm;
|
|
9
|
+
constructor(key) {
|
|
10
|
+
this.key = key;
|
|
11
|
+
this.algorithm = { name: 'A256KW' };
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Wraps a cryptographic key.
|
|
15
|
+
*
|
|
16
|
+
* @param {object} options - The options to use.
|
|
17
|
+
* @param {Uint8Array} options.unwrappedKey - The key material as a
|
|
18
|
+
* `Uint8Array`.
|
|
19
|
+
*
|
|
20
|
+
* @returns {Promise<string>} - The base64url-encoded wrapped key bytes.
|
|
21
|
+
*/
|
|
22
|
+
async wrapKey({ unwrappedKey }) {
|
|
23
|
+
const kek = this.key;
|
|
24
|
+
// Note: `AES-GCM` algorithm name doesn't matter; will be exported raw.
|
|
25
|
+
const extractable = true;
|
|
26
|
+
const unwrappedCryptoKey = await crypto.subtle.importKey('raw', unwrappedKey, { name: 'AES-GCM', length: 256 },
|
|
27
|
+
// key usage of `encrypt` refers to the key that is to be wrapped not
|
|
28
|
+
// the KEK itself; we just treat it like an AES-GCM key regardless of
|
|
29
|
+
// what it is
|
|
30
|
+
extractable, ['encrypt']);
|
|
31
|
+
const wrappedKey = await crypto.subtle.wrapKey('raw', unwrappedCryptoKey, kek, kek.algorithm);
|
|
32
|
+
return base64url.encode(new Uint8Array(wrappedKey));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Unwraps a cryptographic key.
|
|
36
|
+
*
|
|
37
|
+
* @param {object} options - The options to use.
|
|
38
|
+
* @param {string} options.wrappedKey - The wrapped key material as a
|
|
39
|
+
* base64url-encoded string.
|
|
40
|
+
*
|
|
41
|
+
* @returns {Promise<Uint8Array>} - Resolves to the key bytes or null if
|
|
42
|
+
* the unwrapping fails because the key does not match.
|
|
43
|
+
*/
|
|
44
|
+
async unwrapKey({ wrappedKey }) {
|
|
45
|
+
const kek = this.key;
|
|
46
|
+
// Note: `AES-GCM` algorithm name doesn't matter; will be exported raw.
|
|
47
|
+
const wrappedKeyBytes = base64url.decode(wrappedKey);
|
|
48
|
+
try {
|
|
49
|
+
const extractable = true;
|
|
50
|
+
const key = await crypto.subtle.unwrapKey('raw', wrappedKeyBytes, kek, kek.algorithm,
|
|
51
|
+
// key usage of `encrypt` refers to the key that is being unwrapped;
|
|
52
|
+
// we just treat it like an AES-GCM key regardless of what it is
|
|
53
|
+
{ name: 'AES-GCM' }, extractable, ['encrypt']);
|
|
54
|
+
const keyBytes = await crypto.subtle.exportKey('raw', key);
|
|
55
|
+
return new Uint8Array(keyBytes);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// unwrapping key failed
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export async function createKek({ keyData }) {
|
|
64
|
+
const extractable = true;
|
|
65
|
+
const key = await crypto.subtle.importKey('raw', keyData, { name: 'AES-KW', length: 256 }, extractable, ['wrapKey', 'unwrapKey']);
|
|
66
|
+
return new Kek(key);
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=aeskw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aeskw.js","sourceRoot":"","sources":["../../src/algorithms/aeskw.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,MAAM,MAAM,cAAc,CAAA;AAGjC,MAAM,GAAG;IACP,GAAG,CAAW;IACd,SAAS,CAAkB;IAE3B,YAAY,GAAc;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,SAAS,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IACrC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,CAAC,EACZ,YAAY,EAGb;QACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;QACpB,uEAAuE;QACvE,MAAM,WAAW,GAAG,IAAI,CAAA;QAExB,MAAM,kBAAkB,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACtD,KAAK,EACL,YAA4B,EAC5B,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE;QAChC,qEAAqE;QACrE,qEAAqE;QACrE,aAAa;QACb,WAAW,EACX,CAAC,SAAS,CAAC,CACZ,CAAA;QACD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAC5C,KAAK,EACL,kBAAkB,EAClB,GAAG,EACH,GAAG,CAAC,SAAS,CACd,CAAA;QACD,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAA;IACrD,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,SAAS,CAAC,EACd,UAAU,EAGX;QACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAA;QACpB,uEAAuE;QACvE,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QACpD,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,IAAI,CAAA;YACxB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,eAA+B,EAC/B,GAAG,EACH,GAAG,CAAC,SAAS;YACb,oEAAoE;YACpE,gEAAgE;YAChE,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,WAAW,EACX,CAAC,SAAS,CAAC,CACZ,CAAA;YACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAC1D,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAA;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;YACxB,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAC9B,OAAO,EAGR;IACC,MAAM,WAAW,GAAG,IAAI,CAAA;IACxB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,OAAuB,EACvB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,EAC/B,WAAW,EACX,CAAC,SAAS,EAAE,WAAW,CAAC,CACzB,CAAA;IACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CipherDecryptOptions, CipherEncryptOptions, EncryptResult } from '../types.js';
|
|
2
|
+
export declare const JWE_ENC = "C20P";
|
|
3
|
+
interface InternalEncryptOptions {
|
|
4
|
+
data: Uint8Array;
|
|
5
|
+
additionalData?: Uint8Array;
|
|
6
|
+
cek: Uint8Array;
|
|
7
|
+
iv?: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generates a content encryption key (CEK). The 256-bit key is intended to be
|
|
11
|
+
* used as a ChaCha20Poly1305 (RFC8439) key.
|
|
12
|
+
*
|
|
13
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateKey(): Promise<Uint8Array>;
|
|
16
|
+
/**
|
|
17
|
+
* Encrypts some data. The data will be encrypted using the given
|
|
18
|
+
* 256-bit ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
19
|
+
*
|
|
20
|
+
* @param {object} options - The options to use.
|
|
21
|
+
* @param {Uint8Array} options.data - The data to encrypt.
|
|
22
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
23
|
+
* authentication data.
|
|
24
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
25
|
+
*
|
|
26
|
+
* @returns {Promise<object>} - Resolves to `{ciphertext, iv, tag}`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function encrypt({ data, additionalData, cek }: CipherEncryptOptions): Promise<EncryptResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Decrypts some encrypted data. The data must have been encrypted using
|
|
31
|
+
* the given ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
32
|
+
*
|
|
33
|
+
* @param {object} options - The options to use.
|
|
34
|
+
* @param {Uint8Array} options.ciphertext - The data to decrypt.
|
|
35
|
+
* @param {Uint8Array} options.iv - The initialization vector (aka nonce).
|
|
36
|
+
* @param {Uint8Array} options.tag - The authentication tag.
|
|
37
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
38
|
+
* authentication data.
|
|
39
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
40
|
+
*
|
|
41
|
+
* @returns {Promise<Uint8Array>} The decrypted data.
|
|
42
|
+
*/
|
|
43
|
+
export declare function decrypt({ ciphertext, iv, tag, additionalData, cek }: CipherDecryptOptions): Promise<Uint8Array | null>;
|
|
44
|
+
export declare function _encrypt({ data, additionalData, cek, iv }: InternalEncryptOptions): Promise<EncryptResult>;
|
|
45
|
+
export declare function _chacha20({ key, nonce, src }: {
|
|
46
|
+
key: Uint8Array;
|
|
47
|
+
nonce: Uint8Array;
|
|
48
|
+
src: Uint8Array;
|
|
49
|
+
}): Uint8Array;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=c20p-browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c20p-browser.d.ts","sourceRoot":"","sources":["../../src/algorithms/c20p-browser.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACd,MAAM,aAAa,CAAA;AAEpB,eAAO,MAAM,OAAO,SAAS,CAAA;AAE7B,UAAU,sBAAsB;IAC9B,IAAI,EAAE,UAAU,CAAA;IAChB,cAAc,CAAC,EAAE,UAAU,CAAA;IAC3B,GAAG,EAAE,UAAU,CAAA;IACf,EAAE,CAAC,EAAE,UAAU,CAAA;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC,CAGvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,cAAc,EACd,GAAG,EACJ,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAQ/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAAC,EAC5B,UAAU,EACV,EAAE,EACF,GAAG,EACH,cAAc,EACd,GAAG,EACJ,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAoBnD;AAGD,wBAAsB,QAAQ,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,GAAG,EACH,EAAE,EACH,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC,CAiBjD;AAGD,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,KAAK,EACL,GAAG,EACJ,EAAE;IACD,GAAG,EAAE,UAAU,CAAA;IACf,KAAK,EAAE,UAAU,CAAA;IACjB,GAAG,EAAE,UAAU,CAAA;CAChB,GAAG,UAAU,CAeb"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2023 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { ChaCha20Poly1305, KEY_LENGTH } from '@stablelib/chacha20poly1305';
|
|
5
|
+
import crypto from '../crypto.js';
|
|
6
|
+
import { streamXOR } from '@stablelib/chacha';
|
|
7
|
+
export const JWE_ENC = 'C20P';
|
|
8
|
+
/**
|
|
9
|
+
* Generates a content encryption key (CEK). The 256-bit key is intended to be
|
|
10
|
+
* used as a ChaCha20Poly1305 (RFC8439) key.
|
|
11
|
+
*
|
|
12
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
13
|
+
*/
|
|
14
|
+
export async function generateKey() {
|
|
15
|
+
// generate content encryption key
|
|
16
|
+
return crypto.getRandomValues(new Uint8Array(KEY_LENGTH));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Encrypts some data. The data will be encrypted using the given
|
|
20
|
+
* 256-bit ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
21
|
+
*
|
|
22
|
+
* @param {object} options - The options to use.
|
|
23
|
+
* @param {Uint8Array} options.data - The data to encrypt.
|
|
24
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
25
|
+
* authentication data.
|
|
26
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
27
|
+
*
|
|
28
|
+
* @returns {Promise<object>} - Resolves to `{ciphertext, iv, tag}`.
|
|
29
|
+
*/
|
|
30
|
+
export async function encrypt({ data, additionalData, cek }) {
|
|
31
|
+
if (!(data instanceof Uint8Array)) {
|
|
32
|
+
throw new TypeError('"data" must be a Uint8Array.');
|
|
33
|
+
}
|
|
34
|
+
if (!(cek instanceof Uint8Array)) {
|
|
35
|
+
throw new TypeError('"cek" must be a Uint8Array.');
|
|
36
|
+
}
|
|
37
|
+
return _encrypt({ data, additionalData, cek });
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Decrypts some encrypted data. The data must have been encrypted using
|
|
41
|
+
* the given ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
42
|
+
*
|
|
43
|
+
* @param {object} options - The options to use.
|
|
44
|
+
* @param {Uint8Array} options.ciphertext - The data to decrypt.
|
|
45
|
+
* @param {Uint8Array} options.iv - The initialization vector (aka nonce).
|
|
46
|
+
* @param {Uint8Array} options.tag - The authentication tag.
|
|
47
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
48
|
+
* authentication data.
|
|
49
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
50
|
+
*
|
|
51
|
+
* @returns {Promise<Uint8Array>} The decrypted data.
|
|
52
|
+
*/
|
|
53
|
+
export async function decrypt({ ciphertext, iv, tag, additionalData, cek }) {
|
|
54
|
+
if (!(iv instanceof Uint8Array)) {
|
|
55
|
+
throw new Error('Invalid or missing "iv".');
|
|
56
|
+
}
|
|
57
|
+
if (!(ciphertext instanceof Uint8Array)) {
|
|
58
|
+
throw new Error('Invalid or missing "ciphertext".');
|
|
59
|
+
}
|
|
60
|
+
if (!(tag instanceof Uint8Array)) {
|
|
61
|
+
throw new Error('Invalid or missing "tag".');
|
|
62
|
+
}
|
|
63
|
+
if (!(cek instanceof Uint8Array)) {
|
|
64
|
+
throw new TypeError('"cek" must be a Uint8Array.');
|
|
65
|
+
}
|
|
66
|
+
// decrypt `ciphertext`
|
|
67
|
+
const cipher = new ChaCha20Poly1305(cek);
|
|
68
|
+
const encrypted = new Uint8Array(ciphertext.length + cipher.tagLength);
|
|
69
|
+
encrypted.set(ciphertext);
|
|
70
|
+
encrypted.set(tag, ciphertext.length);
|
|
71
|
+
return cipher.open(iv, encrypted, additionalData);
|
|
72
|
+
}
|
|
73
|
+
// internal function exported for reuse by XChaCha20Poly1305
|
|
74
|
+
export async function _encrypt({ data, additionalData, cek, iv }) {
|
|
75
|
+
const cipher = new ChaCha20Poly1305(cek);
|
|
76
|
+
// Note: Use of a random value here as a counter is only viable for a
|
|
77
|
+
// limited set of messages; using XChaCha20Poly1305 instead
|
|
78
|
+
// probabilistically eliminates chances of a collision as it has a 192-bit IV
|
|
79
|
+
if (iv === undefined) {
|
|
80
|
+
iv = crypto.getRandomValues(new Uint8Array(cipher.nonceLength));
|
|
81
|
+
}
|
|
82
|
+
// encrypt data
|
|
83
|
+
const encrypted = cipher.seal(iv, data, additionalData);
|
|
84
|
+
// split ciphertext and tag and return values
|
|
85
|
+
const ciphertext = encrypted.subarray(0, encrypted.length - cipher.tagLength);
|
|
86
|
+
const tag = encrypted.subarray(encrypted.length - cipher.tagLength);
|
|
87
|
+
return { ciphertext, iv, tag };
|
|
88
|
+
}
|
|
89
|
+
// internal function exported for reuse by XChaCha20Poly1305
|
|
90
|
+
export function _chacha20({ key, nonce, src }) {
|
|
91
|
+
const dst = new Uint8Array(64);
|
|
92
|
+
// encrypt a single block (1 == full nonce will be used no counter generated)
|
|
93
|
+
try {
|
|
94
|
+
// `nonce` is modified internally, so copy it first
|
|
95
|
+
nonce = Uint8Array.prototype.slice.call(nonce);
|
|
96
|
+
return streamXOR(key, nonce, src, dst, 1);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
// ignore counter overflow error; we don't use the counter
|
|
100
|
+
if (e.message.includes('counter overflow')) {
|
|
101
|
+
return dst;
|
|
102
|
+
}
|
|
103
|
+
throw e;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=c20p-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c20p-browser.js","sourceRoot":"","sources":["../../src/algorithms/c20p-browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CipherDecryptOptions, CipherEncryptOptions, EncryptResult } from '../types.js';
|
|
2
|
+
export declare const JWE_ENC = "C20P";
|
|
3
|
+
interface InternalEncryptOptions {
|
|
4
|
+
data: Uint8Array;
|
|
5
|
+
additionalData?: Uint8Array;
|
|
6
|
+
cek: Uint8Array;
|
|
7
|
+
iv?: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generates a content encryption key (CEK). The 256-bit key is intended to be
|
|
11
|
+
* used as a ChaCha20Poly1305 (RFC8439) key.
|
|
12
|
+
*
|
|
13
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateKey(): Promise<Uint8Array>;
|
|
16
|
+
/**
|
|
17
|
+
* Encrypts some data. The data will be encrypted using the given
|
|
18
|
+
* 256-bit ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
19
|
+
*
|
|
20
|
+
* @param {object} options - The options to use.
|
|
21
|
+
* @param {Uint8Array} options.data - The data to encrypt.
|
|
22
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
23
|
+
* authentication data.
|
|
24
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
25
|
+
*
|
|
26
|
+
* @returns {Promise<object>} - Resolves to `{ciphertext, iv, tag}`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function encrypt({ data, additionalData, cek }: CipherEncryptOptions): Promise<EncryptResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Decrypts some encrypted data. The data must have been encrypted using
|
|
31
|
+
* the given ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
32
|
+
*
|
|
33
|
+
* @param {object} options - The options to use.
|
|
34
|
+
* @param {Uint8Array} options.ciphertext - The data to decrypt.
|
|
35
|
+
* @param {Uint8Array} options.iv - The initialization vector (aka nonce).
|
|
36
|
+
* @param {Uint8Array} options.tag - The authentication tag.
|
|
37
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
38
|
+
* authentication data.
|
|
39
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
40
|
+
*
|
|
41
|
+
* @returns {Promise<Uint8Array>} The decrypted data.
|
|
42
|
+
*/
|
|
43
|
+
export declare function decrypt({ ciphertext, iv, tag, additionalData, cek }: CipherDecryptOptions): Promise<Uint8Array>;
|
|
44
|
+
export declare function _encrypt({ data, additionalData, cek, iv }: InternalEncryptOptions): Promise<EncryptResult>;
|
|
45
|
+
export declare function _chacha20({ key, nonce, src }: {
|
|
46
|
+
key: Uint8Array;
|
|
47
|
+
nonce: Uint8Array;
|
|
48
|
+
src: Uint8Array;
|
|
49
|
+
}): Uint8Array;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=c20p.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c20p.d.ts","sourceRoot":"","sources":["../../src/algorithms/c20p.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACd,MAAM,aAAa,CAAA;AAEpB,eAAO,MAAM,OAAO,SAAS,CAAA;AAE7B,UAAU,sBAAsB;IAC9B,IAAI,EAAE,UAAU,CAAA;IAChB,cAAc,CAAC,EAAE,UAAU,CAAA;IAC3B,GAAG,EAAE,UAAU,CAAA;IACf,EAAE,CAAC,EAAE,UAAU,CAAA;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,UAAU,CAAC,CAGvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,cAAc,EACd,GAAG,EACJ,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAQ/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,OAAO,CAAC,EAC5B,UAAU,EACV,EAAE,EACF,GAAG,EACH,cAAc,EACd,GAAG,EACJ,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CA0B5C;AAGD,wBAAsB,QAAQ,CAAC,EAC7B,IAAI,EACJ,cAAc,EACd,GAAG,EACH,EAAE,EACH,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC,CAuBjD;AAGD,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,KAAK,EACL,GAAG,EACJ,EAAE;IACD,GAAG,EAAE,UAAU,CAAA;IACf,KAAK,EAAE,UAAU,CAAA;IACjB,GAAG,EAAE,UAAU,CAAA;CAChB,GAAG,UAAU,CAMb"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import { default as webcrypto } from '../crypto.js';
|
|
6
|
+
export const JWE_ENC = 'C20P';
|
|
7
|
+
/**
|
|
8
|
+
* Generates a content encryption key (CEK). The 256-bit key is intended to be
|
|
9
|
+
* used as a ChaCha20Poly1305 (RFC8439) key.
|
|
10
|
+
*
|
|
11
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
12
|
+
*/
|
|
13
|
+
export async function generateKey() {
|
|
14
|
+
// generate content encryption key
|
|
15
|
+
return webcrypto.getRandomValues(new Uint8Array(32));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Encrypts some data. The data will be encrypted using the given
|
|
19
|
+
* 256-bit ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
20
|
+
*
|
|
21
|
+
* @param {object} options - The options to use.
|
|
22
|
+
* @param {Uint8Array} options.data - The data to encrypt.
|
|
23
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
24
|
+
* authentication data.
|
|
25
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
26
|
+
*
|
|
27
|
+
* @returns {Promise<object>} - Resolves to `{ciphertext, iv, tag}`.
|
|
28
|
+
*/
|
|
29
|
+
export async function encrypt({ data, additionalData, cek }) {
|
|
30
|
+
if (!(data instanceof Uint8Array)) {
|
|
31
|
+
throw new TypeError('"data" must be a Uint8Array.');
|
|
32
|
+
}
|
|
33
|
+
if (!(cek instanceof Uint8Array)) {
|
|
34
|
+
throw new TypeError('"cek" must be a Uint8Array.');
|
|
35
|
+
}
|
|
36
|
+
return _encrypt({ data, additionalData, cek });
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decrypts some encrypted data. The data must have been encrypted using
|
|
40
|
+
* the given ChaCha20Poly1305 (RFC8439) content encryption key (CEK).
|
|
41
|
+
*
|
|
42
|
+
* @param {object} options - The options to use.
|
|
43
|
+
* @param {Uint8Array} options.ciphertext - The data to decrypt.
|
|
44
|
+
* @param {Uint8Array} options.iv - The initialization vector (aka nonce).
|
|
45
|
+
* @param {Uint8Array} options.tag - The authentication tag.
|
|
46
|
+
* @param {Uint8Array} [options.additionalData] - Optional additional
|
|
47
|
+
* authentication data.
|
|
48
|
+
* @param {Uint8Array} options.cek - The content encryption key to use.
|
|
49
|
+
*
|
|
50
|
+
* @returns {Promise<Uint8Array>} The decrypted data.
|
|
51
|
+
*/
|
|
52
|
+
export async function decrypt({ ciphertext, iv, tag, additionalData, cek }) {
|
|
53
|
+
if (!(iv instanceof Uint8Array)) {
|
|
54
|
+
throw new Error('Invalid or missing "iv".');
|
|
55
|
+
}
|
|
56
|
+
if (!(ciphertext instanceof Uint8Array)) {
|
|
57
|
+
throw new Error('Invalid or missing "ciphertext".');
|
|
58
|
+
}
|
|
59
|
+
if (!(tag instanceof Uint8Array)) {
|
|
60
|
+
throw new Error('Invalid or missing "tag".');
|
|
61
|
+
}
|
|
62
|
+
if (!(cek instanceof Uint8Array)) {
|
|
63
|
+
throw new TypeError('"cek" must be a Uint8Array.');
|
|
64
|
+
}
|
|
65
|
+
// decrypt `ciphertext` using node.js native implementation
|
|
66
|
+
const decipher = crypto.createDecipheriv('chacha20-poly1305', cek, iv, {
|
|
67
|
+
authTagLength: 16
|
|
68
|
+
});
|
|
69
|
+
decipher.setAuthTag(tag);
|
|
70
|
+
if (additionalData) {
|
|
71
|
+
// `plaintextLength` is optional at runtime for chacha20-poly1305
|
|
72
|
+
;
|
|
73
|
+
decipher.setAAD(additionalData);
|
|
74
|
+
}
|
|
75
|
+
const decrypted = decipher.update(ciphertext);
|
|
76
|
+
const final = decipher.final();
|
|
77
|
+
return final.length > 0 ? Buffer.concat([decrypted, final]) : decrypted;
|
|
78
|
+
}
|
|
79
|
+
// internal function exported for reuse by XChaCha20Poly1305
|
|
80
|
+
export async function _encrypt({ data, additionalData, cek, iv }) {
|
|
81
|
+
// Note: Use of a random value here as a counter is only viable for a
|
|
82
|
+
// limited set of messages; using XChaCha20Poly1305 instead
|
|
83
|
+
// probabilistically eliminates chances of a collision as it has a 192-bit IV
|
|
84
|
+
if (iv === undefined) {
|
|
85
|
+
iv = webcrypto.getRandomValues(new Uint8Array(12));
|
|
86
|
+
}
|
|
87
|
+
// encrypt `data` using node.js native implementation
|
|
88
|
+
const cipher = crypto.createCipheriv('chacha20-poly1305', cek, iv, {
|
|
89
|
+
authTagLength: 16
|
|
90
|
+
});
|
|
91
|
+
if (additionalData) {
|
|
92
|
+
// `plaintextLength` is optional at runtime for chacha20-poly1305
|
|
93
|
+
;
|
|
94
|
+
cipher.setAAD(additionalData);
|
|
95
|
+
}
|
|
96
|
+
const encrypted = cipher.update(data);
|
|
97
|
+
const final = cipher.final();
|
|
98
|
+
const ciphertext = final.length > 0 ? Buffer.concat([encrypted, final]) : encrypted;
|
|
99
|
+
const tag = cipher.getAuthTag();
|
|
100
|
+
return { ciphertext, iv, tag };
|
|
101
|
+
}
|
|
102
|
+
// internal function exported for reuse by XChaCha20Poly1305
|
|
103
|
+
export function _chacha20({ key, nonce, src }) {
|
|
104
|
+
// use node.js implementation
|
|
105
|
+
const cipher = crypto.createCipheriv('chacha20', key, nonce);
|
|
106
|
+
const dst = cipher.update(src);
|
|
107
|
+
const final = cipher.final();
|
|
108
|
+
return final.length > 0 ? Buffer.concat([dst, final]) : dst;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=c20p.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"c20p.js","sourceRoot":"","sources":["../../src/algorithms/c20p.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives a 256-bit AES-KW key encryption key from a shared secret that
|
|
3
|
+
* was derived from an ephemeral and static pair
|
|
4
|
+
* of Elliptic Curve Diffie-Hellman keys.
|
|
5
|
+
*
|
|
6
|
+
* The KDF used is described in RFC 7518. This KDF is referenced by RFC 8037,
|
|
7
|
+
* which defines how to perform Curve25519 (X25519) ECDH key agreement.
|
|
8
|
+
*
|
|
9
|
+
* @param {object} options - The options to use.
|
|
10
|
+
* @param {Uint8Array} options.secret - The shared secret (i.e., `Z`) to use.
|
|
11
|
+
* @param {Uint8Array} options.producerInfo - An array of application-specific
|
|
12
|
+
* bytes describing the consumer (aka the "encrypter" or "sender").
|
|
13
|
+
* @param {Uint8Array} options.consumerInfo - An array of application-specific
|
|
14
|
+
* bytes describing the producer (aka the "decrypter" or
|
|
15
|
+
* "receiver"/"recipient").
|
|
16
|
+
*
|
|
17
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
18
|
+
*/
|
|
19
|
+
export declare function deriveKey({ secret, producerInfo, consumerInfo }: {
|
|
20
|
+
secret: Uint8Array;
|
|
21
|
+
producerInfo: Uint8Array;
|
|
22
|
+
consumerInfo: Uint8Array;
|
|
23
|
+
}): Promise<Uint8Array>;
|
|
24
|
+
//# sourceMappingURL=ecdhkdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdhkdf.d.ts","sourceRoot":"","sources":["../../src/algorithms/ecdhkdf.ts"],"names":[],"mappings":"AA2BA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,SAAS,CAAC,EAC9B,MAAM,EACN,YAAY,EACZ,YAAY,EACb,EAAE;IACD,MAAM,EAAE,UAAU,CAAA;IAClB,YAAY,EAAE,UAAU,CAAA;IACxB,YAAY,EAAE,UAAU,CAAA;CACzB,GAAG,OAAO,CAAC,UAAU,CAAC,CA0CtB"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2019-2020 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
import crypto from '../crypto.js';
|
|
5
|
+
// only supported algorithm
|
|
6
|
+
const KEY_ALGORITHM = 'ECDH-ES+A256KW';
|
|
7
|
+
// create static ALGORITHM_ID
|
|
8
|
+
const ALGORITHM_CONTENT = new TextEncoder().encode(KEY_ALGORITHM);
|
|
9
|
+
const ALGORITHM_ID = new Uint8Array(4 + ALGORITHM_CONTENT.length);
|
|
10
|
+
// write length of content as 32-bit big endian integer, then write content
|
|
11
|
+
const dv = new DataView(ALGORITHM_ID.buffer, ALGORITHM_ID.byteOffset, ALGORITHM_ID.byteLength);
|
|
12
|
+
dv.setUint32(0, ALGORITHM_CONTENT.length);
|
|
13
|
+
ALGORITHM_ID.set(ALGORITHM_CONTENT, 4);
|
|
14
|
+
// RFC 7518 Section 4.6.2 specifies using SHA-256 for ECDH-ES KDF
|
|
15
|
+
// https://tools.ietf.org/html/rfc7518#section-4.6.2
|
|
16
|
+
const HASH_ALGORITHM = { name: 'SHA-256' };
|
|
17
|
+
// derived keys are always 256-bits
|
|
18
|
+
const KEY_LENGTH = 256;
|
|
19
|
+
/**
|
|
20
|
+
* Derives a 256-bit AES-KW key encryption key from a shared secret that
|
|
21
|
+
* was derived from an ephemeral and static pair
|
|
22
|
+
* of Elliptic Curve Diffie-Hellman keys.
|
|
23
|
+
*
|
|
24
|
+
* The KDF used is described in RFC 7518. This KDF is referenced by RFC 8037,
|
|
25
|
+
* which defines how to perform Curve25519 (X25519) ECDH key agreement.
|
|
26
|
+
*
|
|
27
|
+
* @param {object} options - The options to use.
|
|
28
|
+
* @param {Uint8Array} options.secret - The shared secret (i.e., `Z`) to use.
|
|
29
|
+
* @param {Uint8Array} options.producerInfo - An array of application-specific
|
|
30
|
+
* bytes describing the consumer (aka the "encrypter" or "sender").
|
|
31
|
+
* @param {Uint8Array} options.consumerInfo - An array of application-specific
|
|
32
|
+
* bytes describing the producer (aka the "decrypter" or
|
|
33
|
+
* "receiver"/"recipient").
|
|
34
|
+
*
|
|
35
|
+
* @returns {Promise<Uint8Array>} - Resolves to the generated key.
|
|
36
|
+
*/
|
|
37
|
+
export async function deriveKey({ secret, producerInfo, consumerInfo }) {
|
|
38
|
+
if (!(secret instanceof Uint8Array && secret.length > 0)) {
|
|
39
|
+
throw new TypeError('"secret" must be a non-empty Uint8Array.');
|
|
40
|
+
}
|
|
41
|
+
if (!(producerInfo instanceof Uint8Array && producerInfo.length > 0)) {
|
|
42
|
+
throw new TypeError('"producerInfo" must be a non-empty Uint8Array.');
|
|
43
|
+
}
|
|
44
|
+
if (!(consumerInfo instanceof Uint8Array && consumerInfo.length > 0)) {
|
|
45
|
+
throw new TypeError('"consumerInfo" must be a non-empty Uint8Array.');
|
|
46
|
+
}
|
|
47
|
+
// the output of Concat KDF is hash(roundNumber || Z || OtherInfo)
|
|
48
|
+
// where roundNumber is always 1 because the hash length is presumed to
|
|
49
|
+
// ...match the key length, encoded as a big endian 32-bit integer
|
|
50
|
+
// where OtherInfo is:
|
|
51
|
+
// AlgorithmID || PartyUInfo || PartyVInfo || SuppPubInfo
|
|
52
|
+
// where SuppPubInfo is the key length in bits, big endian encoded as a
|
|
53
|
+
// 32-bit number, i.e., 256 === [0, 0, 1, 0]
|
|
54
|
+
const input = new Uint8Array(4 + // round number
|
|
55
|
+
secret.length + // `Z`
|
|
56
|
+
ALGORITHM_ID.length + // AlgorithmID
|
|
57
|
+
4 +
|
|
58
|
+
producerInfo.length + // PartyUInfo
|
|
59
|
+
4 +
|
|
60
|
+
consumerInfo.length + // PartyVInfo
|
|
61
|
+
4); // SuppPubInfo (key data length in bits)
|
|
62
|
+
let offset = 0;
|
|
63
|
+
const dv = new DataView(input.buffer, input.byteOffset, input.byteLength);
|
|
64
|
+
dv.setUint32(offset, 1);
|
|
65
|
+
input.set(secret, (offset += 4));
|
|
66
|
+
input.set(ALGORITHM_ID, (offset += secret.length));
|
|
67
|
+
dv.setUint32((offset += ALGORITHM_ID.length), producerInfo.length);
|
|
68
|
+
input.set(producerInfo, (offset += 4));
|
|
69
|
+
dv.setUint32((offset += producerInfo.length), consumerInfo.length);
|
|
70
|
+
input.set(consumerInfo, (offset += 4));
|
|
71
|
+
// final write position; `offset` is not read again, so avoid reassigning it
|
|
72
|
+
dv.setUint32(offset + consumerInfo.length, KEY_LENGTH);
|
|
73
|
+
// hash input and return result as derived key
|
|
74
|
+
return new Uint8Array(await crypto.subtle.digest(HASH_ALGORITHM, input));
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=ecdhkdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecdhkdf.js","sourceRoot":"","sources":["../../src/algorithms/ecdhkdf.ts"],"names":[],"mappings":"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"}
|