Add comprehensive installation and setup documentation

- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
This commit is contained in:
Dorian
2026-01-27 17:18:21 +00:00
parent a81f655133
commit 0d073fa89e
22658 changed files with 4494151 additions and 6 deletions
+398
View File
@@ -0,0 +1,398 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AesCtr = void 0;
var common_1 = require("@web5/common");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* Constant defining the AES block size in bits.
*
* @remarks
* In AES Counter (CTR) mode, the counter length must match the block size of the AES algorithm,
* which is 128 bits. NIST publication 800-38A, which provides guidelines for block cipher modes of
* operation, specifies this requirement. Maintaining a counter length of 128 bits is essential for
* the correct operation and security of AES-CTR.
*
* This implementation does not support counter lengths that are different from the value defined by
* this constant.
*
* @see {@link https://doi.org/10.6028/NIST.SP.800-38A | NIST SP 800-38A}
*/
var AES_BLOCK_SIZE = 128;
/**
* Constant defining the AES key length values in bits.
*
* @remarks
* NIST publication FIPS 197 states:
* > The AES algorithm is capable of using cryptographic keys of 128, 192, and 256 bits to encrypt
* > and decrypt data in blocks of 128 bits.
*
* This implementation does not support key lengths that are different from the three values
* defined by this constant.
*
* @see {@link https://doi.org/10.6028/NIST.FIPS.197-upd1 | NIST FIPS 197}
*/
var AES_KEY_LENGTHS = [128, 192, 256];
/**
* Constant defining the maximum length of the counter in bits.
*
* @remarks
* The rightmost bits of the counter block are used as the actual counter value, while the leftmost
* bits are used as the nonce. The maximum length of the counter is 128 bits, which is the same as
* the AES block size.
*/
var COUNTER_MAX_LENGTH = AES_BLOCK_SIZE;
/**
* The `AesCtr` class provides a comprehensive set of utilities for cryptographic operations
* using the Advanced Encryption Standard (AES) in Counter (CTR) mode. This class includes
* methods for key generation, encryption, decryption, and conversions between raw byte arrays
* and JSON Web Key (JWK) formats. It is designed to support AES-CTR, a symmetric key algorithm
* that is widely used in various cryptographic applications for its efficiency and security.
*
* AES-CTR mode operates as a stream cipher using a block cipher (AES) and is well-suited for
* scenarios where parallel processing is beneficial or where the same key is required to
* encrypt multiple data blocks. The class adheres to standard cryptographic practices, ensuring
* compatibility and security in its implementations.
*
* Key Features:
* - Key Generation: Generate AES symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using AES-CTR with the provided symmetric key.
* - Decryption: Decrypt data encrypted with AES-CTR using the corresponding symmetric key.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesCtr.generateKey({ length });
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block
* const encryptedData = await AesCtr.encrypt({
* data,
* counter,
* key: privateKey,
* length: 64 // Length of the counter in bits
* });
*
* // Decryption
* const decryptedData = await AesCtr.decrypt({
* data: encryptedData,
* counter,
* key: privateKey,
* length: 64 // Length of the counter in bits
* });
*
* // Key Conversion
* const privateKeyBytes = await AesCtr.privateKeyToBytes({ privateKey });
* ```
*/
var AesCtr = /** @class */ (function () {
function AesCtr() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a symmetric key represented as a byte array (Uint8Array) and
* converts it into a JWK object for use with AES (Advanced Encryption Standard)
* in Counter (CTR) mode. The conversion process involves encoding the key into
* base64url format and setting the appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await AesCtr.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
AesCtr.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using AES in Counter (CTR) mode.
*
* @remarks
* This method performs AES-CTR decryption on the given encrypted data using the specified key.
* Similar to the encryption process, it requires an initial counter block and the length
* of the counter block, along with the encrypted data and the decryption key. The method
* returns the decrypted data as a Uint8Array.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block used during encryption
* const key = { ... }; // A Jwk object representing the same AES key used for encryption
* const decryptedData = await AesCtr.decrypt({
* data: encryptedData,
* counter,
* key,
* length: 64 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.data - The encrypted data to decrypt, as a Uint8Array.
* @param params.counter - The initial value of the counter block.
* @param params.length - The number of bits in the counter block that are used for the actual counter.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesCtr.decrypt = function (_a) {
var key = _a.key, data = _a.data, counter = _a.counter, length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, plaintextBuffer, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initial counter block length matches the AES block size.
if (counter.byteLength !== AES_BLOCK_SIZE / 8) {
throw new TypeError("The counter must be ".concat(AES_BLOCK_SIZE, " bits in length"));
}
// Validate the length of the counter.
if (length === 0 || length > COUNTER_MAX_LENGTH) {
throw new TypeError("The 'length' property must be in the range 1 to ".concat(COUNTER_MAX_LENGTH));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-CTR' }, true, ['decrypt'])];
case 1:
webCryptoKey = _b.sent();
return [4 /*yield*/, webCrypto.decrypt({ name: 'AES-CTR', counter: counter, length: length }, webCryptoKey, data)];
case 2:
plaintextBuffer = _b.sent();
plaintext = new Uint8Array(plaintextBuffer);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Encrypts the provided data using AES in Counter (CTR) mode.
*
* @remarks
* This method performs AES-CTR encryption on the given data using the specified key.
* It requires the initial counter block and the length of the counter block, alongside
* the data and key. The method is designed to work asynchronously and returns the
* encrypted data as a Uint8Array.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await AesCtr.encrypt({
* data,
* counter,
* key,
* length: 64 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.counter - The initial value of the counter block.
* @param params.length - The number of bits in the counter block that are used for the actual counter.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesCtr.encrypt = function (_a) {
var key = _a.key, data = _a.data, counter = _a.counter, length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, ciphertextBuffer, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initial counter block value length.
if (counter.byteLength !== AES_BLOCK_SIZE / 8) {
throw new TypeError("The counter must be ".concat(AES_BLOCK_SIZE, " bits in length"));
}
// Validate the length of the counter.
if (length === 0 || length > COUNTER_MAX_LENGTH) {
throw new TypeError("The 'length' property must be in the range 1 to ".concat(COUNTER_MAX_LENGTH));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-CTR' }, true, ['encrypt', 'decrypt'])];
case 1:
webCryptoKey = _b.sent();
return [4 /*yield*/, webCrypto.encrypt({ name: 'AES-CTR', counter: counter, length: length }, webCryptoKey, data)];
case 2:
ciphertextBuffer = _b.sent();
ciphertext = new Uint8Array(ciphertextBuffer);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Generates a symmetric key for AES in Counter (CTR) mode in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key of a specified length suitable for use with
* AES-CTR encryption. It uses cryptographically secure random number generation to
* ensure the uniqueness and security of the key. The generated key adheres to the JWK
* format, making it compatible with common cryptographic standards and easy to use in
* various cryptographic processes.
*
* The generated key includes the following components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesCtr.generateKey({ length });
* ```
*
* @param params - The parameters for the key generation.
* @param params.length - The length of the key in bits. Common lengths are 128, 192, and 256 bits.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesCtr.generateKey = function (_a) {
var length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _b, ext, key_ops, privateKey, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
// Validate the key length.
if (!AES_KEY_LENGTHS.includes(length)) {
throw new RangeError("The key length is invalid: Must be ".concat(AES_KEY_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-CTR', length: length }, true, ['encrypt'])];
case 1:
webCryptoKey = _d.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_b = _d.sent(), ext = _b.ext, key_ops = _b.key_ops, privateKey = __rest(_b, ["ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_c = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_c.kid = _d.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
* encoding, into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await AesCtr.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
AesCtr.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("AesCtr: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return AesCtr;
}());
exports.AesCtr = AesCtr;
//# sourceMappingURL=aes-ctr.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-ctr.js","sourceRoot":"","sources":["../../../src/primitives/aes-ctr.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,wDAAoE;AAIpE,yCAAuE;AAEvE;;;;;;;;;;;;;GAaG;AACH,IAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;;;;;;;;GAYG;AACH,IAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAEjD;;;;;;;GAOG;AACH,IAAM,kBAAkB,GAAG,cAAc,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH;IAAA;IA8PA,CAAC;IA7PC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACiB,wBAAiB,GAArC,UAAsC,EAErC;YAFuC,eAAe,qBAAA;;;;;;wBAI/C,UAAU,GAAQ;4BACtB,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE;4BACvD,GAAG,EAAG,KAAK;yBACZ,CAAC;wBAEF,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACiB,cAAO,GAA3B,UAA4B,EAK3B;YAL6B,GAAG,SAAA,EAAE,IAAI,UAAA,EAAE,OAAO,aAAA,EAAE,MAAM,YAAA;;;;;;wBAMtD,wEAAwE;wBACxE,IAAI,OAAO,CAAC,UAAU,KAAK,cAAc,GAAG,CAAC,EAAE;4BAC7C,MAAM,IAAI,SAAS,CAAC,8BAAuB,cAAc,oBAAiB,CAAC,CAAC;yBAC7E;wBAED,sCAAsC;wBACtC,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,GAAG,kBAAkB,EAAE;4BAC/C,MAAM,IAAI,SAAS,CAAC,0DAAmD,kBAAkB,CAAE,CAAC,CAAC;yBAC9F;wBAGK,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAGlB,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAA;;wBAA5F,YAAY,GAAG,SAA6E;wBAG1E,qBAAM,SAAS,CAAC,OAAO,CAC7C,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,SAAA,EAAE,MAAM,QAAA,EAAE,EACpC,YAAY,EACZ,IAAI,CACL,EAAA;;wBAJK,eAAe,GAAG,SAIvB;wBAGK,SAAS,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC;wBAElD,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACiB,cAAO,GAA3B,UAA4B,EAK3B;YAL6B,GAAG,SAAA,EAAE,IAAI,UAAA,EAAE,OAAO,aAAA,EAAE,MAAM,YAAA;;;;;;wBAMtD,mDAAmD;wBACnD,IAAI,OAAO,CAAC,UAAU,KAAK,cAAc,GAAG,CAAC,EAAE;4BAC7C,MAAM,IAAI,SAAS,CAAC,8BAAuB,cAAc,oBAAiB,CAAC,CAAC;yBAC7E;wBAED,sCAAsC;wBACtC,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,GAAG,kBAAkB,EAAE;4BAC/C,MAAM,IAAI,SAAS,CAAC,0DAAmD,kBAAkB,CAAE,CAAC,CAAC;yBAC9F;wBAGK,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAGlB,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,EAAA;;wBAAvG,YAAY,GAAG,SAAwF;wBAGpF,qBAAM,SAAS,CAAC,OAAO,CAC9C,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,SAAA,EAAE,MAAM,QAAA,EAAE,EACpC,YAAY,EACZ,IAAI,CACL,EAAA;;wBAJK,gBAAgB,GAAG,SAIxB;wBAGK,UAAU,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;wBAEpD,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACiB,kBAAW,GAA/B,UAAgC,EAE/B;YAFiC,MAAM,YAAA;;;;;;wBAGtC,2BAA2B;wBAC3B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAa,CAAC,EAAE;4BAC5C,MAAM,IAAI,UAAU,CAAC,6CAAsC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,UAAO,CAAC,CAAC;yBAC/F;wBAGK,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAKlB,qBAAM,SAAS,CAAC,WAAW,CAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAA,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAA;;wBAA3F,YAAY,GAAG,SAA4E;wBAGzD,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,EAAA;;wBAAhF,KAAkC,SAA8C,EAA9E,GAAG,SAAA,EAAE,OAAO,aAAA,EAAK,UAAU,cAA7B,kBAA+B,CAAF;wBAEnC,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACiB,wBAAiB,GAArC,UAAsC,EAErC;YAFuC,UAAU,gBAAA;;;;gBAGhD,8DAA8D;gBAC9D,IAAI,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,EAAE;oBAChC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;iBAC7E;gBAGK,eAAe,GAAG,gBAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;gBAEvE,sBAAO,eAAe,EAAC;;;KACxB;IACH,aAAC;AAAD,CAAC,AA9PD,IA8PC;AA9PY,wBAAM"}
+425
View File
@@ -0,0 +1,425 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AesGcm = exports.AES_GCM_TAG_LENGTHS = void 0;
var common_1 = require("@web5/common");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* Const defining the AES-GCM initialization vector (IV) length in bits.
*
* @remarks
* NIST Special Publication 800-38D, Section 5.2.1.1 states that the IV length:
* > For IVs, it is recommended that implementations restrict support to the length of 96 bits, to
* > promote interoperability, efficiency, and simplicity of design.
*
* This implementation does not support IV lengths that are different from the value defined by
* this constant.
*
* @see {@link https://doi.org/10.6028/NIST.SP.800-38D | NIST SP 800-38D}
*/
var AES_GCM_IV_LENGTH = 96;
/**
* Constant defining the AES key length values in bits.
*
* @remarks
* NIST publication FIPS 197 states:
* > The AES algorithm is capable of using cryptographic keys of 128, 192, and 256 bits to encrypt
* > and decrypt data in blocks of 128 bits.
*
* This implementation does not support key lengths that are different from the three values
* defined by this constant.
*
* @see {@link https://doi.org/10.6028/NIST.FIPS.197-upd1 | NIST FIPS 197}
*/
var AES_KEY_LENGTHS = [128, 192, 256];
/**
* Constant defining the AES-GCM tag length values in bits.
*
* @remarks
* NIST Special Publication 800-38D, Section 5.2.1.2 states that the tag length:
* > may be any one of the following five values: 128, 120, 112, 104, or 96
*
* Although the NIST specification allows for tag lengths of 32 or 64 bits in certain applications,
* the use of shorter tag lengths can be problematic for GCM due to targeted forgery attacks. As a
* precaution, this implementation does not support tag lengths that are different from the five
* values defined by this constant. See Appendix C of the NIST SP 800-38D specification for
* additional guidance and details.
*
* @see {@link https://doi.org/10.6028/NIST.SP.800-38D | NIST SP 800-38D}
*/
exports.AES_GCM_TAG_LENGTHS = [96, 104, 112, 120, 128];
/**
* The `AesGcm` class provides a comprehensive set of utilities for cryptographic operations
* using the Advanced Encryption Standard (AES) in Galois/Counter Mode (GCM). This class includes
* methods for key generation, encryption, decryption, and conversions between raw byte arrays
* and JSON Web Key (JWK) formats. It is designed to support AES-GCM, a symmetric key algorithm
* that is widely used for its efficiency, security, and provision of authenticated encryption.
*
* AES-GCM is particularly favored for scenarios that require both confidentiality and integrity
* of data. It integrates the counter mode of encryption with the Galois mode of authentication,
* offering high performance and parallel processing capabilities.
*
* Key Features:
* - Key Generation: Generate AES symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using AES-GCM with the provided symmetric key.
* - Decryption: Decrypt data encrypted with AES-GCM using the corresponding symmetric key.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesGcm.generateKey({ length });
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const iv = new Uint8Array(12); // 12-byte initialization vector
* const encryptedData = await AesGcm.encrypt({
* data,
* iv,
* key: privateKey
* });
*
* // Decryption
* const decryptedData = await AesGcm.decrypt({
* data: encryptedData,
* iv,
* key: privateKey
* });
*
* // Key Conversion
* const privateKeyBytes = await AesGcm.privateKeyToBytes({ privateKey });
* ```
*/
var AesGcm = /** @class */ (function () {
function AesGcm() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a symmetric key represented as a byte array (Uint8Array) and
* converts it into a JWK object for use with AES-GCM (Advanced Encryption Standard -
* Galois/Counter Mode). The conversion process involves encoding the key into
* base64url format and setting the appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await AesGcm.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
AesGcm.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM decryption on the given encrypted data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the decrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag used when encrypting the data. If not specified, the default tag length of 128 bits is
* used.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const iv = new Uint8Array([...]); // Initialization vector used during encryption
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing the AES key
* const decryptedData = await AesGcm.decrypt({
* data: encryptedData,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.data - The encrypted data to decrypt, represented as a Uint8Array.
* @param params.iv - The initialization vector, represented as a Uint8Array.
* @param params.additionalData - Optional additional authenticated data. Optional.
* @param params.tagLength - The length of the authentication tag in bits. Optional.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesGcm.decrypt = function (_a) {
var key = _a.key, data = _a.data, iv = _a.iv, additionalData = _a.additionalData, tagLength = _a.tagLength;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, algorithm, plaintextBuffer, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initialization vector length.
if (iv.byteLength !== AES_GCM_IV_LENGTH / 8) {
throw new TypeError("The initialization vector must be ".concat(AES_GCM_IV_LENGTH, " bits in length"));
}
// Validate the tag length.
if (tagLength && !exports.AES_GCM_TAG_LENGTHS.includes(tagLength)) {
throw new RangeError("The tag length is invalid: Must be ".concat(exports.AES_GCM_TAG_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-GCM' }, true, ['decrypt'])];
case 1:
webCryptoKey = _b.sent();
algorithm = __assign(__assign({ name: 'AES-GCM', iv: iv }, (tagLength && { tagLength: tagLength })), (additionalData && { additionalData: additionalData }));
return [4 /*yield*/, webCrypto.decrypt(algorithm, webCryptoKey, data)];
case 2:
plaintextBuffer = _b.sent();
plaintext = new Uint8Array(plaintextBuffer);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Encrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM encryption on the given data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the encrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag generated in the encryption operation and used for authentication in the corresponding
* decryption. If not specified, the default tag length of 128 bits is used.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const iv = new Uint8Array([...]); // Initialization vector
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await AesGcm.encrypt({
* data,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.iv - The initialization vector, represented as a Uint8Array.
* @param params.additionalData - Optional additional authenticated data. Optional.
* @param params.tagLength - The length of the authentication tag in bits. Optional.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesGcm.encrypt = function (_a) {
var data = _a.data, iv = _a.iv, key = _a.key, additionalData = _a.additionalData, tagLength = _a.tagLength;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, algorithm, ciphertextBuffer, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initialization vector length.
if (iv.byteLength !== AES_GCM_IV_LENGTH / 8) {
throw new TypeError("The initialization vector must be ".concat(AES_GCM_IV_LENGTH, " bits in length"));
}
// Validate the tag length.
if (tagLength && !exports.AES_GCM_TAG_LENGTHS.includes(tagLength)) {
throw new RangeError("The tag length is invalid: Must be ".concat(exports.AES_GCM_TAG_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-GCM' }, true, ['encrypt'])];
case 1:
webCryptoKey = _b.sent();
algorithm = __assign(__assign({ name: 'AES-GCM', iv: iv }, (tagLength && { tagLength: tagLength })), (additionalData && { additionalData: additionalData }));
return [4 /*yield*/, webCrypto.encrypt(algorithm, webCryptoKey, data)];
case 2:
ciphertextBuffer = _b.sent();
ciphertext = new Uint8Array(ciphertextBuffer);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Generates a symmetric key for AES in Galois/Counter Mode (GCM) in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key of a specified length suitable for use with
* AES-GCM encryption. It leverages cryptographically secure random number generation
* to ensure the uniqueness and security of the key. The generated key adheres to the JWK
* format, facilitating compatibility with common cryptographic standards and ease of use
* in various cryptographic applications.
*
* The generated key includes these components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence, indicating a symmetric key.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint, providing a unique identifier.
*
* @example
* ```ts
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesGcm.generateKey({ length });
* ```
*
* @param params - The parameters for the key generation.
* @param params.length - The length of the key in bits. Common lengths are 128, 192, and 256 bits.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesGcm.generateKey = function (_a) {
var length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _b, ext, key_ops, privateKey, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
// Validate the key length.
if (!AES_KEY_LENGTHS.includes(length)) {
throw new RangeError("The key length is invalid: Must be ".concat(AES_KEY_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-GCM', length: length }, true, ['encrypt'])];
case 1:
webCryptoKey = _d.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_b = _d.sent(), ext = _b.ext, key_ops = _b.key_ops, privateKey = __rest(_b, ["ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_c = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_c.kid = _d.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It focuses on the 'k' parameter of the JWK, which represents the symmetric key component
* in base64url encoding. The method decodes this value into a byte array, providing
* the symmetric key in its raw binary form.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await AesGcm.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
AesGcm.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("AesGcm: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return AesGcm;
}());
exports.AesGcm = AesGcm;
//# sourceMappingURL=aes-gcm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-gcm.js","sourceRoot":"","sources":["../../../src/primitives/aes-gcm.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,wDAAoE;AAIpE,yCAAuE;AAEvE;;;;;;;;;;;;GAYG;AACH,IAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;;;;;;;;GAYG;AACH,IAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACU,QAAA,mBAAmB,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH;IAAA;IAqRA,CAAC;IApRC;;;;;;;;;;;;;;;;;;;;;;;;KAwBC;IACmB,wBAAiB,GAArC,UAAsC,EAErC;YAFuC,eAAe,qBAAA;;;;;;wBAI/C,UAAU,GAAQ;4BACtB,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE;4BACvD,GAAG,EAAG,KAAK;yBACZ,CAAC;wBAEF,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACiB,cAAO,GAA3B,UAA4B,EAM3B;YAN6B,GAAG,SAAA,EAAE,IAAI,UAAA,EAAE,EAAE,QAAA,EAAE,cAAc,oBAAA,EAAE,SAAS,eAAA;;;;;;wBAOpE,6CAA6C;wBAC7C,IAAI,EAAE,CAAC,UAAU,KAAK,iBAAiB,GAAG,CAAC,EAAE;4BAC3C,MAAM,IAAI,SAAS,CAAC,4CAAqC,iBAAiB,oBAAiB,CAAC,CAAC;yBAC9F;wBAED,2BAA2B;wBAC3B,IAAI,SAAS,IAAI,CAAC,2BAAmB,CAAC,QAAQ,CAAC,SAAgB,CAAC,EAAE;4BAChE,MAAM,IAAI,UAAU,CAAC,6CAAsC,2BAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAO,CAAC,CAAC;yBACnG;wBAGK,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAGlB,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAA;;wBAA5F,YAAY,GAAG,SAA6E;wBAI5F,SAAS,uBACb,IAAI,EAAE,SAAS,EACf,EAAE,IAAA,IACC,CAAC,SAAS,IAAI,EAAE,SAAS,WAAA,EAAE,CAAC,GAC5B,CAAC,cAAc,IAAI,EAAE,cAAc,gBAAA,EAAC,CAAC,CACzC,CAAC;wBAGsB,qBAAM,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,EAAE,IAAI,CAAC,EAAA;;wBAAxE,eAAe,GAAG,SAAsD;wBAGxE,SAAS,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC;wBAElD,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACiB,cAAO,GAA3B,UAA4B,EAM3B;YAN6B,IAAI,UAAA,EAAE,EAAE,QAAA,EAAE,GAAG,SAAA,EAAE,cAAc,oBAAA,EAAE,SAAS,eAAA;;;;;;wBAOpE,6CAA6C;wBAC7C,IAAI,EAAE,CAAC,UAAU,KAAK,iBAAiB,GAAG,CAAC,EAAE;4BAC3C,MAAM,IAAI,SAAS,CAAC,4CAAqC,iBAAiB,oBAAiB,CAAC,CAAC;yBAC9F;wBAED,2BAA2B;wBAC3B,IAAI,SAAS,IAAI,CAAC,2BAAmB,CAAC,QAAQ,CAAC,SAAgB,CAAC,EAAE;4BAChE,MAAM,IAAI,UAAU,CAAC,6CAAsC,2BAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAO,CAAC,CAAC;yBACnG;wBAGK,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAGlB,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAA;;wBAA5F,YAAY,GAAG,SAA6E;wBAI5F,SAAS,uBACb,IAAI,EAAE,SAAS,EACf,EAAE,IAAA,IACC,CAAC,SAAS,IAAI,EAAE,SAAS,WAAA,EAAE,CAAC,GAC5B,CAAC,cAAc,IAAI,EAAE,cAAc,gBAAA,EAAC,CAAC,CACzC,CAAC;wBAGuB,qBAAM,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,EAAE,IAAI,CAAC,EAAA;;wBAAzE,gBAAgB,GAAG,SAAsD;wBAGzE,UAAU,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;wBAEpD,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACiB,kBAAW,GAA/B,UAAgC,EAE/B;YAFiC,MAAM,YAAA;;;;;;wBAGtC,2BAA2B;wBAC3B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAa,CAAC,EAAE;4BAC5C,MAAM,IAAI,UAAU,CAAC,6CAAsC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,UAAO,CAAC,CAAC;yBAC/F;wBAGK,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAKlB,qBAAM,SAAS,CAAC,WAAW,CAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAA,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAA;;wBAA3F,YAAY,GAAG,SAA4E;wBAGzD,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,EAAA;;wBAAhF,KAAkC,SAA8C,EAA9E,GAAG,SAAA,EAAE,OAAO,aAAA,EAAK,UAAU,cAA7B,kBAA+B,CAAF;wBAEnC,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACiB,wBAAiB,GAArC,UAAsC,EAErC;YAFuC,UAAU,gBAAA;;;;gBAGhD,8DAA8D;gBAC9D,IAAI,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,EAAE;oBAChC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;iBAC7E;gBAGK,eAAe,GAAG,gBAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;gBAEvE,sBAAO,eAAe,EAAC;;;KACxB;IACH,aAAC;AAAD,CAAC,AArRD,IAqRC;AArRY,wBAAM"}
@@ -0,0 +1,215 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConcatKdf = void 0;
var sha256_1 = require("@noble/hashes/sha256");
var common_1 = require("@web5/common");
var utils_1 = require("@noble/hashes/utils");
/**
* An implementation of the Concatenation Key Derivation Function (ConcatKDF)
* as specified in NIST.800-56A, a single-step key-derivation function (SSKDF).
* ConcatKDF produces a derived key from a secret key (like a shared secret
* from ECDH), and other optional public information. This implementation
* specifically uses SHA-256 as the pseudorandom function (PRF).
*
* Note: This implementation allows for only a single round / repetition using the function
* `K(1) = H(counter || Z || FixedInfo)`, where:
* - `K(1)` is the derived key material after one round
* - `H` is the SHA-256 hashing function
* - `counter` is a 32-bit, big-endian bit string counter set to 0x00000001
* - `Z` is the shared secret value obtained from a key agreement protocol
* - `FixedInfo` is a bit string used to ensure that the derived keying material is adequately
* "bound" to the key-agreement transaction.
*
* @example
* ```ts
* // Key Derivation
* const derivedKeyingMaterial = await ConcatKdf.deriveKey({
* sharedSecret: utils.randomBytes(32),
* keyDataLen: 128,
* fixedInfo: {
* algorithmId: "A128GCM",
* partyUInfo: "Alice",
* partyVInfo: "Bob",
* suppPubInfo: 128,
* },
* });
* ```
*
* Additional Information:
*
* `Z`, or "shared secret":
* The shared secret value obtained from a key agreement protocol, such as
* Diffie-Hellman, ECDH (Elliptic Curve Diffie-Hellman). Importantly, this
* shared secret is not directly used as the encryption or authentication
* key, but as an input to a key derivation function (KDF), such as Concat
* KDF, to generate the actual key. This adds an extra layer of security, as
* even if the shared secret gets compromised, the actual encryption or
* authentication key stays safe. This shared secret `Z` value is kept
* confidential between the two parties in the key agreement protocol.
*
* @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf | NIST.800-56A}
* @see {@link https://datatracker.ietf.org/doc/html/rfc7518#section-4.6.2 | RFC 7518, Section 4.6.2}
*/
var ConcatKdf = /** @class */ (function () {
function ConcatKdf() {
}
/**
* Derives a key of a specified length from the input parameters.
*
* @example
* ```ts
* // Key Derivation
* const derivedKeyingMaterial = await ConcatKdf.deriveKey({
* sharedSecret: utils.randomBytes(32),
* keyDataLen: 128,
* fixedInfo: {
* algorithmId: "A128GCM",
* partyUInfo: "Alice",
* partyVInfo: "Bob",
* suppPubInfo: 128,
* },
* });
* ```
*
* @param params - Input parameters for key derivation.
* @param params.keyDataLen - The desired length of the derived key in bits.
* @param params.sharedSecret - The shared secret key to derive from.
* @param params.fixedInfo - Additional public information to use in key derivation.
* @returns The derived key as a Uint8Array.
*
* @throws {Error} If the `keyDataLen` would require multiple rounds.
*/
ConcatKdf.deriveKey = function (_a) {
var keyDataLen = _a.keyDataLen, fixedInfo = _a.fixedInfo, sharedSecret = _a.sharedSecret;
return __awaiter(this, void 0, void 0, function () {
var hashLen, roundCount, counter, fixedInfoBytes, derivedKeyingMaterial;
return __generator(this, function (_b) {
hashLen = 256;
roundCount = Math.ceil(keyDataLen / hashLen);
if (roundCount !== 1) {
throw new Error("Concat KDF with ".concat(roundCount, " rounds not supported."));
}
counter = new Uint8Array(4);
new DataView(counter.buffer).setUint32(0, roundCount);
fixedInfoBytes = ConcatKdf.computeFixedInfo(fixedInfo);
derivedKeyingMaterial = (0, sha256_1.sha256)((0, utils_1.concatBytes)(counter, sharedSecret, fixedInfoBytes));
// Return the bit string of derived keying material of length keyDataLen bits.
return [2 /*return*/, derivedKeyingMaterial.slice(0, keyDataLen / 8)];
});
});
};
/**
* Computes the `FixedInfo` parameter for Concat KDF, which binds the derived key material to the
* context of the key agreement transaction.
*
* @remarks
* This implementation follows the recommended format for `FixedInfo` specified in section
* 5.8.1.2.1 of the NIST.800-56A publication.
*
* `FixedInfo` is a bit string equal to the following concatenation:
* `AlgorithmID || PartyUInfo || PartyVInfo {|| SuppPubInfo }{|| SuppPrivInfo }`.
*
* `SuppPubInfo` is the key length in bits, big endian encoded as a 32-bit number. For example,
* 128 would be [0, 0, 0, 128] and 256 would be [0, 0, 1, 0].
*
* @param params - Input data to construct FixedInfo.
* @returns FixedInfo as a Uint8Array.
*/
ConcatKdf.computeFixedInfo = function (params) {
// Required sub-fields.
var algorithmId = ConcatKdf.toDataLenData({ data: params.algorithmId });
var partyUInfo = ConcatKdf.toDataLenData({ data: params.partyUInfo });
var partyVInfo = ConcatKdf.toDataLenData({ data: params.partyVInfo });
// Optional sub-fields.
var suppPubInfo = ConcatKdf.toDataLenData({ data: params.suppPubInfo, variableLength: false });
var suppPrivInfo = ConcatKdf.toDataLenData({ data: params.suppPrivInfo });
// Concatenate AlgorithmID || PartyUInfo || PartyVInfo || SuppPubInfo || SuppPrivInfo.
var fixedInfo = (0, utils_1.concatBytes)(algorithmId, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo);
return fixedInfo;
};
/**
* Encodes input data as a length-prefixed byte string, or
* as a fixed-length bit string if specified.
*
* If variableLength = true, return the data in the form Datalen || Data,
* where Data is a variable-length string of zero or more (eight-bit)
* bytes, and Datalen is a fixed-length, big-endian counter that
* indicates the length (in bytes) of Data.
*
* If variableLength = false, return the data formatted as a
* fixed-length bit string.
*
* @param params - Input data and options for the conversion.
* @param params.data - The input data to encode. Must be a type convertible to Uint8Array by the Convert class.
* @param params.variableLength - Whether to output the data as variable length. Default is true.
*
* @returns The input data encoded as a Uint8Array.
*
* @throws {TypeError} If fixed-length data is not a number.
*/
ConcatKdf.toDataLenData = function (_a) {
var data = _a.data, _b = _a.variableLength, variableLength = _b === void 0 ? true : _b;
var encodedData;
var dataType = (0, common_1.universalTypeOf)(data);
// Return an emtpy octet sequence if data is not specified.
if (dataType === 'Undefined') {
return new Uint8Array(0);
}
if (variableLength) {
var dataU8A = (dataType === 'Uint8Array')
? data
: new common_1.Convert(data, dataType).toUint8Array();
var bufferLength = dataU8A.length;
encodedData = new Uint8Array(4 + bufferLength);
new DataView(encodedData.buffer).setUint32(0, bufferLength);
encodedData.set(dataU8A, 4);
}
else {
if (typeof data !== 'number') {
throw TypeError('Fixed length input must be a number.');
}
encodedData = new Uint8Array(4);
new DataView(encodedData.buffer).setUint32(0, data);
}
return encodedData;
};
return ConcatKdf;
}());
exports.ConcatKdf = ConcatKdf;
//# sourceMappingURL=concat-kdf.js.map
@@ -0,0 +1 @@
{"version":3,"file":"concat-kdf.js","sourceRoot":"","sources":["../../../src/primitives/concat-kdf.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA8C;AAC9C,uCAAwD;AACxD,6CAA8D;AA+C9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH;IAAA;IAgJA,CAAC;IA/IC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACiB,mBAAS,GAA7B,UAA8B,EAI7B;YAJ+B,UAAU,gBAAA,EAAE,SAAS,eAAA,EAAE,YAAY,kBAAA;;;;gBAS3D,OAAO,GAAG,GAAG,CAAC;gBAGd,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC;gBACnD,IAAI,UAAU,KAAK,CAAC,EAAE;oBACpB,MAAM,IAAI,KAAK,CAAC,0BAAmB,UAAU,2BAAwB,CAAC,CAAC;iBACxE;gBAGK,OAAO,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;gBAClC,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;gBAGhD,cAAc,GAAG,SAAS,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBAIvD,qBAAqB,GAAG,IAAA,eAAM,EAAC,IAAA,mBAAW,EAAC,OAAO,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;gBAEzF,8EAA8E;gBAC9E,sBAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,EAAC;;;KACvD;IAED;;;;;;;;;;;;;;;;OAgBG;IACY,0BAAgB,GAA/B,UAAgC,MACZ;QAElB,uBAAuB;QACvB,IAAM,WAAW,GAAG,SAAS,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1E,IAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACxE,IAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACxE,uBAAuB;QACvB,IAAM,WAAW,GAAG,SAAS,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;QACjG,IAAM,YAAY,GAAG,SAAS,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAE5E,sFAAsF;QACtF,IAAM,SAAS,GAAG,IAAA,mBAAW,EAAC,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QAE9F,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACY,uBAAa,GAA5B,UAA6B,EAG5B;YAH8B,IAAI,UAAA,EAAE,sBAAqB,EAArB,cAAc,mBAAG,IAAI,KAAA;QAIxD,IAAI,WAAuB,CAAC;QAC5B,IAAM,QAAQ,GAAG,IAAA,wBAAe,EAAC,IAAI,CAAC,CAAC;QAEvC,2DAA2D;QAC3D,IAAI,QAAQ,KAAK,WAAW,EAAE;YAC5B,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;SAC1B;QAED,IAAI,cAAc,EAAE;YAClB,IAAM,OAAO,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;gBACzC,CAAC,CAAC,IAAkB;gBACpB,CAAC,CAAC,IAAI,gBAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,YAAY,EAAE,CAAC;YAC/C,IAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;YACpC,WAAW,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC;YAC/C,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YAC5D,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;SAE7B;aAAM;YACL,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;gBAC5B,MAAM,SAAS,CAAC,sCAAsC,CAAC,CAAC;aACzD;YACD,WAAW,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;SACrD;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IACH,gBAAC;AAAD,CAAC,AAhJD,IAgJC;AAhJY,8BAAS"}
+651
View File
@@ -0,0 +1,651 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ed25519 = void 0;
var common_1 = require("@web5/common");
var ed25519_1 = require("@noble/curves/ed25519");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `Ed25519` class provides a comprehensive suite of utilities for working with the Ed25519
* elliptic curve, widely used in modern cryptographic applications. This class includes methods for
* key generation, conversion, signing, verification, and public key derivation.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats. It
* follows the guidelines and specifications outlined in RFC8032 for EdDSA (Edwards-curve Digital
* Signature Algorithm) operations.
*
* Key Features:
* - Key Generation: Generate Ed25519 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - Signing and Verification: Sign data and verify signatures with Ed25519 keys.
* - Key Validation: Validate the mathematical correctness of Ed25519 keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments, and use `Uint8Array` for binary data handling.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await Ed25519.generateKey();
*
* // Public Key Derivation
* const publicKey = await Ed25519.computePublicKey({ key: privateKey });
* console.log(publicKey === await Ed25519.getPublicKey({ key: privateKey })); // Output: true
*
* // EdDSA Signing
* const signature = await Ed25519.sign({
* key: privateKey,
* data: new TextEncoder().encode('Message')
* });
*
* // EdDSA Signature Verification
* const isValid = await Ed25519.verify({
* key: publicKey,
* signature: signature,
* data: new TextEncoder().encode('Message')
* });
*
* // Key Conversion
* const privateKeyBytes = await Ed25519.privateKeyToBytes({ privateKey });
* const publicKeyBytes = await Ed25519.publicKeyToBytes({ publicKey });
*
* // Key Validation
* const isPublicKeyValid = await Ed25519.validatePublicKey({ publicKeyBytes });
* ```
*/
var Ed25519 = /** @class */ (function () {
function Ed25519() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a private key as a byte array (Uint8Array) for the Curve25519 curve in
* Twisted Edwards form and transforms it into a JWK object. The process involves first deriving
* the public key from the private key, then encoding both the private and public keys into
* base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'Ed25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The computed public key, base64url-encoded.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await Ed25519.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
Ed25519.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKeyBytes = ed25519_1.ed25519.getPublicKey(privateKeyBytes);
privateKey = {
crv: 'Ed25519',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'OKP',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key as a byte array (Uint8Array) for the Curve25519 curve in
* Twisted Edwards form and transforms it into a JWK object. The process involves encoding the
* public key bytes into base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `x`: The public key, base64url-encoded.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await X25519.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a `Uint8Array`.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Ed25519.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKey = {
kty: 'OKP',
crv: 'Ed25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Derives the public key in JWK format from a given Ed25519 private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a
* raw byte array and then computing the corresponding public key on the Curve25519 curve in
* Twisted Edwards form. The public key is then encoded into base64url format to construct
* a JWK representation.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an Ed25519 private key
* const publicKey = await Ed25519.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the computed public key in JWK format.
*/
Ed25519.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, publicKeyBytes, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Ed25519.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
publicKeyBytes = ed25519_1.ed25519.getPublicKey(privateKeyBytes);
publicKey = {
kty: 'OKP',
crv: 'Ed25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts an Ed25519 private key to its X25519 counterpart.
*
* @remarks
* This method enables the use of the same key pair for both digital signature (Ed25519)
* and key exchange (X25519) operations. It takes an Ed25519 private key and converts it
* to the corresponding X25519 format, facilitating interoperability between signing
* and encryption protocols.
*
* @example
* ```ts
* const ed25519PrivateKey = { ... }; // An Ed25519 private key in JWK format
* const x25519PrivateKey = await Ed25519.convertPrivateKeyToX25519({
* privateKey: ed25519PrivateKey
* });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The Ed25519 private key to convert, in JWK format.
*
* @returns A Promise that resolves to the X25519 private key in JWK format.
*/
Ed25519.convertPrivateKeyToX25519 = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var ed25519PrivateKeyBytes, x25519PrivateKeyBytes, x25519PublicKeyBytes, x25519PrivateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Ed25519.privateKeyToBytes({ privateKey: privateKey })];
case 1:
ed25519PrivateKeyBytes = _c.sent();
x25519PrivateKeyBytes = (0, ed25519_1.edwardsToMontgomeryPriv)(ed25519PrivateKeyBytes);
x25519PublicKeyBytes = ed25519_1.x25519.getPublicKey(x25519PrivateKeyBytes);
x25519PrivateKey = {
kty: 'OKP',
crv: 'X25519',
d: common_1.Convert.uint8Array(x25519PrivateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(x25519PublicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = x25519PrivateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: x25519PrivateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, x25519PrivateKey];
}
});
});
};
/**
* Converts an Ed25519 public key to its X25519 counterpart.
*
* @remarks
* This method enables the use of the same key pair for both digital signature (Ed25519)
* and key exchange (X25519) operations. It takes an Ed25519 public key and converts it
* to the corresponding X25519 format, facilitating interoperability between signing
* and encryption protocols.
*
* @example
* ```ts
* const ed25519PublicKey = { ... }; // An Ed25519 public key in JWK format
* const x25519PublicKey = await Ed25519.convertPublicKeyToX25519({
* publicKey: ed25519PublicKey
* });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The Ed25519 public key to convert, in JWK format.
*
* @returns A Promise that resolves to the X25519 public key in JWK format.
*/
Ed25519.convertPublicKeyToX25519 = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var ed25519PublicKeyBytes, isValid, x25519PublicKeyBytes, x25519PublicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Ed25519.publicKeyToBytes({ publicKey: publicKey })];
case 1:
ed25519PublicKeyBytes = _c.sent();
return [4 /*yield*/, Ed25519.validatePublicKey({ publicKeyBytes: ed25519PublicKeyBytes })];
case 2:
isValid = _c.sent();
if (!isValid) {
throw new Error('Ed25519: Invalid public key.');
}
x25519PublicKeyBytes = (0, ed25519_1.edwardsToMontgomeryPub)(ed25519PublicKeyBytes);
x25519PublicKey = {
kty: 'OKP',
crv: 'X25519',
x: common_1.Convert.uint8Array(x25519PublicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = x25519PublicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: x25519PublicKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, x25519PublicKey];
}
});
});
};
/**
* Generates an Ed25519 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the Curve25519 elliptic curve in
* Twisted Edwards form. The key generation process involves using cryptographically secure
* random number generation to ensure the uniqueness and security of the key. The resulting
* private key adheres to the JWK format making it compatible with common cryptographic
* standards and easy to use in various cryptographic processes.
*
* The generated private key in JWK format includes the following components:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'Ed25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The derived public key, base64url-encoded.
*
* @example
* ```ts
* const privateKey = await Ed25519.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
Ed25519.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = ed25519_1.ed25519.utils.randomPrivateKey();
return [4 /*yield*/, Ed25519.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an Ed25519 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 100 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an Ed25519 private key
* const publicKey = await Ed25519.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Ed25519.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an octet key pair (OKP) Ed25519 private key.
if (!((0, jwk_js_1.isOkpPrivateJwk)(key) && key.crv === 'Ed25519')) {
throw new Error("Ed25519: The provided key is not an Ed25519 private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a private key in JWK format and extracts its raw byte representation.
*
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'd' parameter of the JWK
* from base64url format into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // An Ed25519 private key in JWK format
* const privateKeyBytes = await Ed25519.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
Ed25519.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP private key.
if (!(0, jwk_js_1.isOkpPrivateJwk)(privateKey)) {
throw new Error("Ed25519: The provided key is not a valid OKP private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary form.
* The conversion process involves decoding the 'x' parameter of the JWK (which represent the
* x coordinate of the elliptic curve point) from base64url format into a byte array.
*
* @example
* ```ts
* const publicKey = { ... }; // An Ed25519 public key in JWK format
* const publicKeyBytes = await Ed25519.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
Ed25519.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP public key.
if (!(0, jwk_js_1.isOkpPublicJwk)(publicKey)) {
throw new Error("Ed25519: The provided key is not a valid OKP public key.");
}
publicKeyBytes = common_1.Convert.base64Url(publicKey.x).toUint8Array();
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Generates an RFC8032-compliant EdDSA signature of given data using an Ed25519 private key.
*
* @remarks
* This method signs the provided data with a specified private key using the EdDSA
* (Edwards-curve Digital Signature Algorithm) as defined in RFC8032. It
* involves converting the private key from JWK format to a byte array and then employing
* the Ed25519 algorithm to sign the data. The output is a digital signature in the form
* of a Uint8Array, uniquely corresponding to both the data and the private key used for
* signing.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data to be signed
* const privateKey = { ... }; // A Jwk object representing an Ed25519 private key
* const signature = await Ed25519.sign({ key: privateKey, data });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign, represented as a Uint8Array.
*
* @returns A Promise that resolves to the signature as a Uint8Array.
*/
Ed25519.sign = function (_a) {
var key = _a.key, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Ed25519.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
signature = ed25519_1.ed25519.sign(data, privateKeyBytes);
return [2 /*return*/, signature];
}
});
});
};
/**
* Validates a given public key to confirm its mathematical correctness on the Edwards curve.
*
* @remarks
* This method decodes the Edwards points from the key bytes and asserts their validity on the
* Curve25519 curve in Twisted Edwards form. If the points are not valid, the method returns
* false. If the points are valid, the method returns true.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Ed25519.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the Edwards curve, false otherwise
* ```
*
* @param params - The parameters for the public key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the key
* corresponds to a valid point on the Edwards curve.
*/
Ed25519.validatePublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
try {
point = ed25519_1.ed25519.ExtendedPoint.fromHex(publicKeyBytes);
// Check if points are on the Twisted Edwards curve.
point.assertValidity();
}
catch (error) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
});
});
};
/**
* Verifies an RFC8032-compliant EdDSA signature against given data using an Ed25519 public key.
*
* @remarks
* This method validates a digital signature to ensure its authenticity and integrity.
* It uses the EdDSA (Edwards-curve Digital Signature Algorithm) as specified in RFC8032.
* The verification process involves converting the public key from JWK format to a raw
* byte array and using the Ed25519 algorithm to validate the signature against the provided data.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // A Jwk object representing an Ed25519 public key
* const signature = new Uint8Array([...]); // Signature to verify
* const isValid = await Ed25519.verify({ key: publicKey, signature, data });
* console.log(isValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key in JWK format used for verification.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
Ed25519.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, isValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Ed25519.publicKeyToBytes({ publicKey: key })];
case 1:
publicKeyBytes = _b.sent();
isValid = ed25519_1.ed25519.verify(signature, data, publicKeyBytes);
return [2 /*return*/, isValid];
}
});
});
};
return Ed25519;
}());
exports.Ed25519 = Ed25519;
//# sourceMappingURL=ed25519.js.map
File diff suppressed because one or more lines are too long
+120
View File
@@ -0,0 +1,120 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pbkdf2 = void 0;
var crypto_1 = require("@noble/hashes/crypto");
/**
* The `Pbkdf2` class provides a secure way to derive cryptographic keys from a password
* using the PBKDF2 (Password-Based Key Derivation Function 2) algorithm.
*
* The PBKDF2 algorithm is widely used for generating keys from passwords, as it applies
* a pseudorandom function to the input password along with a salt value and iterates the
* process multiple times to increase the key's resistance to brute-force attacks.
*
* This class offers a single static method `deriveKey` to perform key derivation.
*
* @example
* ```ts
* // Key Derivation
* const derivedKey = await Pbkdf2.deriveKey({
* hash: 'SHA-256', // The hash function to use ('SHA-256', 'SHA-384', 'SHA-512')
* password: new TextEncoder().encode('password'), // The password as a Uint8Array
* salt: new Uint8Array([...]), // The salt value
* iterations: 1000, // The number of iterations
* length: 256 // The length of the derived key in bits
* });
* ```
*
* @remarks
* This class relies on the availability of the Web Crypto API.
*/
var Pbkdf2 = /** @class */ (function () {
function Pbkdf2() {
}
/**
* Derives a cryptographic key from a password using the PBKDF2 algorithm.
*
* @remarks
* This method applies the PBKDF2 algorithm to the provided password along with
* a salt value and iterates the process a specified number of times. It uses
* a cryptographic hash function to enhance security and produce a key of the
* desired length. The method is capable of utilizing either the Web Crypto API
* or the Node.js Crypto module, depending on the environment's support.
*
* @example
* ```ts
* const derivedKey = await Pbkdf2.deriveKey({
* hash: 'SHA-256',
* password: new TextEncoder().encode('password'),
* salt: new Uint8Array([...]),
* iterations: 1000,
* length: 256
* });
* ```
*
* @param params - The parameters for key derivation.
* @param params.hash - The hash function to use, such as 'SHA-256', 'SHA-384', or 'SHA-512'.
* @param params.password - The password from which to derive the key, represented as a Uint8Array.
* @param params.salt - The salt value to use in the derivation process, as a Uint8Array.
* @param params.iterations - The number of iterations to apply in the PBKDF2 algorithm.
* @param params.length - The desired length of the derived key in bits.
*
* @returns A Promise that resolves to the derived key as a Uint8Array.
*/
Pbkdf2.deriveKey = function (_a) {
var hash = _a.hash, password = _a.password, salt = _a.salt, iterations = _a.iterations, length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCryptoKey, derivedKeyBuffer, derivedKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, crypto_1.crypto.subtle.importKey('raw', password, { name: 'PBKDF2' }, false, ['deriveBits'])];
case 1:
webCryptoKey = _b.sent();
return [4 /*yield*/, crypto_1.crypto.subtle.deriveBits({ name: 'PBKDF2', hash: hash, salt: salt, iterations: iterations }, webCryptoKey, length)];
case 2:
derivedKeyBuffer = _b.sent();
derivedKey = new Uint8Array(derivedKeyBuffer);
return [2 /*return*/, derivedKey];
}
});
});
};
return Pbkdf2;
}());
exports.Pbkdf2 = Pbkdf2;
//# sourceMappingURL=pbkdf2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"pbkdf2.js","sourceRoot":"","sources":["../../../src/primitives/pbkdf2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA8C;AA0C9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH;IAAA;IAsDA,CAAC;IArDC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACiB,gBAAS,GAA7B,UAA8B,EACP;YADS,IAAI,UAAA,EAAE,QAAQ,cAAA,EAAE,IAAI,UAAA,EAAE,UAAU,gBAAA,EAAE,MAAM,YAAA;;;;;4BAIjD,qBAAM,eAAM,CAAC,MAAM,CAAC,SAAS,CAChD,KAAK,EACL,QAAQ,EACR,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,YAAY,CAAC,CACf,EAAA;;wBANK,YAAY,GAAG,SAMpB;wBAEwB,qBAAM,eAAM,CAAC,MAAM,CAAC,UAAU,CACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,MAAA,EAAE,IAAI,MAAA,EAAE,UAAU,YAAA,EAAE,EAC1C,YAAY,EACZ,MAAM,CACP,EAAA;;wBAJK,gBAAgB,GAAG,SAIxB;wBAGK,UAAU,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;wBAEpD,sBAAO,UAAU,EAAC;;;;KACnB;IACH,aAAC;AAAD,CAAC,AAtDD,IAsDC;AAtDY,wBAAM"}
@@ -0,0 +1,958 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Secp256k1 = void 0;
var common_1 = require("@web5/common");
var sha256_1 = require("@noble/hashes/sha256");
var secp256k1_1 = require("@noble/curves/secp256k1");
var utils_1 = require("@noble/curves/abstract/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `Secp256k1` class provides a comprehensive suite of utilities for working with
* the secp256k1 elliptic curve, commonly used in blockchain and cryptographic applications.
* This class includes methods for key generation, conversion, signing, verification, and
* Elliptic Curve Diffie-Hellman (ECDH) key agreement.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats. It
* adheres to RFC6979 for ECDSA signing and verification and RFC6090 for ECDH.
*
* Key Features:
* - Key Generation: Generate secp256k1 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - ECDH Shared Secret Computation: Securely derive shared secrets using private and public keys.
* - ECDSA Signing and Verification: Sign data and verify signatures with secp256k1 keys.
* - Key Validation: Validate the mathematical correctness of secp256k1 keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments, and use `Uint8Array` for binary data handling.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await Secp256k1.generateKey();
*
* // Public Key Derivation
* const publicKey = await Secp256k1.computePublicKey({ key: privateKey });
* console.log(publicKey === await Secp256k1.getPublicKey({ key: privateKey })); // Output: true
*
* // ECDH Shared Secret Computation
* const sharedSecret = await Secp256k1.sharedSecret({
* privateKeyA: privateKey,
* publicKeyB: anotherPublicKey
* });
*
* // ECDSA Signing
* const signature = await Secp256k1.sign({
* key: privateKey,
* data: new TextEncoder().encode('Message')
* });
*
* // ECDSA Signature Verification
* const isValid = await Secp256k1.verify({
* key: publicKey,
* signature: signature,
* data: new TextEncoder().encode('Message')
* });
*
* // Key Conversion
* const publicKeyBytes = await Secp256k1.publicKeyToBytes({ publicKey });
* const privateKeyBytes = await Secp256k1.privateKeyToBytes({ privateKey });
* const compressedPublicKey = await Secp256k1.compressPublicKey({ publicKeyBytes });
* const uncompressedPublicKey = await Secp256k1.decompressPublicKey({ publicKeyBytes });
*
* // Key Validation
* const isPrivateKeyValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
* const isPublicKeyValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
* ```
*/
var Secp256k1 = /** @class */ (function () {
function Secp256k1() {
}
/**
* Adjusts an ECDSA signature to a normalized, low-S form.
*
* @remarks
* All ECDSA signatures, regardless of the curve, consist of two components, `r` and `s`, both of
* which are integers. The curve's order (the total number of points on the curve) is denoted by
* `n`. In a valid ECDSA signature, both `r` and `s` must be in the range [1, n-1]. However, due
* to the mathematical properties of ECDSA, if `(r, s)` is a valid signature, then `(r, n - s)` is
* also a valid signature for the same message and public key. In other words, for every
* signature, there's a "mirror" signature that's equally valid. For these elliptic curves:
*
* - Low S Signature: A signature where the `s` component is in the lower half of the range,
* specifically less than or equal to `n/2`.
*
* - High S Signature: This is where the `s` component is in the upper half of the range, greater
* than `n/2`.
*
* The practical implication is that a third-party can forge a second valid signature for the same
* message by negating the `s` component of the original signature, without any knowledge of the
* private key. This is known as a "signature malleability" attack.
*
* This type of forgery is not a problem in all systems, but it can be an issue in systems that
* rely on digital signature uniqueness to ensure transaction integrity. For example, in Bitcoin,
* transaction malleability is an issue because it allows for the modification of transaction
* identifiers (and potentially, transactions themselves) after they're signed but before they're
* confirmed in a block. By enforcing low `s` values, the Bitcoin network reduces the likelihood of
* this occurring, making the system more secure and predictable.
*
* For this reason, it's common practice to normalize ECDSA signatures to a low-S form. This
* form is considered standard and preferable in some systems and is known as the "normalized"
* form of the signature.
*
* This method takes a signature, and if it's high-S, returns the normalized low-S form. If the
* signature is already low-S, it's returned unmodified. It's important to note that this
* method does not change the validity of the signature but makes it compliant with systems that
* enforce low-S signatures.
*
* @example
* ```ts
* const signature = new Uint8Array([...]); // Your ECDSA signature
* const adjustedSignature = await Secp256k1.adjustSignatureToLowS({ signature });
* // Now 'adjustedSignature' is in the low-S form.
* ```
*
* @param params - The parameters for the signature adjustment.
* @param params.signature - The ECDSA signature as a `Uint8Array`.
*
* @returns A Promise that resolves to the adjusted signature in low-S form as a `Uint8Array`.
*/
Secp256k1.adjustSignatureToLowS = function (_a) {
var signature = _a.signature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, adjustedSignatureObject, adjustedSignature;
return __generator(this, function (_b) {
signatureObject = secp256k1_1.secp256k1.Signature.fromCompact(signature);
if (signatureObject.hasHighS()) {
adjustedSignatureObject = signatureObject.normalizeS();
adjustedSignature = adjustedSignatureObject.toCompactRawBytes();
return [2 /*return*/, adjustedSignature];
}
else {
// Return the unmodified signature if it is already in low-S format.
return [2 /*return*/, signature];
}
return [2 /*return*/];
});
});
};
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a private key represented as a byte array (Uint8Array) and
* converts it into a JWK object. The conversion involves extracting the
* elliptic curve point (x and y coordinates) from the private key and encoding
* them into base64url format, alongside other JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'secp256k1'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await Secp256k1.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
Secp256k1.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256k1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 1:
point = _c.sent();
privateKey = {
kty: 'EC',
crv: 'secp256k1',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw public key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key in a byte array (Uint8Array) format and
* transforms it to a JWK object. It involves decoding the elliptic curve point
* (x and y coordinates) from the raw public key bytes and encoding them into
* base64url format, along with setting appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'secp256k1'.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await Secp256k1.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a Uint8Array.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256k1.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256k1.getCurvePoint({ keyBytes: publicKeyBytes })];
case 1:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'secp256k1',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a public key to its compressed form.
*
* @remarks
* This method takes a public key represented as a byte array and compresses it. Public key
* compression is a process that reduces the size of the public key by removing the y-coordinate,
* making it more efficient for storage and transmission. The compressed key retains the same
* level of security as the uncompressed key.
*
* @example
* ```ts
* const uncompressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual uncompressed public key bytes
* const compressedPublicKey = await Secp256k1.compressPublicKey({
* publicKeyBytes: uncompressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key compression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the compressed public key as a Uint8Array.
*/
Secp256k1.compressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the compressed form of the public key.
return [2 /*return*/, point.toRawBytes(true)];
});
});
};
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a raw
* byte array, then computing the elliptic curve point (x and y coordinates) from this private
* key. These coordinates are then encoded into base64url format to construct the public key in
* JWK format.
*
* The process ensures that the derived public key correctly corresponds to the given private key,
* adhering to the secp256k1 elliptic curve standards. This method is useful in cryptographic
* operations where a public key is needed for operations like signature verification, but only
* the private key is available.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256k1 private key
* const publicKey = await Secp256k1.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
Secp256k1.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256k1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
return [4 /*yield*/, Secp256k1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 2:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'secp256k1',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts an ASN.1 DER encoded ECDSA signature to a compact R+S format.
*
* @remarks
* This method is used for converting an ECDSA signature from the ASN.1 DER encoding to the more
* compact R+S format. This conversion is often required when dealing with ECDSA signatures in
* certain cryptographic standards such as JWS (JSON Web Signature).
*
* The method decodes the DER-encoded signature, extracts the R and S values, and concatenates
* them into a single byte array. This process involves handling the ASN.1 structure to correctly
* parse the R and S values, considering padding and integer encoding specifics of DER.
*
* @example
* ```ts
* const derSignature = new Uint8Array([...]); // Replace with your DER-encoded signature
* const signature = await Secp256k1.convertDerToCompactSignature({ derSignature });
* ```
*
* @param params - The parameters for the signature conversion.
* @param params.derSignature - The signature in ASN.1 DER format as a `Uint8Array`.
*
* @returns A Promise that resolves to the signature in compact R+S format as a `Uint8Array`.
*/
Secp256k1.convertDerToCompactSignature = function (_a) {
var derSignature = _a.derSignature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, compactSignature;
return __generator(this, function (_b) {
signatureObject = secp256k1_1.secp256k1.Signature.fromDER(derSignature);
compactSignature = signatureObject.toCompactRawBytes();
return [2 /*return*/, compactSignature];
});
});
};
/**
* Converts a public key to its uncompressed form.
*
* @remarks
* This method takes a compressed public key represented as a byte array and decompresses it.
* Public key decompression involves reconstructing the y-coordinate from the x-coordinate,
* resulting in the full public key. This method is used when the uncompressed key format is
* required for certain cryptographic operations or interoperability.
*
* @example
* ```ts
* const compressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual compressed public key bytes
* const decompressedPublicKey = await Secp256k1.decompressPublicKey({
* publicKeyBytes: compressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key decompression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the uncompressed public key as a Uint8Array.
*/
Secp256k1.decompressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the uncompressed form of the public key.
return [2 /*return*/, point.toRawBytes(false)];
});
});
};
/**
* Generates a secp256k1 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the secp256k1
* elliptic curve. The key is generated using cryptographically secure random
* number generation to ensure its uniqueness and security. The resulting
* private key adheres to the JWK format, specifically tailored for secp256k1,
* making it compatible with common cryptographic standards and easy to use in
* various cryptographic processes.
*
* The private key generated by this method includes the following components:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'secp256k1'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, derived from the private key, base64url-encoded.
* - `y`: The y-coordinate of the public key point, derived from the private key, base64url-encoded.
*
* The key is returned in a format suitable for direct use in signin and key agreement operations.
*
* @example
* ```ts
* const privateKey = await Secp256k1.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
Secp256k1.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = secp256k1_1.secp256k1.utils.randomPrivateKey();
return [4 /*yield*/, Secp256k1.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from a secp256k1 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 200 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256k1 private key
* const publicKey = await Secp256k1.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256k1.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an elliptic curve (EC) secp256k1 private key.
if (!((0, jwk_js_1.isEcPrivateJwk)(key) && key.crv === 'secp256k1')) {
throw new Error("Secp256k1: The provided key is not a secp256k1 private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a private key in JWK format and extracts its raw byte representation.
* It specifically focuses on the 'd' parameter of the JWK, which represents the private
* key component in base64url encoding. The method decodes this value into a byte array.
*
* This conversion is essential for operations that require the private key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const privateKey = { ... }; // An X25519 private key in JWK format
* const privateKeyBytes = await Secp256k1.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
Secp256k1.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC secp256k1 private key.
if (!(0, jwk_js_1.isEcPrivateJwk)(privateKey)) {
throw new Error("Secp256k1: The provided key is not a valid EC private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'x' and 'y' parameters of the JWK
* (which represent the x and y coordinates of the elliptic curve point, respectively)
* from base64url format into a byte array. The method then concatenates these values,
* along with a prefix indicating the key format, to form the full public key.
*
* This function is particularly useful for use cases where the public key is needed
* in its raw byte format, such as for certain cryptographic operations or when
* interfacing with systems that require raw key formats.
*
* @example
* ```ts
* const publicKey = { ... }; // A Jwk public key object
* const publicKeyBytes = await Secp256k1.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
Secp256k1.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var prefix, x, y, publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC secp256k1 public key, which must have a 'y' value.
if (!((0, jwk_js_1.isEcPublicJwk)(publicKey) && publicKey.y)) {
throw new Error("Secp256k1: The provided key is not a valid EC public key.");
}
prefix = new Uint8Array([0x04]);
x = common_1.Convert.base64Url(publicKey.x).toUint8Array();
y = common_1.Convert.base64Url(publicKey.y).toUint8Array();
publicKeyBytes = new Uint8Array(__spreadArray(__spreadArray(__spreadArray([], __read(prefix), false), __read(x), false), __read(y), false));
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Computes an RFC6090-compliant Elliptic Curve Diffie-Hellman (ECDH) shared secret
* using secp256k1 private and public keys in JSON Web Key (JWK) format.
*
* @remarks
* This method facilitates the ECDH key agreement protocol, which is a method of securely
* deriving a shared secret between two parties based on their private and public keys.
* It takes the private key of one party (privateKeyA) and the public key of another
* party (publicKeyB) to compute a shared secret. The shared secret is derived from the
* x-coordinate of the elliptic curve point resulting from the multiplication of the
* public key with the private key.
*
* Note: When performing Elliptic Curve Diffie-Hellman (ECDH) key agreement,
* the resulting shared secret is a point on the elliptic curve, which
* consists of an x-coordinate and a y-coordinate. With a 256-bit curve like
* secp256k1, each of these coordinates is 32 bytes (256 bits) long. However,
* in the ECDH process, it's standard practice to use only the x-coordinate
* of the shared secret point as the resulting shared key. This is because
* the y-coordinate does not add to the entropy of the key, and both parties
* can independently compute the x-coordinate. Consquently, this implementation
* omits the y-coordinate for simplicity and standard compliance.
*
* @example
* ```ts
* const privateKeyA = { ... }; // A Jwk private key object for party A
* const publicKeyB = { ... }; // A Jwk public key object for party B
* const sharedSecret = await Secp256k1.sharedSecret({
* privateKeyA,
* publicKeyB
* });
* ```
*
* @param params - The parameters for the shared secret computation.
* @param params.privateKeyA - The private key in JWK format of one party.
* @param params.publicKeyB - The public key in JWK format of the other party.
*
* @returns A Promise that resolves to the computed shared secret as a Uint8Array.
*/
Secp256k1.sharedSecret = function (_a) {
var privateKeyA = _a.privateKeyA, publicKeyB = _a.publicKeyB;
return __awaiter(this, void 0, void 0, function () {
var privateKeyABytes, publicKeyBBytes, sharedSecret;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Ensure that keys from the same key pair are not specified.
if ('x' in privateKeyA && 'x' in publicKeyB && privateKeyA.x === publicKeyB.x) {
throw new Error("Secp256k1: ECDH shared secret cannot be computed from a single key pair's public and private keys.");
}
return [4 /*yield*/, Secp256k1.privateKeyToBytes({ privateKey: privateKeyA })];
case 1:
privateKeyABytes = _b.sent();
return [4 /*yield*/, Secp256k1.publicKeyToBytes({ publicKey: publicKeyB })];
case 2:
publicKeyBBytes = _b.sent();
sharedSecret = secp256k1_1.secp256k1.getSharedSecret(privateKeyABytes, publicKeyBBytes, true);
// Remove the leading byte that indicates the sign of the y-coordinate
// of the point on the elliptic curve. See note above.
return [2 /*return*/, sharedSecret.slice(1)];
}
});
});
};
/**
* Generates an RFC6979-compliant ECDSA signature of given data using a secp256k1 private key.
*
* @remarks
* This method signs the provided data with a specified private key using the ECDSA
* (Elliptic Curve Digital Signature Algorithm) signature algorithm, as defined in RFC6979.
* The data to be signed is first hashed using the SHA-256 algorithm, and this hash is then
* signed using the private key. The output is a digital signature in the form of a
* Uint8Array, which uniquely corresponds to both the data and the private key used for signing.
*
* This method is commonly used in cryptographic applications to ensure data integrity and
* authenticity. The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data to be signed
* const privateKey = { ... }; // A Jwk object representing a secp256k1 private key
* const signature = await Secp256k1.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign, represented as a Uint8Array.
*
* @returns A Promise that resolves to the signature as a Uint8Array.
*/
Secp256k1.sign = function (_a) {
var data = _a.data, key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, digest, signatureObject, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256k1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
signatureObject = secp256k1_1.secp256k1.sign(digest, privateKeyBytes);
signature = signatureObject.toCompactRawBytes();
return [2 /*return*/, signature];
}
});
});
};
/**
* Validates a given private key to ensure its compliance with the secp256k1 curve standards.
*
* @remarks
* This method checks whether a provided private key is a valid 32-byte number and falls within
* the range defined by the secp256k1 curve's order. It is essential for ensuring the private
* key's mathematical correctness in the context of secp256k1-based cryptographic operations.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // A 32-byte private key
* const isValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
* console.log(isValid); // true or false based on the key's validity
* ```
*
* @param params - The parameters for the key validation.
* @param params.privateKeyBytes - The private key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the private key is valid.
*/
Secp256k1.validatePrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
return [2 /*return*/, secp256k1_1.secp256k1.utils.isValidPrivateKey(privateKeyBytes)];
});
});
};
/**
* Validates a given public key to confirm its mathematical correctness on the secp256k1 curve.
*
* @remarks
* This method checks if the provided public key represents a valid point on the secp256k1 curve.
* It decodes the key's Weierstrass points (x and y coordinates) and verifies their validity
* against the curve's parameters. A valid point must lie on the curve and meet specific
* mathematical criteria defined by the curve's equation.
*
* It's important to note that this method does not verify the key's ownership or whether it has
* been compromised; it solely focuses on the key's adherence to the curve's mathematical
* principles.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the secp256k1 curve, false otherwise
* ```
*
* @param params - The parameters for the key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating the public key's validity on
* the secp256k1 curve.
*/
Secp256k1.validatePublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
try {
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes);
// Check if points are on the Short Weierstrass curve.
point.assertValidity();
}
catch (error) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
});
});
};
/**
* Verifies an RFC6979-compliant ECDSA signature against given data and a secp256k1 public key.
*
* @remarks
* This method validates a digital signature to ensure that it was generated by the holder of the
* corresponding private key and that the signed data has not been altered. The signature
* verification is performed using the ECDSA (Elliptic Curve Digital Signature Algorithm) as
* specified in RFC6979. The data to be verified is first hashed using the SHA-256 algorithm, and
* this hash is then used along with the public key to verify the signature.
*
* The method returns a boolean value indicating whether the signature is valid. A valid signature
* proves that the signed data was indeed signed by the owner of the private key corresponding to
* the provided public key and that the data has not been tampered with since it was signed.
*
* Note: The verification process does not consider the malleability of low-s signatures, which
* may be relevant in certain contexts, such as Bitcoin transactions.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const isSignatureValid = await Secp256k1.verify({
* key: publicKey,
* signature,
* data
* });
* console.log(isSignatureValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key used for verification, represented in JWK format.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
Secp256k1.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, digest, isValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256k1.publicKeyToBytes({ publicKey: key })];
case 1:
publicKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
isValid = secp256k1_1.secp256k1.verify(signature, digest, publicKeyBytes, { lowS: false });
return [2 /*return*/, isValid];
}
});
});
};
/**
* Returns the elliptic curve point (x and y coordinates) for a given secp256k1 key.
*
* @remarks
* This method extracts the elliptic curve point from a given secp256k1 key, whether
* it's a private or a public key. For a private key, the method first computes the
* corresponding public key and then extracts the x and y coordinates. For a public key,
* it directly returns these coordinates. The coordinates are represented as Uint8Array.
*
* The x and y coordinates represent the key's position on the elliptic curve and can be
* used in various cryptographic operations, such as digital signatures or key agreement
* protocols.
*
* @example
* ```ts
* // For a private key
* const privateKey = new Uint8Array([...]); // A 32-byte private key
* const { x: xFromPrivateKey, y: yFromPrivateKey } = await Secp256k1.getCurvePoint({ keyBytes: privateKey });
*
* // For a public key
* const publicKey = new Uint8Array([...]); // A 33-byte or 65-byte public key
* const { x: xFromPublicKey, y: yFromPublicKey } = await Secp256k1.getCurvePoint({ keyBytes: publicKey });
* ```
*
* @param params - The parameters for the curve point decoding operation.
* @param params.keyBytes - The key for which to get the elliptic curve point.
* Can be either a private key or a public key.
* The key should be passed as a `Uint8Array`.
*
* @returns A Promise that resolves to an object with properties 'x' and 'y',
* each being a Uint8Array representing the x and y coordinates of the key point on the
* elliptic curve.
*/
Secp256k1.getCurvePoint = function (_a) {
var keyBytes = _a.keyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, x, y;
return __generator(this, function (_b) {
// If key is a private key, first compute the public key.
if (keyBytes.byteLength === 32) {
keyBytes = secp256k1_1.secp256k1.getPublicKey(keyBytes);
}
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(keyBytes);
x = (0, utils_1.numberToBytesBE)(point.x, 32);
y = (0, utils_1.numberToBytesBE)(point.y, 32);
return [2 /*return*/, { x: x, y: y }];
});
});
};
return Secp256k1;
}());
exports.Secp256k1 = Secp256k1;
//# sourceMappingURL=secp256k1.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,959 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.P256 = exports.Secp256r1 = void 0;
var common_1 = require("@web5/common");
var sha256_1 = require("@noble/hashes/sha256");
var p256_1 = require("@noble/curves/p256");
var utils_1 = require("@noble/curves/abstract/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `Secp256r1` class provides a comprehensive suite of utilities for working with
* the secp256r1 (aka P-256) elliptic curve, commonly used in blockchain and cryptographic
* applications. This class includes methods for key generation, conversion, signing, verification,
* and Elliptic Curve Diffie-Hellman (ECDH) key agreement.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats. It
* adheres to RFC6979 for ECDSA signing and verification and RFC6090 for ECDH.
*
* Key Features:
* - Key Generation: Generate secp256r1 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - ECDH Shared Secret Computation: Securely derive shared secrets using private and public keys.
* - ECDSA Signing and Verification: Sign data and verify signatures with secp256r1 keys.
* - Key Validation: Validate the mathematical correctness of secp256r1 keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments, and use `Uint8Array` for binary data handling.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await Secp256r1.generateKey();
*
* // Public Key Derivation
* const publicKey = await Secp256r1.computePublicKey({ key: privateKey });
* console.log(publicKey === await Secp256r1.getPublicKey({ key: privateKey })); // Output: true
*
* // ECDH Shared Secret Computation
* const sharedSecret = await Secp256r1.sharedSecret({
* privateKeyA: privateKey,
* publicKeyB: anotherPublicKey
* });
*
* // ECDSA Signing
* const signature = await Secp256r1.sign({
* key: privateKey,
* data: new TextEncoder().encode('Message')
* });
*
* // ECDSA Signature Verification
* const isValid = await Secp256r1.verify({
* key: publicKey,
* signature: signature,
* data: new TextEncoder().encode('Message')
* });
*
* // Key Conversion
* const publicKeyBytes = await Secp256r1.publicKeyToBytes({ publicKey });
* const privateKeyBytes = await Secp256r1.privateKeyToBytes({ privateKey });
* const compressedPublicKey = await Secp256r1.compressPublicKey({ publicKeyBytes });
* const uncompressedPublicKey = await Secp256r1.decompressPublicKey({ publicKeyBytes });
*
* // Key Validation
* const isPrivateKeyValid = await Secp256r1.validatePrivateKey({ privateKeyBytes });
* const isPublicKeyValid = await Secp256r1.validatePublicKey({ publicKeyBytes });
* ```
*/
var Secp256r1 = /** @class */ (function () {
function Secp256r1() {
}
/**
* Adjusts an ECDSA signature to a normalized, low-S form.
*
* @remarks
* All ECDSA signatures, regardless of the curve, consist of two components, `r` and `s`, both of
* which are integers. The curve's order (the total number of points on the curve) is denoted by
* `n`. In a valid ECDSA signature, both `r` and `s` must be in the range [1, n-1]. However, due
* to the mathematical properties of ECDSA, if `(r, s)` is a valid signature, then `(r, n - s)` is
* also a valid signature for the same message and public key. In other words, for every
* signature, there's a "mirror" signature that's equally valid. For these elliptic curves:
*
* - Low S Signature: A signature where the `s` component is in the lower half of the range,
* specifically less than or equal to `n/2`.
*
* - High S Signature: This is where the `s` component is in the upper half of the range, greater
* than `n/2`.
*
* The practical implication is that a third-party can forge a second valid signature for the same
* message by negating the `s` component of the original signature, without any knowledge of the
* private key. This is known as a "signature malleability" attack.
*
* This type of forgery is not a problem in all systems, but it can be an issue in systems that
* rely on digital signature uniqueness to ensure transaction integrity. For example, in Bitcoin,
* transaction malleability is an issue because it allows for the modification of transaction
* identifiers (and potentially, transactions themselves) after they're signed but before they're
* confirmed in a block. By enforcing low `s` values, the Bitcoin network reduces the likelihood of
* this occurring, making the system more secure and predictable.
*
* For this reason, it's common practice to normalize ECDSA signatures to a low-S form. This
* form is considered standard and preferable in some systems and is known as the "normalized"
* form of the signature.
*
* This method takes a signature, and if it's high-S, returns the normalized low-S form. If the
* signature is already low-S, it's returned unmodified. It's important to note that this
* method does not change the validity of the signature but makes it compliant with systems that
* enforce low-S signatures.
*
* @example
* ```ts
* const signature = new Uint8Array([...]); // Your ECDSA signature
* const adjustedSignature = await Secp256r1.adjustSignatureToLowS({ signature });
* // Now 'adjustedSignature' is in the low-S form.
* ```
*
* @param params - The parameters for the signature adjustment.
* @param params.signature - The ECDSA signature as a `Uint8Array`.
*
* @returns A Promise that resolves to the adjusted signature in low-S form as a `Uint8Array`.
*/
Secp256r1.adjustSignatureToLowS = function (_a) {
var signature = _a.signature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, adjustedSignatureObject, adjustedSignature;
return __generator(this, function (_b) {
signatureObject = p256_1.secp256r1.Signature.fromCompact(signature);
if (signatureObject.hasHighS()) {
adjustedSignatureObject = signatureObject.normalizeS();
adjustedSignature = adjustedSignatureObject.toCompactRawBytes();
return [2 /*return*/, adjustedSignature];
}
else {
// Return the unmodified signature if it is already in low-S format.
return [2 /*return*/, signature];
}
return [2 /*return*/];
});
});
};
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a private key represented as a byte array (Uint8Array) and
* converts it into a JWK object. The conversion involves extracting the
* elliptic curve point (x and y coordinates) from the private key and encoding
* them into base64url format, alongside other JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'P-256'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await Secp256r1.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
Secp256r1.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256r1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 1:
point = _c.sent();
privateKey = {
kty: 'EC',
crv: 'P-256',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw public key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key in a byte array (Uint8Array) format and
* transforms it to a JWK object. It involves decoding the elliptic curve point
* (x and y coordinates) from the raw public key bytes and encoding them into
* base64url format, along with setting appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'P-256'.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await Secp256r1.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a Uint8Array.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256r1.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256r1.getCurvePoint({ keyBytes: publicKeyBytes })];
case 1:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'P-256',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a public key to its compressed form.
*
* @remarks
* This method takes a public key represented as a byte array and compresses it. Public key
* compression is a process that reduces the size of the public key by removing the y-coordinate,
* making it more efficient for storage and transmission. The compressed key retains the same
* level of security as the uncompressed key.
*
* @example
* ```ts
* const uncompressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual uncompressed public key bytes
* const compressedPublicKey = await Secp256r1.compressPublicKey({
* publicKeyBytes: uncompressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key compression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the compressed public key as a Uint8Array.
*/
Secp256r1.compressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = p256_1.secp256r1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the compressed form of the public key.
return [2 /*return*/, point.toRawBytes(true)];
});
});
};
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a raw
* byte array, then computing the elliptic curve point (x and y coordinates) from this private
* key. These coordinates are then encoded into base64url format to construct the public key in
* JWK format.
*
* The process ensures that the derived public key correctly corresponds to the given private key,
* adhering to the secp256r1 elliptic curve standards. This method is useful in cryptographic
* operations where a public key is needed for operations like signature verification, but only
* the private key is available.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256r1 private key
* const publicKey = await Secp256r1.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
Secp256r1.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256r1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
return [4 /*yield*/, Secp256r1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 2:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'P-256',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts an ASN.1 DER encoded ECDSA signature to a compact R+S format.
*
* @remarks
* This method is used for converting an ECDSA signature from the ASN.1 DER encoding to the more
* compact R+S format. This conversion is often required when dealing with ECDSA signatures in
* certain cryptographic standards such as JWS (JSON Web Signature).
*
* The method decodes the DER-encoded signature, extracts the R and S values, and concatenates
* them into a single byte array. This process involves handling the ASN.1 structure to correctly
* parse the R and S values, considering padding and integer encoding specifics of DER.
*
* @example
* ```ts
* const derSignature = new Uint8Array([...]); // Replace with your DER-encoded signature
* const signature = await Secp256r1.convertDerToCompactSignature({ derSignature });
* ```
*
* @param params - The parameters for the signature conversion.
* @param params.derSignature - The signature in ASN.1 DER format as a `Uint8Array`.
*
* @returns A Promise that resolves to the signature in compact R+S format as a `Uint8Array`.
*/
Secp256r1.convertDerToCompactSignature = function (_a) {
var derSignature = _a.derSignature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, compactSignature;
return __generator(this, function (_b) {
signatureObject = p256_1.secp256r1.Signature.fromDER(derSignature);
compactSignature = signatureObject.toCompactRawBytes();
return [2 /*return*/, compactSignature];
});
});
};
/**
* Converts a public key to its uncompressed form.
*
* @remarks
* This method takes a compressed public key represented as a byte array and decompresses it.
* Public key decompression involves reconstructing the y-coordinate from the x-coordinate,
* resulting in the full public key. This method is used when the uncompressed key format is
* required for certain cryptographic operations or interoperability.
*
* @example
* ```ts
* const compressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual compressed public key bytes
* const decompressedPublicKey = await Secp256r1.decompressPublicKey({
* publicKeyBytes: compressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key decompression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the uncompressed public key as a Uint8Array.
*/
Secp256r1.decompressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = p256_1.secp256r1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the uncompressed form of the public key.
return [2 /*return*/, point.toRawBytes(false)];
});
});
};
/**
* Generates a secp256r1 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the secp256r1
* elliptic curve. The key is generated using cryptographically secure random
* number generation to ensure its uniqueness and security. The resulting
* private key adheres to the JWK format, specifically tailored for secp256r1,
* making it compatible with common cryptographic standards and easy to use in
* various cryptographic processes.
*
* The private key generated by this method includes the following components:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'P-256'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, derived from the private key, base64url-encoded.
* - `y`: The y-coordinate of the public key point, derived from the private key, base64url-encoded.
*
* The key is returned in a format suitable for direct use in signin and key agreement operations.
*
* @example
* ```ts
* const privateKey = await Secp256r1.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
Secp256r1.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = p256_1.secp256r1.utils.randomPrivateKey();
return [4 /*yield*/, Secp256r1.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from a secp256r1 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 200 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256r1 private key
* const publicKey = await Secp256r1.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256r1.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an elliptic curve (EC) secp256r1 private key.
if (!((0, jwk_js_1.isEcPrivateJwk)(key) && key.crv === 'P-256')) {
throw new Error("Secp256r1: The provided key is not a 'P-256' private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a private key in JWK format and extracts its raw byte representation.
* It specifically focuses on the 'd' parameter of the JWK, which represents the private
* key component in base64url encoding. The method decodes this value into a byte array.
*
* This conversion is essential for operations that require the private key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const privateKey = { ... }; // An X25519 private key in JWK format
* const privateKeyBytes = await Secp256r1.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
Secp256r1.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC P-256 private key.
if (!(0, jwk_js_1.isEcPrivateJwk)(privateKey)) {
throw new Error("Secp256r1: The provided key is not a valid EC private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'x' and 'y' parameters of the JWK
* (which represent the x and y coordinates of the elliptic curve point, respectively)
* from base64url format into a byte array. The method then concatenates these values,
* along with a prefix indicating the key format, to form the full public key.
*
* This function is particularly useful for use cases where the public key is needed
* in its raw byte format, such as for certain cryptographic operations or when
* interfacing with systems that require raw key formats.
*
* @example
* ```ts
* const publicKey = { ... }; // A Jwk public key object
* const publicKeyBytes = await Secp256r1.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
Secp256r1.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var prefix, x, y, publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC P-256 public key, which must have a 'y' value.
if (!((0, jwk_js_1.isEcPublicJwk)(publicKey) && publicKey.y)) {
throw new Error("Secp256r1: The provided key is not a valid EC public key.");
}
prefix = new Uint8Array([0x04]);
x = common_1.Convert.base64Url(publicKey.x).toUint8Array();
y = common_1.Convert.base64Url(publicKey.y).toUint8Array();
publicKeyBytes = new Uint8Array(__spreadArray(__spreadArray(__spreadArray([], __read(prefix), false), __read(x), false), __read(y), false));
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Computes an RFC6090-compliant Elliptic Curve Diffie-Hellman (ECDH) shared secret
* using secp256r1 private and public keys in JSON Web Key (JWK) format.
*
* @remarks
* This method facilitates the ECDH key agreement protocol, which is a method of securely
* deriving a shared secret between two parties based on their private and public keys.
* It takes the private key of one party (privateKeyA) and the public key of another
* party (publicKeyB) to compute a shared secret. The shared secret is derived from the
* x-coordinate of the elliptic curve point resulting from the multiplication of the
* public key with the private key.
*
* Note: When performing Elliptic Curve Diffie-Hellman (ECDH) key agreement,
* the resulting shared secret is a point on the elliptic curve, which
* consists of an x-coordinate and a y-coordinate. With a 256-bit curve like
* secp256r1, each of these coordinates is 32 bytes (256 bits) long. However,
* in the ECDH process, it's standard practice to use only the x-coordinate
* of the shared secret point as the resulting shared key. This is because
* the y-coordinate does not add to the entropy of the key, and both parties
* can independently compute the x-coordinate. Consquently, this implementation
* omits the y-coordinate for simplicity and standard compliance.
*
* @example
* ```ts
* const privateKeyA = { ... }; // A Jwk private key object for party A
* const publicKeyB = { ... }; // A Jwk public key object for party B
* const sharedSecret = await Secp256r1.sharedSecret({
* privateKeyA,
* publicKeyB
* });
* ```
*
* @param params - The parameters for the shared secret computation.
* @param params.privateKeyA - The private key in JWK format of one party.
* @param params.publicKeyB - The public key in JWK format of the other party.
*
* @returns A Promise that resolves to the computed shared secret as a Uint8Array.
*/
Secp256r1.sharedSecret = function (_a) {
var privateKeyA = _a.privateKeyA, publicKeyB = _a.publicKeyB;
return __awaiter(this, void 0, void 0, function () {
var privateKeyABytes, publicKeyBBytes, sharedSecret;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Ensure that keys from the same key pair are not specified.
if ('x' in privateKeyA && 'x' in publicKeyB && privateKeyA.x === publicKeyB.x) {
throw new Error("Secp256r1: ECDH shared secret cannot be computed from a single key pair's public and private keys.");
}
return [4 /*yield*/, Secp256r1.privateKeyToBytes({ privateKey: privateKeyA })];
case 1:
privateKeyABytes = _b.sent();
return [4 /*yield*/, Secp256r1.publicKeyToBytes({ publicKey: publicKeyB })];
case 2:
publicKeyBBytes = _b.sent();
sharedSecret = p256_1.secp256r1.getSharedSecret(privateKeyABytes, publicKeyBBytes, true);
// Remove the leading byte that indicates the sign of the y-coordinate
// of the point on the elliptic curve. See note above.
return [2 /*return*/, sharedSecret.slice(1)];
}
});
});
};
/**
* Generates an RFC6979-compliant ECDSA signature of given data using a secp256r1 private key.
*
* @remarks
* This method signs the provided data with a specified private key using the ECDSA
* (Elliptic Curve Digital Signature Algorithm) signature algorithm, as defined in RFC6979.
* The data to be signed is first hashed using the SHA-256 algorithm, and this hash is then
* signed using the private key. The output is a digital signature in the form of a
* Uint8Array, which uniquely corresponds to both the data and the private key used for signing.
*
* This method is commonly used in cryptographic applications to ensure data integrity and
* authenticity. The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data to be signed
* const privateKey = { ... }; // A Jwk object representing a secp256r1 private key
* const signature = await Secp256r1.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign, represented as a Uint8Array.
*
* @returns A Promise that resolves to the signature as a Uint8Array.
*/
Secp256r1.sign = function (_a) {
var data = _a.data, key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, digest, signatureObject, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256r1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
signatureObject = p256_1.secp256r1.sign(digest, privateKeyBytes);
signature = signatureObject.toCompactRawBytes();
return [2 /*return*/, signature];
}
});
});
};
/**
* Validates a given private key to ensure its compliance with the secp256r1 curve standards.
*
* @remarks
* This method checks whether a provided private key is a valid 32-byte number and falls within
* the range defined by the secp256r1 curve's order. It is essential for ensuring the private
* key's mathematical correctness in the context of secp256r1-based cryptographic operations.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // A 32-byte private key
* const isValid = await Secp256r1.validatePrivateKey({ privateKeyBytes });
* console.log(isValid); // true or false based on the key's validity
* ```
*
* @param params - The parameters for the key validation.
* @param params.privateKeyBytes - The private key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the private key is valid.
*/
Secp256r1.validatePrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
return [2 /*return*/, p256_1.secp256r1.utils.isValidPrivateKey(privateKeyBytes)];
});
});
};
/**
* Validates a given public key to confirm its mathematical correctness on the secp256r1 curve.
*
* @remarks
* This method checks if the provided public key represents a valid point on the secp256r1 curve.
* It decodes the key's Weierstrass points (x and y coordinates) and verifies their validity
* against the curve's parameters. A valid point must lie on the curve and meet specific
* mathematical criteria defined by the curve's equation.
*
* It's important to note that this method does not verify the key's ownership or whether it has
* been compromised; it solely focuses on the key's adherence to the curve's mathematical
* principles.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Secp256r1.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the secp256r1 curve, false otherwise
* ```
*
* @param params - The parameters for the key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating the public key's validity on
* the secp256r1 curve.
*/
Secp256r1.validatePublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
try {
point = p256_1.secp256r1.ProjectivePoint.fromHex(publicKeyBytes);
// Check if points are on the Short Weierstrass curve.
point.assertValidity();
}
catch (error) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
});
});
};
/**
* Verifies an RFC6979-compliant ECDSA signature against given data and a secp256r1 public key.
*
* @remarks
* This method validates a digital signature to ensure that it was generated by the holder of the
* corresponding private key and that the signed data has not been altered. The signature
* verification is performed using the ECDSA (Elliptic Curve Digital Signature Algorithm) as
* specified in RFC6979. The data to be verified is first hashed using the SHA-256 algorithm, and
* this hash is then used along with the public key to verify the signature.
*
* The method returns a boolean value indicating whether the signature is valid. A valid signature
* proves that the signed data was indeed signed by the owner of the private key corresponding to
* the provided public key and that the data has not been tampered with since it was signed.
*
* Note: The verification process does not consider the malleability of low-s signatures, which
* may be relevant in certain contexts, such as Bitcoin transactions.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const isSignatureValid = await Secp256r1.verify({
* key: publicKey,
* signature,
* data
* });
* console.log(isSignatureValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key used for verification, represented in JWK format.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
Secp256r1.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, digest, isValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256r1.publicKeyToBytes({ publicKey: key })];
case 1:
publicKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
isValid = p256_1.secp256r1.verify(signature, digest, publicKeyBytes, { lowS: false });
return [2 /*return*/, isValid];
}
});
});
};
/**
* Returns the elliptic curve point (x and y coordinates) for a given secp256r1 key.
*
* @remarks
* This method extracts the elliptic curve point from a given secp256r1 key, whether
* it's a private or a public key. For a private key, the method first computes the
* corresponding public key and then extracts the x and y coordinates. For a public key,
* it directly returns these coordinates. The coordinates are represented as Uint8Array.
*
* The x and y coordinates represent the key's position on the elliptic curve and can be
* used in various cryptographic operations, such as digital signatures or key agreement
* protocols.
*
* @example
* ```ts
* // For a private key
* const privateKey = new Uint8Array([...]); // A 32-byte private key
* const { x: xFromPrivateKey, y: yFromPrivateKey } = await Secp256r1.getCurvePoint({ keyBytes: privateKey });
*
* // For a public key
* const publicKey = new Uint8Array([...]); // A 33-byte or 65-byte public key
* const { x: xFromPublicKey, y: yFromPublicKey } = await Secp256r1.getCurvePoint({ keyBytes: publicKey });
* ```
*
* @param params - The parameters for the curve point decoding operation.
* @param params.keyBytes - The key for which to get the elliptic curve point.
* Can be either a private key or a public key.
* The key should be passed as a `Uint8Array`.
*
* @returns A Promise that resolves to an object with properties 'x' and 'y',
* each being a Uint8Array representing the x and y coordinates of the key point on the
* elliptic curve.
*/
Secp256r1.getCurvePoint = function (_a) {
var keyBytes = _a.keyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, x, y;
return __generator(this, function (_b) {
// If key is a private key, first compute the public key.
if (keyBytes.byteLength === 32) {
keyBytes = p256_1.secp256r1.getPublicKey(keyBytes);
}
point = p256_1.secp256r1.ProjectivePoint.fromHex(keyBytes);
x = (0, utils_1.numberToBytesBE)(point.x, 32);
y = (0, utils_1.numberToBytesBE)(point.y, 32);
return [2 /*return*/, { x: x, y: y }];
});
});
};
return Secp256r1;
}());
exports.Secp256r1 = Secp256r1;
exports.P256 = Secp256r1;
//# sourceMappingURL=secp256r1.js.map
File diff suppressed because one or more lines are too long
+93
View File
@@ -0,0 +1,93 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sha256 = void 0;
var sha256_1 = require("@noble/hashes/sha256");
/**
* The `Sha256` class provides an interface for generating SHA-256 hash digests.
*
* This class utilizes the '@noble/hashes/sha256' function to generate hash digests
* of the provided data. The SHA-256 algorithm is widely used in cryptographic
* applications to produce a fixed-size 256-bit (32-byte) hash.
*
* The methods of this class are asynchronous and return Promises. They use the Uint8Array
* type for input data and the resulting digest, ensuring a consistent interface
* for binary data processing.
*
* @example
* ```ts
* const data = new Uint8Array([...]);
* const hash = await Sha256.digest({ data });
* ```
*/
var Sha256 = /** @class */ (function () {
function Sha256() {
}
/**
* Generates a SHA-256 hash digest for the given data.
*
* @remarks
* This method produces a hash digest using the SHA-256 algorithm. The resultant digest
* is deterministic, meaning the same data will always produce the same hash, but
* is computationally infeasible to regenerate the original data from the hash.
*
* @example
* ```ts
* const data = new Uint8Array([...]);
* const hash = await Sha256.digest({ data });
* ```
*
* @param params - The parameters for the hashing operation.
* @param params.data - The data to hash, represented as a Uint8Array.
*
* @returns A Promise that resolves to the SHA-256 hash digest of the provided data as a Uint8Array.
*/
Sha256.digest = function (_a) {
var data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var hash;
return __generator(this, function (_b) {
hash = (0, sha256_1.sha256)(data);
return [2 /*return*/, hash];
});
});
};
return Sha256;
}());
exports.Sha256 = Sha256;
//# sourceMappingURL=sha256.js.map
@@ -0,0 +1 @@
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../../src/primitives/sha256.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA8C;AAE9C;;;;;;;;;;;;;;;;GAgBG;AACH;IAAA;IA2BA,CAAC;IA1BC;;;;;;;;;;;;;;;;;;OAkBG;IACiB,aAAM,GAA1B,UAA2B,EAE1B;YAF4B,IAAI,UAAA;;;;gBAGzB,IAAI,GAAG,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC;gBAE1B,sBAAO,IAAI,EAAC;;;KACb;IACH,aAAC;AAAD,CAAC,AA3BD,IA2BC;AA3BY,wBAAM"}
+498
View File
@@ -0,0 +1,498 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.X25519 = void 0;
var common_1 = require("@web5/common");
var ed25519_1 = require("@noble/curves/ed25519");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `X25519` class provides a comprehensive suite of utilities for working with the X25519
* elliptic curve, widely used for key agreement protocols and cryptographic applications. It
* provides methods for key generation, conversion, and Elliptic Curve Diffie-Hellman (ECDH)
* key agreement, all aligned with standard cryptographic practices.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats,
* making it versatile for various cryptographic tasks. It adheres to RFC6090 for ECDH, ensuring
* secure and effective handling of keys and cryptographic operations.
*
* Key Features:
* - Key Generation: Generate X25519 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - ECDH Shared Secret Computation: Securely derive shared secrets using private and public keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await X25519.generateKey();
*
* // Public Key Derivation
* const publicKey = await X25519.computePublicKey({ key: privateKey });
* console.log(publicKey === await X25519.getPublicKey({ key: privateKey })); // Output: true
*
* // ECDH Shared Secret Computation
* const sharedSecret = await X25519.sharedSecret({
* privateKeyA: privateKey,
* publicKeyB: anotherPublicKey
* });
*
* // Key Conversion
* const publicKeyBytes = await X25519.publicKeyToBytes({ publicKey });
* const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey });
* ```
*/
var X25519 = /** @class */ (function () {
function X25519() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a private key as a byte array (Uint8Array) for the X25519 elliptic curve
* and transforms it into a JWK object. The process involves first deriving the public key from
* the private key, then encoding both the private and public keys into base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The derived public key, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await X25519.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
X25519.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKeyBytes = ed25519_1.x25519.getPublicKey(privateKeyBytes);
privateKey = {
kty: 'OKP',
crv: 'X25519',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw public key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key as a byte array (Uint8Array) for the X25519 elliptic curve
* and transforms it into a JWK object. The conversion process involves encoding the public
* key bytes into base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `x`: The public key, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await X25519.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a Uint8Array.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
X25519.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKey = {
kty: 'OKP',
crv: 'X25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Derives the public key in JWK format from a given X25519 private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a
* raw byte array and then computing the corresponding public key on the Curve25519 curve.
* The public key is then encoded into base64url format to construct a JWK representation.
*
* The process ensures that the derived public key correctly corresponds to the given private key,
* adhering to the Curve25519 elliptic curve in Twisted Edwards form standards. This method is
* useful in cryptographic operations where a public key is needed for operations like signature
* verification, but only the private key is available.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an X25519 private key
* const publicKey = await X25519.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
X25519.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, publicKeyBytes, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, X25519.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
publicKeyBytes = ed25519_1.x25519.getPublicKey(privateKeyBytes);
publicKey = {
kty: 'OKP',
crv: 'X25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Generates an X25519 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the X25519 elliptic curve.
* The key generation process involves using cryptographically secure random number generation
* to ensure the uniqueness and security of the key. The resulting private key adheres to the
* JWK format making it compatible with common cryptographic standards and easy to use in various
* cryptographic processes.
*
* The generated private key in JWK format includes the following components:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The derived public key, base64url-encoded.
*
* The key is returned in a format suitable for direct use in key agreement operations.
*
* @example
* ```ts
* const privateKey = await X25519.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
X25519.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = ed25519_1.x25519.utils.randomPrivateKey();
return [4 /*yield*/, X25519.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an X25519 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 500 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an X25519 private key
* const publicKey = await X25519.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
X25519.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an octet key pair (OKP) X25519 private key.
if (!((0, jwk_js_1.isOkpPrivateJwk)(key) && key.crv === 'X25519')) {
throw new Error("X25519: The provided key is not an X25519 private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a private key in JWK format and extracts its raw byte representation.
*
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'd' parameter of the JWK
* from base64url format into a byte array.
*
* This conversion is essential for operations that require the private key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const privateKey = { ... }; // An X25519 private key in JWK format
* const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
X25519.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP private key.
if (!(0, jwk_js_1.isOkpPrivateJwk)(privateKey)) {
throw new Error("X25519: The provided key is not a valid OKP private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary form.
* The conversion process involves decoding the 'x' parameter of the JWK (which represent the
* x coordinate of the elliptic curve point) from base64url format into a byte array.
*
* This conversion is essential for operations that require the public key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const publicKey = { ... }; // An X25519 public key in JWK format
* const publicKeyBytes = await X25519.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
X25519.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP public key.
if (!(0, jwk_js_1.isOkpPublicJwk)(publicKey)) {
throw new Error("X25519: The provided key is not a valid OKP public key.");
}
publicKeyBytes = common_1.Convert.base64Url(publicKey.x).toUint8Array();
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Computes an RFC6090-compliant Elliptic Curve Diffie-Hellman (ECDH) shared secret
* using secp256k1 private and public keys in JSON Web Key (JWK) format.
*
* @remarks
* This method facilitates the ECDH key agreement protocol, which is a method of securely
* deriving a shared secret between two parties based on their private and public keys.
* It takes the private key of one party (privateKeyA) and the public key of another
* party (publicKeyB) to compute a shared secret. The shared secret is derived from the
* x-coordinate of the elliptic curve point resulting from the multiplication of the
* public key with the private key.
*
* Note: When performing Elliptic Curve Diffie-Hellman (ECDH) key agreement,
* the resulting shared secret is a point on the elliptic curve, which
* consists of an x-coordinate and a y-coordinate. With a 256-bit curve like
* secp256k1, each of these coordinates is 32 bytes (256 bits) long. However,
* in the ECDH process, it's standard practice to use only the x-coordinate
* of the shared secret point as the resulting shared key. This is because
* the y-coordinate does not add to the entropy of the key, and both parties
* can independently compute the x-coordinate. Consquently, this implementation
* omits the y-coordinate for simplicity and standard compliance.
*
* @example
* ```ts
* const privateKeyA = { ... }; // A Jwk object for party A
* const publicKeyB = { ... }; // A PublicKeyJwk object for party B
* const sharedSecret = await Secp256k1.sharedSecret({
* privateKeyA,
* publicKeyB
* });
* ```
*
* @param params - The parameters for the shared secret computation.
* @param params.privateKeyA - The private key in JWK format of one party.
* @param params.publicKeyB - The public key in JWK format of the other party.
*
* @returns A Promise that resolves to the computed shared secret as a Uint8Array.
*/
X25519.sharedSecret = function (_a) {
var privateKeyA = _a.privateKeyA, publicKeyB = _a.publicKeyB;
return __awaiter(this, void 0, void 0, function () {
var privateKeyABytes, publicKeyBBytes, sharedSecret;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Ensure that keys from the same key pair are not specified.
if ('x' in privateKeyA && 'x' in publicKeyB && privateKeyA.x === publicKeyB.x) {
throw new Error("X25519: ECDH shared secret cannot be computed from a single key pair's public and private keys.");
}
return [4 /*yield*/, X25519.privateKeyToBytes({ privateKey: privateKeyA })];
case 1:
privateKeyABytes = _b.sent();
return [4 /*yield*/, X25519.publicKeyToBytes({ publicKey: publicKeyB })];
case 2:
publicKeyBBytes = _b.sent();
sharedSecret = ed25519_1.x25519.getSharedSecret(privateKeyABytes, publicKeyBBytes);
return [2 /*return*/, sharedSecret];
}
});
});
};
return X25519;
}());
exports.X25519 = X25519;
//# sourceMappingURL=x25519.js.map
@@ -0,0 +1 @@
{"version":3,"file":"x25519.js","sourceRoot":"","sources":["../../../src/primitives/x25519.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,iDAA+C;AAK/C,yCAAuF;AAEvF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH;IAAA;IAmWA,CAAC;IAlWC;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACiB,wBAAiB,GAArC,UAAsC,EAErC;YAFuC,eAAe,qBAAA;;;;;;wBAI/C,cAAc,GAAI,gBAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;wBAGvD,UAAU,GAAQ;4BACtB,GAAG,EAAG,KAAK;4BACX,GAAG,EAAG,QAAQ;4BACd,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE;4BACvD,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE;yBACvD,CAAC;wBAEF,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACiB,uBAAgB,GAApC,UAAqC,EAEpC;YAFsC,cAAc,oBAAA;;;;;;wBAI7C,SAAS,GAAQ;4BACrB,GAAG,EAAG,KAAK;4BACX,GAAG,EAAG,QAAQ;4BACd,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE;yBACvD,CAAC;wBAEF,oDAAoD;wBACpD,KAAA,SAAS,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAA;;wBAD9D,oDAAoD;wBACpD,GAAU,GAAG,GAAG,SAA8C,CAAC;wBAE/D,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACiB,uBAAgB,GAApC,UAAqC,EACb;YADe,GAAG,SAAA;;;;;4BAIf,qBAAM,MAAM,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAA;;wBAAtE,eAAe,GAAI,SAAmD;wBAGtE,cAAc,GAAG,gBAAM,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;wBAGtD,SAAS,GAAQ;4BACrB,GAAG,EAAG,KAAK;4BACX,GAAG,EAAG,QAAQ;4BACd,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE;yBACvD,CAAC;wBAEF,oDAAoD;wBACpD,KAAA,SAAS,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAA;;wBAD9D,oDAAoD;wBACpD,GAAU,GAAG,GAAG,SAA8C,CAAC;wBAE/D,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACiB,kBAAW,GAA/B;;;;;;wBAEQ,eAAe,GAAG,gBAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;wBAGrC,qBAAM,MAAM,CAAC,iBAAiB,CAAC,EAAE,eAAe,iBAAA,EAAE,CAAC,EAAA;;wBAAhE,UAAU,GAAG,SAAmD;wBAEtE,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACiB,mBAAY,GAAhC,UAAiC,EACb;;YADe,GAAG,SAAA;;;;;;wBAGtC,iFAAiF;wBAC/E,IAAI,CAAC,CAAC,IAAA,wBAAe,EAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,EAAE;4BACnD,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;yBAC3E;wBAGK,CAAC,GAAmB,GAAG,EAAtB,EAAK,SAAS,UAAK,GAAG,EAAzB,KAAmB,CAAF,CAAS;;wBAE9B,4DAA4D;wBAC5D,SAAS,CAAC,GAAG;;;;wBADb,4DAA4D;wBAC5D,KAAA,SAAS,CAAA;wBAAS,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAA;;iCAAtD,GAAG,GAAK,SAA8C;;;wBADhE,4DAA4D;wBAC5D,GAAiE;wBAEjE,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACiB,wBAAiB,GAArC,UAAsC,EAErC;YAFuC,UAAU,gBAAA;;;;gBAGhD,8DAA8D;gBAC9D,IAAI,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,EAAE;oBAChC,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;iBAC7E;gBAGK,eAAe,GAAG,gBAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;gBAEvE,sBAAO,eAAe,EAAC;;;KACxB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACiB,uBAAgB,GAApC,UAAqC,EAEpC;YAFsC,SAAS,eAAA;;;;gBAG9C,6DAA6D;gBAC7D,IAAI,CAAC,IAAA,uBAAc,EAAC,SAAS,CAAC,EAAE;oBAC9B,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;iBAC5E;gBAGK,cAAc,GAAG,gBAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;gBAErE,sBAAO,cAAc,EAAC;;;KACvB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACiB,mBAAY,GAAhC,UAAiC,EAGhC;YAHkC,WAAW,iBAAA,EAAE,UAAU,gBAAA;;;;;;wBAIxD,6DAA6D;wBAC7D,IAAI,GAAG,IAAI,WAAW,IAAI,GAAG,IAAI,UAAU,IAAI,WAAW,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,EAAE;4BAC7E,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAC;yBACpH;wBAGwB,qBAAM,MAAM,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,EAAA;;wBAA9E,gBAAgB,GAAG,SAA2D;wBAC5D,qBAAM,MAAM,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAA;;wBAA1E,eAAe,GAAG,SAAwD;wBAG1E,YAAY,GAAG,gBAAM,CAAC,eAAe,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;wBAE/E,sBAAO,YAAY,EAAC;;;;KACrB;IACH,aAAC;AAAD,CAAC,AAnWD,IAmWC;AAnWY,wBAAM"}
@@ -0,0 +1,340 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XChaCha20Poly1305 = exports.POLY1305_TAG_LENGTH = void 0;
var common_1 = require("@web5/common");
var chacha_1 = require("@noble/ciphers/chacha");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* Constant defining the length of the authentication tag in bytes for XChaCha20-Poly1305.
*
* @remarks
* The `POLY1305_TAG_LENGTH` is set to 16 bytes (128 bits), which is the standard size for the
* Poly1305 authentication tag in XChaCha20-Poly1305 encryption. This tag length ensures
* a strong level of security for message authentication, verifying the integrity and
* authenticity of the data during decryption.
*/
exports.POLY1305_TAG_LENGTH = 16;
/**
* The `XChaCha20Poly1305` class provides a suite of utilities for cryptographic operations
* using the XChaCha20-Poly1305 algorithm, a combination of the XChaCha20 stream cipher and the
* Poly1305 message authentication code (MAC). This class encompasses methods for key generation,
* encryption, decryption, and conversions between raw byte arrays and JSON Web Key (JWK) formats.
*
* XChaCha20-Poly1305 is renowned for its high security and efficiency, especially in scenarios
* involving large data volumes or where data integrity and confidentiality are paramount. The
* extended nonce size of XChaCha20 reduces the risks of nonce reuse, while Poly1305 provides
* a strong MAC ensuring data integrity.
*
* Key Features:
* - Key Generation: Generate XChaCha20-Poly1305 symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using XChaCha20-Poly1305, returning both ciphertext and MAC tag.
* - Decryption: Decrypt data and verify integrity using the XChaCha20-Poly1305 algorithm.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await XChaCha20Poly1305.generateKey();
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce
* const additionalData = new TextEncoder().encode('Associated data');
* const { ciphertext, tag } = await XChaCha20Poly1305.encrypt({
* data,
* nonce,
* additionalData,
* key: privateKey
* });
*
* // Decryption
* const decryptedData = await XChaCha20Poly1305.decrypt({
* data: ciphertext,
* nonce,
* tag,
* additionalData,
* key: privateKey
* });
*
* // Key Conversion
* const privateKeyBytes = await XChaCha20Poly1305.privateKeyToBytes({ privateKey });
* ```
*/
var XChaCha20Poly1305 = /** @class */ (function () {
function XChaCha20Poly1305() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a symmetric key represented as a byte array (Uint8Array) and converts it into
* a JWK object for use with the XChaCha20-Poly1305 algorithm. The process involves encoding the
* key into base64url format and setting the appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await XChaCha20Poly1305.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
XChaCha20Poly1305.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using XChaCha20-Poly1305.
*
* @remarks
* This method performs XChaCha20-Poly1305 decryption on the given encrypted data using the
* specified key, nonce, and authentication tag. It supports optional additional authenticated
* data (AAD) for enhanced security. The nonce must be 24 bytes long, consistent with XChaCha20's
* specifications.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const nonce = new Uint8Array(24); // 24-byte nonce
* const additionalData = new Uint8Array([...]); // Optional AAD
* const key = { ... }; // A Jwk object representing the XChaCha20-Poly1305 key
* const decryptedData = await XChaCha20Poly1305.decrypt({
* data: encryptedData,
* nonce,
* additionalData,
* key
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.data - The encrypted data to decrypt including the authentication tag,
* represented as a Uint8Array.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.nonce - The nonce used during the encryption process.
* @param params.additionalData - Optional additional authenticated data.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
XChaCha20Poly1305.decrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce, additionalData = _a.additionalData;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, xc20p, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20Poly1305.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
xc20p = (0, chacha_1.xchacha20poly1305)(privateKeyBytes, nonce, additionalData);
plaintext = xc20p.decrypt(data);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Encrypts the provided data using XChaCha20-Poly1305.
*
* @remarks
* This method performs XChaCha20-Poly1305 encryption on the given data using the specified key
* and nonce. It supports optional additional authenticated data (AAD) for enhanced security. The
* nonce must be 24 bytes long, as per XChaCha20's specifications. The method returns the
* encrypted data along with an authentication tag as a Uint8Array, ensuring both confidentiality
* and integrity of the data.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce
* const additionalData = new TextEncoder().encode('Associated data'); // Optional AAD
* const key = { ... }; // A Jwk object representing an XChaCha20-Poly1305 key
* const encryptedData = await XChaCha20Poly1305.encrypt({
* data,
* nonce,
* additionalData,
* key
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.nonce - A 24-byte nonce for the encryption process.
* @param params.additionalData - Optional additional authenticated data.
*
* @returns A Promise that resolves to a byte array containing the encrypted data and the
* authentication tag.
*/
XChaCha20Poly1305.encrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce, additionalData = _a.additionalData;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, xc20p, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20Poly1305.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
xc20p = (0, chacha_1.xchacha20poly1305)(privateKeyBytes, nonce, additionalData);
ciphertext = xc20p.encrypt(data);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Generates a symmetric key for XChaCha20-Poly1305 in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key suitable for use with the XChaCha20-Poly1305 algorithm.
* The key is generated using cryptographically secure random number generation to ensure its
* uniqueness and security. The XChaCha20-Poly1305 algorithm requires a 256-bit key (32 bytes),
* and this method adheres to that specification.
*
* Key components included in the JWK:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKey = await XChaCha20Poly1305.generateKey();
* ```
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
XChaCha20Poly1305.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _a, alg, ext, key_ops, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-CTR', length: 256 }, true, ['encrypt'])];
case 1:
webCryptoKey = _c.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_a = _c.sent(), alg = _a.alg, ext = _a.ext, key_ops = _a.key_ops, privateKey = __rest(_a, ["alg", "ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
* encoding, into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await XChaCha20Poly1305.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
XChaCha20Poly1305.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("XChaCha20Poly1305: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return XChaCha20Poly1305;
}());
exports.XChaCha20Poly1305 = XChaCha20Poly1305;
//# sourceMappingURL=xchacha20-poly1305.js.map
@@ -0,0 +1 @@
{"version":3,"file":"xchacha20-poly1305.js","sourceRoot":"","sources":["../../../src/primitives/xchacha20-poly1305.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,gDAA0D;AAC1D,wDAAoE;AAIpE,yCAAuE;AAEvE;;;;;;;;GAQG;AACU,QAAA,mBAAmB,GAAG,EAAE,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH;IAAA;IA6MA,CAAC;IA5MC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACiB,mCAAiB,GAArC,UAAsC,EAErC;YAFuC,eAAe,qBAAA;;;;;;wBAI/C,UAAU,GAAQ;4BACtB,CAAC,EAAK,gBAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE;4BACvD,GAAG,EAAG,KAAK;yBACZ,CAAC;wBAEF,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACiB,yBAAO,GAA3B,UAA4B,EAK3B;YAL6B,IAAI,UAAA,EAAE,GAAG,SAAA,EAAE,KAAK,WAAA,EAAE,cAAc,oBAAA;;;;;4BAOpC,qBAAM,iBAAiB,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAA;;wBAAhF,eAAe,GAAG,SAA8D;wBAEhF,KAAK,GAAG,IAAA,0BAAiB,EAAC,eAAe,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;wBAClE,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;wBAEtC,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACiB,yBAAO,GAA3B,UAA4B,EAK3B;YAL6B,IAAI,UAAA,EAAE,GAAG,SAAA,EAAE,KAAK,WAAA,EAAE,cAAc,oBAAA;;;;;4BAOpC,qBAAM,iBAAiB,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAA;;wBAAhF,eAAe,GAAG,SAA8D;wBAEhF,KAAK,GAAG,IAAA,0BAAiB,EAAC,eAAe,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;wBAClE,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;wBAEvC,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACiB,6BAAW,GAA/B;;;;;;wBAEQ,SAAS,GAAG,IAAA,0BAAkB,GAAE,CAAC;wBAKlB,qBAAM,SAAS,CAAC,WAAW,CAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAA;;wBAAhG,YAAY,GAAG,SAAiF;wBAGzD,qBAAM,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,EAAA;;wBAArF,KAAuC,SAA8C,EAAnF,GAAG,SAAA,EAAE,GAAG,SAAA,EAAE,OAAO,aAAA,EAAK,UAAU,cAAlC,yBAAoC,CAAF;wBAExC,oDAAoD;wBACpD,KAAA,UAAU,CAAA;wBAAO,qBAAM,IAAA,6BAAoB,EAAC,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAA;;wBADhE,oDAAoD;wBACpD,GAAW,GAAG,GAAG,SAA+C,CAAC;wBAEjE,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACiB,mCAAiB,GAArC,UAAsC,EAErC;YAFuC,UAAU,gBAAA;;;;gBAGhD,8DAA8D;gBAC9D,IAAI,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,EAAE;oBAChC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;iBACxF;gBAGK,eAAe,GAAG,gBAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;gBAEvE,sBAAO,eAAe,EAAC;;;KACxB;IACH,wBAAC;AAAD,CAAC,AA7MD,IA6MC;AA7MY,8CAAiB"}
@@ -0,0 +1,316 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XChaCha20 = void 0;
var common_1 = require("@web5/common");
var chacha_1 = require("@noble/ciphers/chacha");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `XChaCha20` class provides a comprehensive suite of utilities for cryptographic operations
* using the XChaCha20 symmetric encryption algorithm. This class includes methods for key
* generation, encryption, decryption, and conversions between raw byte arrays and JSON Web Key
* (JWK) formats. XChaCha20 is an extended nonce variant of ChaCha20, a stream cipher designed for
* high-speed encryption with substantial security margins.
*
* The XChaCha20 algorithm is particularly well-suited for encrypting large volumes of data or
* data streams, especially where random access is required. The class adheres to standard
* cryptographic practices, ensuring robustness and security in its implementations.
*
* Key Features:
* - Key Generation: Generate XChaCha20 symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using XChaCha20 with the provided symmetric key.
* - Decryption: Decrypt data encrypted with XChaCha20 using the corresponding symmetric key.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await XChaCha20.generateKey();
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce for XChaCha20
* const encryptedData = await XChaCha20.encrypt({
* data,
* nonce,
* key: privateKey
* });
*
* // Decryption
* const decryptedData = await XChaCha20.decrypt({
* data: encryptedData,
* nonce,
* key: privateKey
* });
*
* // Key Conversion
* const privateKeyBytes = await XChaCha20.privateKeyToBytes({ privateKey });
* ```
*/
var XChaCha20 = /** @class */ (function () {
function XChaCha20() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a symmetric key represented as a byte array (Uint8Array) and
* converts it into a JWK object for use with the XChaCha20 symmetric encryption algorithm. The
* conversion process involves encoding the key into base64url format and setting the appropriate
* JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await XChaCha20.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
XChaCha20.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using XChaCha20.
*
* @remarks
* This method performs XChaCha20 decryption on the given encrypted data using the specified key
* and nonce. The nonce should be the same as used in the encryption process and must be 24 bytes
* long. The method returns the decrypted data as a Uint8Array.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const nonce = new Uint8Array(24); // 24-byte nonce used during encryption
* const key = { ... }; // A Jwk object representing the XChaCha20 key
* const decryptedData = await XChaCha20.decrypt({
* data: encryptedData,
* nonce,
* key
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.data - The encrypted data to decrypt, represented as a Uint8Array.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.nonce - The nonce used during the encryption process.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
XChaCha20.decrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
ciphertext = (0, chacha_1.xchacha20)(privateKeyBytes, nonce, data);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Encrypts the provided data using XChaCha20.
*
* @remarks
* This method performs XChaCha20 encryption on the given data using the specified key and nonce.
* The nonce must be 24 bytes long, ensuring a high level of security through a vast nonce space,
* reducing the risks associated with nonce reuse. The method returns the encrypted data as a
* Uint8Array.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce for XChaCha20
* const key = { ... }; // A Jwk object representing an XChaCha20 key
* const encryptedData = await XChaCha20.encrypt({
* data,
* nonce,
* key
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.nonce - A 24-byte nonce for the encryption process.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
XChaCha20.encrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
plaintext = (0, chacha_1.xchacha20)(privateKeyBytes, nonce, data);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Generates a symmetric key for XChaCha20 in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key suitable for use with the XChaCha20 encryption
* algorithm. The key is generated using cryptographically secure random number generation
* to ensure its uniqueness and security. The XChaCha20 algorithm requires a 256-bit key
* (32 bytes), and this method adheres to that specification.
*
* Key components included in the JWK:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKey = await XChaCha20.generateKey();
* ```
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
XChaCha20.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _a, alg, ext, key_ops, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-CTR', length: 256 }, true, ['encrypt'])];
case 1:
webCryptoKey = _c.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_a = _c.sent(), alg = _a.alg, ext = _a.ext, key_ops = _a.key_ops, privateKey = __rest(_a, ["alg", "ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
* encoding, into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await XChaCha20.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
XChaCha20.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("XChaCha20: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return XChaCha20;
}());
exports.XChaCha20 = XChaCha20;
//# sourceMappingURL=xchacha20.js.map
@@ -0,0 +1 @@
{"version":3,"file":"xchacha20.js","sourceRoot":"","sources":["../../../src/primitives/xchacha20.ts"],"names":[],"mappings":"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"}