if (typeof Crypto == "undefined" || ! Crypto.util) | |
{ | |
(function(){ | |
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
// Global Crypto object | |
var Crypto = window.Crypto = {}; | |
// Crypto utilities | |
var util = Crypto.util = { | |
// Bit-wise rotate left | |
rotl: function (n, b) { | |
return (n << b) | (n >>> (32 - b)); | |
}, | |
// Bit-wise rotate right | |
rotr: function (n, b) { | |
return (n << (32 - b)) | (n >>> b); | |
}, | |
// Swap big-endian to little-endian and vice versa | |
endian: function (n) { | |
// If number given, swap endian | |
if (n.constructor == Number) { | |
return util.rotl(n, 8) & 0x00FF00FF | | |
util.rotl(n, 24) & 0xFF00FF00; | |
} | |
// Else, assume array and swap all items | |
for (var i = 0; i < n.length; i++) | |
n[i] = util.endian(n[i]); | |
return n; | |
}, | |
// Generate an array of any length of random bytes | |
randomBytes: function (n) { | |
var array = new Uint8Array(n); | |
crypto.getRandomValues(array); | |
// Now convert them from a Uint8Array to a regular array of ints. | |
return [].map.call(array, function(_){ return _; }); | |
}, | |
// Convert a byte array to big-endian 32-bit words | |
bytesToWords: function (bytes) { | |
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8) | |
words[b >>> 5] |= bytes[i] << (24 - b % 32); | |
return words; | |
}, | |
// Convert big-endian 32-bit words to a byte array | |
wordsToBytes: function (words) { | |
for (var bytes = [], b = 0; b < words.length * 32; b += 8) | |
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); | |
return bytes; | |
}, | |
// Convert a byte array to a hex string | |
bytesToHex: function (bytes) { | |
for (var hex = [], i = 0; i < bytes.length; i++) { | |
hex.push((bytes[i] >>> 4).toString(16)); | |
hex.push((bytes[i] & 0xF).toString(16)); | |
} | |
return hex.join(""); | |
}, | |
// Convert a hex string to a byte array | |
hexToBytes: function (hex) { | |
for (var bytes = [], c = 0; c < hex.length; c += 2) | |
bytes.push(parseInt(hex.substr(c, 2), 16)); | |
return bytes; | |
}, | |
// Convert a byte array to a base-64 string | |
bytesToBase64: function (bytes) { | |
// Use browser-native function if it exists | |
if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes)); | |
for(var base64 = [], i = 0; i < bytes.length; i += 3) { | |
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]; | |
for (var j = 0; j < 4; j++) { | |
if (i * 8 + j * 6 <= bytes.length * 8) | |
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F)); | |
else base64.push("="); | |
} | |
} | |
return base64.join(""); | |
}, | |
// Convert a base-64 string to a byte array | |
base64ToBytes: function (base64) { | |
// Use browser-native function if it exists | |
if (typeof atob == "function") return Binary.stringToBytes(atob(base64)); | |
// Remove non-base-64 characters | |
base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); | |
for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) { | |
if (imod4 == 0) continue; | |
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) | | |
(base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2))); | |
} | |
return bytes; | |
} | |
}; | |
// Crypto character encodings | |
var charenc = Crypto.charenc = {}; | |
// UTF-8 encoding | |
var UTF8 = charenc.UTF8 = { | |
// Convert a string to a byte array | |
stringToBytes: function (str) { | |
return Binary.stringToBytes(unescape(encodeURIComponent(str))); | |
}, | |
// Convert a byte array to a string | |
bytesToString: function (bytes) { | |
return decodeURIComponent(escape(Binary.bytesToString(bytes))); | |
} | |
}; | |
// Binary encoding | |
var Binary = charenc.Binary = { | |
// Convert a string to a byte array | |
stringToBytes: function (str) { | |
for (var bytes = [], i = 0; i < str.length; i++) | |
bytes.push(str.charCodeAt(i) & 0xFF); | |
return bytes; | |
}, | |
// Convert a byte array to a string | |
bytesToString: function (bytes) { | |
for (var str = [], i = 0; i < bytes.length; i++) | |
str.push(String.fromCharCode(bytes[i])); | |
return str.join(""); | |
} | |
}; | |
})(); | |
} |