try/catch WebCrypto, fallback to forge

This commit is contained in:
AJ ONeal 2015-10-23 03:12:20 -07:00
parent 20afbd65b1
commit aa28eaa713
3 changed files with 38 additions and 18 deletions

View File

@ -17,11 +17,11 @@ if (!window.crypto) {
// Generate a key // Generate a key
function generateOtpKey() { function generateOtpKey() {
// 20 cryptographically random binary bytes (160-bit key) // 20 cryptographically random binary bytes (160-bit key)
if (window.crypto) { try {
var key = window.crypto.getRandomValues(new Uint8Array(20)); var key = window.crypto.getRandomValues(new Uint8Array(20));
return Promise.resolve(key); return Promise.resolve(key);
} else { } catch(e) {
// Promises are supported even in Microsoft Edge // Promises are supported even in Microsoft Edge
// only old IE and old android need shims // only old IE and old android need shims
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {

View File

@ -12,7 +12,18 @@ exports.sha1Hmac = function (key, bytes) {
var Unibabel = window.Unibabel; var Unibabel = window.Unibabel;
if (window.crypto) { function useForge() {
var forge = window.forge;
var hmac = forge.hmac.create();
var digest;
hmac.start('sha1', Unibabel.bufferToBinaryString(key));
hmac.update(Unibabel.bufferToBinaryString(bytes));
digest = hmac.digest().toHex();
return window.Promise.resolve(digest);
}
function useWebCrypto() {
return (window.crypto.subtle||window.crypto.webkitSubtle).importKey( return (window.crypto.subtle||window.crypto.webkitSubtle).importKey(
"raw" "raw"
, key.buffer , key.buffer
@ -52,15 +63,29 @@ exports.sha1Hmac = function (key, bytes) {
}); });
}); });
} }
else if (window.forge) {
var forge = window.forge;
var hmac = forge.hmac.create();
var digest;
hmac.start('sha1', Unibabel.bufferToBinaryString(key));
hmac.update(Unibabel.bufferToBinaryString(bytes));
digest = hmac.digest().toHex();
return window.Promise.resolve(digest); if (window.crypto) {
// WebCrypto is so unreliable right now... ugh...
try {
return useWebCrypto().then(function (result) {
return result;
}, function (err) {
console.warn(err);
console.warn(err.stack);
console.warn("WebCrypto failed, trying forge.js");
return useForge();
});
} catch(e) {
console.warn(e);
console.warn(e.stack);
console.warn("WebCrypto threw exception, trying forge.js");
return useForge();
}
}
else if (window.forge) {
return useForge();
} }
else { else {
throw new Error("WebCrypto or forge.js is required to create a sha1 hmac"); throw new Error("WebCrypto or forge.js is required to create a sha1 hmac");

View File

@ -95,7 +95,6 @@ exports.base32ToBuffer = function(encoded) {
} else { } else {
decoded = new Array(len); decoded = new Array(len);
} }
console.log('debug mobile safari: decoded', decoded);
/* byte by byte isn't as pretty as octet by octet but tests a bit /* byte by byte isn't as pretty as octet by octet but tests a bit
faster. will have to revisit. */ faster. will have to revisit. */
@ -133,13 +132,9 @@ exports.base32ToBuffer = function(encoded) {
} }
} }
console.log('debug mobile safari: decoded 2', decoded); if (decoded.slice) { // Array or TypedArray
if (decoded.slice) {
console.log('debug mobile safari: decoded 3a', decoded);
return decoded.slice(0, plainPos); return decoded.slice(0, plainPos);
} else { } else { // Mobile Safari TypedArray
console.log('debug mobile safari: decoded 3b', decoded);
// Mobile Safari's Uint8Array doesn't have slice
return new Uint8Array(Array.prototype.slice.call(decoded, 0, plainPos)); return new Uint8Array(Array.prototype.slice.call(decoded, 0, plainPos));
} }
}; };