try/catch WebCrypto, fallback to forge
This commit is contained in:
parent
20afbd65b1
commit
aa28eaa713
|
@ -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) {
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue