| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 82eccdd commit 1149af6
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1284,6 +1284,25 @@ passing keys as strings or `Buffer`s due to improved security features. | |||
| 1284 | 1284 | The receiver obtains a cloned `KeyObject`, and the `KeyObject` does not need to | |
| 1285 | 1285 | be listed in the `transferList` argument. | |
| 1286 | 1286 | ||
| 1287 | + ### `keyObject.asymmetricKeyDetails` | ||
| 1288 | + <!-- YAML | ||
| 1289 | + added: REPLACEME | ||
| 1290 | + --> | ||
| 1291 | + | ||
| 1292 | + * {Object} | ||
| 1293 | + * `modulusLength`: {number} Key size in bits (RSA, DSA). | ||
| 1294 | + * `publicExponent`: {bigint} Public exponent (RSA). | ||
| 1295 | + * `divisorLength`: {number} Size of `q` in bits (DSA). | ||
| 1296 | + * `namedCurve`: {string} Name of the curve (EC). | ||
| 1297 | + | ||
| 1298 | + This property exists only on asymmetric keys. Depending on the type of the key, | ||
| 1299 | + this object contains information about the key. None of the information obtained | ||
| 1300 | + through this property can be used to uniquely identify a key or to compromise | ||
| 1301 | + the security of the key. | ||
| 1302 | + | ||
| 1303 | + RSA-PSS parameters, DH, or any future key type details might be exposed via this | ||
| 1304 | + API using additional attributes. | ||
| 1305 | + | ||
| 1287 | 1306 | ### `keyObject.asymmetricKeyType` | |
| 1288 | 1307 | <!-- YAML | |
| 1289 | 1308 | added: v11.6.0 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ const { | |||
| 5 | 5 | ObjectDefineProperty, | |
| 6 | 6 | ObjectSetPrototypeOf, | |
| 7 | 7 | Symbol, | |
| 8 | + Uint8Array, | ||
| 8 | 9 | } = primordials; | |
| 9 | 10 | ||
| 10 | 11 | const { | |
@@ -36,6 +37,7 @@ const { | |||
| 36 | 37 | kHandle, | |
| 37 | 38 | kKeyObject, | |
| 38 | 39 | getArrayBufferOrView, | |
| 40 | + bigIntArrayToUnsignedBigInt, | ||
| 39 | 41 | } = require('internal/crypto/util'); | |
| 40 | 42 | ||
| 41 | 43 | const { | |
@@ -128,12 +130,39 @@ const [ | |||
| 128 | 130 | } | |
| 129 | 131 | ||
| 130 | 132 | const kAsymmetricKeyType = Symbol('kAsymmetricKeyType'); | |
| 133 | + const kAsymmetricKeyDetails = Symbol('kAsymmetricKeyDetails'); | ||
| 134 | + | ||
| 135 | + function normalizeKeyDetails(details = {}) { | ||
| 136 | + if (details.publicExponent !== undefined) { | ||
| 137 | + return { | ||
| 138 | + ...details, | ||
| 139 | + publicExponent: | ||
| 140 | + bigIntArrayToUnsignedBigInt(new Uint8Array(details.publicExponent)) | ||
| 141 | + }; | ||
| 142 | + } | ||
| 143 | + return details; | ||
| 144 | + } | ||
| 131 | 145 | ||
| 132 | 146 | class AsymmetricKeyObject extends KeyObject { | |
| 133 | 147 | get asymmetricKeyType() { | |
| 134 | 148 | return this[kAsymmetricKeyType] || | |
| 135 | 149 | (this[kAsymmetricKeyType] = this[kHandle].getAsymmetricKeyType()); | |
| 136 | 150 | } | |
| 151 | + | ||
| 152 | + get asymmetricKeyDetails() { | ||
| 153 | + switch (this.asymmetricKeyType) { | ||
| 154 | + case 'rsa': | ||
| 155 | + case 'rsa-pss': | ||
| 156 | + case 'dsa': | ||
| 157 | + case 'ec': | ||
| 158 | + return this[kAsymmetricKeyDetails] || | ||
| 159 | + (this[kAsymmetricKeyDetails] = normalizeKeyDetails( | ||
| 160 | + this[kHandle].keyDetail({}) | ||
| 161 | + )); | ||
| 162 | + default: | ||
| 163 | + return {}; | ||
| 164 | + } | ||
| 165 | + } | ||
| 137 | 166 | } | |
| 138 | 167 | ||
| 139 | 168 | class PublicKeyObject extends AsymmetricKeyObject { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,6 +3,7 @@ | |||
| 3 | 3 | const { | |
| 4 | 4 | ArrayPrototypeIncludes, | |
| 5 | 5 | ArrayPrototypePush, | |
| 6 | + BigInt, | ||
| 6 | 7 | FunctionPrototypeBind, | |
| 7 | 8 | Number, | |
| 8 | 9 | Promise, | |
@@ -308,6 +309,17 @@ function bigIntArrayToUnsignedInt(input) { | |||
| 308 | 309 | return result; | |
| 309 | 310 | } | |
| 310 | 311 | ||
| 312 | + function bigIntArrayToUnsignedBigInt(input) { | ||
| 313 | + let result = 0n; | ||
| 314 | + | ||
| 315 | + for (let n = 0; n < input.length; ++n) { | ||
| 316 | + const n_reversed = input.length - n - 1; | ||
| 317 | + result |= BigInt(input[n]) << 8n * BigInt(n_reversed); | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + return result; | ||
| 321 | + } | ||
| 322 | + | ||
| 311 | 323 | function getStringOption(options, key) { | |
| 312 | 324 | let value; | |
| 313 | 325 | if (options && (value = options[key]) != null) | |
@@ -413,6 +425,7 @@ module.exports = { | |||
| 413 | 425 | jobPromise, | |
| 414 | 426 | lazyRequire, | |
| 415 | 427 | validateMaxBufferLength, | |
| 428 | + bigIntArrayToUnsignedBigInt, | ||
| 416 | 429 | bigIntArrayToUnsignedInt, | |
| 417 | 430 | getStringOption, | |
| 418 | 431 | getUsagesUnion, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,6 +70,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', | |||
| 70 | 70 | assert.strictEqual(key.type, 'secret'); | |
| 71 | 71 | assert.strictEqual(key.symmetricKeySize, 32); | |
| 72 | 72 | assert.strictEqual(key.asymmetricKeyType, undefined); | |
| 73 | + assert.strictEqual(key.asymmetricKeyDetails, undefined); | ||
| 73 | 74 | ||
| 74 | 75 | const exportedKey = key.export(); | |
| 75 | 76 | assert(keybuf.equals(exportedKey)); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -114,6 +114,31 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); | |||
| 114 | 114 | testSignVerify(publicKey, privateKey); | |
| 115 | 115 | } | |
| 116 | 116 | ||
| 117 | + { | ||
| 118 | + // Test sync key generation with key objects with a non-standard | ||
| 119 | + // publicExpononent | ||
| 120 | + const { publicKey, privateKey } = generateKeyPairSync('rsa', { | ||
| 121 | + publicExponent: 3, | ||
| 122 | + modulusLength: 512 | ||
| 123 | + }); | ||
| 124 | + | ||
| 125 | + assert.strictEqual(typeof publicKey, 'object'); | ||
| 126 | + assert.strictEqual(publicKey.type, 'public'); | ||
| 127 | + assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); | ||
| 128 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { | ||
| 129 | + modulusLength: 512, | ||
| 130 | + publicExponent: 3n | ||
| 131 | + }); | ||
| 132 | + | ||
| 133 | + assert.strictEqual(typeof privateKey, 'object'); | ||
| 134 | + assert.strictEqual(privateKey.type, 'private'); | ||
| 135 | + assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); | ||
| 136 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { | ||
| 137 | + modulusLength: 512, | ||
| 138 | + publicExponent: 3n | ||
| 139 | + }); | ||
| 140 | + } | ||
| 141 | + | ||
| 117 | 142 | { | |
| 118 | 143 | // Test sync key generation with key objects. | |
| 119 | 144 | const { publicKey, privateKey } = generateKeyPairSync('rsa', { | |
@@ -123,10 +148,18 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); | |||
| 123 | 148 | assert.strictEqual(typeof publicKey, 'object'); | |
| 124 | 149 | assert.strictEqual(publicKey.type, 'public'); | |
| 125 | 150 | assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); | |
| 151 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { | ||
| 152 | + modulusLength: 512, | ||
| 153 | + publicExponent: 65537n | ||
| 154 | + }); | ||
| 126 | 155 | ||
| 127 | 156 | assert.strictEqual(typeof privateKey, 'object'); | |
| 128 | 157 | assert.strictEqual(privateKey.type, 'private'); | |
| 129 | 158 | assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); | |
| 159 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { | ||
| 160 | + modulusLength: 512, | ||
| 161 | + publicExponent: 65537n | ||
| 162 | + }); | ||
| 130 | 163 | } | |
| 131 | 164 | ||
| 132 | 165 | { | |
@@ -268,9 +301,17 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); | |||
| 268 | 301 | }, common.mustSucceed((publicKey, privateKey) => { | |
| 269 | 302 | assert.strictEqual(publicKey.type, 'public'); | |
| 270 | 303 | assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); | |
| 304 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { | ||
| 305 | + modulusLength: 512, | ||
| 306 | + publicExponent: 65537n | ||
| 307 | + }); | ||
| 271 | 308 | ||
| 272 | 309 | assert.strictEqual(privateKey.type, 'private'); | |
| 273 | 310 | assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); | |
| 311 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { | ||
| 312 | + modulusLength: 512, | ||
| 313 | + publicExponent: 65537n | ||
| 314 | + }); | ||
| 274 | 315 | ||
| 275 | 316 | // Unlike RSA, RSA-PSS does not allow encryption. | |
| 276 | 317 | assert.throws(() => { | |
@@ -342,6 +383,28 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); | |||
| 342 | 383 | })); | |
| 343 | 384 | } | |
| 344 | 385 | ||
| 386 | + { | ||
| 387 | + // Test async DSA key object generation. | ||
| 388 | + generateKeyPair('dsa', { | ||
| 389 | + modulusLength: 512, | ||
| 390 | + divisorLength: 256 | ||
| 391 | + }, common.mustSucceed((publicKey, privateKey) => { | ||
| 392 | + assert.strictEqual(publicKey.type, 'public'); | ||
| 393 | + assert.strictEqual(publicKey.asymmetricKeyType, 'dsa'); | ||
| 394 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { | ||
| 395 | + modulusLength: 512, | ||
| 396 | + divisorLength: 256 | ||
| 397 | + }); | ||
| 398 | + | ||
| 399 | + assert.strictEqual(privateKey.type, 'private'); | ||
| 400 | + assert.strictEqual(privateKey.asymmetricKeyType, 'dsa'); | ||
| 401 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { | ||
| 402 | + modulusLength: 512, | ||
| 403 | + divisorLength: 256 | ||
| 404 | + }); | ||
| 405 | + })); | ||
| 406 | + } | ||
| 407 | + | ||
| 345 | 408 | { | |
| 346 | 409 | // Test async elliptic curve key generation, e.g. for ECDSA, with a SEC1 | |
| 347 | 410 | // private key. | |
@@ -925,16 +988,24 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); | |||
| 925 | 988 | // It should recognize both NIST and standard curve names. | |
| 926 | 989 | generateKeyPair('ec', { | |
| 927 | 990 | namedCurve: 'P-256', | |
| 928 | - publicKeyEncoding: { type: 'spki', format: 'pem' }, | ||
| 929 | - privateKeyEncoding: { type: 'pkcs8', format: 'pem' } | ||
| 930 | 991 | }, common.mustSucceed((publicKey, privateKey) => { | |
| 992 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { | ||
| 993 | + namedCurve: 'prime256v1' | ||
| 994 | + }); | ||
| 995 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { | ||
| 996 | + namedCurve: 'prime256v1' | ||
| 997 | + }); | ||
| 931 | 998 | })); | |
| 932 | 999 | ||
| 933 | 1000 | generateKeyPair('ec', { | |
| 934 | 1001 | namedCurve: 'secp256k1', | |
| 935 | - publicKeyEncoding: { type: 'spki', format: 'pem' }, | ||
| 936 | - privateKeyEncoding: { type: 'pkcs8', format: 'pem' } | ||
| 937 | 1002 | }, common.mustSucceed((publicKey, privateKey) => { | |
| 1003 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { | ||
| 1004 | + namedCurve: 'secp256k1' | ||
| 1005 | + }); | ||
| 1006 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { | ||
| 1007 | + namedCurve: 'secp256k1' | ||
| 1008 | + }); | ||
| 938 | 1009 | })); | |
| 939 | 1010 | } | |
| 940 | 1011 | ||
@@ -945,9 +1016,11 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); | |||
| 945 | 1016 | generateKeyPair(keyType, common.mustSucceed((publicKey, privateKey) => { | |
| 946 | 1017 | assert.strictEqual(publicKey.type, 'public'); | |
| 947 | 1018 | assert.strictEqual(publicKey.asymmetricKeyType, keyType); | |
| 1019 | + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {}); | ||
| 948 | 1020 | ||
| 949 | 1021 | assert.strictEqual(privateKey.type, 'private'); | |
| 950 | 1022 | assert.strictEqual(privateKey.asymmetricKeyType, keyType); | |
| 1023 | + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {}); | ||
| 951 | 1024 | })); | |
| 952 | 1025 | }); | |
| 953 | 1026 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments