diff --git a/src/crypto/public_key/rsa.js b/src/crypto/public_key/rsa.js index 71e68479..fe293897 100644 --- a/src/crypto/public_key/rsa.js +++ b/src/crypto/public_key/rsa.js @@ -135,7 +135,6 @@ function RSA() { function generate(B, E) { var webCrypto = util.getWebCrypto(); - var promise; // // Native RSA keygen using Web Crypto @@ -144,22 +143,41 @@ function RSA() { if (webCrypto) { var Euint32 = new Uint32Array([parseInt(E, 16)]); // get integer of exponent var Euint8 = new Uint8Array(Euint32.buffer); // get bytes of exponent - var keyGenOpt = { - name: 'RSASSA-PKCS1-v1_5', - modulusLength: B, // the specified keysize in bits - publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537) - hash: { - name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' - } - }; - promise = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']); - return promise.then(exportKey).then(decodeKey); + var keyGenOpt; + + if (window.crypto.subtle) { + // current standard spec + keyGenOpt = { + name: 'RSASSA-PKCS1-v1_5', + modulusLength: B, // the specified keysize in bits + publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537) + hash: { + name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify' + } + }; + return webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']).then(exportKey).then(decodeKey); + + } else if (window.crypto.webkitSubtle) { + // outdated spec implemented by Webkit + keyGenOpt = { + name: 'RSA-OAEP', + modulusLength: B, // the specified keysize in bits + publicExponent: Euint8.subarray(0, 3), // take three bytes (max 65537) + }; + return webCrypto.generateKey(keyGenOpt, true, ['encrypt', 'decrypt']).then(exportKey).then(function(key) { + if (key instanceof ArrayBuffer) { + // parse raw ArrayBuffer bytes to jwk/json (WebKit/Safari quirk) + return decodeKey(JSON.parse(String.fromCharCode.apply(null, new Uint8Array(key)))); + } + return decodeKey(key); + }); + } } - function exportKey(key) { + function exportKey(keypair) { // export the generated keys as JsonWebKey (JWK) // https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33 - return webCrypto.exportKey('jwk', key.privateKey); + return webCrypto.exportKey('jwk', keypair.privateKey); } function decodeKey(jwk) { @@ -185,7 +203,7 @@ function RSA() { // JS code // - promise = new Promise(function(resolve) { + return new Promise(function(resolve) { var key = new keyObject(); var rng = new SecureRandom(); var qs = B >> 1; @@ -223,8 +241,6 @@ function RSA() { resolve(key); }); - - return promise; } this.encrypt = encrypt; diff --git a/src/util.js b/src/util.js index b4a56fd8..89a08387 100644 --- a/src/util.js +++ b/src/util.js @@ -320,8 +320,8 @@ module.exports = { return; } - if (typeof window !== 'undefined' && window.crypto && window.crypto.subtle) { - return window.crypto.subtle; + if (typeof window !== 'undefined' && window.crypto) { + return window.crypto.subtle || window.crypto.webkitSubtle; } } };