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
@@ -0,0 +1,188 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
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.AesCtrAlgorithm = void 0;
var aes_ctr_js_1 = require("../primitives/aes-ctr.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
/**
* The `AesCtrAlgorithm` class provides a concrete implementation for cryptographic operations using
* the AES algorithm in Counter (CTR) mode. This class implements both {@link Cipher | `Cipher`} and
* { @link KeyGenerator | `KeyGenerator`} interfaces, providing key generation, encryption, and
* decryption features.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var AesCtrAlgorithm = /** @class */ (function (_super) {
__extends(AesCtrAlgorithm, _super);
function AesCtrAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Decrypts the provided data using AES-CTR.
*
* @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 aesCtr = new AesCtrAlgorithm();
* 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: 128 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesCtrAlgorithm.prototype.decrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var plaintext;
return __generator(this, function (_a) {
plaintext = aes_ctr_js_1.AesCtr.decrypt(params);
return [2 /*return*/, plaintext];
});
});
};
/**
* Encrypts the provided data using AES-CTR.
*
* @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 aesCtr = new AesCtrAlgorithm();
* 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: 128 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesCtrAlgorithm.prototype.encrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var ciphertext;
return __generator(this, function (_a) {
ciphertext = aes_ctr_js_1.AesCtr.encrypt(params);
return [2 /*return*/, ciphertext];
});
});
};
/**
* Generates a symmetric key for AES in Counter (CTR) mode in JSON Web Key (JWK) format.
*
* @remarks
* This method generates a symmetric AES key for use in CTR mode, based on the specified
* `algorithm` parameter which determines the key length. It uses cryptographically secure random
* number generation to ensure the uniqueness and security of the key. The key is returned in JWK
* format.
*
* 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 aesCtr = new AesCtrAlgorithm();
* const privateKey = await aesCtr.generateKey({ algorithm: 'A256CTR' });
* ```
*
* @param params - The parameters for the key generation.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesCtrAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var length, privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
length = { A128CTR: 128, A192CTR: 192, A256CTR: 256 }[algorithm];
return [4 /*yield*/, aes_ctr_js_1.AesCtr.generateKey({ length: length })];
case 1:
privateKey = _b.sent();
// Set the `alg` property based on the specified algorithm.
privateKey.alg = algorithm;
return [2 /*return*/, privateKey];
}
});
});
};
return AesCtrAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.AesCtrAlgorithm = AesCtrAlgorithm;
//# sourceMappingURL=aes-ctr.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-ctr.js","sourceRoot":"","sources":["../../../src/algorithms/aes-ctr.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,uDAAkD;AAClD,6DAAwD;AA4BxD;;;;;;;;GAQG;AACH;IAAqC,mCAAe;IAApD;;IAgHA,CAAC;IA5GC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,SAAS,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAEzC,sBAAO,SAAS,EAAC;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,UAAU,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE1C,sBAAO,UAAU,EAAC;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,qCAAW,GAAxB,UAAyB,EACA;YADE,SAAS,eAAA;;;;;;wBAI5B,MAAM,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAoB,CAAC;wBAGvE,qBAAM,mBAAM,CAAC,WAAW,CAAC,EAAE,MAAM,QAAA,EAAE,CAAC,EAAA;;wBAAjD,UAAU,GAAG,SAAoC;wBAEvD,2DAA2D;wBAC3D,UAAU,CAAC,GAAG,GAAG,SAAS,CAAC;wBAE3B,sBAAO,UAAU,EAAC;;;;KACnB;IACH,sBAAC;AAAD,CAAC,AAhHD,CAAqC,qCAAe,GAgHnD;AAhHY,0CAAe"}
@@ -0,0 +1,196 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
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.AesGcmAlgorithm = void 0;
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
var aes_gcm_js_1 = require("../primitives/aes-gcm.js");
/**
* The `AesGcmAlgorithm` class provides a concrete implementation for cryptographic operations using
* the AES algorithm in Galois/Counter Mode (GCM). This class implements both
* {@link Cipher | `Cipher`} and { @link KeyGenerator | `KeyGenerator`} interfaces, providing
* key generation, encryption, and decryption features.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var AesGcmAlgorithm = /** @class */ (function (_super) {
__extends(AesGcmAlgorithm, _super);
function AesGcmAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* 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 aesGcm = new AesGcmAlgorithm();
* 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.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesGcmAlgorithm.prototype.decrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var plaintext;
return __generator(this, function (_a) {
plaintext = aes_gcm_js_1.AesGcm.decrypt(params);
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 aesGcm = new AesGcmAlgorithm();
* 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.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesGcmAlgorithm.prototype.encrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var ciphertext;
return __generator(this, function (_a) {
ciphertext = aes_gcm_js_1.AesGcm.encrypt(params);
return [2 /*return*/, ciphertext];
});
});
};
/**
* Generates a symmetric key for AES in Galois/Counter Mode (GCM) in JSON Web Key (JWK) format.
*
* @remarks
* This method generates a symmetric AES key for use in GCM mode, based on the specified
* `algorithm` parameter which determines the key length. It uses cryptographically secure random
* number generation to ensure the uniqueness and security of the key. The key is returned in JWK
* format.
*
* 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 aesGcm = new AesGcmAlgorithm();
* const privateKey = await aesGcm.generateKey({ algorithm: 'A256GCM' });
* ```
*
* @param params - The parameters for the key generation.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesGcmAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var length, privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
length = { A128GCM: 128, A192GCM: 192, A256GCM: 256 }[algorithm];
return [4 /*yield*/, aes_gcm_js_1.AesGcm.generateKey({ length: length })];
case 1:
privateKey = _b.sent();
// Set the `alg` property based on the specified algorithm.
privateKey.alg = algorithm;
return [2 /*return*/, privateKey];
}
});
});
};
return AesGcmAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.AesGcmAlgorithm = AesGcmAlgorithm;
//# sourceMappingURL=aes-gcm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-gcm.js","sourceRoot":"","sources":["../../../src/algorithms/aes-gcm.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,6DAAwD;AACxD,uDAAuE;AAmDvE;;;;;;;;GAQG;AACH;IAAqC,mCAAe;IAApD;;IAwHA,CAAC;IApHC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,SAAS,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAEzC,sBAAO,SAAS,EAAC;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,UAAU,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE1C,sBAAO,UAAU,EAAC;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,qCAAW,GAAxB,UAAyB,EACA;YADE,SAAS,eAAA;;;;;;wBAI5B,MAAM,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAoB,CAAC;wBAGvE,qBAAM,mBAAM,CAAC,WAAW,CAAC,EAAE,MAAM,QAAA,EAAE,CAAC,EAAA;;wBAAjD,UAAU,GAAG,SAAoC;wBAEvD,2DAA2D;wBAC3D,UAAU,CAAC,GAAG,GAAG,SAAS,CAAC;wBAE3B,sBAAO,UAAU,EAAC;;;;KACnB;IACH,sBAAC;AAAD,CAAC,AAxHD,CAAqC,qCAAe,GAwHnD;AAxHY,0CAAe"}
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CryptoAlgorithm = void 0;
/**
* Base class for all cryptographic algorithm implementations.
*/
var CryptoAlgorithm = /** @class */ (function () {
function CryptoAlgorithm() {
}
return CryptoAlgorithm;
}());
exports.CryptoAlgorithm = CryptoAlgorithm;
//# sourceMappingURL=crypto-algorithm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"crypto-algorithm.js","sourceRoot":"","sources":["../../../src/algorithms/crypto-algorithm.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH;IAAA;IAAuC,CAAC;IAAD,sBAAC;AAAD,CAAC,AAAxC,IAAwC;AAAlB,0CAAe"}
+352
View File
@@ -0,0 +1,352 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
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.EcdsaAlgorithm = void 0;
var secp256k1_js_1 = require("../primitives/secp256k1.js");
var secp256r1_js_1 = require("../primitives/secp256r1.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `EcdsaAlgorithm` class provides a concrete implementation for cryptographic operations using
* the Elliptic Curve Digital Signature Algorithm (ECDSA). This class implements both
* {@link Signer | `Signer`} and { @link AsymmetricKeyGenerator | `AsymmetricKeyGenerator`}
* interfaces, providing private key generation, public key derivation, and creation/verification
* of signatures.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var EcdsaAlgorithm = /** @class */ (function (_super) {
__extends(EcdsaAlgorithm, _super);
function EcdsaAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* 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 process ensures that the derived public key correctly corresponds to
* the given private key.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await ecdsa.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.
*/
EcdsaAlgorithm.prototype.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.computePublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'ES256K';
return [2 /*return*/, publicKey];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.computePublicKey({ key: key })];
case 4:
publicKey = _c.sent();
publicKey.alg = 'ES256';
return [2 /*return*/, publicKey];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
/**
* Generates a new private key with the specified algorithm in JSON Web Key (JWK) format.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = await ecdsa.generateKey({ algorithm: 'ES256K' });
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation.
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
EcdsaAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var _b, privateKey, privateKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = algorithm;
switch (_b) {
case 'ES256K': return [3 /*break*/, 1];
case 'secp256k1': return [3 /*break*/, 1];
case 'ES256': return [3 /*break*/, 3];
case 'secp256r1': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.generateKey()];
case 2:
privateKey = _c.sent();
privateKey.alg = 'ES256K';
return [2 /*return*/, privateKey];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.generateKey()];
case 4:
privateKey = _c.sent();
privateKey.alg = 'ES256';
return [2 /*return*/, privateKey];
case 5: return [2 /*return*/];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an ECDSA 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.
*
* 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 ecdsa = new EcdsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await ecdsa.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.
*/
EcdsaAlgorithm.prototype.getPublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.getPublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'ES256K';
return [2 /*return*/, publicKey];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.getPublicKey({ key: key })];
case 4:
publicKey = _c.sent();
publicKey.alg = 'ES256';
return [2 /*return*/, publicKey];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
/**
* Generates an ECDSA signature of given data using a private key.
*
* @remarks
* This method uses the signature algorithm determined by the given `algorithm` to sign the
* provided data.
*
* 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 ecdsa = new EcdsaAlgorithm();
* const data = new TextEncoder().encode('Message');
* const privateKey = { ... }; // A Jwk object representing a private key
* const signature = await ecdsa.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.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
EcdsaAlgorithm.prototype.sign = function (_a) {
var key = _a.key, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.sign({ key: key, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.sign({ key: key, data: data })];
case 4: return [2 /*return*/, _c.sent()];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
/**
* Verifies an ECDSA signature associated with the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `crv` property of the provided key
* to check the validity of a digital signature against the original data. It confirms whether the
* signature was created by the holder of the corresponding private key and that the data has not
* been tampered with.
*s
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const data = new TextEncoder().encode('Message');
* const isValid = await ecdsa.verify({
* key: publicKey,
* signature,
* data
* });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
EcdsaAlgorithm.prototype.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPublicJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) public key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.verify({ key: key, signature: signature, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.verify({ key: key, signature: signature, data: data })];
case 4: return [2 /*return*/, _c.sent()];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
return EcdsaAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.EcdsaAlgorithm = EcdsaAlgorithm;
//# sourceMappingURL=ecdsa.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ecdsa.js","sourceRoot":"","sources":["../../../src/algorithms/ecdsa.ts"],"names":[],"mappings":"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"}
+325
View File
@@ -0,0 +1,325 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
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.EdDsaAlgorithm = void 0;
var ed25519_js_1 = require("../primitives/ed25519.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `EdDsaAlgorithm` class provides a concrete implementation for cryptographic operations using
* the Edwards-curve Digital Signature Algorithm (EdDSA). This class implements both
* {@link Signer | `Signer`} and { @link AsymmetricKeyGenerator | `AsymmetricKeyGenerator`}
* interfaces, providing private key generation, public key derivation, and creation/verification
* of signatures.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var EdDsaAlgorithm = /** @class */ (function (_super) {
__extends(EdDsaAlgorithm, _super);
function EdDsaAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* 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 process ensures that the derived public key correctly corresponds to
* the given private key.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await eddsa.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.
*/
EdDsaAlgorithm.prototype.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.computePublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'EdDSA';
return [2 /*return*/, publicKey];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Generates a new private key with the specified algorithm in JSON Web Key (JWK) format.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = await eddsa.generateKey({ algorithm: 'Ed25519' });
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation.
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
EdDsaAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var _b, privateKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = algorithm;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.generateKey()];
case 2:
privateKey = _c.sent();
privateKey.alg = 'EdDSA';
return [2 /*return*/, privateKey];
case 3: return [2 /*return*/];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an EdDSA 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.
*
* 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 eddsa = new EdDsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await eddsa.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.
*/
EdDsaAlgorithm.prototype.getPublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.getPublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'EdDSA';
return [2 /*return*/, publicKey];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Generates an EdDSA signature of given data using a private key.
*
* @remarks
* This method uses the signature algorithm determined by the given `algorithm` to sign the
* provided data.
*
* 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 eddsa = new EdDsaAlgorithm();
* const data = new TextEncoder().encode('Message');
* const privateKey = { ... }; // A Jwk object representing a private key
* const signature = await eddsa.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.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
EdDsaAlgorithm.prototype.sign = function (_a) {
var key = _a.key, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.sign({ key: key, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Verifies an EdDSA signature associated with the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `crv` property of the provided key
* to check the validity of a digital signature against the original data. It confirms whether the
* signature was created by the holder of the corresponding private key and that the data has not
* been tampered with.
*s
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const data = new TextEncoder().encode('Message');
* const isValid = await eddsa.verify({
* key: publicKey,
* signature,
* data
* });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
EdDsaAlgorithm.prototype.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPublicJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) public key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.verify({ key: key, signature: signature, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
return EdDsaAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.EdDsaAlgorithm = EdDsaAlgorithm;
//# sourceMappingURL=eddsa.js.map
@@ -0,0 +1 @@
{"version":3,"file":"eddsa.js","sourceRoot":"","sources":["../../../src/algorithms/eddsa.ts"],"names":[],"mappings":"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"}
+119
View File
@@ -0,0 +1,119 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
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.Sha2Algorithm = void 0;
var sha256_js_1 = require("../primitives/sha256.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
/**
* The `Sha2Algorithm` class is an implementation of the {@link Hasher | `Hasher`} interface for the
* SHA-2 family of cryptographic hash functions. The `digest` method takes the algorithm identifier
* of the hash function and arbitrary data as input and returns the hash digest of the data.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var Sha2Algorithm = /** @class */ (function (_super) {
__extends(Sha2Algorithm, _super);
function Sha2Algorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Generates a hash digest of the provided data.
*
* @remarks
* A digest is the output of the hash function. It's a fixed-size string of bytes
* that uniquely represents the data input into the hash function. The digest is often used for
* data integrity checks, as any alteration in the input data results in a significantly
* different digest.
*
* It takes the algorithm identifier of the hash function and data to digest as input and returns
* the digest of the data.
*
* @example
* ```ts
* const sha2 = new Sha2Algorithm();
* const data = new TextEncoder().encode('Messsage');
* const digest = await sha2.digest({ data });
* ```
*
* @param params - The parameters for the digest operation.
* @param params.algorithm - The name of hash function to use.
* @param params.data - The data to digest.
*
* @returns A Promise which will be fulfilled with the hash digest.
*/
Sha2Algorithm.prototype.digest = function (_a) {
var algorithm = _a.algorithm, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b, hash;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = algorithm;
switch (_b) {
case 'SHA-256': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, sha256_js_1.Sha256.digest({ data: data })];
case 2:
hash = _c.sent();
return [2 /*return*/, hash];
case 3: return [2 /*return*/];
}
});
});
};
return Sha2Algorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.Sha2Algorithm = Sha2Algorithm;
//# sourceMappingURL=sha-2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"sha-2.js","sourceRoot":"","sources":["../../../src/algorithms/sha-2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,qDAAiD;AACjD,6DAAwD;AAcxD;;;;;;;GAOG;AACH;IAAmC,iCAAe;IAAlD;;IAsCA,CAAC;IAnCC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,8BAAM,GAAnB,UAAoB,EAAqC;YAAnC,SAAS,eAAA,EAAE,IAAI,UAAA;;;;;;wBAC3B,KAAA,SAAS,CAAA;;iCAEV,SAAS,CAAC,CAAV,wBAAS;;;4BACC,qBAAM,kBAAM,CAAC,MAAM,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,EAAA;;wBAApC,IAAI,GAAG,SAA6B;wBAC1C,sBAAO,IAAI,EAAC;;;;;KAIjB;IACH,oBAAC;AAAD,CAAC,AAtCD,CAAmC,qCAAe,GAsCjD;AAtCY,sCAAa"}
+54
View File
@@ -0,0 +1,54 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.utils = void 0;
__exportStar(require("./local-key-manager.js"), exports);
exports.utils = __importStar(require("./utils.js"));
__exportStar(require("./algorithms/aes-ctr.js"), exports);
__exportStar(require("./algorithms/aes-gcm.js"), exports);
__exportStar(require("./algorithms/crypto-algorithm.js"), exports);
__exportStar(require("./algorithms/ecdsa.js"), exports);
__exportStar(require("./algorithms/eddsa.js"), exports);
__exportStar(require("./algorithms/sha-2.js"), exports);
__exportStar(require("./jose/jwe.js"), exports);
__exportStar(require("./jose/jwk.js"), exports);
__exportStar(require("./jose/jws.js"), exports);
__exportStar(require("./jose/jwt.js"), exports);
__exportStar(require("./jose/utils.js"), exports);
__exportStar(require("./primitives/aes-ctr.js"), exports);
__exportStar(require("./primitives/aes-gcm.js"), exports);
__exportStar(require("./primitives/concat-kdf.js"), exports);
__exportStar(require("./primitives/ed25519.js"), exports);
__exportStar(require("./primitives/secp256r1.js"), exports);
__exportStar(require("./primitives/pbkdf2.js"), exports);
__exportStar(require("./primitives/secp256k1.js"), exports);
__exportStar(require("./primitives/sha256.js"), exports);
__exportStar(require("./primitives/x25519.js"), exports);
__exportStar(require("./primitives/xchacha20.js"), exports);
__exportStar(require("./primitives/xchacha20-poly1305.js"), exports);
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,oDAAoC;AAEpC,0DAAwC;AACxC,0DAAwC;AACxC,mEAAiD;AACjD,wDAAsC;AACtC,wDAAsC;AACtC,wDAAsC;AAEtC,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,kDAAgC;AAEhC,0DAAwC;AACxC,0DAAwC;AACxC,6DAA2C;AAC3C,0DAAwC;AACxC,4DAA0C;AAC1C,yDAAuC;AACvC,4DAA0C;AAC1C,yDAAuC;AACvC,yDAAuC;AACvC,4DAA0C;AAC1C,qEAAmD"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jwe.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jwe.js","sourceRoot":"","sources":["../../../src/jose/jwe.ts"],"names":[],"mappings":""}
+278
View File
@@ -0,0 +1,278 @@
"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.isPublicJwk = exports.isPrivateJwk = exports.isOkpPublicJwk = exports.isOkpPrivateJwk = exports.isOctPrivateJwk = exports.isEcPublicJwk = exports.isEcPrivateJwk = exports.computeJwkThumbprint = exports.KEY_URI_PREFIX_JWK = void 0;
var common_1 = require("@web5/common");
var utils_js_1 = require("./utils.js");
var sha256_js_1 = require("../primitives/sha256.js");
/**
* Constant defining the prefix for JSON Web Keys (JWK) key URIs in this library.
*
* The prefix 'urn:jwk:' makes it explicit that a string represents a JWK, referenced by a
* {@link https://datatracker.ietf.org/doc/html/rfc3986 | URI} (Uniform Resource Identifier),
* which ensures consistent key referencing across all Web5 Key Management System (KMS)
* implementations.
*
* These key URIs take the form `urn:jwk:<JWK thumbprint>`, where the
* {@link https://datatracker.ietf.org/doc/html/rfc7638 | JWK thumbprint}, derived from the JWK, is
* unique to the key's material, unaffected by the order or optional properties in the JWK.
*/
exports.KEY_URI_PREFIX_JWK = 'urn:jwk:';
/**
* Computes the thumbprint of a JSON Web Key (JWK) using the method
* specified in RFC 7638. This function accepts RSA, EC, OKP, and oct keys
* and returns the thumbprint as a base64url encoded SHA-256 hash of the
* JWK's required members, serialized and sorted lexicographically.
*
* Purpose:
* - Uniquely Identifying Keys: The thumbprint allows the unique
* identification of a specific JWK within a set of JWKs. It provides a
* deterministic way to generate a value that can be used as a key
* identifier (kid) or to match a specific key.
*
* - Simplifying Key Management: In systems where multiple keys are used,
* managing and identifying individual keys can become complex. The
* thumbprint method simplifies this by creating a standardized, unique
* identifier for each key.
*
* - Enabling Interoperability: By standardizing the method to compute a
* thumbprint, different systems can compute the same thumbprint value for
* a given JWK. This enables interoperability among systems that use JWKs.
*
* - Secure Comparison: The thumbprint provides a way to securely compare
* JWKs to determine if they are equivalent.
*
* @example
* ```ts
* const jwk: PublicKeyJwk = {
* 'kty': 'EC',
* 'crv': 'secp256k1',
* 'x': '61iPYuGefxotzBdQZtDvv6cWHZmXrTTscY-u7Y2pFZc',
* 'y': '88nPCVLfrAY9i-wg5ORcwVbHWC_tbeAd1JE2e0co0lU'
* };
*
* const thumbprint = jwkThumbprint(jwk);
* console.log(`JWK thumbprint: ${thumbprint}`);
* ```
*
* @see {@link https://datatracker.ietf.org/doc/html/rfc7638 | RFC7638} for
* the specification of JWK thumbprint computation.
*
* @param jwk - The JSON Web Key for which the thumbprint will be computed.
* This must be an RSA, EC, OKP, or oct key.
* @returns The thumbprint as a base64url encoded string.
* @throws Throws an `Error` if the provided key type is unsupported.
*/
function computeJwkThumbprint(_a) {
var jwk = _a.jwk;
return __awaiter(this, void 0, void 0, function () {
var keyType, normalizedJwk, serializedJwk, utf8Bytes, digest, thumbprint;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
keyType = jwk.kty;
if (keyType === 'EC') {
normalizedJwk = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y };
}
else if (keyType === 'oct') {
normalizedJwk = { k: jwk.k, kty: jwk.kty };
}
else if (keyType === 'OKP') {
normalizedJwk = { crv: jwk.crv, kty: jwk.kty, x: jwk.x };
}
else if (keyType === 'RSA') {
normalizedJwk = { e: jwk.e, kty: jwk.kty, n: jwk.n };
}
else {
throw new Error("Unsupported key type: ".concat(keyType));
}
(0, common_1.removeUndefinedProperties)(normalizedJwk);
serializedJwk = (0, utils_js_1.canonicalize)(normalizedJwk);
utf8Bytes = common_1.Convert.string(serializedJwk).toUint8Array();
return [4 /*yield*/, sha256_js_1.Sha256.digest({ data: utf8Bytes })];
case 1:
digest = _b.sent();
thumbprint = common_1.Convert.uint8Array(digest).toBase64Url();
return [2 /*return*/, thumbprint];
}
});
});
}
exports.computeJwkThumbprint = computeJwkThumbprint;
/**
* Checks if the provided object is a valid elliptic curve private key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid EC private JWK; otherwise, false.
*/
function isEcPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj && 'd' in obj))
return false;
if (obj.kty !== 'EC')
return false;
if (typeof obj.d !== 'string')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isEcPrivateJwk = isEcPrivateJwk;
/**
* Checks if the provided object is a valid elliptic curve public key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid EC public JWK; otherwise, false.
*/
function isEcPublicJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj))
return false;
if ('d' in obj)
return false;
if (obj.kty !== 'EC')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isEcPublicJwk = isEcPublicJwk;
/**
* Checks if the provided object is a valid octet sequence (symmetric key) in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid oct private JWK; otherwise, false.
*/
function isOctPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'k' in obj))
return false;
if (obj.kty !== 'oct')
return false;
if (typeof obj.k !== 'string')
return false;
return true;
}
exports.isOctPrivateJwk = isOctPrivateJwk;
/**
* Checks if the provided object is a valid octet key pair private key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid OKP private JWK; otherwise, false.
*/
function isOkpPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj && 'd' in obj))
return false;
if (obj.kty !== 'OKP')
return false;
if (typeof obj.d !== 'string')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isOkpPrivateJwk = isOkpPrivateJwk;
/**
* Checks if the provided object is a valid octet key pair public key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid OKP public JWK; otherwise, false.
*/
function isOkpPublicJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if ('d' in obj)
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj))
return false;
if (obj.kty !== 'OKP')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isOkpPublicJwk = isOkpPublicJwk;
/**
* Checks if the provided object is a valid private key in JWK format of any supported type.
*
* @param obj - The object to check.
* @returns True if the object is a valid private JWK; otherwise, false.
*/
function isPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
var kty = obj.kty;
switch (kty) {
case 'EC':
case 'OKP':
case 'RSA':
return 'd' in obj;
case 'oct':
return 'k' in obj;
default:
return false;
}
}
exports.isPrivateJwk = isPrivateJwk;
/**
* Checks if the provided object is a valid public key in JWK format of any supported type.
*
* @param obj - The object to check.
* @returns True if the object is a valid public JWK; otherwise, false.
*/
function isPublicJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
var kty = obj.kty;
switch (kty) {
case 'EC':
case 'OKP':
return 'x' in obj && !('d' in obj);
case 'RSA':
return 'n' in obj && 'e' in obj && !('d' in obj);
default:
return false;
}
}
exports.isPublicJwk = isPublicJwk;
//# sourceMappingURL=jwk.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jwk.js","sourceRoot":"","sources":["../../../src/jose/jwk.ts"],"names":[],"mappings":"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"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jws.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jws.js","sourceRoot":"","sources":["../../../src/jose/jws.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jwt.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../../src/jose/jwt.ts"],"names":[],"mappings":""}
+60
View File
@@ -0,0 +1,60 @@
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.canonicalize = void 0;
/**
* Canonicalizes a given object according to RFC 8785 (https://tools.ietf.org/html/rfc8785),
* which describes JSON Canonicalization Scheme (JCS). This function sorts the keys of the
* object and its nested objects alphabetically and then returns a stringified version of it.
* This method handles nested objects, array values, and null values appropriately.
*
* @param obj - The object to canonicalize.
* @returns The stringified version of the input object with its keys sorted alphabetically
* per RFC 8785.
*/
function canonicalize(obj) {
/**
* Recursively sorts the keys of an object.
*
* @param obj - The object whose keys are to be sorted.
* @returns A new object with sorted keys.
*/
var sortObjKeys = function (obj) {
var e_1, _a;
if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) {
var sortedKeys = Object.keys(obj).sort();
var sortedObj_1 = {};
try {
for (var sortedKeys_1 = __values(sortedKeys), sortedKeys_1_1 = sortedKeys_1.next(); !sortedKeys_1_1.done; sortedKeys_1_1 = sortedKeys_1.next()) {
var key = sortedKeys_1_1.value;
// Recursively sort keys of nested objects.
sortedObj_1[key] = sortObjKeys(obj[key]);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (sortedKeys_1_1 && !sortedKeys_1_1.done && (_a = sortedKeys_1.return)) _a.call(sortedKeys_1);
}
finally { if (e_1) throw e_1.error; }
}
return sortedObj_1;
}
return obj;
};
// Stringify and return the final sorted object.
var sortedObj = sortObjKeys(obj);
return JSON.stringify(sortedObj);
}
exports.canonicalize = canonicalize;
//# sourceMappingURL=utils.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/jose/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,GAA2B;IACtD;;;;;OAKG;IACH,IAAM,WAAW,GAAG,UAAC,GAA2B;;QAC9C,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAClE,IAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAM,WAAS,GAA2B,EAAE,CAAC;;gBAC7C,KAAkB,IAAA,eAAA,SAAA,UAAU,CAAA,sCAAA,8DAAE;oBAAzB,IAAM,GAAG,uBAAA;oBACZ,2CAA2C;oBAC3C,WAAS,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;iBACxC;;;;;;;;;YACD,OAAO,WAAS,CAAC;SAClB;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,gDAAgD;IAChD,IAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAvBD,oCAuBC"}
+521
View File
@@ -0,0 +1,521 @@
"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.LocalKeyManager = void 0;
var common_1 = require("@web5/common");
var sha_2_js_1 = require("./algorithms/sha-2.js");
var ecdsa_js_1 = require("./algorithms/ecdsa.js");
var eddsa_js_1 = require("./algorithms/eddsa.js");
var jwk_js_1 = require("./jose/jwk.js");
/**
* `supportedAlgorithms` is an object mapping algorithm names to their respective implementations
* Each entry in this map specifies the algorithm name and its associated properties, including the
* implementation class and any relevant names or identifiers for the algorithm. This structure
* allows for easy retrieval and instantiation of algorithm implementations based on the algorithm
* name or key specification. It facilitates the support of multiple algorithms within the
* `LocalKeyManager` class.
*/
var supportedAlgorithms = {
'Ed25519': {
implementation: eddsa_js_1.EdDsaAlgorithm,
names: ['Ed25519'],
},
'secp256k1': {
implementation: ecdsa_js_1.EcdsaAlgorithm,
names: ['ES256K', 'secp256k1'],
},
'secp256r1': {
implementation: ecdsa_js_1.EcdsaAlgorithm,
names: ['ES256', 'secp256r1'],
},
'SHA-256': {
implementation: sha_2_js_1.Sha2Algorithm,
names: ['SHA-256']
}
};
var LocalKeyManager = /** @class */ (function () {
function LocalKeyManager(params) {
var _a;
/**
* A private map that stores instances of cryptographic algorithm implementations. Each key in
* this map is an `AlgorithmConstructor`, and its corresponding value is an instance of a class
* that implements a specific cryptographic algorithm. This map is used to cache and reuse
* instances for performance optimization, ensuring that each algorithm is instantiated only once.
*/
this._algorithmInstances = new Map();
this._keyStore = (_a = params === null || params === void 0 ? void 0 : params.keyStore) !== null && _a !== void 0 ? _a : new common_1.MemoryStore();
}
/**
* Generates a hash digest of the provided data.
*
* @remarks
* A digest is the output of the hash function. It's a fixed-size string of bytes
* that uniquely represents the data input into the hash function. The digest is often used for
* data integrity checks, as any alteration in the input data results in a significantly
* different digest.
*
* It takes the algorithm identifier of the hash function and data to digest as input and returns
* the digest of the data.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const data = new Uint8Array([...]);
* const digest = await keyManager.digest({ algorithm: 'SHA-256', data });
* ```
*
* @param params - The parameters for the digest operation.
* @param params.algorithm - The name of hash function to use.
* @param params.data - The data to digest.
*
* @returns A Promise which will be fulfilled with the hash digest.
*/
LocalKeyManager.prototype.digest = function (_a) {
var algorithm = _a.algorithm, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var hasher, hash;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
hasher = this.getAlgorithm({ algorithm: algorithm });
return [4 /*yield*/, hasher.digest({ algorithm: algorithm, data: data })];
case 1:
hash = _b.sent();
return [2 /*return*/, hash];
}
});
});
};
/**
* Exports a private key identified by the provided key URI from the local KMS.
*
* @remarks
* This method retrieves the key from the key store and returns it. It is primarily used
* for extracting keys for backup or transfer purposes.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const privateKey = await keyManager.exportKey({ keyUri });
* ```
*
* @param params - Parameters for exporting the key.
* @param params.keyUri - The key URI identifying the key to export.
*
* @returns A Promise resolving to the JWK representation of the exported key.
*/
LocalKeyManager.prototype.exportKey = function (_a) {
var keyUri = _a.keyUri;
return __awaiter(this, void 0, void 0, function () {
var privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getPrivateKey({ keyUri: keyUri })];
case 1:
privateKey = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Generates a new cryptographic key in the local KMS with the specified algorithm and returns a
* unique key URI which can be used to reference the key in subsequent operations.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* console.log(keyUri); // Outputs the key URI
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation, defined in `SupportedAlgorithm`.
*
* @returns A Promise that resolves to the key URI, a unique identifier for the generated key.
*/
LocalKeyManager.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var keyGenerator, key, keyUri;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
keyGenerator = this.getAlgorithm({ algorithm: algorithm });
return [4 /*yield*/, keyGenerator.generateKey({ algorithm: algorithm })];
case 1:
key = _b.sent();
if ((key === null || key === void 0 ? void 0 : key.kid) === undefined) {
throw new Error('Generated key is missing a required property: kid');
}
keyUri = "".concat(jwk_js_1.KEY_URI_PREFIX_JWK).concat(key.kid);
// Store the key in the key store.
return [4 /*yield*/, this._keyStore.set(keyUri, key)];
case 2:
// Store the key in the key store.
_b.sent();
return [2 /*return*/, keyUri];
}
});
});
};
/**
* Computes the Key URI for a given public JWK (JSON Web Key).
*
* @remarks
* This method generates a {@link https://datatracker.ietf.org/doc/html/rfc3986 | URI}
* (Uniform Resource Identifier) for the given JWK, which uniquely identifies the key across all
* `CryptoApi` implementations. The key URI is constructed by appending the
* {@link https://datatracker.ietf.org/doc/html/rfc7638 | JWK thumbprint} to the prefix
* `urn:jwk:`. The JWK thumbprint is deterministically computed from the JWK and is consistent
* regardless of property order or optional property inclusion in the JWK. This ensures that the
* same key material represented as a JWK will always yield the same thumbprint, and therefore,
* the same key URI.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const publicKey = await keyManager.getPublicKey({ keyUri });
* const keyUriFromPublicKey = await keyManager.getKeyUri({ key: publicKey });
* console.log(keyUri === keyUriFromPublicKey); // Outputs `true`
* ```
*
* @param params - The parameters for getting the key URI.
* @param params.key - The JWK for which to compute the key URI.
*
* @returns A Promise that resolves to the key URI as a string.
*/
LocalKeyManager.prototype.getKeyUri = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var jwkThumbprint, keyUri;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: key })];
case 1:
jwkThumbprint = _b.sent();
keyUri = "".concat(jwk_js_1.KEY_URI_PREFIX_JWK).concat(jwkThumbprint);
return [2 /*return*/, keyUri];
}
});
});
};
/**
* Retrieves the public key associated with a previously generated private key, identified by
* the provided key URI.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const publicKey = await keyManager.getPublicKey({ keyUri });
* ```
*
* @param params - The parameters for retrieving the public key.
* @param params.keyUri - The key URI of the private key to retrieve the public key for.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
LocalKeyManager.prototype.getPublicKey = function (_a) {
var keyUri = _a.keyUri;
return __awaiter(this, void 0, void 0, function () {
var privateKey, algorithm, keyGenerator, publicKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getPrivateKey({ keyUri: keyUri })];
case 1:
privateKey = _b.sent();
algorithm = this.getAlgorithmName({ key: privateKey });
keyGenerator = this.getAlgorithm({ algorithm: algorithm });
return [4 /*yield*/, keyGenerator.getPublicKey({ key: privateKey })];
case 2:
publicKey = _b.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Imports a private key into the local KMS.
*
* @remarks
* This method stores the provided JWK in the key store, making it available for subsequent
* cryptographic operations. It is particularly useful for initializing the KMS with pre-existing
* keys or for restoring keys from backups.
*
* Note that, if defined, the `kid` (key ID) property of the JWK is used as the key URI for the
* imported key. If the `kid` property is not provided, the key URI is computed from the JWK
* thumbprint of the key.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const privateKey = { ... } // A private key in JWK format
* const keyUri = await keyManager.importKey({ key: privateKey });
* ```
*
* @param params - Parameters for importing the key.
* @param params.key - The private key to import to in JWK format.
*
* @returns A Promise resolving to the key URI, uniquely identifying the imported key.
*/
LocalKeyManager.prototype.importKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _c, _d, keyUri;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
if (!(0, jwk_js_1.isPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be a private key in JWK format.');
privateKey = structuredClone(key);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
privateKey.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 = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
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 [4 /*yield*/, this.getKeyUri({ key: privateKey })];
case 4:
keyUri = _e.sent();
// Store the key in the key store.
return [4 /*yield*/, this._keyStore.set(keyUri, privateKey)];
case 5:
// Store the key in the key store.
_e.sent();
return [2 /*return*/, keyUri];
}
});
});
};
/**
* Signs the provided data using the private key identified by the provided key URI.
*
* @remarks
* This method uses the signature algorithm determined by the `alg` and/or `crv` properties of the
* private key identified by the provided key URI to sign the provided data. 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 keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const data = new TextEncoder().encode('Message to sign');
* const signature = await keyManager.sign({ keyUri, data });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.keyUri - The key URI of the private key to use for signing.
* @param params.data - The data to sign.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
LocalKeyManager.prototype.sign = function (_a) {
var keyUri = _a.keyUri, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var privateKey, algorithm, signer, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getPrivateKey({ keyUri: keyUri })];
case 1:
privateKey = _b.sent();
algorithm = this.getAlgorithmName({ key: privateKey });
signer = this.getAlgorithm({ algorithm: algorithm });
signature = signer.sign({ data: data, key: privateKey });
return [2 /*return*/, signature];
}
});
});
};
/**
* Verifies a digital signature associated the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `alg` and/or `crv` properties of the
* provided key to check the validity of a digital signature against the original data. It
* confirms whether the signature was created by the holder of the corresponding private key and
* that the data has not been tampered with.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const data = new TextEncoder().encode('Message to sign');
* const signature = await keyManager.sign({ keyUri, data });
* const isSignatureValid = await keyManager.verify({ keyUri, data, signature });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
LocalKeyManager.prototype.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var algorithm, signer, isSignatureValid;
return __generator(this, function (_b) {
algorithm = this.getAlgorithmName({ key: key });
signer = this.getAlgorithm({ algorithm: algorithm });
isSignatureValid = signer.verify({ key: key, signature: signature, data: data });
return [2 /*return*/, isSignatureValid];
});
});
};
/**
* Retrieves an algorithm implementation instance based on the provided algorithm name.
*
* @remarks
* This method checks if the requested algorithm is supported and returns a cached instance
* if available. If an instance does not exist, it creates and caches a new one. This approach
* optimizes performance by reusing algorithm instances across cryptographic operations.
*
* @example
* ```ts
* const signer = this.getAlgorithm({ algorithm: 'Ed25519' });
* ```
*
* @param params - The parameters for retrieving the algorithm implementation.
* @param params.algorithm - The name of the algorithm to retrieve.
*
* @returns An instance of the requested algorithm implementation.
*
* @throws Error if the requested algorithm is not supported.
*/
LocalKeyManager.prototype.getAlgorithm = function (_a) {
var _b;
var algorithm = _a.algorithm;
// Check if algorithm is supported.
var AlgorithmImplementation = (_b = supportedAlgorithms[algorithm]) === null || _b === void 0 ? void 0 : _b['implementation'];
if (!AlgorithmImplementation) {
throw new Error("Algorithm not supported: ".concat(algorithm));
}
// Check if instance already exists for the `AlgorithmImplementation`.
if (!this._algorithmInstances.has(AlgorithmImplementation)) {
// If not, create a new instance and store it in the cache
this._algorithmInstances.set(AlgorithmImplementation, new AlgorithmImplementation());
}
// Return the cached instance
return this._algorithmInstances.get(AlgorithmImplementation);
};
/**
* Determines the name of the algorithm based on the key's properties.
*
* @remarks
* This method facilitates the identification of the correct algorithm for cryptographic
* operations based on the `alg` or `crv` properties of a {@link Jwk | JWK}.
*
* @example
* ```ts
* const publicKey = { ... }; // Public key in JWK format
* const algorithm = this.getAlgorithmName({ key: publicKey });
* ```
*
* @param params - The parameters for determining the algorithm name.
* @param params.key - A JWK containing the `alg` or `crv` properties.
*
* @returns The name of the algorithm associated with the key.
*
* @throws Error if the algorithm cannot be determined from the provided input.
*/
LocalKeyManager.prototype.getAlgorithmName = function (_a) {
var key = _a.key;
var algProperty = key.alg;
var crvProperty = key.crv;
for (var algName in supportedAlgorithms) {
var algorithmInfo = supportedAlgorithms[algName];
if (algProperty && algorithmInfo.names.includes(algProperty)) {
return algName;
}
else if (crvProperty && algorithmInfo.names.includes(crvProperty)) {
return algName;
}
}
throw new Error("Unable to determine algorithm based on provided input: alg=".concat(algProperty, ", crv=").concat(crvProperty));
};
/**
* Retrieves a private key from the key store based on the provided key URI.
*
* @example
* ```ts
* const privateKey = this.getPrivateKey({ keyUri: 'urn:jwk:...' });
* ```
*
* @param params - Parameters for retrieving the private key.
* @param params.keyUri - The key URI identifying the private key to retrieve.
*
* @returns A Promise resolving to the JWK representation of the private key.
*
* @throws Error if the key is not found in the key store.
*/
LocalKeyManager.prototype.getPrivateKey = function (_a) {
var keyUri = _a.keyUri;
return __awaiter(this, void 0, void 0, function () {
var privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this._keyStore.get(keyUri)];
case 1:
privateKey = _b.sent();
if (!privateKey) {
throw new Error("Key not found: ".concat(keyUri));
}
return [2 /*return*/, privateKey];
}
});
});
};
return LocalKeyManager;
}());
exports.LocalKeyManager = LocalKeyManager;
//# sourceMappingURL=local-key-manager.js.map
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"type": "commonjs"}
@@ -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":"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"}
@@ -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":"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"}
@@ -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
@@ -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":"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"}
@@ -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":"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"}
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAuC;AACvC,gDAAkD;AAClD,wDAAoE;AAIpE,yCAAuE;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH;IAAA;IAiMA,CAAC;IAhMC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACiB,2BAAiB,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;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACiB,iBAAO,GAA3B,UAA4B,EAI3B;YAJ6B,IAAI,UAAA,EAAE,GAAG,SAAA,EAAE,KAAK,WAAA;;;;;4BAMpB,qBAAM,SAAS,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAA;;wBAAxE,eAAe,GAAG,SAAsD;wBAExE,UAAU,GAAG,IAAA,kBAAS,EAAC,eAAe,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;wBAE3D,sBAAO,UAAU,EAAC;;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACiB,iBAAO,GAA3B,UAA4B,EAI3B;YAJ6B,IAAI,UAAA,EAAE,GAAG,SAAA,EAAE,KAAK,WAAA;;;;;4BAMpB,qBAAM,SAAS,CAAC,iBAAiB,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAA;;wBAAxE,eAAe,GAAG,SAAsD;wBAExE,SAAS,GAAG,IAAA,kBAAS,EAAC,eAAe,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;wBAE1D,sBAAO,SAAS,EAAC;;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACiB,qBAAW,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;;;;;;;;;;;;;;;;;;OAkBG;IACiB,2BAAiB,GAArC,UAAsC,EAErC;YAFuC,UAAU,gBAAA;;;;gBAGhD,8DAA8D;gBAC9D,IAAI,CAAC,IAAA,wBAAe,EAAC,UAAU,CAAC,EAAE;oBAChC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;iBAChF;gBAGK,eAAe,GAAG,gBAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;gBAEvE,sBAAO,eAAe,EAAC;;;KACxB;IACH,gBAAC;AAAD,CAAC,AAjMD,IAiMC;AAjMY,8BAAS"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=cipher.js.map
@@ -0,0 +1 @@
{"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../../src/types/cipher.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=crypto-api.js.map
@@ -0,0 +1 @@
{"version":3,"file":"crypto-api.js","sourceRoot":"","sources":["../../../src/types/crypto-api.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=hasher.js.map
@@ -0,0 +1 @@
{"version":3,"file":"hasher.js","sourceRoot":"","sources":["../../../src/types/hasher.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=identifier.js.map
@@ -0,0 +1 @@
{"version":3,"file":"identifier.js","sourceRoot":"","sources":["../../../src/types/identifier.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-compressor.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-compressor.js","sourceRoot":"","sources":["../../../src/types/key-compressor.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-converter.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-converter.js","sourceRoot":"","sources":["../../../src/types/key-converter.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-deriver.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-deriver.js","sourceRoot":"","sources":["../../../src/types/key-deriver.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-generator.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-generator.js","sourceRoot":"","sources":["../../../src/types/key-generator.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-io.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-io.js","sourceRoot":"","sources":["../../../src/types/key-io.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-wrapper.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-wrapper.js","sourceRoot":"","sources":["../../../src/types/key-wrapper.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=params-direct.js.map
@@ -0,0 +1 @@
{"version":3,"file":"params-direct.js","sourceRoot":"","sources":["../../../src/types/params-direct.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=params-enclosed.js.map
@@ -0,0 +1 @@
{"version":3,"file":"params-enclosed.js","sourceRoot":"","sources":["../../../src/types/params-enclosed.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=params-kms.js.map
@@ -0,0 +1 @@
{"version":3,"file":"params-kms.js","sourceRoot":"","sources":["../../../src/types/params-kms.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
{"version":3,"file":"signer.js","sourceRoot":"","sources":["../../../src/types/signer.ts"],"names":[],"mappings":""}
+198
View File
@@ -0,0 +1,198 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.randomUuid = exports.randomBytes = exports.isWebCryptoSupported = exports.getJoseSignatureAlgorithmFromPublicKey = exports.checkValidProperty = exports.checkRequiredProperty = void 0;
var crypto_1 = require("@noble/hashes/crypto");
var utils_1 = require("@noble/hashes/utils");
/**
* Checks whether the properties object provided contains the specified property.
*
* @example
* ```ts
* const obj = { a: 'Bob', t: 30 };
* checkRequiredProperty({ property: 'a', inObject: obj }); // No error
* checkRequiredProperty({ property: 'z', inObject: obj }); // Throws TypeError
* ```
*
* @param params - The parameters for the check.
* @param params.property - Property key to check for.
* @param params.properties - Properties object to check within.
* @returns void
* @throws {TypeError} If the property is not a key in the properties object.
*/
function checkRequiredProperty(params) {
if (!params || params.property === undefined || params.inObject === undefined) {
throw new TypeError("One or more required parameters missing: 'property, properties'");
}
var property = params.property, inObject = params.inObject;
if (!(property in inObject)) {
throw new TypeError("Required parameter missing: '".concat(property, "'"));
}
}
exports.checkRequiredProperty = checkRequiredProperty;
/**
* Checks whether the property specified is a member of the list of valid properties.
*
* @example
* ```ts
* const property = 'color';
* const allowedProperties = ['size', 'shape', 'color'];
* checkValidProperty({ property, allowedProperties }); // No error
* checkValidProperty({ property: 'weight', allowedProperties }); // Throws TypeError
* ```
*
* @param property Property key to check for.
* @param allowedProperties Properties Array, Map, or Set to check within.
* @returns void
* @throws {TypeError} If the property is not a member of the allowedProperties Array, Map, or Set.
*/
function checkValidProperty(params) {
if (!params || params.property === undefined || params.allowedProperties === undefined) {
throw new TypeError("One or more required parameters missing: 'property, allowedProperties'");
}
var property = params.property, allowedProperties = params.allowedProperties;
if ((Array.isArray(allowedProperties) && !allowedProperties.includes(property)) ||
(allowedProperties instanceof Set && !allowedProperties.has(property)) ||
(allowedProperties instanceof Map && !allowedProperties.has(property))) {
var validProperties = Array.from((allowedProperties instanceof Map) ? allowedProperties.keys() : allowedProperties).join(', ');
throw new TypeError("Out of range: '".concat(property, "'. Must be one of '").concat(validProperties, "'"));
}
}
exports.checkValidProperty = checkValidProperty;
/**
* Determines the JOSE algorithm identifier of the digital signature algorithm based on the `alg` or
* `crv` property of a {@link Jwk | JWK}.
*
* If the `alg` property is present, its value takes precedence and is returned. Otherwise, the
* `crv` property is used to determine the algorithm.
*
* @see {@link https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms | JOSE Algorithms}
* @see {@link https://datatracker.ietf.org/doc/draft-ietf-jose-fully-specified-algorithms/ | Fully-Specified Algorithms for JOSE and COSE}
*
* @example
* ```ts
* const publicKey: Jwk = {
* "kty": "OKP",
* "crv": "Ed25519",
* "x": "FEJG7OakZi500EydXxuE8uMc8uaAzEJkmQeG8khXANw"
* }
* const algorithm = getJoseSignatureAlgorithmFromPublicKey(publicKey);
* console.log(algorithm); // Output: "EdDSA"
* ```
*
* @param publicKey - A JWK containing the `alg` and/or `crv` properties.
* @returns The name of the algorithm associated with the key.
* @throws Error if the algorithm cannot be determined from the provided input.
*/
function getJoseSignatureAlgorithmFromPublicKey(publicKey) {
var curveToJoseAlgorithm = {
'Ed25519': 'EdDSA',
'P-256': 'ES256',
'P-384': 'ES384',
'P-521': 'ES512',
'secp256k1': 'ES256K',
};
// If the key contains an `alg` property that matches a JOSE registered algorithm identifier,
// return its value.
if (publicKey.alg && Object.values(curveToJoseAlgorithm).includes(publicKey.alg)) {
return publicKey.alg;
}
// If the key contains a `crv` property, return the corresponding algorithm.
if (publicKey.crv && Object.keys(curveToJoseAlgorithm).includes(publicKey.crv)) {
return curveToJoseAlgorithm[publicKey.crv];
}
throw new Error("Unable to determine algorithm based on provided input: alg=".concat(publicKey.alg, ", crv=").concat(publicKey.crv, ". ") +
"Supported 'alg' values: ".concat(Object.values(curveToJoseAlgorithm).join(', '), ". ") +
"Supported 'crv' values: ".concat(Object.keys(curveToJoseAlgorithm).join(', '), "."));
}
exports.getJoseSignatureAlgorithmFromPublicKey = getJoseSignatureAlgorithmFromPublicKey;
/**
* Checks if the Web Crypto API is supported in the current runtime environment.
*
* @remarks
* The function uses `globalThis` to provide a universal reference to the global
* scope, regardless of the environment. `globalThis` is a standard feature introduced
* in ECMAScript 2020 that is agnostic to the underlying JavaScript environment, making
* the code portable across browser, Node.js, and Web Workers environments.
*
* In a web browser, `globalThis` is equivalent to the `window` object. In Node.js, it
* is equivalent to the `global` object, and in Web Workers, it corresponds to `self`.
*
* This method checks for the `crypto` object and its `subtle` property on the global scope
* to determine the availability of the Web Crypto API. If both are present, the API is
* supported; otherwise, it is not.
*
* @example
* ```ts
* if (isWebCryptoSupported()) {
* console.log('Crypto operations can be performed');
* } else {
* console.log('Crypto operations are not supported in this environment');
* }
* ```
*
* @returns A boolean indicating whether the Web Crypto API is supported in the current environment.
*/
function isWebCryptoSupported() {
if (globalThis.crypto && globalThis.crypto.subtle) {
return true;
}
else {
return false;
}
}
exports.isWebCryptoSupported = isWebCryptoSupported;
/**
* Generates secure pseudorandom values of the specified length using
* `crypto.getRandomValues`, which defers to the operating system.
*
* @remarks
* This function is a wrapper around `randomBytes` from the '@noble/hashes'
* package. It's designed to be cryptographically strong, suitable for
* generating initialization vectors, nonces, and other random values.
*
* @see {@link https://www.npmjs.com/package/@noble/hashes | @noble/hashes on NPM} for more
* information about the underlying implementation.
*
* @example
* ```ts
* const bytes = randomBytes(32); // Generates 32 random bytes
* ```
*
* @param bytesLength - The number of bytes to generate.
* @returns A Uint8Array containing the generated random bytes.
*/
function randomBytes(bytesLength) {
return (0, utils_1.randomBytes)(bytesLength);
}
exports.randomBytes = randomBytes;
/**
* Generates a UUID (Universally Unique Identifier) using a
* cryptographically strong random number generator following
* the version 4 format, as specified in RFC 4122.
*
* A version 4 UUID is a randomly generated UUID. The 13th character
* is set to '4' to denote version 4, and the 17th character is one
* of '8', '9', 'A', or 'B' to comply with the variant 1 format of
* UUIDs (the high bits are set to '10').
*
* The UUID is a 36 character string, including hyphens, and looks like this:
* xxxxxxxx-xxxx-4xxx-axxx-xxxxxxxxxxxx
*
* Note that while UUIDs are not guaranteed to be unique, they are
* practically unique" given the large number of possible UUIDs and
* the randomness of generation.
*
* @example
* ```ts
* const uuid = randomUuid();
* console.log(uuid); // Outputs a version 4 UUID, e.g., '123e4567-e89b-12d3-a456-426655440000'
* ```
*
* @returns A string containing a randomly generated, 36 character long v4 UUID.
*/
function randomUuid() {
var uuid = crypto_1.crypto.randomUUID();
return uuid;
}
exports.randomUuid = randomUuid;
//# sourceMappingURL=utils.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}