From aa28eaa713c10374000ad0e01661eed41a9d071b Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Fri, 23 Oct 2015 03:12:20 -0700 Subject: [PATCH] try/catch WebCrypto, fallback to forge --- authenticator.js | 4 +- bower_components/botp/sha1-hmac.js | 43 ++++++++++++++++---- bower_components/unibabel/unibabel.base32.js | 9 +--- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/authenticator.js b/authenticator.js index 42fc48f..b9f2c25 100644 --- a/authenticator.js +++ b/authenticator.js @@ -17,11 +17,11 @@ if (!window.crypto) { // Generate a key function generateOtpKey() { // 20 cryptographically random binary bytes (160-bit key) - if (window.crypto) { + try { var key = window.crypto.getRandomValues(new Uint8Array(20)); return Promise.resolve(key); - } else { + } catch(e) { // Promises are supported even in Microsoft Edge // only old IE and old android need shims return new Promise(function (resolve, reject) { diff --git a/bower_components/botp/sha1-hmac.js b/bower_components/botp/sha1-hmac.js index a0a2494..3a0e00c 100644 --- a/bower_components/botp/sha1-hmac.js +++ b/bower_components/botp/sha1-hmac.js @@ -12,7 +12,18 @@ exports.sha1Hmac = function (key, bytes) { 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( "raw" , 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 { throw new Error("WebCrypto or forge.js is required to create a sha1 hmac"); diff --git a/bower_components/unibabel/unibabel.base32.js b/bower_components/unibabel/unibabel.base32.js index 7e4142a..8a0baac 100644 --- a/bower_components/unibabel/unibabel.base32.js +++ b/bower_components/unibabel/unibabel.base32.js @@ -95,7 +95,6 @@ exports.base32ToBuffer = function(encoded) { } else { 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 faster. will have to revisit. */ @@ -133,13 +132,9 @@ exports.base32ToBuffer = function(encoded) { } } - console.log('debug mobile safari: decoded 2', decoded); - if (decoded.slice) { - console.log('debug mobile safari: decoded 3a', decoded); + if (decoded.slice) { // Array or TypedArray return decoded.slice(0, plainPos); - } else { - console.log('debug mobile safari: decoded 3b', decoded); - // Mobile Safari's Uint8Array doesn't have slice + } else { // Mobile Safari TypedArray return new Uint8Array(Array.prototype.slice.call(decoded, 0, plainPos)); } };