diff --git a/lib/algorithms/rsa.js b/lib/algorithms/rsa.js index 929abf8..b07cd83 100644 --- a/lib/algorithms/rsa.js +++ b/lib/algorithms/rsa.js @@ -37,7 +37,7 @@ function uint8ArrayToUint32(bigInteger) { } function uint32ToUint8Array(integer) { - const result = Buffer.alloc(8); + const result = new Uint8Array(8); let i = 7; while (integer !== 0) { result[i--] = integer & 0xff; @@ -46,6 +46,33 @@ function uint32ToUint8Array(integer) { return result.slice(i + 1); } +function getAlgorithmProperties(key) { + const der = key.export({ + format: 'der', + type: 'pkcs1' + }); + + const dec = new Asn1SequenceDecoder(der); + if (key.type === 'private') { + // Skip the version field. + dec.unsignedInteger(); + } + + const n = dec.unsignedInteger(); + const e = dec.unsignedInteger(); + + // n cannot have a leading zero byte, but leading zero bits. + let modulusLength = 8; + while ((n[0] & (1 << (modulusLength - 1))) === 0) + modulusLength--; + modulusLength += (n.length - 1) * 8; + + return { + modulusLength, + publicExponent: new Uint8Array(e) + }; +} + function jwkToDer(jwk, jwkHashMapping) { if (jwk.kty !== 'RSA') throw new DataError(); @@ -205,8 +232,13 @@ const rsaBase = { type: keyFormat }); - return new CryptoKey(key.type, { name: this.name, hash }, - extractable, keyUsages, key); + const algorithm = { + name: this.name, + hash, + ...getAlgorithmProperties(key) + }; + + return new CryptoKey(key.type, algorithm, extractable, keyUsages, key); }, exportKey(format, key) { diff --git a/test/unit/algorithms/rsa.js b/test/unit/algorithms/rsa.js index bc7055f..9eb834e 100644 --- a/test/unit/algorithms/rsa.js +++ b/test/unit/algorithms/rsa.js @@ -23,7 +23,7 @@ function testGenImportExport(name, pubKeyUsage, privKeyUsage) { assert.strictEqual(key.algorithm.name, name); assert.strictEqual(key.algorithm.modulusLength, 2048); assert.deepStrictEqual(key.algorithm.publicExponent, - Buffer.from([0x01, 0x00, 0x01])); + new Uint8Array([0x01, 0x00, 0x01])); assert.strictEqual(key.algorithm.hash.name, 'SHA-384'); } @@ -41,6 +41,14 @@ function testGenImportExport(name, pubKeyUsage, privKeyUsage) { hash: 'SHA-384' }, true, [privKeyUsage]); + for (const key of [impPublicKey, impPrivateKey]) { + assert.strictEqual(key.algorithm.name, name); + assert.strictEqual(key.algorithm.modulusLength, 2048); + assert.deepStrictEqual(key.algorithm.publicExponent, + new Uint8Array([0x01, 0x00, 0x01])); + assert.strictEqual(key.algorithm.hash.name, 'SHA-384'); + } + assert.deepStrictEqual(await subtle.exportKey('spki', impPublicKey), expPublicKey); assert.deepStrictEqual(await subtle.exportKey('pkcs8', impPrivateKey),