@enbox/crypto 0.0.2 → 0.0.3
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/README.md +34 -102
- package/dist/browser.js +6 -10
- package/dist/browser.js.map +4 -4
- package/dist/browser.mjs +6 -10
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/algorithms/aes-gcm.js +1 -1
- package/dist/esm/algorithms/aes-gcm.js.map +1 -1
- package/dist/esm/algorithms/ecdsa.js +9 -5
- package/dist/esm/algorithms/ecdsa.js.map +1 -1
- package/dist/esm/algorithms/eddsa.js +9 -5
- package/dist/esm/algorithms/eddsa.js.map +1 -1
- package/dist/esm/algorithms/sha-2.js +1 -1
- package/dist/esm/algorithms/sha-2.js.map +1 -1
- package/dist/esm/crypto-error.js +41 -0
- package/dist/esm/crypto-error.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/jose/jwk.js +52 -26
- package/dist/esm/jose/jwk.js.map +1 -1
- package/dist/esm/local-key-manager.js +3 -2
- package/dist/esm/local-key-manager.js.map +1 -1
- package/dist/esm/primitives/aes-ctr.js.map +1 -1
- package/dist/esm/primitives/aes-gcm.js.map +1 -1
- package/dist/esm/primitives/aes-kw.js +246 -0
- package/dist/esm/primitives/aes-kw.js.map +1 -0
- package/dist/esm/primitives/concat-kdf.js +1 -1
- package/dist/esm/primitives/concat-kdf.js.map +1 -1
- package/dist/esm/primitives/ed25519.js +3 -3
- package/dist/esm/primitives/ed25519.js.map +1 -1
- package/dist/esm/primitives/hkdf.js +79 -0
- package/dist/esm/primitives/hkdf.js.map +1 -0
- package/dist/esm/primitives/pbkdf2.js +49 -0
- package/dist/esm/primitives/pbkdf2.js.map +1 -1
- package/dist/esm/primitives/secp256k1.js +4 -4
- package/dist/esm/primitives/secp256k1.js.map +1 -1
- package/dist/esm/primitives/secp256r1.js +4 -4
- package/dist/esm/primitives/secp256r1.js.map +1 -1
- package/dist/esm/primitives/x25519.js +1 -1
- package/dist/esm/primitives/x25519.js.map +1 -1
- package/dist/esm/primitives/xchacha20-poly1305.js +48 -3
- package/dist/esm/primitives/xchacha20-poly1305.js.map +1 -1
- package/dist/esm/primitives/xchacha20.js +1 -1
- package/dist/esm/primitives/xchacha20.js.map +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/dist/types/algorithms/aes-ctr.d.ts +1 -1
- package/dist/types/algorithms/aes-ctr.d.ts.map +1 -1
- package/dist/types/algorithms/aes-gcm.d.ts +2 -2
- package/dist/types/algorithms/aes-gcm.d.ts.map +1 -1
- package/dist/types/algorithms/ecdsa.d.ts +1 -1
- package/dist/types/algorithms/ecdsa.d.ts.map +1 -1
- package/dist/types/algorithms/eddsa.d.ts +2 -2
- package/dist/types/algorithms/eddsa.d.ts.map +1 -1
- package/dist/types/algorithms/sha-2.d.ts +1 -1
- package/dist/types/algorithms/sha-2.d.ts.map +1 -1
- package/dist/types/crypto-error.d.ts +29 -0
- package/dist/types/crypto-error.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/jose/jwk.d.ts.map +1 -1
- package/dist/types/local-key-manager.d.ts +3 -3
- package/dist/types/local-key-manager.d.ts.map +1 -1
- package/dist/types/primitives/aes-kw.d.ts +103 -0
- package/dist/types/primitives/aes-kw.d.ts.map +1 -0
- package/dist/types/primitives/concat-kdf.d.ts +1 -1
- package/dist/types/primitives/concat-kdf.d.ts.map +1 -1
- package/dist/types/primitives/hkdf.d.ts +90 -0
- package/dist/types/primitives/hkdf.d.ts.map +1 -0
- package/dist/types/primitives/pbkdf2.d.ts +58 -0
- package/dist/types/primitives/pbkdf2.d.ts.map +1 -1
- package/dist/types/primitives/xchacha20-poly1305.d.ts +47 -0
- package/dist/types/primitives/xchacha20-poly1305.d.ts.map +1 -1
- package/dist/types/types/cipher.d.ts +1 -1
- package/dist/types/types/crypto-api.d.ts +3 -3
- package/dist/types/types/crypto-api.d.ts.map +1 -1
- package/dist/types/types/params-direct.d.ts +79 -1
- package/dist/types/types/params-direct.d.ts.map +1 -1
- package/dist/utils.js.map +2 -2
- package/package.json +26 -39
- package/src/algorithms/aes-ctr.ts +1 -1
- package/src/algorithms/aes-gcm.ts +3 -2
- package/src/algorithms/ecdsa.ts +13 -7
- package/src/algorithms/eddsa.ts +9 -9
- package/src/algorithms/sha-2.ts +2 -2
- package/src/crypto-error.ts +45 -0
- package/src/index.ts +3 -0
- package/src/jose/jwk.ts +32 -32
- package/src/local-key-manager.ts +14 -13
- package/src/primitives/aes-ctr.ts +1 -1
- package/src/primitives/aes-gcm.ts +5 -5
- package/src/primitives/aes-kw.ts +269 -0
- package/src/primitives/concat-kdf.ts +4 -2
- package/src/primitives/ed25519.ts +6 -6
- package/src/primitives/hkdf.ts +121 -0
- package/src/primitives/pbkdf2.ts +91 -0
- package/src/primitives/secp256k1.ts +6 -6
- package/src/primitives/secp256r1.ts +6 -6
- package/src/primitives/x25519.ts +3 -3
- package/src/primitives/xchacha20-poly1305.ts +57 -4
- package/src/primitives/xchacha20.ts +1 -1
- package/src/types/cipher.ts +1 -1
- package/src/types/crypto-api.ts +5 -5
- package/src/types/params-direct.ts +97 -1
- package/src/utils.ts +2 -2
- package/dist/cjs/algorithms/aes-ctr.js +0 -188
- package/dist/cjs/algorithms/aes-ctr.js.map +0 -1
- package/dist/cjs/algorithms/aes-gcm.js +0 -196
- package/dist/cjs/algorithms/aes-gcm.js.map +0 -1
- package/dist/cjs/algorithms/crypto-algorithm.js +0 -13
- package/dist/cjs/algorithms/crypto-algorithm.js.map +0 -1
- package/dist/cjs/algorithms/ecdsa.js +0 -352
- package/dist/cjs/algorithms/ecdsa.js.map +0 -1
- package/dist/cjs/algorithms/eddsa.js +0 -325
- package/dist/cjs/algorithms/eddsa.js.map +0 -1
- package/dist/cjs/algorithms/sha-2.js +0 -119
- package/dist/cjs/algorithms/sha-2.js.map +0 -1
- package/dist/cjs/index.js +0 -41
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/jose/jwe.js +0 -3
- package/dist/cjs/jose/jwe.js.map +0 -1
- package/dist/cjs/jose/jwk.js +0 -278
- package/dist/cjs/jose/jwk.js.map +0 -1
- package/dist/cjs/jose/jws.js +0 -3
- package/dist/cjs/jose/jws.js.map +0 -1
- package/dist/cjs/jose/jwt.js +0 -3
- package/dist/cjs/jose/jwt.js.map +0 -1
- package/dist/cjs/jose/utils.js +0 -60
- package/dist/cjs/jose/utils.js.map +0 -1
- package/dist/cjs/local-key-manager.js +0 -521
- package/dist/cjs/local-key-manager.js.map +0 -1
- package/dist/cjs/package.json +0 -1
- package/dist/cjs/primitives/aes-ctr.js +0 -398
- package/dist/cjs/primitives/aes-ctr.js.map +0 -1
- package/dist/cjs/primitives/aes-gcm.js +0 -425
- package/dist/cjs/primitives/aes-gcm.js.map +0 -1
- package/dist/cjs/primitives/concat-kdf.js +0 -215
- package/dist/cjs/primitives/concat-kdf.js.map +0 -1
- package/dist/cjs/primitives/ed25519.js +0 -651
- package/dist/cjs/primitives/ed25519.js.map +0 -1
- package/dist/cjs/primitives/pbkdf2.js +0 -120
- package/dist/cjs/primitives/pbkdf2.js.map +0 -1
- package/dist/cjs/primitives/secp256k1.js +0 -958
- package/dist/cjs/primitives/secp256k1.js.map +0 -1
- package/dist/cjs/primitives/secp256r1.js +0 -959
- package/dist/cjs/primitives/secp256r1.js.map +0 -1
- package/dist/cjs/primitives/sha256.js +0 -93
- package/dist/cjs/primitives/sha256.js.map +0 -1
- package/dist/cjs/primitives/x25519.js +0 -498
- package/dist/cjs/primitives/x25519.js.map +0 -1
- package/dist/cjs/primitives/xchacha20-poly1305.js +0 -340
- package/dist/cjs/primitives/xchacha20-poly1305.js.map +0 -1
- package/dist/cjs/primitives/xchacha20.js +0 -316
- package/dist/cjs/primitives/xchacha20.js.map +0 -1
- package/dist/cjs/types/cipher.js +0 -3
- package/dist/cjs/types/cipher.js.map +0 -1
- package/dist/cjs/types/crypto-api.js +0 -3
- package/dist/cjs/types/crypto-api.js.map +0 -1
- package/dist/cjs/types/hasher.js +0 -3
- package/dist/cjs/types/hasher.js.map +0 -1
- package/dist/cjs/types/identifier.js +0 -3
- package/dist/cjs/types/identifier.js.map +0 -1
- package/dist/cjs/types/key-compressor.js +0 -3
- package/dist/cjs/types/key-compressor.js.map +0 -1
- package/dist/cjs/types/key-converter.js +0 -3
- package/dist/cjs/types/key-converter.js.map +0 -1
- package/dist/cjs/types/key-deriver.js +0 -3
- package/dist/cjs/types/key-deriver.js.map +0 -1
- package/dist/cjs/types/key-generator.js +0 -3
- package/dist/cjs/types/key-generator.js.map +0 -1
- package/dist/cjs/types/key-io.js +0 -3
- package/dist/cjs/types/key-io.js.map +0 -1
- package/dist/cjs/types/key-wrapper.js +0 -3
- package/dist/cjs/types/key-wrapper.js.map +0 -1
- package/dist/cjs/types/params-direct.js +0 -3
- package/dist/cjs/types/params-direct.js.map +0 -1
- package/dist/cjs/types/params-enclosed.js +0 -3
- package/dist/cjs/types/params-enclosed.js.map +0 -1
- package/dist/cjs/types/params-kms.js +0 -3
- package/dist/cjs/types/params-kms.js.map +0 -1
- package/dist/cjs/types/signer.js +0 -3
- package/dist/cjs/types/signer.js.map +0 -1
- package/dist/cjs/utils.js +0 -173
- package/dist/cjs/utils.js.map +0 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import type { Jwk } from '../jose/jwk.js';
|
|
2
|
+
import type { UnwrapKeyParams, WrapKeyParams } from '../types/params-direct.js';
|
|
3
|
+
|
|
4
|
+
import { getWebcryptoSubtle } from '@noble/ciphers/webcrypto';
|
|
5
|
+
|
|
6
|
+
import { Convert } from '@enbox/common';
|
|
7
|
+
import { computeJwkThumbprint, isOctPrivateJwk } from '../jose/jwk.js';
|
|
8
|
+
import { CryptoError, CryptoErrorCode } from '../crypto-error.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Constant defining the AES key length values in bits.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* NIST publication FIPS 197 states:
|
|
15
|
+
* > The AES algorithm is capable of using cryptographic keys of 128, 192, and 256 bits to encrypt
|
|
16
|
+
* > and decrypt data in blocks of 128 bits.
|
|
17
|
+
*
|
|
18
|
+
* This implementation does not support key lengths that are different from the three values
|
|
19
|
+
* defined by this constant.
|
|
20
|
+
*
|
|
21
|
+
* @see {@link https://doi.org/10.6028/NIST.FIPS.197-upd1 | NIST FIPS 197}
|
|
22
|
+
*/
|
|
23
|
+
const AES_KEY_LENGTHS = [128, 192, 256] as const;
|
|
24
|
+
|
|
25
|
+
export class AesKw {
|
|
26
|
+
/**
|
|
27
|
+
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* This method takes a symmetric key represented as a byte array (Uint8Array) and
|
|
31
|
+
* converts it into a JWK object for use with AES (Advanced Encryption Standard)
|
|
32
|
+
* for key wrapping. The conversion process involves encoding the key into
|
|
33
|
+
* base64url format and setting the appropriate JWK parameters.
|
|
34
|
+
*
|
|
35
|
+
* The resulting JWK object includes the following properties:
|
|
36
|
+
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
|
|
37
|
+
* - `k`: The symmetric key, base64url-encoded.
|
|
38
|
+
* - `kid`: Key ID, generated based on the JWK thumbprint.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
|
|
43
|
+
* const privateKey = await AesKw.bytesToPrivateKey({ privateKeyBytes });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @param params - The parameters for the symmetric key conversion.
|
|
47
|
+
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
|
|
48
|
+
*
|
|
49
|
+
* @returns A Promise that resolves to the symmetric key in JWK format.
|
|
50
|
+
*/
|
|
51
|
+
public static async bytesToPrivateKey({ privateKeyBytes }: {
|
|
52
|
+
privateKeyBytes: Uint8Array;
|
|
53
|
+
}): Promise<Jwk> {
|
|
54
|
+
// Construct the private key in JWK format.
|
|
55
|
+
const privateKey: Jwk = {
|
|
56
|
+
k : Convert.uint8Array(privateKeyBytes).toBase64Url(),
|
|
57
|
+
kty : 'oct'
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Compute the JWK thumbprint and set as the key ID.
|
|
61
|
+
privateKey.kid = await computeJwkThumbprint({ jwk: privateKey });
|
|
62
|
+
|
|
63
|
+
// Add algorithm identifier based on key length.
|
|
64
|
+
const lengthInBits = privateKeyBytes.length * 8;
|
|
65
|
+
privateKey.alg = { 128: 'A128KW', 192: 'A192KW', 256: 'A256KW' }[lengthInBits];
|
|
66
|
+
|
|
67
|
+
return privateKey;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Generates a symmetric key for AES for key wrapping in JSON Web Key (JWK) format.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* This method creates a new symmetric key of a specified length suitable for use with
|
|
75
|
+
* AES key wrapping. It uses cryptographically secure random number generation to
|
|
76
|
+
* ensure the uniqueness and security of the key. The generated key adheres to the JWK
|
|
77
|
+
* format, making it compatible with common cryptographic standards and easy to use in
|
|
78
|
+
* various cryptographic processes.
|
|
79
|
+
*
|
|
80
|
+
* The generated key includes the following components:
|
|
81
|
+
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
|
|
82
|
+
* - `k`: The symmetric key component, base64url-encoded.
|
|
83
|
+
* - `kid`: Key ID, generated based on the JWK thumbprint.
|
|
84
|
+
* - `alg`: Algorithm, set to 'A128KW', 'A192KW', or 'A256KW' for AES Key Wrap with the
|
|
85
|
+
* specified key length.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
|
|
90
|
+
* const privateKey = await AesKw.generateKey({ length });
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @param params - The parameters for the key generation.
|
|
94
|
+
* @param params.length - The length of the key in bits. Common lengths are 128, 192, and 256 bits.
|
|
95
|
+
*
|
|
96
|
+
* @returns A Promise that resolves to the generated symmetric key in JWK format.
|
|
97
|
+
*/
|
|
98
|
+
public static async generateKey({ length }: {
|
|
99
|
+
length: typeof AES_KEY_LENGTHS[number];
|
|
100
|
+
}): Promise<Jwk> {
|
|
101
|
+
// Validate the key length.
|
|
102
|
+
if (!(AES_KEY_LENGTHS as readonly number[]).includes(length)) {
|
|
103
|
+
throw new RangeError(`The key length is invalid: Must be ${AES_KEY_LENGTHS.join(', ')} bits`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Get the Web Crypto API interface.
|
|
107
|
+
const webCrypto = getWebcryptoSubtle() as SubtleCrypto;
|
|
108
|
+
|
|
109
|
+
// Generate a random private key.
|
|
110
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#usage_notes for
|
|
111
|
+
// an explanation for why Web Crypto generateKey() is used instead of getRandomValues().
|
|
112
|
+
const webCryptoKey = await webCrypto.generateKey( { name: 'AES-KW', length }, true, ['wrapKey', 'unwrapKey']);
|
|
113
|
+
|
|
114
|
+
// Export the private key in JWK format.
|
|
115
|
+
const { ext, key_ops, ...privateKey } = await webCrypto.exportKey('jwk', webCryptoKey) as Jwk;
|
|
116
|
+
|
|
117
|
+
// Compute the JWK thumbprint and set as the key ID.
|
|
118
|
+
privateKey.kid = await computeJwkThumbprint({ jwk: privateKey });
|
|
119
|
+
|
|
120
|
+
return privateKey;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
|
|
125
|
+
*
|
|
126
|
+
* @remarks
|
|
127
|
+
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
|
|
128
|
+
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
|
|
129
|
+
* encoding, into a byte array.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* const privateKey = { ... }; // A symmetric key in JWK format
|
|
134
|
+
* const privateKeyBytes = await AesKw.privateKeyToBytes({ privateKey });
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @param params - The parameters for the symmetric key conversion.
|
|
138
|
+
* @param params.privateKey - The symmetric key in JWK format.
|
|
139
|
+
*
|
|
140
|
+
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
|
|
141
|
+
*/
|
|
142
|
+
public static async privateKeyToBytes({ privateKey }: {
|
|
143
|
+
privateKey: Jwk;
|
|
144
|
+
}): Promise<Uint8Array> {
|
|
145
|
+
// Verify the provided JWK represents a valid oct private key.
|
|
146
|
+
if (!isOctPrivateJwk(privateKey)) {
|
|
147
|
+
throw new Error(`AesKw: The provided key is not a valid oct private key.`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Decode the provided private key to bytes.
|
|
151
|
+
const privateKeyBytes = Convert.base64Url(privateKey.k).toUint8Array();
|
|
152
|
+
|
|
153
|
+
return privateKeyBytes;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public static async unwrapKey({ wrappedKeyBytes, wrappedKeyAlgorithm, decryptionKey }:
|
|
157
|
+
UnwrapKeyParams
|
|
158
|
+
): Promise<Jwk> {
|
|
159
|
+
if (!('alg' in decryptionKey && decryptionKey.alg)) {
|
|
160
|
+
throw new CryptoError(CryptoErrorCode.InvalidJwk, `The decryption key is missing the 'alg' property.`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!['A128KW', 'A192KW', 'A256KW'].includes(decryptionKey.alg)) {
|
|
164
|
+
throw new CryptoError(CryptoErrorCode.AlgorithmNotSupported, `The 'decryptionKey' algorithm is not supported: ${decryptionKey.alg}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Get the Web Crypto API interface.
|
|
168
|
+
const webCrypto = getWebcryptoSubtle() as SubtleCrypto;
|
|
169
|
+
|
|
170
|
+
// Import the decryption key for use with the Web Crypto API.
|
|
171
|
+
const decryptionCryptoKey = await webCrypto.importKey(
|
|
172
|
+
'jwk', // key format
|
|
173
|
+
decryptionKey as JsonWebKey, // key data
|
|
174
|
+
{ name: 'AES-KW' }, // algorithm identifier
|
|
175
|
+
true, // key is extractable
|
|
176
|
+
['unwrapKey'] // key usages
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// Map the private key's JOSE algorithm name to the Web Crypto API algorithm identifier.
|
|
180
|
+
const webCryptoAlgorithm = {
|
|
181
|
+
A128KW : 'AES-KW', A192KW : 'AES-KW', A256KW : 'AES-KW',
|
|
182
|
+
A128GCM : 'AES-GCM', A192GCM : 'AES-GCM', A256GCM : 'AES-GCM',
|
|
183
|
+
}[wrappedKeyAlgorithm];
|
|
184
|
+
|
|
185
|
+
if (!webCryptoAlgorithm) {
|
|
186
|
+
throw new CryptoError(CryptoErrorCode.AlgorithmNotSupported, `The 'wrappedKeyAlgorithm' is not supported: ${wrappedKeyAlgorithm}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Unwrap the key using the Web Crypto API.
|
|
190
|
+
const unwrappedCryptoKey = await webCrypto.unwrapKey(
|
|
191
|
+
'raw', // output format
|
|
192
|
+
wrappedKeyBytes.buffer, // key to unwrap
|
|
193
|
+
decryptionCryptoKey, // unwrapping key
|
|
194
|
+
'AES-KW', // algorithm identifier
|
|
195
|
+
{ name: webCryptoAlgorithm }, // unwrapped key algorithm identifier
|
|
196
|
+
true, // key is extractable
|
|
197
|
+
['unwrapKey'] // key usages
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Export the unwrapped key in JWK format.
|
|
201
|
+
const { ext, key_ops, ...unwrappedJsonWebKey } = await webCrypto.exportKey('jwk', unwrappedCryptoKey);
|
|
202
|
+
const unwrappedKey = unwrappedJsonWebKey as Jwk;
|
|
203
|
+
|
|
204
|
+
// Compute the JWK thumbprint and set as the key ID.
|
|
205
|
+
unwrappedKey.kid = await computeJwkThumbprint({ jwk: unwrappedKey });
|
|
206
|
+
|
|
207
|
+
return unwrappedKey;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
public static async wrapKey({ unwrappedKey, encryptionKey }:
|
|
211
|
+
WrapKeyParams
|
|
212
|
+
): Promise<Uint8Array> {
|
|
213
|
+
if (!('alg' in encryptionKey && encryptionKey.alg)) {
|
|
214
|
+
throw new CryptoError(CryptoErrorCode.InvalidJwk, `The encryption key is missing the 'alg' property.`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!['A128KW', 'A192KW', 'A256KW'].includes(encryptionKey.alg)) {
|
|
218
|
+
throw new CryptoError(CryptoErrorCode.AlgorithmNotSupported, `The 'encryptionKey' algorithm is not supported: ${encryptionKey.alg}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!('alg' in unwrappedKey && unwrappedKey.alg)) {
|
|
222
|
+
throw new CryptoError(CryptoErrorCode.InvalidJwk, `The private key to wrap is missing the 'alg' property.`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Get the Web Crypto API interface.
|
|
226
|
+
const webCrypto = getWebcryptoSubtle() as SubtleCrypto;
|
|
227
|
+
|
|
228
|
+
// Import the encryption key for use with the Web Crypto API.
|
|
229
|
+
const encryptionCryptoKey = await webCrypto.importKey(
|
|
230
|
+
'jwk', // key format
|
|
231
|
+
encryptionKey as JsonWebKey, // key data
|
|
232
|
+
{ name: 'AES-KW' }, // algorithm identifier
|
|
233
|
+
true, // key is extractable
|
|
234
|
+
['wrapKey'] // key usages
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
// Map the private key's JOSE algorithm name to the Web Crypto API algorithm identifier.
|
|
238
|
+
const webCryptoAlgorithm = {
|
|
239
|
+
A128KW : 'AES-KW', A192KW : 'AES-KW', A256KW : 'AES-KW',
|
|
240
|
+
A128GCM : 'AES-GCM', A192GCM : 'AES-GCM', A256GCM : 'AES-GCM',
|
|
241
|
+
}[unwrappedKey.alg];
|
|
242
|
+
|
|
243
|
+
if (!webCryptoAlgorithm) {
|
|
244
|
+
throw new CryptoError(CryptoErrorCode.AlgorithmNotSupported, `The 'unwrappedKey' algorithm is not supported: ${unwrappedKey.alg}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Import the private key to wrap for use with the Web Crypto API.
|
|
248
|
+
const unwrappedCryptoKey = await webCrypto.importKey(
|
|
249
|
+
'jwk', // key format
|
|
250
|
+
unwrappedKey as JsonWebKey, // key data
|
|
251
|
+
{ name: webCryptoAlgorithm }, // algorithm identifier
|
|
252
|
+
true, // key is extractable
|
|
253
|
+
['unwrapKey'] // key usages
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
// Wrap the key using the Web Crypto API.
|
|
257
|
+
const wrappedKeyBuffer = await webCrypto.wrapKey(
|
|
258
|
+
'raw', // output format
|
|
259
|
+
unwrappedCryptoKey, // key to wrap
|
|
260
|
+
encryptionCryptoKey, // wrapping key
|
|
261
|
+
'AES-KW' // algorithm identifier
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
// Convert from ArrayBuffer to Uint8Array.
|
|
265
|
+
const wrappedKeyBytes = new Uint8Array(wrappedKeyBuffer);
|
|
266
|
+
|
|
267
|
+
return wrappedKeyBytes;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { TypedArray } from '@noble/hashes/utils';
|
|
2
|
+
|
|
3
|
+
import { concatBytes } from '@noble/hashes/utils';
|
|
1
4
|
import { sha256 } from '@noble/hashes/sha256';
|
|
2
5
|
import { Convert, universalTypeOf } from '@enbox/common';
|
|
3
|
-
import { TypedArray, concatBytes } from '@noble/hashes/utils';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* ConcatKDF FixedInfo Parameters.
|
|
@@ -45,7 +47,7 @@ export type ConcatKdfFixedInfo = {
|
|
|
45
47
|
* to the key agreement.
|
|
46
48
|
*/
|
|
47
49
|
suppPrivInfo?: string | TypedArray;
|
|
48
|
-
}
|
|
50
|
+
};
|
|
49
51
|
|
|
50
52
|
/**
|
|
51
53
|
* An implementation of the Concatenation Key Derivation Function (ConcatKDF)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Convert } from '@enbox/common';
|
|
2
|
-
import { ed25519,
|
|
2
|
+
import { ed25519, edwardsToMontgomeryPriv, edwardsToMontgomeryPub, x25519 } from '@noble/curves/ed25519';
|
|
3
3
|
|
|
4
4
|
import type { Jwk } from '../jose/jwk.js';
|
|
5
5
|
import type { ComputePublicKeyParams, GetPublicKeyParams, SignParams, VerifyParams } from '../types/params-direct.js';
|
|
@@ -86,7 +86,7 @@ export class Ed25519 {
|
|
|
86
86
|
privateKeyBytes: Uint8Array;
|
|
87
87
|
}): Promise<Jwk> {
|
|
88
88
|
// Derive the public key from the private key.
|
|
89
|
-
const publicKeyBytes
|
|
89
|
+
const publicKeyBytes = ed25519.getPublicKey(privateKeyBytes);
|
|
90
90
|
|
|
91
91
|
// Construct the private key in JWK format.
|
|
92
92
|
const privateKey: Jwk = {
|
|
@@ -167,10 +167,10 @@ export class Ed25519 {
|
|
|
167
167
|
ComputePublicKeyParams
|
|
168
168
|
): Promise<Jwk> {
|
|
169
169
|
// Convert the provided private key to a byte array.
|
|
170
|
-
const privateKeyBytes
|
|
170
|
+
const privateKeyBytes = await Ed25519.privateKeyToBytes({ privateKey: key });
|
|
171
171
|
|
|
172
172
|
// Derive the public key from the private key.
|
|
173
|
-
const publicKeyBytes
|
|
173
|
+
const publicKeyBytes = ed25519.getPublicKey(privateKeyBytes);
|
|
174
174
|
|
|
175
175
|
// Construct the public key in JWK format.
|
|
176
176
|
const publicKey: Jwk = {
|
|
@@ -355,7 +355,7 @@ export class Ed25519 {
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
// Remove the private key property ('d') and make a shallow copy of the provided key.
|
|
358
|
-
|
|
358
|
+
const { d, ...publicKey } = key;
|
|
359
359
|
|
|
360
360
|
// If the key ID is undefined, set it to the JWK thumbprint.
|
|
361
361
|
publicKey.kid ??= await computeJwkThumbprint({ jwk: publicKey });
|
|
@@ -502,7 +502,7 @@ export class Ed25519 {
|
|
|
502
502
|
// Check if points are on the Twisted Edwards curve.
|
|
503
503
|
point.assertValidity();
|
|
504
504
|
|
|
505
|
-
} catch
|
|
505
|
+
} catch {
|
|
506
506
|
return false;
|
|
507
507
|
}
|
|
508
508
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { DeriveKeyBytesParams } from '../types/params-direct.js';
|
|
2
|
+
|
|
3
|
+
import { getWebcryptoSubtle } from '@noble/ciphers/webcrypto';
|
|
4
|
+
|
|
5
|
+
import { Convert } from '@enbox/common';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The object that should be passed into `Hkdf.deriveKeyBytes()`, when using the HKDF algorithm.
|
|
9
|
+
*/
|
|
10
|
+
export type HkdfParams = {
|
|
11
|
+
/**
|
|
12
|
+
* A string representing the digest algorithm to use. This may be one of:
|
|
13
|
+
* - 'SHA-256'
|
|
14
|
+
* - 'SHA-384'
|
|
15
|
+
* - 'SHA-512'
|
|
16
|
+
*/
|
|
17
|
+
hash: 'SHA-256' | 'SHA-384' | 'SHA-512';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The salt value to use in the derivation process.
|
|
21
|
+
*
|
|
22
|
+
* Ideally, the salt is a random or pseudo-random value with the same length as the output of the
|
|
23
|
+
* digest function. Unlike the input key material passed into deriveKey(), salt does not need to
|
|
24
|
+
* be kept secret.
|
|
25
|
+
*
|
|
26
|
+
* Note: The {@link https://datatracker.ietf.org/doc/html/rfc5869 | HKDF specification} states
|
|
27
|
+
* that adding salt "adds significantly to the strength of HKDF".
|
|
28
|
+
*/
|
|
29
|
+
salt: string | Uint8Array;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Optional application-specific information to use in the HKDF.
|
|
33
|
+
*
|
|
34
|
+
* If given, this value is used to bind the derived key to application-specific contextual
|
|
35
|
+
* information. This makes it possible to derive different keys for different contexts while using
|
|
36
|
+
* the same input key material.
|
|
37
|
+
*
|
|
38
|
+
* If not provided, the `info` value is set to an empty array.
|
|
39
|
+
*
|
|
40
|
+
* Note: It is important that the `info` value be independent and unrelated to the input key
|
|
41
|
+
* material.
|
|
42
|
+
*/
|
|
43
|
+
info?: string | Uint8Array,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The `Hkdf` class provides an interface for HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
|
|
48
|
+
* as defined in RFC 5869.
|
|
49
|
+
*
|
|
50
|
+
* Note: The `baseKeyBytes` that will be the input key material for HKDF should be a high-entropy secret
|
|
51
|
+
* value, such as a cryptographic key. It should be kept confidential and not be derived from a
|
|
52
|
+
* low-entropy value, such as a password.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* const info = new Uint8Array([...]);
|
|
57
|
+
* const derivedKeyBytes = await Hkdf.deriveKeyBytes({
|
|
58
|
+
* baseKeyBytes: new Uint8Array([...]), // Input keying material
|
|
59
|
+
* hash: 'SHA-256', // The hash function to use ('SHA-256', 'SHA-384', 'SHA-512')
|
|
60
|
+
* salt: new Uint8Array([...]), // The salt value
|
|
61
|
+
* info: new Uint8Array([...]), // Optional application-specific information
|
|
62
|
+
* length: 256 // The length of the derived key in bits
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export class Hkdf {
|
|
67
|
+
/**
|
|
68
|
+
* Derives a key using the HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
|
|
69
|
+
*
|
|
70
|
+
* This method generates a derived key using a hash function from input keying material given as
|
|
71
|
+
* `baseKeyBytes`. The length of the derived key can be specified. Optionally, it can also use a salt
|
|
72
|
+
* and info for the derivation process.
|
|
73
|
+
*
|
|
74
|
+
* HKDF is useful in various cryptographic applications and protocols, especially when
|
|
75
|
+
* there's a need to derive multiple keys from a single source of key material.
|
|
76
|
+
*
|
|
77
|
+
* Note: The `baseKeyBytes` that will be the input key material for HKDF should be a high-entropy
|
|
78
|
+
* secret value, such as a cryptographic key. It should be kept confidential and not be derived
|
|
79
|
+
* from a low-entropy value, such as a password.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const info = new Uint8Array([...]);
|
|
84
|
+
* const derivedKeyBytes = await Hkdf.deriveKeyBytes({
|
|
85
|
+
* baseKeyBytes: new Uint8Array([...]), // Input keying material
|
|
86
|
+
* hash: 'SHA-256', // The hash function to use ('SHA-256', 'SHA-384', 'SHA-512')
|
|
87
|
+
* salt: new Uint8Array([...]), // The salt value
|
|
88
|
+
* info: new Uint8Array([...]), // Optional application-specific information
|
|
89
|
+
* length: 256 // The length of the derived key in bits
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @param params - The parameters for key derivation.
|
|
94
|
+
* @returns A Promise that resolves to the derived key as a byte array.
|
|
95
|
+
*/
|
|
96
|
+
public static async deriveKeyBytes({ baseKeyBytes, length, hash, salt, info = new Uint8Array() }:
|
|
97
|
+
DeriveKeyBytesParams & HkdfParams
|
|
98
|
+
): Promise<Uint8Array> {
|
|
99
|
+
// Get the Web Crypto API interface.
|
|
100
|
+
const webCrypto = getWebcryptoSubtle() as SubtleCrypto;
|
|
101
|
+
|
|
102
|
+
// Import the baseKeyBytes into the Web Crypto API to use for the key derivation operation.
|
|
103
|
+
const webCryptoKey = await webCrypto.importKey('raw', baseKeyBytes, { name: 'HKDF' }, false, ['deriveBits']);
|
|
104
|
+
|
|
105
|
+
// Convert the salt and info to Uint8Array if they are provided as strings.
|
|
106
|
+
const saltBytes = typeof salt === 'string' ? Convert.string(salt).toUint8Array() : salt;
|
|
107
|
+
const infoBytes = typeof info === 'string' ? Convert.string(info).toUint8Array() : info;
|
|
108
|
+
|
|
109
|
+
// Derive the bytes using the Web Crypto API.
|
|
110
|
+
const derivedKeyBuffer = await webCrypto.deriveBits(
|
|
111
|
+
{ name: 'HKDF', hash, salt: saltBytes, info: infoBytes },
|
|
112
|
+
webCryptoKey,
|
|
113
|
+
length
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// Convert from ArrayBuffer to Uint8Array.
|
|
117
|
+
const derivedKeyBytes = new Uint8Array(derivedKeyBuffer);
|
|
118
|
+
|
|
119
|
+
return derivedKeyBytes;
|
|
120
|
+
}
|
|
121
|
+
}
|
package/src/primitives/pbkdf2.ts
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
|
+
import type { DeriveKeyBytesParams } from '../types/params-direct.js';
|
|
2
|
+
|
|
3
|
+
import { getWebcryptoSubtle } from '@noble/ciphers/webcrypto';
|
|
4
|
+
|
|
1
5
|
import { crypto } from '@noble/hashes/crypto';
|
|
2
6
|
|
|
7
|
+
/**
|
|
8
|
+
* The object that should be passed into `Pbkdf2.deriveKeyBytes()`, when using the PBKDF2 algorithm.
|
|
9
|
+
*/
|
|
10
|
+
export interface Pbkdf2Params {
|
|
11
|
+
/**
|
|
12
|
+
* A string representing the digest algorithm to use. This may be one of:
|
|
13
|
+
* - 'SHA-256'
|
|
14
|
+
* - 'SHA-384'
|
|
15
|
+
* - 'SHA-512'
|
|
16
|
+
*/
|
|
17
|
+
hash: 'SHA-256' | 'SHA-384' | 'SHA-512';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The salt value to use in the derivation process, as a Uint8Array. This should be a random or
|
|
21
|
+
* pseudo-random value of at least 16 bytes. Unlike the `password`, `salt` does not need to be
|
|
22
|
+
* kept secret.
|
|
23
|
+
*/
|
|
24
|
+
salt: Uint8Array;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A `Number` representing the number of iterations the hash function will be executed in
|
|
28
|
+
* `deriveKey()`. This impacts the computational cost of the `deriveKey()` operation, making it
|
|
29
|
+
* more resistant to dictionary attacks. The higher the number, the more secure, but also slower,
|
|
30
|
+
* the operation. Choose a value that balances security needs and performance for your
|
|
31
|
+
* application.
|
|
32
|
+
*/
|
|
33
|
+
iterations: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
3
36
|
/**
|
|
4
37
|
* The object that should be passed into `Pbkdf2.deriveKey()`, when using the PBKDF2 algorithm.
|
|
5
38
|
*/
|
|
@@ -119,4 +152,62 @@ export class Pbkdf2 {
|
|
|
119
152
|
|
|
120
153
|
return derivedKey;
|
|
121
154
|
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Derives cryptographic key bytes from base key material using the PBKDF2 algorithm.
|
|
158
|
+
*
|
|
159
|
+
* @remarks
|
|
160
|
+
* This method is similar to {@link Pbkdf2.deriveKey | `deriveKey()`} but accepts
|
|
161
|
+
* raw key bytes (`baseKeyBytes`) instead of a password. It is intended for use cases
|
|
162
|
+
* where the input key material is already available as a byte array.
|
|
163
|
+
*
|
|
164
|
+
* Notes:
|
|
165
|
+
* - The `baseKeyBytes` that will be the input key material for PBKDF2 is expected to be a
|
|
166
|
+
* low-entropy value, such as a password or passphrase. It should be kept confidential.
|
|
167
|
+
* - In 2023,
|
|
168
|
+
* {@link https://web.archive.org/web/20230123232056/https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
|
|
169
|
+
* | OWASP recommended}
|
|
170
|
+
* a minimum of 600,000 iterations for PBKDF2-HMAC-SHA256 and 210,000 for PBKDF2-HMAC-SHA512.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* const derivedKeyBytes = await Pbkdf2.deriveKeyBytes({
|
|
175
|
+
* baseKeyBytes: new TextEncoder().encode('password'),
|
|
176
|
+
* hash: 'SHA-256',
|
|
177
|
+
* salt: new Uint8Array([...]),
|
|
178
|
+
* iterations: 600_000,
|
|
179
|
+
* length: 256
|
|
180
|
+
* });
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @param params - The parameters for key derivation.
|
|
184
|
+
* @returns A Promise that resolves to the derived key as a byte array.
|
|
185
|
+
*/
|
|
186
|
+
public static async deriveKeyBytes({ baseKeyBytes, hash, salt, iterations, length }:
|
|
187
|
+
DeriveKeyBytesParams & Pbkdf2Params
|
|
188
|
+
): Promise<Uint8Array> {
|
|
189
|
+
// Get the Web Crypto API interface.
|
|
190
|
+
const webCrypto = getWebcryptoSubtle() as SubtleCrypto;
|
|
191
|
+
|
|
192
|
+
// Import the password as a raw key for use with the Web Crypto API.
|
|
193
|
+
const webCryptoKey = await webCrypto.importKey(
|
|
194
|
+
'raw', // key format is raw bytes
|
|
195
|
+
baseKeyBytes, // key data to import
|
|
196
|
+
{ name: 'PBKDF2' }, // algorithm identifier
|
|
197
|
+
false, // key is not extractable
|
|
198
|
+
['deriveBits'] // key usages
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Derive the bytes using the Web Crypto API.
|
|
202
|
+
const derivedKeyBuffer = await webCrypto.deriveBits(
|
|
203
|
+
{ name: 'PBKDF2', hash, salt, iterations },
|
|
204
|
+
webCryptoKey,
|
|
205
|
+
length
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// Convert from ArrayBuffer to Uint8Array.
|
|
209
|
+
const derivedKeyBytes = new Uint8Array(derivedKeyBuffer);
|
|
210
|
+
|
|
211
|
+
return derivedKeyBytes;
|
|
212
|
+
}
|
|
122
213
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { AffinePoint } from '@noble/curves/abstract/weierstrass';
|
|
2
2
|
|
|
3
3
|
import { Convert } from '@enbox/common';
|
|
4
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
5
|
-
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
6
4
|
import { numberToBytesBE } from '@noble/curves/abstract/utils';
|
|
5
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
6
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
7
7
|
|
|
8
8
|
import type { Jwk } from '../jose/jwk.js';
|
|
9
9
|
import type { ComputePublicKeyParams, GetPublicKeyParams, SignParams, VerifyParams } from '../types/params-direct.js';
|
|
@@ -304,7 +304,7 @@ export class Secp256k1 {
|
|
|
304
304
|
ComputePublicKeyParams
|
|
305
305
|
): Promise<Jwk> {
|
|
306
306
|
// Convert the provided private key to a byte array.
|
|
307
|
-
const privateKeyBytes
|
|
307
|
+
const privateKeyBytes = await Secp256k1.privateKeyToBytes({ privateKey: key });
|
|
308
308
|
|
|
309
309
|
// Get the elliptic curve point (x and y coordinates) for the provided private key.
|
|
310
310
|
const point = await Secp256k1.getCurvePoint({ keyBytes: privateKeyBytes });
|
|
@@ -357,7 +357,7 @@ export class Secp256k1 {
|
|
|
357
357
|
// into a single byte array.
|
|
358
358
|
const compactSignature = signatureObject.toCompactRawBytes();
|
|
359
359
|
|
|
360
|
-
return
|
|
360
|
+
return compactSignature;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
/**
|
|
@@ -468,7 +468,7 @@ export class Secp256k1 {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
// Remove the private key property ('d') and make a shallow copy of the provided key.
|
|
471
|
-
|
|
471
|
+
const { d, ...publicKey } = key;
|
|
472
472
|
|
|
473
473
|
// If the key ID is undefined, set it to the JWK thumbprint.
|
|
474
474
|
publicKey.kid ??= await computeJwkThumbprint({ jwk: publicKey });
|
|
@@ -732,7 +732,7 @@ export class Secp256k1 {
|
|
|
732
732
|
// Check if points are on the Short Weierstrass curve.
|
|
733
733
|
point.assertValidity();
|
|
734
734
|
|
|
735
|
-
} catch
|
|
735
|
+
} catch {
|
|
736
736
|
return false;
|
|
737
737
|
}
|
|
738
738
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { AffinePoint } from '@noble/curves/abstract/weierstrass';
|
|
2
2
|
|
|
3
3
|
import { Convert } from '@enbox/common';
|
|
4
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
5
|
-
import { secp256r1 } from '@noble/curves/p256';
|
|
6
4
|
import { numberToBytesBE } from '@noble/curves/abstract/utils';
|
|
5
|
+
import { secp256r1 } from '@noble/curves/p256';
|
|
6
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
7
7
|
|
|
8
8
|
import type { Jwk } from '../jose/jwk.js';
|
|
9
9
|
import type { ComputePublicKeyParams, GetPublicKeyParams, SignParams, VerifyParams } from '../types/params-direct.js';
|
|
@@ -304,7 +304,7 @@ export class Secp256r1 {
|
|
|
304
304
|
ComputePublicKeyParams
|
|
305
305
|
): Promise<Jwk> {
|
|
306
306
|
// Convert the provided private key to a byte array.
|
|
307
|
-
const privateKeyBytes
|
|
307
|
+
const privateKeyBytes = await Secp256r1.privateKeyToBytes({ privateKey: key });
|
|
308
308
|
|
|
309
309
|
// Get the elliptic curve point (x and y coordinates) for the provided private key.
|
|
310
310
|
const point = await Secp256r1.getCurvePoint({ keyBytes: privateKeyBytes });
|
|
@@ -357,7 +357,7 @@ export class Secp256r1 {
|
|
|
357
357
|
// into a single byte array.
|
|
358
358
|
const compactSignature = signatureObject.toCompactRawBytes();
|
|
359
359
|
|
|
360
|
-
return
|
|
360
|
+
return compactSignature;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
/**
|
|
@@ -468,7 +468,7 @@ export class Secp256r1 {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
// Remove the private key property ('d') and make a shallow copy of the provided key.
|
|
471
|
-
|
|
471
|
+
const { d, ...publicKey } = key;
|
|
472
472
|
|
|
473
473
|
// If the key ID is undefined, set it to the JWK thumbprint.
|
|
474
474
|
publicKey.kid ??= await computeJwkThumbprint({ jwk: publicKey });
|
|
@@ -732,7 +732,7 @@ export class Secp256r1 {
|
|
|
732
732
|
// Check if points are on the Short Weierstrass curve.
|
|
733
733
|
point.assertValidity();
|
|
734
734
|
|
|
735
|
-
} catch
|
|
735
|
+
} catch {
|
|
736
736
|
return false;
|
|
737
737
|
}
|
|
738
738
|
|
package/src/primitives/x25519.ts
CHANGED
|
@@ -79,7 +79,7 @@ export class X25519 {
|
|
|
79
79
|
privateKeyBytes: Uint8Array;
|
|
80
80
|
}): Promise<Jwk> {
|
|
81
81
|
// Derive the public key from the private key.
|
|
82
|
-
const publicKeyBytes
|
|
82
|
+
const publicKeyBytes = x25519.getPublicKey(privateKeyBytes);
|
|
83
83
|
|
|
84
84
|
// Construct the private key in JWK format.
|
|
85
85
|
const privateKey: Jwk = {
|
|
@@ -168,7 +168,7 @@ export class X25519 {
|
|
|
168
168
|
ComputePublicKeyParams
|
|
169
169
|
): Promise<Jwk> {
|
|
170
170
|
// Convert the provided private key to a byte array.
|
|
171
|
-
const privateKeyBytes
|
|
171
|
+
const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey: key });
|
|
172
172
|
|
|
173
173
|
// Derive the public key from the private key.
|
|
174
174
|
const publicKeyBytes = x25519.getPublicKey(privateKeyBytes);
|
|
@@ -260,7 +260,7 @@ export class X25519 {
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
// Remove the private key property ('d') and make a shallow copy of the provided key.
|
|
263
|
-
|
|
263
|
+
const { d, ...publicKey } = key;
|
|
264
264
|
|
|
265
265
|
// If the key ID is undefined, set it to the JWK thumbprint.
|
|
266
266
|
publicKey.kid ??= await computeJwkThumbprint({ jwk: publicKey });
|