@sphereon/ssi-sdk-ext.key-utils 0.28.1-feature.oyd.cmsm.improv.21 → 0.28.1-next.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1434 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +231 -0
- package/dist/index.d.ts +228 -9
- package/dist/index.js +1401 -26
- package/dist/index.js.map +1 -1
- package/package.json +26 -13
- package/src/conversion.ts +8 -6
- package/src/digest-methods.ts +12 -11
- package/src/functions.ts +299 -53
- package/src/jwk-jcs.ts +3 -1
- package/src/types/key-util-types.ts +1 -1
- package/dist/conversion.d.ts +0 -12
- package/dist/conversion.d.ts.map +0 -1
- package/dist/conversion.js +0 -206
- package/dist/conversion.js.map +0 -1
- package/dist/digest-methods.d.ts +0 -11
- package/dist/digest-methods.d.ts.map +0 -1
- package/dist/digest-methods.js +0 -106
- package/dist/digest-methods.js.map +0 -1
- package/dist/functions.d.ts +0 -100
- package/dist/functions.d.ts.map +0 -1
- package/dist/functions.js +0 -756
- package/dist/functions.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/jwk-jcs.d.ts +0 -41
- package/dist/jwk-jcs.d.ts.map +0 -1
- package/dist/jwk-jcs.js +0 -182
- package/dist/jwk-jcs.js.map +0 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -18
- package/dist/types/index.js.map +0 -1
- package/dist/types/key-util-types.d.ts +0 -46
- package/dist/types/key-util-types.d.ts.map +0 -1
- package/dist/types/key-util-types.js +0 -19
- package/dist/types/key-util-types.js.map +0 -1
package/dist/functions.js
DELETED
|
@@ -1,756 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
-
};
|
|
37
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.sanitizedJwk = exports.globalCrypto = exports.keyTypeFromCryptographicSuite = exports.signatureAlgorithmFromKeyType = exports.signatureAlgorithmFromKey = exports.hexStringFromUint8Array = exports.toRawCompressedHexPublicKey = exports.isRawCompressedPublicKey = exports.asn1DerToRawPublicKey = exports.isAsn1Der = exports.padLeft = exports.jwkDetermineUse = exports.jwkToRawHexKey = exports.toJwk = exports.toJwkFromKey = exports.calculateJwkThumbprint = exports.toBase64url = exports.calculateJwkThumbprintForKey = exports.generatePrivateKeyHex = exports.getKms = exports.logger = void 0;
|
|
39
|
-
exports.importProvidedOrGeneratedKey = importProvidedOrGeneratedKey;
|
|
40
|
-
exports.removeNulls = removeNulls;
|
|
41
|
-
exports.verifyRawSignature = verifyRawSignature;
|
|
42
|
-
const random_1 = require("@ethersproject/random");
|
|
43
|
-
// Do not change these require statements to imports before we change to ESM. Breaks external CJS packages depending on this module
|
|
44
|
-
const bls12_381_1 = require("@noble/curves/bls12-381");
|
|
45
|
-
const ed25519_1 = require("@noble/curves/ed25519");
|
|
46
|
-
const p256_1 = require("@noble/curves/p256");
|
|
47
|
-
const p384_1 = require("@noble/curves/p384");
|
|
48
|
-
const p521_1 = require("@noble/curves/p521");
|
|
49
|
-
const secp256k1_1 = require("@noble/curves/secp256k1");
|
|
50
|
-
const sha256_1 = require("@noble/hashes/sha256");
|
|
51
|
-
const sha512_1 = require("@noble/hashes/sha512");
|
|
52
|
-
const ssi_sdk_ext_x509_utils_1 = require("@sphereon/ssi-sdk-ext.x509-utils");
|
|
53
|
-
const ssi_types_1 = require("@sphereon/ssi-types");
|
|
54
|
-
const ed25519_2 = require("@stablelib/ed25519");
|
|
55
|
-
const debug_1 = __importDefault(require("debug"));
|
|
56
|
-
const elliptic_1 = __importDefault(require("elliptic"));
|
|
57
|
-
const rsa = __importStar(require("micro-rsa-dsa-dh/rsa.js"));
|
|
58
|
-
const u8a = __importStar(require("uint8arrays"));
|
|
59
|
-
const digest_methods_1 = require("./digest-methods");
|
|
60
|
-
const jwk_jcs_1 = require("./jwk-jcs");
|
|
61
|
-
const types_1 = require("./types");
|
|
62
|
-
exports.logger = ssi_types_1.Loggers.DEFAULT.get('sphereon:key-utils');
|
|
63
|
-
/**
|
|
64
|
-
* Function that returns the provided KMS name or the default KMS name if none is provided.
|
|
65
|
-
* The default KMS is either explicitly defined during agent construction, or the first KMS available in the system
|
|
66
|
-
* @param context
|
|
67
|
-
* @param kms. Optional KMS to use. If provided will be the returned name. Otherwise the default KMS will be returned
|
|
68
|
-
*/
|
|
69
|
-
const getKms = (context, kms) => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
|
-
if (kms) {
|
|
71
|
-
return kms;
|
|
72
|
-
}
|
|
73
|
-
if (!context.agent.availableMethods().includes('keyManagerGetDefaultKeyManagementSystem')) {
|
|
74
|
-
throw Error('Cannot determine default KMS if not provided and a non Sphereon Key Manager is being used');
|
|
75
|
-
}
|
|
76
|
-
return context.agent.keyManagerGetDefaultKeyManagementSystem();
|
|
77
|
-
});
|
|
78
|
-
exports.getKms = getKms;
|
|
79
|
-
/**
|
|
80
|
-
* Generates a random Private Hex Key for the specified key type
|
|
81
|
-
* @param type The key type
|
|
82
|
-
* @return The private key in Hex form
|
|
83
|
-
*/
|
|
84
|
-
const generatePrivateKeyHex = (type) => __awaiter(void 0, void 0, void 0, function* () {
|
|
85
|
-
switch (type) {
|
|
86
|
-
case 'Ed25519': {
|
|
87
|
-
const keyPairEd25519 = (0, ed25519_2.generateKeyPair)();
|
|
88
|
-
return u8a.toString(keyPairEd25519.secretKey, 'base16');
|
|
89
|
-
}
|
|
90
|
-
// The Secp256 types use the same method to generate the key
|
|
91
|
-
case 'Secp256r1':
|
|
92
|
-
case 'Secp256k1': {
|
|
93
|
-
const privateBytes = (0, random_1.randomBytes)(32);
|
|
94
|
-
return u8a.toString(privateBytes, 'base16');
|
|
95
|
-
}
|
|
96
|
-
case 'RSA': {
|
|
97
|
-
const pem = yield (0, ssi_sdk_ext_x509_utils_1.generateRSAKeyAsPEM)('RSA-PSS', 'SHA-256', 2048);
|
|
98
|
-
return (0, ssi_sdk_ext_x509_utils_1.privateKeyHexFromPEM)(pem);
|
|
99
|
-
}
|
|
100
|
-
default:
|
|
101
|
-
throw Error(`not_supported: Key type ${type} not yet supported for this did:jwk implementation`);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
exports.generatePrivateKeyHex = generatePrivateKeyHex;
|
|
105
|
-
const keyMetaAlgorithmsFromKeyType = (type) => {
|
|
106
|
-
switch (type) {
|
|
107
|
-
case 'Ed25519':
|
|
108
|
-
return ['Ed25519', 'EdDSA'];
|
|
109
|
-
case 'ES256K':
|
|
110
|
-
case 'Secp256k1':
|
|
111
|
-
return ['ES256K', 'ES256K-R', 'eth_signTransaction', 'eth_signTypedData', 'eth_signMessage', 'eth_rawSign'];
|
|
112
|
-
case 'Secp256r1':
|
|
113
|
-
return ['ES256'];
|
|
114
|
-
case 'X25519':
|
|
115
|
-
return ['ECDH', 'ECDH-ES', 'ECDH-1PU'];
|
|
116
|
-
case 'RSA':
|
|
117
|
-
return ['RS256', 'RS512', 'PS256', 'PS512'];
|
|
118
|
-
}
|
|
119
|
-
return [type];
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* We optionally generate and then import our own keys.
|
|
123
|
-
*
|
|
124
|
-
* @param args The key arguments
|
|
125
|
-
* @param context The Veramo agent context
|
|
126
|
-
* @private
|
|
127
|
-
*/
|
|
128
|
-
function importProvidedOrGeneratedKey(args, context) {
|
|
129
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
const type = (_g = (_e = (_b = (_a = args.options) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : (_d = (_c = args.options) === null || _c === void 0 ? void 0 : _c.key) === null || _d === void 0 ? void 0 : _d.type) !== null && _e !== void 0 ? _e : (_f = args.options) === null || _f === void 0 ? void 0 : _f.keyType) !== null && _g !== void 0 ? _g : 'Secp256r1';
|
|
133
|
-
const key = (_h = args === null || args === void 0 ? void 0 : args.options) === null || _h === void 0 ? void 0 : _h.key;
|
|
134
|
-
// Make sure x509 options are also set on the metadata as that is what the kms will look for
|
|
135
|
-
if (((_j = args.options) === null || _j === void 0 ? void 0 : _j.x509) && key) {
|
|
136
|
-
key.meta = Object.assign(Object.assign({}, key.meta), { x509: Object.assign(Object.assign({}, args.options.x509), (_k = key.meta) === null || _k === void 0 ? void 0 : _k.x509) });
|
|
137
|
-
}
|
|
138
|
-
if (args.options && ((_l = args.options) === null || _l === void 0 ? void 0 : _l.use) === types_1.JwkKeyUse.Encryption && !types_1.ENC_KEY_ALGS.includes(type)) {
|
|
139
|
-
throw new Error(`${type} keys are not valid for encryption`);
|
|
140
|
-
}
|
|
141
|
-
let privateKeyHex = undefined;
|
|
142
|
-
if (key) {
|
|
143
|
-
privateKeyHex = (_m = key.privateKeyHex) !== null && _m !== void 0 ? _m : (_p = (_o = key.meta) === null || _o === void 0 ? void 0 : _o.x509) === null || _p === void 0 ? void 0 : _p.privateKeyHex;
|
|
144
|
-
if ((!privateKeyHex || privateKeyHex.trim() === '') && ((_r = (_q = key === null || key === void 0 ? void 0 : key.meta) === null || _q === void 0 ? void 0 : _q.x509) === null || _r === void 0 ? void 0 : _r.privateKeyPEM)) {
|
|
145
|
-
// If we do not have a privateKeyHex but do have a PEM
|
|
146
|
-
privateKeyHex = (0, ssi_sdk_ext_x509_utils_1.privateKeyHexFromPEM)(key.meta.x509.privateKeyPEM);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
if (privateKeyHex) {
|
|
150
|
-
return context.agent.keyManagerImport(Object.assign(Object.assign({}, key), { kms: args.kms, type, privateKeyHex: privateKeyHex }));
|
|
151
|
-
}
|
|
152
|
-
return context.agent.keyManagerCreate({
|
|
153
|
-
type,
|
|
154
|
-
kms: args.kms,
|
|
155
|
-
meta: Object.assign(Object.assign({}, key === null || key === void 0 ? void 0 : key.meta), { algorithms: keyMetaAlgorithmsFromKeyType(type), keyAlias: args.alias }),
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
const calculateJwkThumbprintForKey = (args) => {
|
|
160
|
-
const { key } = args;
|
|
161
|
-
const jwk = key.publicKeyHex
|
|
162
|
-
? (0, exports.toJwk)(key.publicKeyHex, key.type, { key: key, isPrivateKey: false })
|
|
163
|
-
: 'privateKeyHex' in key && key.privateKeyHex
|
|
164
|
-
? (0, exports.toJwk)(key.privateKeyHex, key.type, { isPrivateKey: true })
|
|
165
|
-
: undefined;
|
|
166
|
-
if (!jwk) {
|
|
167
|
-
throw Error(`Could not determine jwk from key ${key.kid}`);
|
|
168
|
-
}
|
|
169
|
-
return (0, exports.calculateJwkThumbprint)({ jwk, digestAlgorithm: args.digestAlgorithm });
|
|
170
|
-
};
|
|
171
|
-
exports.calculateJwkThumbprintForKey = calculateJwkThumbprintForKey;
|
|
172
|
-
const assertJwkClaimPresent = (value, description) => {
|
|
173
|
-
if (typeof value !== 'string' || !value) {
|
|
174
|
-
throw new Error(`${description} missing or invalid`);
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
const toBase64url = (input) => u8a.toString(u8a.fromString(input), 'base64url');
|
|
178
|
-
exports.toBase64url = toBase64url;
|
|
179
|
-
/**
|
|
180
|
-
* Calculate the JWK thumbprint
|
|
181
|
-
* @param args
|
|
182
|
-
*/
|
|
183
|
-
const calculateJwkThumbprint = (args) => {
|
|
184
|
-
const { digestAlgorithm = 'sha256' } = args;
|
|
185
|
-
const jwk = (0, exports.sanitizedJwk)(args.jwk);
|
|
186
|
-
let components;
|
|
187
|
-
switch (jwk.kty) {
|
|
188
|
-
case 'EC':
|
|
189
|
-
assertJwkClaimPresent(jwk.crv, '"crv" (Curve) Parameter');
|
|
190
|
-
assertJwkClaimPresent(jwk.x, '"x" (X Coordinate) Parameter');
|
|
191
|
-
assertJwkClaimPresent(jwk.y, '"y" (Y Coordinate) Parameter');
|
|
192
|
-
components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y };
|
|
193
|
-
break;
|
|
194
|
-
case 'OKP':
|
|
195
|
-
assertJwkClaimPresent(jwk.crv, '"crv" (Subtype of Key Pair) Parameter');
|
|
196
|
-
assertJwkClaimPresent(jwk.x, '"x" (Public Key) Parameter');
|
|
197
|
-
components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x };
|
|
198
|
-
break;
|
|
199
|
-
case 'RSA':
|
|
200
|
-
assertJwkClaimPresent(jwk.e, '"e" (Exponent) Parameter');
|
|
201
|
-
assertJwkClaimPresent(jwk.n, '"n" (Modulus) Parameter');
|
|
202
|
-
components = { e: jwk.e, kty: jwk.kty, n: jwk.n };
|
|
203
|
-
break;
|
|
204
|
-
case 'oct':
|
|
205
|
-
assertJwkClaimPresent(jwk.k, '"k" (Key Value) Parameter');
|
|
206
|
-
components = { k: jwk.k, kty: jwk.kty };
|
|
207
|
-
break;
|
|
208
|
-
default:
|
|
209
|
-
throw new Error('"kty" (Key Type) Parameter missing or unsupported');
|
|
210
|
-
}
|
|
211
|
-
const data = JSON.stringify(components);
|
|
212
|
-
return digestAlgorithm === 'sha512'
|
|
213
|
-
? (0, digest_methods_1.digestMethodParams)('SHA-512').digestMethod(data, 'base64url')
|
|
214
|
-
: (0, digest_methods_1.digestMethodParams)('SHA-256').digestMethod(data, 'base64url');
|
|
215
|
-
};
|
|
216
|
-
exports.calculateJwkThumbprint = calculateJwkThumbprint;
|
|
217
|
-
const toJwkFromKey = (key, opts) => {
|
|
218
|
-
const isPrivateKey = 'privateKeyHex' in key;
|
|
219
|
-
return (0, exports.toJwk)(key.publicKeyHex, key.type, Object.assign(Object.assign({}, opts), { key, isPrivateKey }));
|
|
220
|
-
};
|
|
221
|
-
exports.toJwkFromKey = toJwkFromKey;
|
|
222
|
-
/**
|
|
223
|
-
* Converts a public key in hex format to a JWK
|
|
224
|
-
* @param publicKeyHex public key in hex
|
|
225
|
-
* @param type The type of the key (Ed25519, Secp256k1/r1)
|
|
226
|
-
* @param opts. Options, like the optional use for the key (sig/enc)
|
|
227
|
-
* @return The JWK
|
|
228
|
-
*/
|
|
229
|
-
const toJwk = (publicKeyHex, type, opts) => {
|
|
230
|
-
const { key, noKidThumbprint = false } = opts !== null && opts !== void 0 ? opts : {};
|
|
231
|
-
if (key && key.publicKeyHex !== publicKeyHex && (opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) !== true) {
|
|
232
|
-
throw Error(`Provided key with id ${key.kid}, has a different public key hex ${key.publicKeyHex} than supplied public key ${publicKeyHex}`);
|
|
233
|
-
}
|
|
234
|
-
let jwk;
|
|
235
|
-
switch (type) {
|
|
236
|
-
case 'Ed25519':
|
|
237
|
-
jwk = toEd25519OrX25519Jwk(publicKeyHex, Object.assign(Object.assign({}, opts), { crv: ssi_types_1.JoseCurve.Ed25519 }));
|
|
238
|
-
break;
|
|
239
|
-
case 'X25519':
|
|
240
|
-
jwk = toEd25519OrX25519Jwk(publicKeyHex, Object.assign(Object.assign({}, opts), { crv: ssi_types_1.JoseCurve.X25519 }));
|
|
241
|
-
break;
|
|
242
|
-
case 'Secp256k1':
|
|
243
|
-
jwk = toSecp256k1Jwk(publicKeyHex, opts);
|
|
244
|
-
break;
|
|
245
|
-
case 'Secp256r1':
|
|
246
|
-
jwk = toSecp256r1Jwk(publicKeyHex, opts);
|
|
247
|
-
break;
|
|
248
|
-
case 'RSA':
|
|
249
|
-
jwk = toRSAJwk(publicKeyHex, opts);
|
|
250
|
-
break;
|
|
251
|
-
default:
|
|
252
|
-
throw new Error(`not_supported: Key type ${type} not yet supported for this did:jwk implementation`);
|
|
253
|
-
}
|
|
254
|
-
if (!jwk.kid && !noKidThumbprint) {
|
|
255
|
-
jwk['kid'] = (0, exports.calculateJwkThumbprint)({ jwk });
|
|
256
|
-
}
|
|
257
|
-
return (0, exports.sanitizedJwk)(jwk);
|
|
258
|
-
};
|
|
259
|
-
exports.toJwk = toJwk;
|
|
260
|
-
/**
|
|
261
|
-
* Convert a JWK to a raw hex key.
|
|
262
|
-
* Currently supports `RSA` and `EC` keys. Extendable for other key types.
|
|
263
|
-
* @param jwk - The JSON Web Key object.
|
|
264
|
-
* @returns A string representing the key in raw hexadecimal format.
|
|
265
|
-
*/
|
|
266
|
-
const jwkToRawHexKey = (jwk) => __awaiter(void 0, void 0, void 0, function* () {
|
|
267
|
-
// TODO: Probably makes sense to have an option to do the same for private keys
|
|
268
|
-
jwk = (0, exports.sanitizedJwk)(jwk);
|
|
269
|
-
if (jwk.kty === 'RSA') {
|
|
270
|
-
return rsaJwkToRawHexKey(jwk);
|
|
271
|
-
}
|
|
272
|
-
else if (jwk.kty === 'EC') {
|
|
273
|
-
return ecJwkToRawHexKey(jwk);
|
|
274
|
-
}
|
|
275
|
-
else if (jwk.kty === 'OKP') {
|
|
276
|
-
return okpJwkToRawHexKey(jwk);
|
|
277
|
-
}
|
|
278
|
-
else if (jwk.kty === 'oct') {
|
|
279
|
-
return octJwkToRawHexKey(jwk);
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
throw new Error(`Unsupported key type: ${jwk.kty}`);
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
exports.jwkToRawHexKey = jwkToRawHexKey;
|
|
286
|
-
/**
|
|
287
|
-
* Convert an RSA JWK to a raw hex key.
|
|
288
|
-
* @param jwk - The RSA JWK object.
|
|
289
|
-
* @returns A string representing the RSA key in raw hexadecimal format.
|
|
290
|
-
*/
|
|
291
|
-
function rsaJwkToRawHexKey(jwk) {
|
|
292
|
-
jwk = (0, exports.sanitizedJwk)(jwk);
|
|
293
|
-
if (!jwk.n || !jwk.e) {
|
|
294
|
-
throw new Error("RSA JWK must contain 'n' and 'e' properties.");
|
|
295
|
-
}
|
|
296
|
-
// We are converting from base64 to base64url to be sure. The spec uses base64url, but in the wild we sometimes encounter a base64 string
|
|
297
|
-
const modulus = u8a.fromString(jwk.n.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), 'base64url'); // 'n' is the modulus
|
|
298
|
-
const exponent = u8a.fromString(jwk.e.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), 'base64url'); // 'e' is the exponent
|
|
299
|
-
return u8a.toString(modulus, 'hex') + u8a.toString(exponent, 'hex');
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Convert an EC JWK to a raw hex key.
|
|
303
|
-
* @param jwk - The EC JWK object.
|
|
304
|
-
* @returns A string representing the EC key in raw hexadecimal format.
|
|
305
|
-
*/
|
|
306
|
-
function ecJwkToRawHexKey(jwk) {
|
|
307
|
-
jwk = (0, exports.sanitizedJwk)(jwk);
|
|
308
|
-
if (!jwk.x || !jwk.y) {
|
|
309
|
-
throw new Error("EC JWK must contain 'x' and 'y' properties.");
|
|
310
|
-
}
|
|
311
|
-
// We are converting from base64 to base64url to be sure. The spec uses base64url, but in the wild we sometimes encounter a base64 string
|
|
312
|
-
const x = u8a.fromString(jwk.x.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), 'base64url');
|
|
313
|
-
const y = u8a.fromString(jwk.y.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), 'base64url');
|
|
314
|
-
return '04' + u8a.toString(x, 'hex') + u8a.toString(y, 'hex');
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Convert an EC JWK to a raw hex key.
|
|
318
|
-
* @param jwk - The EC JWK object.
|
|
319
|
-
* @returns A string representing the EC key in raw hexadecimal format.
|
|
320
|
-
*/
|
|
321
|
-
function okpJwkToRawHexKey(jwk) {
|
|
322
|
-
jwk = (0, exports.sanitizedJwk)(jwk);
|
|
323
|
-
if (!jwk.x) {
|
|
324
|
-
throw new Error("OKP JWK must contain 'x' property.");
|
|
325
|
-
}
|
|
326
|
-
// We are converting from base64 to base64url to be sure. The spec uses base64url, but in the wild we sometimes encounter a base64 string
|
|
327
|
-
const x = u8a.fromString(jwk.x.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), 'base64url');
|
|
328
|
-
return u8a.toString(x, 'hex');
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Convert an octet JWK to a raw hex key.
|
|
332
|
-
* @param jwk - The octet JWK object.
|
|
333
|
-
* @returns A string representing the octet key in raw hexadecimal format.
|
|
334
|
-
*/
|
|
335
|
-
function octJwkToRawHexKey(jwk) {
|
|
336
|
-
jwk = (0, exports.sanitizedJwk)(jwk);
|
|
337
|
-
if (!jwk.k) {
|
|
338
|
-
throw new Error("Octet JWK must contain 'k' property.");
|
|
339
|
-
}
|
|
340
|
-
// We are converting from base64 to base64url to be sure. The spec uses base64url, but in the wild we sometimes encounter a base64 string
|
|
341
|
-
const key = u8a.fromString(jwk.k.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), 'base64url');
|
|
342
|
-
return u8a.toString(key, 'hex');
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Determines the use param based upon the key/signature type or supplied use value.
|
|
346
|
-
*
|
|
347
|
-
* @param type The key type
|
|
348
|
-
* @param suppliedUse A supplied use. Will be used in case it is present
|
|
349
|
-
*/
|
|
350
|
-
const jwkDetermineUse = (type, suppliedUse) => {
|
|
351
|
-
return suppliedUse
|
|
352
|
-
? suppliedUse
|
|
353
|
-
: types_1.SIG_KEY_ALGS.includes(type)
|
|
354
|
-
? types_1.JwkKeyUse.Signature
|
|
355
|
-
: types_1.ENC_KEY_ALGS.includes(type)
|
|
356
|
-
? types_1.JwkKeyUse.Encryption
|
|
357
|
-
: undefined;
|
|
358
|
-
};
|
|
359
|
-
exports.jwkDetermineUse = jwkDetermineUse;
|
|
360
|
-
/**
|
|
361
|
-
* Assert the key has a proper length
|
|
362
|
-
*
|
|
363
|
-
* @param keyHex Input key
|
|
364
|
-
* @param expectedKeyLength Expected key length(s)
|
|
365
|
-
*/
|
|
366
|
-
const assertProperKeyLength = (keyHex, expectedKeyLength) => {
|
|
367
|
-
if (Array.isArray(expectedKeyLength)) {
|
|
368
|
-
if (!expectedKeyLength.includes(keyHex.length)) {
|
|
369
|
-
throw Error(`Invalid key length. Needs to be a hex string with length from ${JSON.stringify(expectedKeyLength)} instead of ${keyHex.length}. Input: ${keyHex}`);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
else if (keyHex.length !== expectedKeyLength) {
|
|
373
|
-
throw Error(`Invalid key length. Needs to be a hex string with length ${expectedKeyLength} instead of ${keyHex.length}. Input: ${keyHex}`);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
/**
|
|
377
|
-
* Generates a JWK from a Secp256k1 public key
|
|
378
|
-
* @param keyHex Secp256k1 public or private key in hex
|
|
379
|
-
* @param use The use for the key
|
|
380
|
-
* @return The JWK
|
|
381
|
-
*/
|
|
382
|
-
const toSecp256k1Jwk = (keyHex, opts) => {
|
|
383
|
-
const { use } = opts !== null && opts !== void 0 ? opts : {};
|
|
384
|
-
exports.logger.debug(`toSecp256k1Jwk keyHex: ${keyHex}, length: ${keyHex.length}`);
|
|
385
|
-
if (opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) {
|
|
386
|
-
assertProperKeyLength(keyHex, [64]);
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
assertProperKeyLength(keyHex, [66, 130]);
|
|
390
|
-
}
|
|
391
|
-
const secp256k1 = new elliptic_1.default.ec('secp256k1');
|
|
392
|
-
const keyBytes = u8a.fromString(keyHex, 'base16');
|
|
393
|
-
const keyPair = (opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) ? secp256k1.keyFromPrivate(keyBytes) : secp256k1.keyFromPublic(keyBytes);
|
|
394
|
-
const pubPoint = keyPair.getPublic();
|
|
395
|
-
return (0, exports.sanitizedJwk)(Object.assign(Object.assign(Object.assign({ alg: ssi_types_1.JoseSignatureAlgorithm.ES256K }, (use !== undefined && { use })), { kty: ssi_types_1.JwkKeyType.EC, crv: ssi_types_1.JoseCurve.secp256k1, x: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(pubPoint.getX().toString('hex'), 'base64url'), y: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(pubPoint.getY().toString('hex'), 'base64url') }), ((opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) && { d: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(keyPair.getPrivate('hex'), 'base64url') })));
|
|
396
|
-
};
|
|
397
|
-
/**
|
|
398
|
-
* Generates a JWK from a Secp256r1 public key
|
|
399
|
-
* @param keyHex Secp256r1 public key in hex
|
|
400
|
-
* @param use The use for the key
|
|
401
|
-
* @return The JWK
|
|
402
|
-
*/
|
|
403
|
-
const toSecp256r1Jwk = (keyHex, opts) => {
|
|
404
|
-
const { use } = opts !== null && opts !== void 0 ? opts : {};
|
|
405
|
-
exports.logger.debug(`toSecp256r1Jwk keyHex: ${keyHex}, length: ${keyHex.length}`);
|
|
406
|
-
if (opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) {
|
|
407
|
-
assertProperKeyLength(keyHex, [64]);
|
|
408
|
-
}
|
|
409
|
-
else {
|
|
410
|
-
assertProperKeyLength(keyHex, [66, 130]);
|
|
411
|
-
}
|
|
412
|
-
const secp256r1 = new elliptic_1.default.ec('p256');
|
|
413
|
-
const keyBytes = u8a.fromString(keyHex, 'base16');
|
|
414
|
-
exports.logger.debug(`keyBytes length: ${keyBytes}`);
|
|
415
|
-
const keyPair = (opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) ? secp256r1.keyFromPrivate(keyBytes) : secp256r1.keyFromPublic(keyBytes);
|
|
416
|
-
const pubPoint = keyPair.getPublic();
|
|
417
|
-
return (0, exports.sanitizedJwk)(Object.assign(Object.assign(Object.assign({ alg: ssi_types_1.JoseSignatureAlgorithm.ES256 }, (use !== undefined && { use })), { kty: ssi_types_1.JwkKeyType.EC, crv: ssi_types_1.JoseCurve.P_256, x: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(pubPoint.getX().toString('hex'), 'base64url'), y: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(pubPoint.getY().toString('hex'), 'base64url') }), ((opts === null || opts === void 0 ? void 0 : opts.isPrivateKey) && { d: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(keyPair.getPrivate('hex'), 'base64url') })));
|
|
418
|
-
};
|
|
419
|
-
/**
|
|
420
|
-
* Generates a JWK from an Ed25519/X25519 public key
|
|
421
|
-
* @param publicKeyHex Ed25519/X25519 public key in hex
|
|
422
|
-
* @param opts
|
|
423
|
-
* @return The JWK
|
|
424
|
-
*/
|
|
425
|
-
const toEd25519OrX25519Jwk = (publicKeyHex, opts) => {
|
|
426
|
-
var _a;
|
|
427
|
-
assertProperKeyLength(publicKeyHex, 64);
|
|
428
|
-
const { use } = opts !== null && opts !== void 0 ? opts : {};
|
|
429
|
-
return (0, exports.sanitizedJwk)(Object.assign(Object.assign({ alg: ssi_types_1.JoseSignatureAlgorithm.EdDSA }, (use !== undefined && { use })), { kty: ssi_types_1.JwkKeyType.OKP, crv: (_a = opts === null || opts === void 0 ? void 0 : opts.crv) !== null && _a !== void 0 ? _a : ssi_types_1.JoseCurve.Ed25519, x: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(publicKeyHex, 'base64url') }));
|
|
430
|
-
};
|
|
431
|
-
const toRSAJwk = (publicKeyHex, opts) => {
|
|
432
|
-
var _a, _b;
|
|
433
|
-
const meta = (_a = opts === null || opts === void 0 ? void 0 : opts.key) === null || _a === void 0 ? void 0 : _a.meta;
|
|
434
|
-
if ((meta === null || meta === void 0 ? void 0 : meta.publicKeyJwk) || (meta === null || meta === void 0 ? void 0 : meta.publicKeyPEM)) {
|
|
435
|
-
if (meta === null || meta === void 0 ? void 0 : meta.publicKeyJwk) {
|
|
436
|
-
return meta.publicKeyJwk;
|
|
437
|
-
}
|
|
438
|
-
const publicKeyPEM = (_b = meta === null || meta === void 0 ? void 0 : meta.publicKeyPEM) !== null && _b !== void 0 ? _b : (0, ssi_sdk_ext_x509_utils_1.hexToPEM)(publicKeyHex, 'public');
|
|
439
|
-
return (0, ssi_sdk_ext_x509_utils_1.PEMToJwk)(publicKeyPEM, 'public');
|
|
440
|
-
}
|
|
441
|
-
// exponent (e) is 5 chars long, rest is modulus (n)
|
|
442
|
-
// const publicKey = publicKeyHex
|
|
443
|
-
// assertProperKeyLength(publicKey, [2048, 3072, 4096])
|
|
444
|
-
const exponent = publicKeyHex.slice(-5);
|
|
445
|
-
const modulus = publicKeyHex.slice(0, -5);
|
|
446
|
-
// const modulusBitLength = (modulus.length / 2) * 8
|
|
447
|
-
// const alg = modulusBitLength === 2048 ? JoseSignatureAlgorithm.RS256 : modulusBitLength === 3072 ? JoseSignatureAlgorithm.RS384 : modulusBitLength === 4096 ? JoseSignatureAlgorithm.RS512 : undefined
|
|
448
|
-
return (0, exports.sanitizedJwk)({
|
|
449
|
-
kty: 'RSA',
|
|
450
|
-
n: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(modulus, 'base64url'),
|
|
451
|
-
e: (0, ssi_sdk_ext_x509_utils_1.hexToBase64)(exponent, 'base64url'),
|
|
452
|
-
// ...(alg && { alg }),
|
|
453
|
-
});
|
|
454
|
-
};
|
|
455
|
-
const padLeft = (args) => {
|
|
456
|
-
var _a, _b;
|
|
457
|
-
const { data } = args;
|
|
458
|
-
const size = (_a = args.size) !== null && _a !== void 0 ? _a : 32;
|
|
459
|
-
const padString = (_b = args.padString) !== null && _b !== void 0 ? _b : '0';
|
|
460
|
-
if (data.length >= size) {
|
|
461
|
-
return data;
|
|
462
|
-
}
|
|
463
|
-
if (padString && padString.length === 0) {
|
|
464
|
-
throw Error(`Pad string needs to have at least a length of 1`);
|
|
465
|
-
}
|
|
466
|
-
const length = padString.length;
|
|
467
|
-
return padString.repeat((size - data.length) / length) + data;
|
|
468
|
-
};
|
|
469
|
-
exports.padLeft = padLeft;
|
|
470
|
-
var OIDType;
|
|
471
|
-
(function (OIDType) {
|
|
472
|
-
OIDType[OIDType["Secp256k1"] = 0] = "Secp256k1";
|
|
473
|
-
OIDType[OIDType["Secp256r1"] = 1] = "Secp256r1";
|
|
474
|
-
OIDType[OIDType["Ed25519"] = 2] = "Ed25519";
|
|
475
|
-
})(OIDType || (OIDType = {}));
|
|
476
|
-
const OID = {
|
|
477
|
-
[OIDType.Secp256k1]: new Uint8Array([0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01]),
|
|
478
|
-
[OIDType.Secp256r1]: new Uint8Array([0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07]),
|
|
479
|
-
[OIDType.Ed25519]: new Uint8Array([0x06, 0x03, 0x2b, 0x65, 0x70]),
|
|
480
|
-
};
|
|
481
|
-
const compareUint8Arrays = (a, b) => {
|
|
482
|
-
if (a.length !== b.length) {
|
|
483
|
-
return false;
|
|
484
|
-
}
|
|
485
|
-
for (let i = 0; i < a.length; i++) {
|
|
486
|
-
if (a[i] !== b[i]) {
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
return true;
|
|
491
|
-
};
|
|
492
|
-
const findSubarray = (haystack, needle) => {
|
|
493
|
-
for (let i = 0; i <= haystack.length - needle.length; i++) {
|
|
494
|
-
if (compareUint8Arrays(haystack.subarray(i, i + needle.length), needle)) {
|
|
495
|
-
return i;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
return -1;
|
|
499
|
-
};
|
|
500
|
-
const getTargetOID = (keyType) => {
|
|
501
|
-
switch (keyType) {
|
|
502
|
-
case 'Secp256k1':
|
|
503
|
-
return OID[OIDType.Secp256k1];
|
|
504
|
-
case 'Secp256r1':
|
|
505
|
-
return OID[OIDType.Secp256r1];
|
|
506
|
-
case 'Ed25519':
|
|
507
|
-
return OID[OIDType.Ed25519];
|
|
508
|
-
default:
|
|
509
|
-
throw new Error(`Unsupported key type: ${keyType}`);
|
|
510
|
-
}
|
|
511
|
-
};
|
|
512
|
-
const isAsn1Der = (key) => key[0] === 0x30;
|
|
513
|
-
exports.isAsn1Der = isAsn1Der;
|
|
514
|
-
const asn1DerToRawPublicKey = (derKey, keyType) => {
|
|
515
|
-
if (!(0, exports.isAsn1Der)(derKey)) {
|
|
516
|
-
throw new Error('Invalid DER encoding: Expected to start with sequence tag');
|
|
517
|
-
}
|
|
518
|
-
let index = 2;
|
|
519
|
-
if (derKey[1] & 0x80) {
|
|
520
|
-
const lengthBytesCount = derKey[1] & 0x7f;
|
|
521
|
-
index += lengthBytesCount;
|
|
522
|
-
}
|
|
523
|
-
const targetOid = getTargetOID(keyType);
|
|
524
|
-
const oidIndex = findSubarray(derKey, targetOid);
|
|
525
|
-
if (oidIndex === -1) {
|
|
526
|
-
throw new Error(`OID for ${keyType} not found in DER encoding`);
|
|
527
|
-
}
|
|
528
|
-
index = oidIndex + targetOid.length;
|
|
529
|
-
while (index < derKey.length && derKey[index] !== 0x03) {
|
|
530
|
-
index++;
|
|
531
|
-
}
|
|
532
|
-
if (index >= derKey.length) {
|
|
533
|
-
throw new Error('Invalid DER encoding: Bit string not found');
|
|
534
|
-
}
|
|
535
|
-
// Skip the bit string tag (0x03) and length byte
|
|
536
|
-
index += 2;
|
|
537
|
-
// Skip the unused bits count byte
|
|
538
|
-
index++;
|
|
539
|
-
return derKey.slice(index);
|
|
540
|
-
};
|
|
541
|
-
exports.asn1DerToRawPublicKey = asn1DerToRawPublicKey;
|
|
542
|
-
const isRawCompressedPublicKey = (key) => key.length === 33 && (key[0] === 0x02 || key[0] === 0x03);
|
|
543
|
-
exports.isRawCompressedPublicKey = isRawCompressedPublicKey;
|
|
544
|
-
const toRawCompressedHexPublicKey = (rawPublicKey, keyType) => {
|
|
545
|
-
if ((0, exports.isRawCompressedPublicKey)(rawPublicKey)) {
|
|
546
|
-
return (0, exports.hexStringFromUint8Array)(rawPublicKey);
|
|
547
|
-
}
|
|
548
|
-
if (keyType === 'Secp256k1' || keyType === 'Secp256r1') {
|
|
549
|
-
if (rawPublicKey[0] === 0x04 && rawPublicKey.length === 65) {
|
|
550
|
-
const xCoordinate = rawPublicKey.slice(1, 33);
|
|
551
|
-
const yCoordinate = rawPublicKey.slice(33);
|
|
552
|
-
const prefix = new Uint8Array([yCoordinate[31] % 2 === 0 ? 0x02 : 0x03]);
|
|
553
|
-
const resultKey = (0, exports.hexStringFromUint8Array)(new Uint8Array([...prefix, ...xCoordinate]));
|
|
554
|
-
exports.logger.debug(`converted public key ${(0, exports.hexStringFromUint8Array)(rawPublicKey)} to ${resultKey}`);
|
|
555
|
-
return resultKey;
|
|
556
|
-
}
|
|
557
|
-
return u8a.toString(rawPublicKey, 'base16');
|
|
558
|
-
}
|
|
559
|
-
else if (keyType === 'Ed25519') {
|
|
560
|
-
// Ed25519 keys are always in compressed form
|
|
561
|
-
return u8a.toString(rawPublicKey, 'base16');
|
|
562
|
-
}
|
|
563
|
-
throw new Error(`Unsupported key type: ${keyType}`);
|
|
564
|
-
};
|
|
565
|
-
exports.toRawCompressedHexPublicKey = toRawCompressedHexPublicKey;
|
|
566
|
-
const hexStringFromUint8Array = (value) => u8a.toString(value, 'base16');
|
|
567
|
-
exports.hexStringFromUint8Array = hexStringFromUint8Array;
|
|
568
|
-
const signatureAlgorithmFromKey = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
569
|
-
const { key } = args;
|
|
570
|
-
return (0, exports.signatureAlgorithmFromKeyType)({ type: key.type });
|
|
571
|
-
});
|
|
572
|
-
exports.signatureAlgorithmFromKey = signatureAlgorithmFromKey;
|
|
573
|
-
const signatureAlgorithmFromKeyType = (args) => {
|
|
574
|
-
const { type } = args;
|
|
575
|
-
switch (type) {
|
|
576
|
-
case 'Ed25519':
|
|
577
|
-
case 'X25519':
|
|
578
|
-
return ssi_types_1.JoseSignatureAlgorithm.EdDSA;
|
|
579
|
-
case 'Secp256r1':
|
|
580
|
-
return ssi_types_1.JoseSignatureAlgorithm.ES256;
|
|
581
|
-
case 'Secp384r1':
|
|
582
|
-
return ssi_types_1.JoseSignatureAlgorithm.ES384;
|
|
583
|
-
case 'Secp521r1':
|
|
584
|
-
return ssi_types_1.JoseSignatureAlgorithm.ES512;
|
|
585
|
-
case 'Secp256k1':
|
|
586
|
-
return ssi_types_1.JoseSignatureAlgorithm.ES256K;
|
|
587
|
-
default:
|
|
588
|
-
throw new Error(`Key type '${type}' not supported`);
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
exports.signatureAlgorithmFromKeyType = signatureAlgorithmFromKeyType;
|
|
592
|
-
// TODO improve this conversion for jwt and jsonld, not a fan of current structure
|
|
593
|
-
const keyTypeFromCryptographicSuite = (args) => {
|
|
594
|
-
const { crv, kty, alg } = args;
|
|
595
|
-
switch (alg) {
|
|
596
|
-
case 'RSASSA-PSS':
|
|
597
|
-
case 'RS256':
|
|
598
|
-
case 'RS384':
|
|
599
|
-
case 'RS512':
|
|
600
|
-
case 'PS256':
|
|
601
|
-
case 'PS384':
|
|
602
|
-
case 'PS512':
|
|
603
|
-
return 'RSA';
|
|
604
|
-
}
|
|
605
|
-
switch (crv) {
|
|
606
|
-
case 'EdDSA':
|
|
607
|
-
case 'Ed25519':
|
|
608
|
-
case 'Ed25519Signature2018':
|
|
609
|
-
case 'Ed25519Signature2020':
|
|
610
|
-
case 'JcsEd25519Signature2020':
|
|
611
|
-
return 'Ed25519';
|
|
612
|
-
case 'JsonWebSignature2020':
|
|
613
|
-
case 'ES256':
|
|
614
|
-
case 'ECDSA':
|
|
615
|
-
case 'P-256':
|
|
616
|
-
return 'Secp256r1';
|
|
617
|
-
case 'ES384':
|
|
618
|
-
case 'P-384':
|
|
619
|
-
return 'Secp384r1';
|
|
620
|
-
case 'ES512':
|
|
621
|
-
case 'P-521':
|
|
622
|
-
return 'Secp521r1';
|
|
623
|
-
case 'EcdsaSecp256k1Signature2019':
|
|
624
|
-
case 'secp256k1':
|
|
625
|
-
case 'ES256K':
|
|
626
|
-
return 'Secp256k1';
|
|
627
|
-
}
|
|
628
|
-
if (kty) {
|
|
629
|
-
return kty;
|
|
630
|
-
}
|
|
631
|
-
throw new Error(`Cryptographic suite '${crv}' not supported`);
|
|
632
|
-
};
|
|
633
|
-
exports.keyTypeFromCryptographicSuite = keyTypeFromCryptographicSuite;
|
|
634
|
-
function removeNulls(obj) {
|
|
635
|
-
Object.keys(obj).forEach((key) => {
|
|
636
|
-
if (obj[key] && typeof obj[key] === 'object')
|
|
637
|
-
removeNulls(obj[key]);
|
|
638
|
-
else if (obj[key] == null)
|
|
639
|
-
delete obj[key];
|
|
640
|
-
});
|
|
641
|
-
return obj;
|
|
642
|
-
}
|
|
643
|
-
const globalCrypto = (setGlobal, suppliedCrypto) => {
|
|
644
|
-
var _a, _b;
|
|
645
|
-
let webcrypto;
|
|
646
|
-
if (typeof suppliedCrypto !== 'undefined') {
|
|
647
|
-
webcrypto = suppliedCrypto;
|
|
648
|
-
}
|
|
649
|
-
else if (typeof crypto !== 'undefined') {
|
|
650
|
-
webcrypto = crypto;
|
|
651
|
-
}
|
|
652
|
-
else if (typeof global.crypto !== 'undefined') {
|
|
653
|
-
webcrypto = global.crypto;
|
|
654
|
-
}
|
|
655
|
-
else if (typeof ((_b = (_a = global.window) === null || _a === void 0 ? void 0 : _a.crypto) === null || _b === void 0 ? void 0 : _b.subtle) !== 'undefined') {
|
|
656
|
-
webcrypto = global.window.crypto;
|
|
657
|
-
}
|
|
658
|
-
else {
|
|
659
|
-
webcrypto = require('crypto');
|
|
660
|
-
}
|
|
661
|
-
if (setGlobal) {
|
|
662
|
-
global.crypto = webcrypto;
|
|
663
|
-
}
|
|
664
|
-
return webcrypto;
|
|
665
|
-
};
|
|
666
|
-
exports.globalCrypto = globalCrypto;
|
|
667
|
-
const sanitizedJwk = (input) => {
|
|
668
|
-
const inputJwk = typeof input['toJsonDTO'] === 'function' ? input['toJsonDTO']() : Object.assign({}, input); // KMP code can expose this. It converts a KMP JWK with mangled names into a clean JWK
|
|
669
|
-
const jwk = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, inputJwk), (inputJwk.x && { x: base64ToBase64Url(inputJwk.x) })), (inputJwk.y && { y: base64ToBase64Url(inputJwk.y) })), (inputJwk.d && { d: base64ToBase64Url(inputJwk.d) })), (inputJwk.n && { n: base64ToBase64Url(inputJwk.n) })), (inputJwk.e && { e: base64ToBase64Url(inputJwk.e) })), (inputJwk.k && { k: base64ToBase64Url(inputJwk.k) }));
|
|
670
|
-
return removeNulls(jwk);
|
|
671
|
-
};
|
|
672
|
-
exports.sanitizedJwk = sanitizedJwk;
|
|
673
|
-
const base64ToBase64Url = (input) => {
|
|
674
|
-
return input.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
675
|
-
};
|
|
676
|
-
/**
|
|
677
|
-
*
|
|
678
|
-
*/
|
|
679
|
-
function verifyRawSignature(_a) {
|
|
680
|
-
return __awaiter(this, arguments, void 0, function* ({ data, signature, key: inputKey, opts, }) {
|
|
681
|
-
var _b, _c;
|
|
682
|
-
/**
|
|
683
|
-
* Converts a Base64URL-encoded JWK property to a BigInt.
|
|
684
|
-
* @param jwkProp - The Base64URL-encoded string.
|
|
685
|
-
* @returns The BigInt representation of the decoded value.
|
|
686
|
-
*/
|
|
687
|
-
function jwkPropertyToBigInt(jwkProp) {
|
|
688
|
-
// Decode Base64URL to Uint8Array
|
|
689
|
-
const byteArray = u8a.fromString(jwkProp, 'base64url');
|
|
690
|
-
// Convert Uint8Array to hexadecimal string and then to BigInt
|
|
691
|
-
const hex = u8a.toString(byteArray, 'hex');
|
|
692
|
-
return BigInt(`0x${hex}`);
|
|
693
|
-
}
|
|
694
|
-
try {
|
|
695
|
-
(0, debug_1.default)(`verifyRawSignature for: ${inputKey}`);
|
|
696
|
-
const jwk = (0, exports.sanitizedJwk)(inputKey);
|
|
697
|
-
(0, jwk_jcs_1.validateJwk)(jwk, { crvOptional: true });
|
|
698
|
-
const keyType = (0, exports.keyTypeFromCryptographicSuite)({ crv: jwk.crv, kty: jwk.kty, alg: jwk.alg });
|
|
699
|
-
const publicKeyHex = yield (0, exports.jwkToRawHexKey)(jwk);
|
|
700
|
-
// TODO: We really should look at the signature alg first if provided! From key type should be the last resort
|
|
701
|
-
switch (keyType) {
|
|
702
|
-
case 'Secp256k1':
|
|
703
|
-
return secp256k1_1.secp256k1.verify(signature, data, publicKeyHex, { format: 'compact', prehash: true });
|
|
704
|
-
case 'Secp256r1':
|
|
705
|
-
return p256_1.p256.verify(signature, data, publicKeyHex, { format: 'compact', prehash: true });
|
|
706
|
-
case 'Secp384r1':
|
|
707
|
-
return p384_1.p384.verify(signature, data, publicKeyHex, { format: 'compact', prehash: true });
|
|
708
|
-
case 'Secp521r1':
|
|
709
|
-
return p521_1.p521.verify(signature, data, publicKeyHex, { format: 'compact', prehash: true });
|
|
710
|
-
case 'Ed25519':
|
|
711
|
-
return ed25519_1.ed25519.verify(signature, data, u8a.fromString(publicKeyHex, 'hex'));
|
|
712
|
-
case 'Bls12381G1':
|
|
713
|
-
case 'Bls12381G2':
|
|
714
|
-
return bls12_381_1.bls12_381.verify(signature, data, u8a.fromString(publicKeyHex, 'hex'));
|
|
715
|
-
case 'RSA': {
|
|
716
|
-
const signatureAlgorithm = (_c = (_b = opts === null || opts === void 0 ? void 0 : opts.signatureAlg) !== null && _b !== void 0 ? _b : jwk.alg) !== null && _c !== void 0 ? _c : ssi_types_1.JoseSignatureAlgorithm.PS256;
|
|
717
|
-
const hashAlg = signatureAlgorithm === (ssi_types_1.JoseSignatureAlgorithm.RS512 || ssi_types_1.JoseSignatureAlgorithm.PS512)
|
|
718
|
-
? sha512_1.sha512
|
|
719
|
-
: signatureAlgorithm === (ssi_types_1.JoseSignatureAlgorithm.RS384 || ssi_types_1.JoseSignatureAlgorithm.PS384)
|
|
720
|
-
? sha512_1.sha384
|
|
721
|
-
: sha256_1.sha256;
|
|
722
|
-
switch (signatureAlgorithm) {
|
|
723
|
-
case ssi_types_1.JoseSignatureAlgorithm.RS256:
|
|
724
|
-
return rsa.PKCS1_SHA256.verify({
|
|
725
|
-
n: jwkPropertyToBigInt(jwk.n),
|
|
726
|
-
e: jwkPropertyToBigInt(jwk.e),
|
|
727
|
-
}, data, signature);
|
|
728
|
-
case ssi_types_1.JoseSignatureAlgorithm.RS384:
|
|
729
|
-
return rsa.PKCS1_SHA384.verify({
|
|
730
|
-
n: jwkPropertyToBigInt(jwk.n),
|
|
731
|
-
e: jwkPropertyToBigInt(jwk.e),
|
|
732
|
-
}, data, signature);
|
|
733
|
-
case ssi_types_1.JoseSignatureAlgorithm.RS512:
|
|
734
|
-
return rsa.PKCS1_SHA512.verify({
|
|
735
|
-
n: jwkPropertyToBigInt(jwk.n),
|
|
736
|
-
e: jwkPropertyToBigInt(jwk.e),
|
|
737
|
-
}, data, signature);
|
|
738
|
-
case ssi_types_1.JoseSignatureAlgorithm.PS256:
|
|
739
|
-
case ssi_types_1.JoseSignatureAlgorithm.PS384:
|
|
740
|
-
case ssi_types_1.JoseSignatureAlgorithm.PS512:
|
|
741
|
-
return rsa.PSS(hashAlg, rsa.mgf1(hashAlg)).verify({
|
|
742
|
-
n: jwkPropertyToBigInt(jwk.n),
|
|
743
|
-
e: jwkPropertyToBigInt(jwk.e),
|
|
744
|
-
}, data, signature);
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
throw Error(`Unsupported key type for signature validation: ${keyType}`);
|
|
749
|
-
}
|
|
750
|
-
catch (error) {
|
|
751
|
-
exports.logger.error(`Error: ${error}`);
|
|
752
|
-
throw error;
|
|
753
|
-
}
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
//# sourceMappingURL=functions.js.map
|