pbca26
8 years ago
29 changed files with 7199 additions and 428 deletions
@ -0,0 +1,164 @@ |
|||||
|
import { |
||||
|
triggerToaster, |
||||
|
getNewKMDAddresses |
||||
|
} from '../actionCreators'; |
||||
|
import { |
||||
|
logGuiHttp, |
||||
|
guiLogState |
||||
|
} from './log'; |
||||
|
import Config from '../../config'; |
||||
|
|
||||
|
function getNewAddress(coin) { // TODO: remove(?)
|
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'getnewaddress' |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'genJumblrAddress + getKMDAddressesNative', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function setJumblrAddress(coin, type, address) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: type === 'deposit' ? 'jumblr_deposit' : 'jumblr_secret', |
||||
|
params: [address], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'setJumblrAddress', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function dumpPrivkey(coin, key) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'dumpprivkey', |
||||
|
params: [key], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'dumpPrivkey ', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function importPrivkey(coin, key) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'importprivkey', |
||||
|
params: [ |
||||
|
key, |
||||
|
'', |
||||
|
false |
||||
|
], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'importPrivkey ', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
// Array.prototype.map function is in the public domain.
|
||||
|
// Production steps of ECMA-262, Edition 5, 15.4.4.19
|
||||
|
// Reference: http://es5.github.com/#x15.4.4.19
|
||||
|
if (!Array.prototype.map) { |
||||
|
Array.prototype.map = function (callback, thisArg) { |
||||
|
var T, A, k; |
||||
|
if (this == null) { |
||||
|
throw new TypeError(" this is null or not defined"); |
||||
|
} |
||||
|
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
|
||||
|
var O = Object(this); |
||||
|
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
|
||||
|
// 3. Let len be ToUint32(lenValue).
|
||||
|
var len = O.length >>> 0; |
||||
|
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
||||
|
// See: http://es5.github.com/#x9.11
|
||||
|
if ({}.toString.call(callback) != "[object Function]") { |
||||
|
throw new TypeError(callback + " is not a function"); |
||||
|
} |
||||
|
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
||||
|
if (thisArg) { |
||||
|
T = thisArg; |
||||
|
} |
||||
|
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
|
||||
|
// the standard built-in constructor with that name and len is the value of len.
|
||||
|
A = new Array(len); |
||||
|
// 7. Let k be 0
|
||||
|
k = 0; |
||||
|
// 8. Repeat, while k < len
|
||||
|
while (k < len) { |
||||
|
var kValue, mappedValue; |
||||
|
// a. Let Pk be ToString(k).
|
||||
|
// This is implicit for LHS operands of the in operator
|
||||
|
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
|
||||
|
// This step can be combined with c
|
||||
|
// c. If kPresent is true, then
|
||||
|
if (k in O) { |
||||
|
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
|
||||
|
kValue = O[k]; |
||||
|
// ii. Let mappedValue be the result of calling the Call internal method of callback
|
||||
|
// with T as the this value and argument list containing kValue, k, and O.
|
||||
|
mappedValue = callback.call(T, kValue, k, O); |
||||
|
// iii. Call the DefineOwnProperty internal method of A with arguments
|
||||
|
// Pk, Property Descriptor {Value: mappedValue, Writable: true, Enumerable: true, Configurable: true},
|
||||
|
// and false.
|
||||
|
// In browsers that support Object.defineProperty, use the following:
|
||||
|
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
|
||||
|
// For best browser support, use the following:
|
||||
|
A[k] = mappedValue; |
||||
|
} |
||||
|
// d. Increase k by 1.
|
||||
|
k++; |
||||
|
} |
||||
|
// 9. return A
|
||||
|
return A; |
||||
|
}; |
||||
|
} |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,295 @@ |
|||||
|
/* |
||||
|
* Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved |
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to deal |
||||
|
* in the Software without restriction, including without limitation the rights |
||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
* copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
||||
|
* THE SOFTWARE. |
||||
|
*/ |
||||
|
// https://github.com/cheongwy/node-scrypt-js
|
||||
|
(function () { |
||||
|
|
||||
|
var MAX_VALUE = 2147483647; |
||||
|
var workerUrl = null; |
||||
|
|
||||
|
//function scrypt(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen)
|
||||
|
/* |
||||
|
* N = Cpu cost |
||||
|
* r = Memory cost |
||||
|
* p = parallelization cost |
||||
|
* |
||||
|
*/ |
||||
|
window.Crypto_scrypt = function (passwd, salt, N, r, p, dkLen, callback) { |
||||
|
if (N == 0 || (N & (N - 1)) != 0) throw Error("N must be > 0 and a power of 2"); |
||||
|
|
||||
|
if (N > MAX_VALUE / 128 / r) throw Error("Parameter N is too large"); |
||||
|
if (r > MAX_VALUE / 128 / p) throw Error("Parameter r is too large"); |
||||
|
|
||||
|
var PBKDF2_opts = { iterations: 1, hasher: Crypto.SHA256, asBytes: true }; |
||||
|
|
||||
|
var B = Crypto.PBKDF2(passwd, salt, p * 128 * r, PBKDF2_opts); |
||||
|
|
||||
|
try { |
||||
|
var i = 0; |
||||
|
var worksDone = 0; |
||||
|
var makeWorker = function () { |
||||
|
if (!workerUrl) { |
||||
|
var code = '(' + scryptCore.toString() + ')()'; |
||||
|
var blob; |
||||
|
try { |
||||
|
blob = new Blob([code], { type: "text/javascript" }); |
||||
|
} catch (e) { |
||||
|
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; |
||||
|
blob = new BlobBuilder(); |
||||
|
blob.append(code); |
||||
|
blob = blob.getBlob("text/javascript"); |
||||
|
} |
||||
|
workerUrl = URL.createObjectURL(blob); |
||||
|
} |
||||
|
var worker = new Worker(workerUrl); |
||||
|
worker.onmessage = function (event) { |
||||
|
var Bi = event.data[0], Bslice = event.data[1]; |
||||
|
worksDone++; |
||||
|
|
||||
|
if (i < p) { |
||||
|
worker.postMessage([N, r, p, B, i++]); |
||||
|
} |
||||
|
|
||||
|
var length = Bslice.length, destPos = Bi * 128 * r, srcPos = 0; |
||||
|
while (length--) { |
||||
|
B[destPos++] = Bslice[srcPos++]; |
||||
|
} |
||||
|
|
||||
|
if (worksDone == p) { |
||||
|
callback(Crypto.PBKDF2(passwd, B, dkLen, PBKDF2_opts)); |
||||
|
} |
||||
|
}; |
||||
|
return worker; |
||||
|
}; |
||||
|
var workers = [makeWorker(), makeWorker()]; |
||||
|
workers[0].postMessage([N, r, p, B, i++]); |
||||
|
if (p > 1) { |
||||
|
workers[1].postMessage([N, r, p, B, i++]); |
||||
|
} |
||||
|
} catch (e) { |
||||
|
window.setTimeout(function () { |
||||
|
scryptCore(); |
||||
|
callback(Crypto.PBKDF2(passwd, B, dkLen, PBKDF2_opts)); |
||||
|
}, 0); |
||||
|
} |
||||
|
|
||||
|
// using this function to enclose everything needed to create a worker (but also invokable directly for synchronous use)
|
||||
|
function scryptCore() { |
||||
|
var XY = [], V = []; |
||||
|
|
||||
|
if (typeof B === 'undefined') { |
||||
|
onmessage = function (event) { |
||||
|
var data = event.data; |
||||
|
var N = data[0], r = data[1], p = data[2], B = data[3], i = data[4]; |
||||
|
|
||||
|
var Bslice = []; |
||||
|
arraycopy32(B, i * 128 * r, Bslice, 0, 128 * r); |
||||
|
smix(Bslice, 0, r, N, V, XY); |
||||
|
|
||||
|
postMessage([i, Bslice]); |
||||
|
}; |
||||
|
} else { |
||||
|
for (var i = 0; i < p; i++) { |
||||
|
smix(B, i * 128 * r, r, N, V, XY); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function smix(B, Bi, r, N, V, XY) { |
||||
|
var Xi = 0; |
||||
|
var Yi = 128 * r; |
||||
|
var i; |
||||
|
|
||||
|
arraycopy32(B, Bi, XY, Xi, Yi); |
||||
|
|
||||
|
for (i = 0; i < N; i++) { |
||||
|
arraycopy32(XY, Xi, V, i * Yi, Yi); |
||||
|
blockmix_salsa8(XY, Xi, Yi, r); |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < N; i++) { |
||||
|
var j = integerify(XY, Xi, r) & (N - 1); |
||||
|
blockxor(V, j * Yi, XY, Xi, Yi); |
||||
|
blockmix_salsa8(XY, Xi, Yi, r); |
||||
|
} |
||||
|
|
||||
|
arraycopy32(XY, Xi, B, Bi, Yi); |
||||
|
} |
||||
|
|
||||
|
function blockmix_salsa8(BY, Bi, Yi, r) { |
||||
|
var X = []; |
||||
|
var i; |
||||
|
|
||||
|
arraycopy32(BY, Bi + (2 * r - 1) * 64, X, 0, 64); |
||||
|
|
||||
|
for (i = 0; i < 2 * r; i++) { |
||||
|
blockxor(BY, i * 64, X, 0, 64); |
||||
|
salsa20_8(X); |
||||
|
arraycopy32(X, 0, BY, Yi + (i * 64), 64); |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < r; i++) { |
||||
|
arraycopy32(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64); |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < r; i++) { |
||||
|
arraycopy32(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function R(a, b) { |
||||
|
return (a << b) | (a >>> (32 - b)); |
||||
|
} |
||||
|
|
||||
|
function salsa20_8(B) { |
||||
|
var B32 = new Array(32); |
||||
|
var x = new Array(32); |
||||
|
var i; |
||||
|
|
||||
|
for (i = 0; i < 16; i++) { |
||||
|
B32[i] = (B[i * 4 + 0] & 0xff) << 0; |
||||
|
B32[i] |= (B[i * 4 + 1] & 0xff) << 8; |
||||
|
B32[i] |= (B[i * 4 + 2] & 0xff) << 16; |
||||
|
B32[i] |= (B[i * 4 + 3] & 0xff) << 24; |
||||
|
} |
||||
|
|
||||
|
arraycopy(B32, 0, x, 0, 16); |
||||
|
|
||||
|
for (i = 8; i > 0; i -= 2) { |
||||
|
x[4] ^= R(x[0] + x[12], 7); x[8] ^= R(x[4] + x[0], 9); |
||||
|
x[12] ^= R(x[8] + x[4], 13); x[0] ^= R(x[12] + x[8], 18); |
||||
|
x[9] ^= R(x[5] + x[1], 7); x[13] ^= R(x[9] + x[5], 9); |
||||
|
x[1] ^= R(x[13] + x[9], 13); x[5] ^= R(x[1] + x[13], 18); |
||||
|
x[14] ^= R(x[10] + x[6], 7); x[2] ^= R(x[14] + x[10], 9); |
||||
|
x[6] ^= R(x[2] + x[14], 13); x[10] ^= R(x[6] + x[2], 18); |
||||
|
x[3] ^= R(x[15] + x[11], 7); x[7] ^= R(x[3] + x[15], 9); |
||||
|
x[11] ^= R(x[7] + x[3], 13); x[15] ^= R(x[11] + x[7], 18); |
||||
|
x[1] ^= R(x[0] + x[3], 7); x[2] ^= R(x[1] + x[0], 9); |
||||
|
x[3] ^= R(x[2] + x[1], 13); x[0] ^= R(x[3] + x[2], 18); |
||||
|
x[6] ^= R(x[5] + x[4], 7); x[7] ^= R(x[6] + x[5], 9); |
||||
|
x[4] ^= R(x[7] + x[6], 13); x[5] ^= R(x[4] + x[7], 18); |
||||
|
x[11] ^= R(x[10] + x[9], 7); x[8] ^= R(x[11] + x[10], 9); |
||||
|
x[9] ^= R(x[8] + x[11], 13); x[10] ^= R(x[9] + x[8], 18); |
||||
|
x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9); |
||||
|
x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18); |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i]; |
||||
|
|
||||
|
for (i = 0; i < 16; i++) { |
||||
|
var bi = i * 4; |
||||
|
B[bi + 0] = (B32[i] >> 0 & 0xff); |
||||
|
B[bi + 1] = (B32[i] >> 8 & 0xff); |
||||
|
B[bi + 2] = (B32[i] >> 16 & 0xff); |
||||
|
B[bi + 3] = (B32[i] >> 24 & 0xff); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function blockxor(S, Si, D, Di, len) { |
||||
|
var i = len >> 6; |
||||
|
while (i--) { |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
|
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function integerify(B, bi, r) { |
||||
|
var n; |
||||
|
|
||||
|
bi += (2 * r - 1) * 64; |
||||
|
|
||||
|
n = (B[bi + 0] & 0xff) << 0; |
||||
|
n |= (B[bi + 1] & 0xff) << 8; |
||||
|
n |= (B[bi + 2] & 0xff) << 16; |
||||
|
n |= (B[bi + 3] & 0xff) << 24; |
||||
|
|
||||
|
return n; |
||||
|
} |
||||
|
|
||||
|
function arraycopy(src, srcPos, dest, destPos, length) { |
||||
|
while (length--) { |
||||
|
dest[destPos++] = src[srcPos++]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function arraycopy32(src, srcPos, dest, destPos, length) { |
||||
|
var i = length >> 5; |
||||
|
while (i--) { |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
|
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
|
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
|
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++]; |
||||
|
} |
||||
|
} |
||||
|
} // scryptCore
|
||||
|
}; // window.Crypto_scrypt
|
||||
|
})(); |
@ -0,0 +1,407 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS v2.5.4 AES.js |
||||
|
* http://code.google.com/p/crypto-js/
|
||||
|
* Copyright (c) 2009-2013, Jeff Mott. All rights reserved. |
||||
|
* http://code.google.com/p/crypto-js/wiki/License
|
||||
|
*/ |
||||
|
(function () { |
||||
|
|
||||
|
// Shortcuts
|
||||
|
var C = Crypto, |
||||
|
util = C.util, |
||||
|
charenc = C.charenc, |
||||
|
UTF8 = charenc.UTF8; |
||||
|
|
||||
|
// Precomputed SBOX
|
||||
|
var SBOX = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, |
||||
|
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, |
||||
|
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, |
||||
|
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, |
||||
|
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, |
||||
|
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, |
||||
|
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, |
||||
|
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, |
||||
|
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, |
||||
|
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, |
||||
|
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, |
||||
|
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, |
||||
|
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, |
||||
|
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, |
||||
|
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, |
||||
|
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, |
||||
|
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, |
||||
|
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, |
||||
|
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, |
||||
|
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, |
||||
|
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, |
||||
|
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, |
||||
|
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, |
||||
|
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, |
||||
|
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, |
||||
|
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, |
||||
|
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, |
||||
|
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, |
||||
|
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, |
||||
|
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, |
||||
|
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, |
||||
|
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]; |
||||
|
|
||||
|
// Compute inverse SBOX lookup table
|
||||
|
for (var INVSBOX = [], i = 0; i < 256; i++) INVSBOX[SBOX[i]] = i; |
||||
|
|
||||
|
// Compute multiplication in GF(2^8) lookup tables
|
||||
|
var MULT2 = [], |
||||
|
MULT3 = [], |
||||
|
MULT9 = [], |
||||
|
MULTB = [], |
||||
|
MULTD = [], |
||||
|
MULTE = []; |
||||
|
|
||||
|
function xtime(a, b) { |
||||
|
for (var result = 0, i = 0; i < 8; i++) { |
||||
|
if (b & 1) result ^= a; |
||||
|
var hiBitSet = a & 0x80; |
||||
|
a = (a << 1) & 0xFF; |
||||
|
if (hiBitSet) a ^= 0x1b; |
||||
|
b >>>= 1; |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; i < 256; i++) { |
||||
|
MULT2[i] = xtime(i, 2); |
||||
|
MULT3[i] = xtime(i, 3); |
||||
|
MULT9[i] = xtime(i, 9); |
||||
|
MULTB[i] = xtime(i, 0xB); |
||||
|
MULTD[i] = xtime(i, 0xD); |
||||
|
MULTE[i] = xtime(i, 0xE); |
||||
|
} |
||||
|
|
||||
|
// Precomputed RCon lookup
|
||||
|
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; |
||||
|
|
||||
|
// Inner state
|
||||
|
var state = [[], [], [], []], |
||||
|
keylength, |
||||
|
nrounds, |
||||
|
keyschedule; |
||||
|
|
||||
|
var AES = C.AES = { |
||||
|
|
||||
|
/** |
||||
|
* Public API |
||||
|
*/ |
||||
|
|
||||
|
encrypt: function (message, password, options) { |
||||
|
|
||||
|
options = options || {}; |
||||
|
|
||||
|
// Determine mode
|
||||
|
var mode = options.mode || new C.mode.OFB; |
||||
|
|
||||
|
// Allow mode to override options
|
||||
|
if (mode.fixOptions) mode.fixOptions(options); |
||||
|
|
||||
|
var |
||||
|
|
||||
|
// Convert to bytes if message is a string
|
||||
|
m = ( |
||||
|
message.constructor == String ? |
||||
|
UTF8.stringToBytes(message) : |
||||
|
message |
||||
|
), |
||||
|
|
||||
|
// Generate random IV
|
||||
|
iv = options.iv || util.randomBytes(AES._blocksize * 4), |
||||
|
|
||||
|
// Generate key
|
||||
|
k = ( |
||||
|
password.constructor == String ? |
||||
|
// Derive key from pass-phrase
|
||||
|
C.PBKDF2(password, iv, 32, { asBytes: true }) : |
||||
|
// else, assume byte array representing cryptographic key
|
||||
|
password |
||||
|
); |
||||
|
|
||||
|
// Encrypt
|
||||
|
AES._init(k); |
||||
|
mode.encrypt(AES, m, iv); |
||||
|
|
||||
|
// Return ciphertext
|
||||
|
m = options.iv ? m : iv.concat(m); |
||||
|
return (options && options.asBytes) ? m : util.bytesToBase64(m); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
decrypt: function (ciphertext, password, options) { |
||||
|
|
||||
|
options = options || {}; |
||||
|
|
||||
|
// Determine mode
|
||||
|
var mode = options.mode || new C.mode.OFB; |
||||
|
|
||||
|
// Allow mode to override options
|
||||
|
if (mode.fixOptions) mode.fixOptions(options); |
||||
|
|
||||
|
var |
||||
|
|
||||
|
// Convert to bytes if ciphertext is a string
|
||||
|
c = ( |
||||
|
ciphertext.constructor == String ? |
||||
|
util.base64ToBytes(ciphertext) : |
||||
|
ciphertext |
||||
|
), |
||||
|
|
||||
|
// Separate IV and message
|
||||
|
iv = options.iv || c.splice(0, AES._blocksize * 4), |
||||
|
|
||||
|
// Generate key
|
||||
|
k = ( |
||||
|
password.constructor == String ? |
||||
|
// Derive key from pass-phrase
|
||||
|
C.PBKDF2(password, iv, 32, { asBytes: true }) : |
||||
|
// else, assume byte array representing cryptographic key
|
||||
|
password |
||||
|
); |
||||
|
|
||||
|
// Decrypt
|
||||
|
AES._init(k); |
||||
|
mode.decrypt(AES, c, iv); |
||||
|
|
||||
|
// Return plaintext
|
||||
|
return (options && options.asBytes) ? c : UTF8.bytesToString(c); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Package private methods and properties |
||||
|
*/ |
||||
|
|
||||
|
_blocksize: 4, |
||||
|
|
||||
|
_encryptblock: function (m, offset) { |
||||
|
|
||||
|
// Set input
|
||||
|
for (var row = 0; row < AES._blocksize; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] = m[offset + col * 4 + row]; |
||||
|
} |
||||
|
|
||||
|
// Add round key
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] ^= keyschedule[col][row]; |
||||
|
} |
||||
|
|
||||
|
for (var round = 1; round < nrounds; round++) { |
||||
|
|
||||
|
// Sub bytes
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] = SBOX[state[row][col]]; |
||||
|
} |
||||
|
|
||||
|
// Shift rows
|
||||
|
state[1].push(state[1].shift()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[3].unshift(state[3].pop()); |
||||
|
|
||||
|
// Mix columns
|
||||
|
for (var col = 0; col < 4; col++) { |
||||
|
|
||||
|
var s0 = state[0][col], |
||||
|
s1 = state[1][col], |
||||
|
s2 = state[2][col], |
||||
|
s3 = state[3][col]; |
||||
|
|
||||
|
state[0][col] = MULT2[s0] ^ MULT3[s1] ^ s2 ^ s3; |
||||
|
state[1][col] = s0 ^ MULT2[s1] ^ MULT3[s2] ^ s3; |
||||
|
state[2][col] = s0 ^ s1 ^ MULT2[s2] ^ MULT3[s3]; |
||||
|
state[3][col] = MULT3[s0] ^ s1 ^ s2 ^ MULT2[s3]; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Add round key
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] ^= keyschedule[round * 4 + col][row]; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Sub bytes
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] = SBOX[state[row][col]]; |
||||
|
} |
||||
|
|
||||
|
// Shift rows
|
||||
|
state[1].push(state[1].shift()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[3].unshift(state[3].pop()); |
||||
|
|
||||
|
// Add round key
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] ^= keyschedule[nrounds * 4 + col][row]; |
||||
|
} |
||||
|
|
||||
|
// Set output
|
||||
|
for (var row = 0; row < AES._blocksize; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
m[offset + col * 4 + row] = state[row][col]; |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
_decryptblock: function (c, offset) { |
||||
|
|
||||
|
// Set input
|
||||
|
for (var row = 0; row < AES._blocksize; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] = c[offset + col * 4 + row]; |
||||
|
} |
||||
|
|
||||
|
// Add round key
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] ^= keyschedule[nrounds * 4 + col][row]; |
||||
|
} |
||||
|
|
||||
|
for (var round = 1; round < nrounds; round++) { |
||||
|
|
||||
|
// Inv shift rows
|
||||
|
state[1].unshift(state[1].pop()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[3].push(state[3].shift()); |
||||
|
|
||||
|
// Inv sub bytes
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] = INVSBOX[state[row][col]]; |
||||
|
} |
||||
|
|
||||
|
// Add round key
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] ^= keyschedule[(nrounds - round) * 4 + col][row]; |
||||
|
} |
||||
|
|
||||
|
// Inv mix columns
|
||||
|
for (var col = 0; col < 4; col++) { |
||||
|
|
||||
|
var s0 = state[0][col], |
||||
|
s1 = state[1][col], |
||||
|
s2 = state[2][col], |
||||
|
s3 = state[3][col]; |
||||
|
|
||||
|
state[0][col] = MULTE[s0] ^ MULTB[s1] ^ MULTD[s2] ^ MULT9[s3]; |
||||
|
state[1][col] = MULT9[s0] ^ MULTE[s1] ^ MULTB[s2] ^ MULTD[s3]; |
||||
|
state[2][col] = MULTD[s0] ^ MULT9[s1] ^ MULTE[s2] ^ MULTB[s3]; |
||||
|
state[3][col] = MULTB[s0] ^ MULTD[s1] ^ MULT9[s2] ^ MULTE[s3]; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Inv shift rows
|
||||
|
state[1].unshift(state[1].pop()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[2].push(state[2].shift()); |
||||
|
state[3].push(state[3].shift()); |
||||
|
|
||||
|
// Inv sub bytes
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] = INVSBOX[state[row][col]]; |
||||
|
} |
||||
|
|
||||
|
// Add round key
|
||||
|
for (var row = 0; row < 4; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
state[row][col] ^= keyschedule[col][row]; |
||||
|
} |
||||
|
|
||||
|
// Set output
|
||||
|
for (var row = 0; row < AES._blocksize; row++) { |
||||
|
for (var col = 0; col < 4; col++) |
||||
|
c[offset + col * 4 + row] = state[row][col]; |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Private methods |
||||
|
*/ |
||||
|
|
||||
|
_init: function (k) { |
||||
|
keylength = k.length / 4; |
||||
|
nrounds = keylength + 6; |
||||
|
AES._keyexpansion(k); |
||||
|
}, |
||||
|
|
||||
|
// Generate a key schedule
|
||||
|
_keyexpansion: function (k) { |
||||
|
|
||||
|
keyschedule = []; |
||||
|
|
||||
|
for (var row = 0; row < keylength; row++) { |
||||
|
keyschedule[row] = [ |
||||
|
k[row * 4], |
||||
|
k[row * 4 + 1], |
||||
|
k[row * 4 + 2], |
||||
|
k[row * 4 + 3] |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
for (var row = keylength; row < AES._blocksize * (nrounds + 1); row++) { |
||||
|
|
||||
|
var temp = [ |
||||
|
keyschedule[row - 1][0], |
||||
|
keyschedule[row - 1][1], |
||||
|
keyschedule[row - 1][2], |
||||
|
keyschedule[row - 1][3] |
||||
|
]; |
||||
|
|
||||
|
if (row % keylength == 0) { |
||||
|
|
||||
|
// Rot word
|
||||
|
temp.push(temp.shift()); |
||||
|
|
||||
|
// Sub word
|
||||
|
temp[0] = SBOX[temp[0]]; |
||||
|
temp[1] = SBOX[temp[1]]; |
||||
|
temp[2] = SBOX[temp[2]]; |
||||
|
temp[3] = SBOX[temp[3]]; |
||||
|
|
||||
|
temp[0] ^= RCON[row / keylength]; |
||||
|
|
||||
|
} else if (keylength > 6 && row % keylength == 4) { |
||||
|
|
||||
|
// Sub word
|
||||
|
temp[0] = SBOX[temp[0]]; |
||||
|
temp[1] = SBOX[temp[1]]; |
||||
|
temp[2] = SBOX[temp[2]]; |
||||
|
temp[3] = SBOX[temp[3]]; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
keyschedule[row] = [ |
||||
|
keyschedule[row - keylength][0] ^ temp[0], |
||||
|
keyschedule[row - keylength][1] ^ temp[1], |
||||
|
keyschedule[row - keylength][2] ^ temp[2], |
||||
|
keyschedule[row - keylength][3] ^ temp[3] |
||||
|
]; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})(); |
@ -0,0 +1,410 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS 2.5.4 BlockModes.js |
||||
|
* contribution from Simon Greatrix |
||||
|
*/ |
||||
|
|
||||
|
(function (C) { |
||||
|
|
||||
|
// Create pad namespace
|
||||
|
var C_pad = C.pad = {}; |
||||
|
|
||||
|
// Calculate the number of padding bytes required.
|
||||
|
function _requiredPadding(cipher, message) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
var reqd = blockSizeInBytes - message.length % blockSizeInBytes; |
||||
|
return reqd; |
||||
|
} |
||||
|
|
||||
|
// Remove padding when the final byte gives the number of padding bytes.
|
||||
|
var _unpadLength = function (cipher, message, alg, padding) { |
||||
|
var pad = message.pop(); |
||||
|
if (pad == 0) { |
||||
|
throw new Error("Invalid zero-length padding specified for " + alg |
||||
|
+ ". Wrong cipher specification or key used?"); |
||||
|
} |
||||
|
var maxPad = cipher._blocksize * 4; |
||||
|
if (pad > maxPad) { |
||||
|
throw new Error("Invalid padding length of " + pad |
||||
|
+ " specified for " + alg |
||||
|
+ ". Wrong cipher specification or key used?"); |
||||
|
} |
||||
|
for (var i = 1; i < pad; i++) { |
||||
|
var b = message.pop(); |
||||
|
if (padding != undefined && padding != b) { |
||||
|
throw new Error("Invalid padding byte of 0x" + b.toString(16) |
||||
|
+ " specified for " + alg |
||||
|
+ ". Wrong cipher specification or key used?"); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// No-operation padding, used for stream ciphers
|
||||
|
C_pad.NoPadding = { |
||||
|
pad: function (cipher, message) { }, |
||||
|
unpad: function (cipher, message) { } |
||||
|
}; |
||||
|
|
||||
|
// Zero Padding.
|
||||
|
//
|
||||
|
// If the message is not an exact number of blocks, the final block is
|
||||
|
// completed with 0x00 bytes. There is no unpadding.
|
||||
|
C_pad.ZeroPadding = { |
||||
|
pad: function (cipher, message) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
var reqd = message.length % blockSizeInBytes; |
||||
|
if (reqd != 0) { |
||||
|
for (reqd = blockSizeInBytes - reqd; reqd > 0; reqd--) { |
||||
|
message.push(0x00); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
unpad: function (cipher, message) { |
||||
|
while (message[message.length - 1] == 0) { |
||||
|
message.pop(); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// ISO/IEC 7816-4 padding.
|
||||
|
//
|
||||
|
// Pads the plain text with an 0x80 byte followed by as many 0x00
|
||||
|
// bytes are required to complete the block.
|
||||
|
C_pad.iso7816 = { |
||||
|
pad: function (cipher, message) { |
||||
|
var reqd = _requiredPadding(cipher, message); |
||||
|
message.push(0x80); |
||||
|
for (; reqd > 1; reqd--) { |
||||
|
message.push(0x00); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
unpad: function (cipher, message) { |
||||
|
var padLength; |
||||
|
for (padLength = cipher._blocksize * 4; padLength > 0; padLength--) { |
||||
|
var b = message.pop(); |
||||
|
if (b == 0x80) return; |
||||
|
if (b != 0x00) { |
||||
|
throw new Error("ISO-7816 padding byte must be 0, not 0x" + b.toString(16) + ". Wrong cipher specification or key used?"); |
||||
|
} |
||||
|
} |
||||
|
throw new Error("ISO-7816 padded beyond cipher block size. Wrong cipher specification or key used?"); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// ANSI X.923 padding
|
||||
|
//
|
||||
|
// The final block is padded with zeros except for the last byte of the
|
||||
|
// last block which contains the number of padding bytes.
|
||||
|
C_pad.ansix923 = { |
||||
|
pad: function (cipher, message) { |
||||
|
var reqd = _requiredPadding(cipher, message); |
||||
|
for (var i = 1; i < reqd; i++) { |
||||
|
message.push(0x00); |
||||
|
} |
||||
|
message.push(reqd); |
||||
|
}, |
||||
|
|
||||
|
unpad: function (cipher, message) { |
||||
|
_unpadLength(cipher, message, "ANSI X.923", 0); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// ISO 10126
|
||||
|
//
|
||||
|
// The final block is padded with random bytes except for the last
|
||||
|
// byte of the last block which contains the number of padding bytes.
|
||||
|
C_pad.iso10126 = { |
||||
|
pad: function (cipher, message) { |
||||
|
var reqd = _requiredPadding(cipher, message); |
||||
|
for (var i = 1; i < reqd; i++) { |
||||
|
message.push(Math.floor(Math.random() * 256)); |
||||
|
} |
||||
|
message.push(reqd); |
||||
|
}, |
||||
|
|
||||
|
unpad: function (cipher, message) { |
||||
|
_unpadLength(cipher, message, "ISO 10126", undefined); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// PKCS7 padding
|
||||
|
//
|
||||
|
// PKCS7 is described in RFC 5652. Padding is in whole bytes. The
|
||||
|
// value of each added byte is the number of bytes that are added,
|
||||
|
// i.e. N bytes, each of value N are added.
|
||||
|
C_pad.pkcs7 = { |
||||
|
pad: function (cipher, message) { |
||||
|
var reqd = _requiredPadding(cipher, message); |
||||
|
for (var i = 0; i < reqd; i++) { |
||||
|
message.push(reqd); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
unpad: function (cipher, message) { |
||||
|
_unpadLength(cipher, message, "PKCS 7", message[message.length - 1]); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Create mode namespace
|
||||
|
var C_mode = C.mode = {}; |
||||
|
|
||||
|
/** |
||||
|
* Mode base "class". |
||||
|
*/ |
||||
|
var Mode = C_mode.Mode = function (padding) { |
||||
|
if (padding) { |
||||
|
this._padding = padding; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
Mode.prototype = { |
||||
|
encrypt: function (cipher, m, iv) { |
||||
|
this._padding.pad(cipher, m); |
||||
|
this._doEncrypt(cipher, m, iv); |
||||
|
}, |
||||
|
|
||||
|
decrypt: function (cipher, m, iv) { |
||||
|
this._doDecrypt(cipher, m, iv); |
||||
|
this._padding.unpad(cipher, m); |
||||
|
}, |
||||
|
|
||||
|
// Default padding
|
||||
|
_padding: C_pad.iso7816 |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Electronic Code Book mode. |
||||
|
* |
||||
|
* ECB applies the cipher directly against each block of the input. |
||||
|
* |
||||
|
* ECB does not require an initialization vector. |
||||
|
*/ |
||||
|
var ECB = C_mode.ECB = function () { |
||||
|
// Call parent constructor
|
||||
|
Mode.apply(this, arguments); |
||||
|
}; |
||||
|
|
||||
|
// Inherit from Mode
|
||||
|
var ECB_prototype = ECB.prototype = new Mode; |
||||
|
|
||||
|
// Concrete steps for Mode template
|
||||
|
ECB_prototype._doEncrypt = function (cipher, m, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
// Encrypt each block
|
||||
|
for (var offset = 0; offset < m.length; offset += blockSizeInBytes) { |
||||
|
cipher._encryptblock(m, offset); |
||||
|
} |
||||
|
}; |
||||
|
ECB_prototype._doDecrypt = function (cipher, c, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
// Decrypt each block
|
||||
|
for (var offset = 0; offset < c.length; offset += blockSizeInBytes) { |
||||
|
cipher._decryptblock(c, offset); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// ECB never uses an IV
|
||||
|
ECB_prototype.fixOptions = function (options) { |
||||
|
options.iv = []; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Cipher block chaining |
||||
|
* |
||||
|
* The first block is XORed with the IV. Subsequent blocks are XOR with the |
||||
|
* previous cipher output. |
||||
|
*/ |
||||
|
var CBC = C_mode.CBC = function () { |
||||
|
// Call parent constructor
|
||||
|
Mode.apply(this, arguments); |
||||
|
}; |
||||
|
|
||||
|
// Inherit from Mode
|
||||
|
var CBC_prototype = CBC.prototype = new Mode; |
||||
|
|
||||
|
// Concrete steps for Mode template
|
||||
|
CBC_prototype._doEncrypt = function (cipher, m, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
|
||||
|
// Encrypt each block
|
||||
|
for (var offset = 0; offset < m.length; offset += blockSizeInBytes) { |
||||
|
if (offset == 0) { |
||||
|
// XOR first block using IV
|
||||
|
for (var i = 0; i < blockSizeInBytes; i++) |
||||
|
m[i] ^= iv[i]; |
||||
|
} else { |
||||
|
// XOR this block using previous crypted block
|
||||
|
for (var i = 0; i < blockSizeInBytes; i++) |
||||
|
m[offset + i] ^= m[offset + i - blockSizeInBytes]; |
||||
|
} |
||||
|
// Encrypt block
|
||||
|
cipher._encryptblock(m, offset); |
||||
|
} |
||||
|
}; |
||||
|
CBC_prototype._doDecrypt = function (cipher, c, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
|
||||
|
// At the start, the previously crypted block is the IV
|
||||
|
var prevCryptedBlock = iv; |
||||
|
|
||||
|
// Decrypt each block
|
||||
|
for (var offset = 0; offset < c.length; offset += blockSizeInBytes) { |
||||
|
// Save this crypted block
|
||||
|
var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes); |
||||
|
// Decrypt block
|
||||
|
cipher._decryptblock(c, offset); |
||||
|
// XOR decrypted block using previous crypted block
|
||||
|
for (var i = 0; i < blockSizeInBytes; i++) { |
||||
|
c[offset + i] ^= prevCryptedBlock[i]; |
||||
|
} |
||||
|
prevCryptedBlock = thisCryptedBlock; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Cipher feed back |
||||
|
* |
||||
|
* The cipher output is XORed with the plain text to produce the cipher output, |
||||
|
* which is then fed back into the cipher to produce a bit pattern to XOR the |
||||
|
* next block with. |
||||
|
* |
||||
|
* This is a stream cipher mode and does not require padding. |
||||
|
*/ |
||||
|
var CFB = C_mode.CFB = function () { |
||||
|
// Call parent constructor
|
||||
|
Mode.apply(this, arguments); |
||||
|
}; |
||||
|
|
||||
|
// Inherit from Mode
|
||||
|
var CFB_prototype = CFB.prototype = new Mode; |
||||
|
|
||||
|
// Override padding
|
||||
|
CFB_prototype._padding = C_pad.NoPadding; |
||||
|
|
||||
|
// Concrete steps for Mode template
|
||||
|
CFB_prototype._doEncrypt = function (cipher, m, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4, |
||||
|
keystream = iv.slice(0); |
||||
|
|
||||
|
// Encrypt each byte
|
||||
|
for (var i = 0; i < m.length; i++) { |
||||
|
|
||||
|
var j = i % blockSizeInBytes; |
||||
|
if (j == 0) cipher._encryptblock(keystream, 0); |
||||
|
|
||||
|
m[i] ^= keystream[j]; |
||||
|
keystream[j] = m[i]; |
||||
|
} |
||||
|
}; |
||||
|
CFB_prototype._doDecrypt = function (cipher, c, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4, |
||||
|
keystream = iv.slice(0); |
||||
|
|
||||
|
// Encrypt each byte
|
||||
|
for (var i = 0; i < c.length; i++) { |
||||
|
|
||||
|
var j = i % blockSizeInBytes; |
||||
|
if (j == 0) cipher._encryptblock(keystream, 0); |
||||
|
|
||||
|
var b = c[i]; |
||||
|
c[i] ^= keystream[j]; |
||||
|
keystream[j] = b; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Output feed back |
||||
|
* |
||||
|
* The cipher repeatedly encrypts its own output. The output is XORed with the |
||||
|
* plain text to produce the cipher text. |
||||
|
* |
||||
|
* This is a stream cipher mode and does not require padding. |
||||
|
*/ |
||||
|
var OFB = C_mode.OFB = function () { |
||||
|
// Call parent constructor
|
||||
|
Mode.apply(this, arguments); |
||||
|
}; |
||||
|
|
||||
|
// Inherit from Mode
|
||||
|
var OFB_prototype = OFB.prototype = new Mode; |
||||
|
|
||||
|
// Override padding
|
||||
|
OFB_prototype._padding = C_pad.NoPadding; |
||||
|
|
||||
|
// Concrete steps for Mode template
|
||||
|
OFB_prototype._doEncrypt = function (cipher, m, iv) { |
||||
|
|
||||
|
var blockSizeInBytes = cipher._blocksize * 4, |
||||
|
keystream = iv.slice(0); |
||||
|
|
||||
|
// Encrypt each byte
|
||||
|
for (var i = 0; i < m.length; i++) { |
||||
|
|
||||
|
// Generate keystream
|
||||
|
if (i % blockSizeInBytes == 0) |
||||
|
cipher._encryptblock(keystream, 0); |
||||
|
|
||||
|
// Encrypt byte
|
||||
|
m[i] ^= keystream[i % blockSizeInBytes]; |
||||
|
|
||||
|
} |
||||
|
}; |
||||
|
OFB_prototype._doDecrypt = OFB_prototype._doEncrypt; |
||||
|
|
||||
|
/** |
||||
|
* Counter |
||||
|
* @author Gergely Risko |
||||
|
* |
||||
|
* After every block the last 4 bytes of the IV is increased by one |
||||
|
* with carry and that IV is used for the next block. |
||||
|
* |
||||
|
* This is a stream cipher mode and does not require padding. |
||||
|
*/ |
||||
|
var CTR = C_mode.CTR = function () { |
||||
|
// Call parent constructor
|
||||
|
Mode.apply(this, arguments); |
||||
|
}; |
||||
|
|
||||
|
// Inherit from Mode
|
||||
|
var CTR_prototype = CTR.prototype = new Mode; |
||||
|
|
||||
|
// Override padding
|
||||
|
CTR_prototype._padding = C_pad.NoPadding; |
||||
|
|
||||
|
CTR_prototype._doEncrypt = function (cipher, m, iv) { |
||||
|
var blockSizeInBytes = cipher._blocksize * 4; |
||||
|
var counter = iv.slice(0); |
||||
|
|
||||
|
for (var i = 0; i < m.length; ) { |
||||
|
// do not lose iv
|
||||
|
var keystream = counter.slice(0); |
||||
|
|
||||
|
// Generate keystream for next block
|
||||
|
cipher._encryptblock(keystream, 0); |
||||
|
|
||||
|
// XOR keystream with block
|
||||
|
for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) { |
||||
|
m[i] ^= keystream[j]; |
||||
|
} |
||||
|
|
||||
|
// Increase counter
|
||||
|
if (++(counter[blockSizeInBytes - 1]) == 256) { |
||||
|
counter[blockSizeInBytes - 1] = 0; |
||||
|
if (++(counter[blockSizeInBytes - 2]) == 256) { |
||||
|
counter[blockSizeInBytes - 2] = 0; |
||||
|
if (++(counter[blockSizeInBytes - 3]) == 256) { |
||||
|
counter[blockSizeInBytes - 3] = 0; |
||||
|
++(counter[blockSizeInBytes - 4]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
CTR_prototype._doDecrypt = CTR_prototype._doEncrypt; |
||||
|
|
||||
|
})(Crypto); |
@ -0,0 +1,43 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS v2.5.4 HMAC.js |
||||
|
* http://code.google.com/p/crypto-js/
|
||||
|
* Copyright (c) 2009-2013, Jeff Mott. All rights reserved. |
||||
|
* http://code.google.com/p/crypto-js/wiki/License
|
||||
|
*/ |
||||
|
(function () { |
||||
|
|
||||
|
// Shortcuts
|
||||
|
var C = Crypto, |
||||
|
util = C.util, |
||||
|
charenc = C.charenc, |
||||
|
UTF8 = charenc.UTF8, |
||||
|
Binary = charenc.Binary; |
||||
|
|
||||
|
C.HMAC = function (hasher, message, key, options) { |
||||
|
|
||||
|
// Convert to byte arrays
|
||||
|
if (message.constructor == String) message = UTF8.stringToBytes(message); |
||||
|
if (key.constructor == String) key = UTF8.stringToBytes(key); |
||||
|
/* else, assume byte arrays already */ |
||||
|
|
||||
|
// Allow arbitrary length keys
|
||||
|
if (key.length > hasher._blocksize * 4) |
||||
|
key = hasher(key, { asBytes: true }); |
||||
|
|
||||
|
// XOR keys with pad constants
|
||||
|
var okey = key.slice(0), |
||||
|
ikey = key.slice(0); |
||||
|
for (var i = 0; i < hasher._blocksize * 4; i++) { |
||||
|
okey[i] ^= 0x5C; |
||||
|
ikey[i] ^= 0x36; |
||||
|
} |
||||
|
|
||||
|
var hmacbytes = hasher(okey.concat(hasher(ikey.concat(message), { asBytes: true })), { asBytes: true }); |
||||
|
|
||||
|
return options && options.asBytes ? hmacbytes : |
||||
|
options && options.asString ? Binary.bytesToString(hmacbytes) : |
||||
|
util.bytesToHex(hmacbytes); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})(); |
@ -0,0 +1,149 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS v2.5.4 Crypto.js |
||||
|
* http://code.google.com/p/crypto-js/
|
||||
|
* Copyright (c) 2009-2013, Jeff Mott. All rights reserved. |
||||
|
* http://code.google.com/p/crypto-js/wiki/License
|
||||
|
*/ |
||||
|
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) { |
||||
|
for (var bytes = []; n > 0; n--) |
||||
|
bytes.push(Math.floor(Math.random() * 256)); |
||||
|
return bytes; |
||||
|
}, |
||||
|
|
||||
|
// 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] & 0xFF) << (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) { |
||||
|
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) { |
||||
|
// 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(""); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})(); |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS v2.5.4 PBKDF2.js |
||||
|
* http://code.google.com/p/crypto-js/
|
||||
|
* Copyright (c) 2009-2013, Jeff Mott. All rights reserved. |
||||
|
* http://code.google.com/p/crypto-js/wiki/License
|
||||
|
*/ |
||||
|
(function () { |
||||
|
|
||||
|
// Shortcuts
|
||||
|
var C = Crypto, |
||||
|
util = C.util, |
||||
|
charenc = C.charenc, |
||||
|
UTF8 = charenc.UTF8, |
||||
|
Binary = charenc.Binary; |
||||
|
|
||||
|
C.PBKDF2 = function (password, salt, keylen, options) { |
||||
|
|
||||
|
// Convert to byte arrays
|
||||
|
if (password.constructor == String) password = UTF8.stringToBytes(password); |
||||
|
if (salt.constructor == String) salt = UTF8.stringToBytes(salt); |
||||
|
/* else, assume byte arrays already */ |
||||
|
|
||||
|
// Defaults
|
||||
|
var hasher = options && options.hasher || C.SHA1, |
||||
|
iterations = options && options.iterations || 1; |
||||
|
|
||||
|
// Pseudo-random function
|
||||
|
function PRF(password, salt) { |
||||
|
return C.HMAC(hasher, salt, password, { asBytes: true }); |
||||
|
} |
||||
|
|
||||
|
// Generate key
|
||||
|
var derivedKeyBytes = [], |
||||
|
blockindex = 1; |
||||
|
while (derivedKeyBytes.length < keylen) { |
||||
|
var block = PRF(password, salt.concat(util.wordsToBytes([blockindex]))); |
||||
|
for (var u = block, i = 1; i < iterations; i++) { |
||||
|
u = PRF(password, u); |
||||
|
for (var j = 0; j < block.length; j++) block[j] ^= u[j]; |
||||
|
} |
||||
|
derivedKeyBytes = derivedKeyBytes.concat(block); |
||||
|
blockindex++; |
||||
|
} |
||||
|
|
||||
|
// Truncate excess bytes
|
||||
|
derivedKeyBytes.length = keylen; |
||||
|
|
||||
|
return options && options.asBytes ? derivedKeyBytes : |
||||
|
options && options.asString ? Binary.bytesToString(derivedKeyBytes) : |
||||
|
util.bytesToHex(derivedKeyBytes); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
})(); |
@ -0,0 +1,164 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS v2.0.0 RIPEMD-160 |
||||
|
* http://code.google.com/p/crypto-js/
|
||||
|
* Copyright (c) 2009, Jeff Mott. All rights reserved. |
||||
|
* http://code.google.com/p/crypto-js/wiki/License
|
||||
|
* |
||||
|
* A JavaScript implementation of the RIPEMD-160 Algorithm |
||||
|
* Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009. |
||||
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet |
||||
|
* Distributed under the BSD License |
||||
|
* See http://pajhome.org.uk/crypt/md5 for details.
|
||||
|
* Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
|
||||
|
* Ported to Crypto-JS by Stefan Thomas. |
||||
|
*/ |
||||
|
|
||||
|
(function () { |
||||
|
// Shortcuts
|
||||
|
var C = Crypto, |
||||
|
util = C.util, |
||||
|
charenc = C.charenc, |
||||
|
UTF8 = charenc.UTF8, |
||||
|
Binary = charenc.Binary; |
||||
|
|
||||
|
// Convert a byte array to little-endian 32-bit words
|
||||
|
util.bytesToLWords = function (bytes) { |
||||
|
|
||||
|
var output = Array(bytes.length >> 2); |
||||
|
for (var i = 0; i < output.length; i++) |
||||
|
output[i] = 0; |
||||
|
for (var i = 0; i < bytes.length * 8; i += 8) |
||||
|
output[i >> 5] |= (bytes[i / 8] & 0xFF) << (i % 32); |
||||
|
return output; |
||||
|
}; |
||||
|
|
||||
|
// Convert little-endian 32-bit words to a byte array
|
||||
|
util.lWordsToBytes = function (words) { |
||||
|
var output = []; |
||||
|
for (var i = 0; i < words.length * 32; i += 8) |
||||
|
output.push((words[i >> 5] >>> (i % 32)) & 0xff); |
||||
|
return output; |
||||
|
}; |
||||
|
|
||||
|
// Public API
|
||||
|
var RIPEMD160 = C.RIPEMD160 = function (message, options) { |
||||
|
var digestbytes = util.lWordsToBytes(RIPEMD160._rmd160(message)); |
||||
|
return options && options.asBytes ? digestbytes : |
||||
|
options && options.asString ? Binary.bytesToString(digestbytes) : |
||||
|
util.bytesToHex(digestbytes); |
||||
|
}; |
||||
|
|
||||
|
// The core
|
||||
|
RIPEMD160._rmd160 = function (message) { |
||||
|
// Convert to byte array
|
||||
|
if (message.constructor == String) message = UTF8.stringToBytes(message); |
||||
|
|
||||
|
var x = util.bytesToLWords(message), |
||||
|
len = message.length * 8; |
||||
|
|
||||
|
/* append padding */ |
||||
|
x[len >> 5] |= 0x80 << (len % 32); |
||||
|
x[(((len + 64) >>> 9) << 4) + 14] = len; |
||||
|
|
||||
|
var h0 = 0x67452301; |
||||
|
var h1 = 0xefcdab89; |
||||
|
var h2 = 0x98badcfe; |
||||
|
var h3 = 0x10325476; |
||||
|
var h4 = 0xc3d2e1f0; |
||||
|
|
||||
|
for (var i = 0; i < x.length; i += 16) { |
||||
|
var T; |
||||
|
var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4; |
||||
|
var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4; |
||||
|
for (var j = 0; j <= 79; ++j) { |
||||
|
T = safe_add(A1, rmd160_f(j, B1, C1, D1)); |
||||
|
T = safe_add(T, x[i + rmd160_r1[j]]); |
||||
|
T = safe_add(T, rmd160_K1(j)); |
||||
|
T = safe_add(bit_rol(T, rmd160_s1[j]), E1); |
||||
|
A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T; |
||||
|
T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2)); |
||||
|
T = safe_add(T, x[i + rmd160_r2[j]]); |
||||
|
T = safe_add(T, rmd160_K2(j)); |
||||
|
T = safe_add(bit_rol(T, rmd160_s2[j]), E2); |
||||
|
A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T; |
||||
|
} |
||||
|
T = safe_add(h1, safe_add(C1, D2)); |
||||
|
h1 = safe_add(h2, safe_add(D1, E2)); |
||||
|
h2 = safe_add(h3, safe_add(E1, A2)); |
||||
|
h3 = safe_add(h4, safe_add(A1, B2)); |
||||
|
h4 = safe_add(h0, safe_add(B1, C2)); |
||||
|
h0 = T; |
||||
|
} |
||||
|
return [h0, h1, h2, h3, h4]; |
||||
|
} |
||||
|
|
||||
|
function rmd160_f(j, x, y, z) { |
||||
|
return (0 <= j && j <= 15) ? (x ^ y ^ z) : |
||||
|
(16 <= j && j <= 31) ? (x & y) | (~x & z) : |
||||
|
(32 <= j && j <= 47) ? (x | ~y) ^ z : |
||||
|
(48 <= j && j <= 63) ? (x & z) | (y & ~z) : |
||||
|
(64 <= j && j <= 79) ? x ^ (y | ~z) : |
||||
|
"rmd160_f: j out of range"; |
||||
|
} |
||||
|
function rmd160_K1(j) { |
||||
|
return (0 <= j && j <= 15) ? 0x00000000 : |
||||
|
(16 <= j && j <= 31) ? 0x5a827999 : |
||||
|
(32 <= j && j <= 47) ? 0x6ed9eba1 : |
||||
|
(48 <= j && j <= 63) ? 0x8f1bbcdc : |
||||
|
(64 <= j && j <= 79) ? 0xa953fd4e : |
||||
|
"rmd160_K1: j out of range"; |
||||
|
} |
||||
|
function rmd160_K2(j) { |
||||
|
return (0 <= j && j <= 15) ? 0x50a28be6 : |
||||
|
(16 <= j && j <= 31) ? 0x5c4dd124 : |
||||
|
(32 <= j && j <= 47) ? 0x6d703ef3 : |
||||
|
(48 <= j && j <= 63) ? 0x7a6d76e9 : |
||||
|
(64 <= j && j <= 79) ? 0x00000000 : |
||||
|
"rmd160_K2: j out of range"; |
||||
|
} |
||||
|
var rmd160_r1 = [ |
||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
||||
|
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, |
||||
|
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, |
||||
|
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, |
||||
|
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 |
||||
|
]; |
||||
|
var rmd160_r2 = [ |
||||
|
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, |
||||
|
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, |
||||
|
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, |
||||
|
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, |
||||
|
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 |
||||
|
]; |
||||
|
var rmd160_s1 = [ |
||||
|
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, |
||||
|
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, |
||||
|
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, |
||||
|
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, |
||||
|
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 |
||||
|
]; |
||||
|
var rmd160_s2 = [ |
||||
|
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, |
||||
|
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, |
||||
|
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, |
||||
|
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, |
||||
|
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 |
||||
|
]; |
||||
|
|
||||
|
/* |
||||
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally |
||||
|
* to work around bugs in some JS interpreters. |
||||
|
*/ |
||||
|
function safe_add(x, y) { |
||||
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF); |
||||
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); |
||||
|
return (msw << 16) | (lsw & 0xFFFF); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Bitwise rotate a 32-bit number to the left. |
||||
|
*/ |
||||
|
function bit_rol(num, cnt) { |
||||
|
return (num << cnt) | (num >>> (32 - cnt)); |
||||
|
} |
||||
|
})(); |
@ -0,0 +1,135 @@ |
|||||
|
/*! |
||||
|
* Crypto-JS v2.5.4 SHA256.js |
||||
|
* http://code.google.com/p/crypto-js/
|
||||
|
* Copyright (c) 2009-2013, Jeff Mott. All rights reserved. |
||||
|
* http://code.google.com/p/crypto-js/wiki/License
|
||||
|
*/ |
||||
|
(function () { |
||||
|
|
||||
|
// Shortcuts
|
||||
|
var C = Crypto, |
||||
|
util = C.util, |
||||
|
charenc = C.charenc, |
||||
|
UTF8 = charenc.UTF8, |
||||
|
Binary = charenc.Binary; |
||||
|
|
||||
|
// Constants
|
||||
|
var K = [0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, |
||||
|
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, |
||||
|
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, |
||||
|
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, |
||||
|
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, |
||||
|
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, |
||||
|
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, |
||||
|
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, |
||||
|
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, |
||||
|
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, |
||||
|
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, |
||||
|
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, |
||||
|
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, |
||||
|
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, |
||||
|
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, |
||||
|
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2]; |
||||
|
|
||||
|
// Public API
|
||||
|
var SHA256 = C.SHA256 = function (message, options) { |
||||
|
var digestbytes = util.wordsToBytes(SHA256._sha256(message)); |
||||
|
return options && options.asBytes ? digestbytes : |
||||
|
options && options.asString ? Binary.bytesToString(digestbytes) : |
||||
|
util.bytesToHex(digestbytes); |
||||
|
}; |
||||
|
|
||||
|
// The core
|
||||
|
SHA256._sha256 = function (message) { |
||||
|
|
||||
|
// Convert to byte array
|
||||
|
if (message.constructor == String) message = UTF8.stringToBytes(message); |
||||
|
/* else, assume byte array already */ |
||||
|
|
||||
|
var m = util.bytesToWords(message), |
||||
|
l = message.length * 8, |
||||
|
H = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, |
||||
|
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19], |
||||
|
w = [], |
||||
|
a, b, c, d, e, f, g, h, i, j, |
||||
|
t1, t2; |
||||
|
|
||||
|
// Padding
|
||||
|
m[l >> 5] |= 0x80 << (24 - l % 32); |
||||
|
m[((l + 64 >> 9) << 4) + 15] = l; |
||||
|
|
||||
|
for (var i = 0; i < m.length; i += 16) { |
||||
|
|
||||
|
a = H[0]; |
||||
|
b = H[1]; |
||||
|
c = H[2]; |
||||
|
d = H[3]; |
||||
|
e = H[4]; |
||||
|
f = H[5]; |
||||
|
g = H[6]; |
||||
|
h = H[7]; |
||||
|
|
||||
|
for (var j = 0; j < 64; j++) { |
||||
|
|
||||
|
if (j < 16) w[j] = m[j + i]; |
||||
|
else { |
||||
|
|
||||
|
var gamma0x = w[j - 15], |
||||
|
gamma1x = w[j - 2], |
||||
|
gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ |
||||
|
((gamma0x << 14) | (gamma0x >>> 18)) ^ |
||||
|
(gamma0x >>> 3), |
||||
|
gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ |
||||
|
((gamma1x << 13) | (gamma1x >>> 19)) ^ |
||||
|
(gamma1x >>> 10); |
||||
|
|
||||
|
w[j] = gamma0 + (w[j - 7] >>> 0) + |
||||
|
gamma1 + (w[j - 16] >>> 0); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
var ch = e & f ^ ~e & g, |
||||
|
maj = a & b ^ a & c ^ b & c, |
||||
|
sigma0 = ((a << 30) | (a >>> 2)) ^ |
||||
|
((a << 19) | (a >>> 13)) ^ |
||||
|
((a << 10) | (a >>> 22)), |
||||
|
sigma1 = ((e << 26) | (e >>> 6)) ^ |
||||
|
((e << 21) | (e >>> 11)) ^ |
||||
|
((e << 7) | (e >>> 25)); |
||||
|
|
||||
|
|
||||
|
t1 = (h >>> 0) + sigma1 + ch + (K[j]) + (w[j] >>> 0); |
||||
|
t2 = sigma0 + maj; |
||||
|
|
||||
|
h = g; |
||||
|
g = f; |
||||
|
f = e; |
||||
|
e = (d + t1) >>> 0; |
||||
|
d = c; |
||||
|
c = b; |
||||
|
b = a; |
||||
|
a = (t1 + t2) >>> 0; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
H[0] += a; |
||||
|
H[1] += b; |
||||
|
H[2] += c; |
||||
|
H[3] += d; |
||||
|
H[4] += e; |
||||
|
H[5] += f; |
||||
|
H[6] += g; |
||||
|
H[7] += h; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
return H; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
// Package private blocksize
|
||||
|
SHA256._blocksize = 16; |
||||
|
|
||||
|
SHA256._digestsize = 32; |
||||
|
|
||||
|
})(); |
@ -0,0 +1,669 @@ |
|||||
|
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/faa10f0f6a1fff0b9a99fffb9bc30cee33b17212/src/ecdsa.js
|
||||
|
/*! |
||||
|
* Basic Javascript Elliptic Curve implementation |
||||
|
* Ported loosely from BouncyCastle's Java EC code |
||||
|
* Only Fp curves implemented for now |
||||
|
* |
||||
|
* Copyright Tom Wu, bitaddress.org BSD License. |
||||
|
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
|
||||
|
*/ |
||||
|
(function () { |
||||
|
|
||||
|
// Constructor function of Global EllipticCurve object
|
||||
|
var ec = window.EllipticCurve = function () { }; |
||||
|
|
||||
|
|
||||
|
// ----------------
|
||||
|
// ECFieldElementFp constructor
|
||||
|
// q instanceof BigInteger
|
||||
|
// x instanceof BigInteger
|
||||
|
ec.FieldElementFp = function (q, x) { |
||||
|
this.x = x; |
||||
|
// TODO if(x.compareTo(q) >= 0) error
|
||||
|
this.q = q; |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.equals = function (other) { |
||||
|
if (other == this) return true; |
||||
|
return (this.q.equals(other.q) && this.x.equals(other.x)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.toBigInteger = function () { |
||||
|
return this.x; |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.negate = function () { |
||||
|
return new ec.FieldElementFp(this.q, this.x.negate().mod(this.q)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.add = function (b) { |
||||
|
return new ec.FieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.subtract = function (b) { |
||||
|
return new ec.FieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.multiply = function (b) { |
||||
|
return new ec.FieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.square = function () { |
||||
|
return new ec.FieldElementFp(this.q, this.x.square().mod(this.q)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.divide = function (b) { |
||||
|
return new ec.FieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q)); |
||||
|
}; |
||||
|
|
||||
|
ec.FieldElementFp.prototype.getByteLength = function () { |
||||
|
return Math.floor((this.toBigInteger().bitLength() + 7) / 8); |
||||
|
}; |
||||
|
|
||||
|
// D.1.4 91
|
||||
|
/** |
||||
|
* return a sqrt root - the routine verifies that the calculation |
||||
|
* returns the right value - if none exists it returns null. |
||||
|
* |
||||
|
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||||
|
* Ported to JavaScript by bitaddress.org |
||||
|
*/ |
||||
|
ec.FieldElementFp.prototype.sqrt = function () { |
||||
|
if (!this.q.testBit(0)) throw new Error("even value of q"); |
||||
|
|
||||
|
// p mod 4 == 3
|
||||
|
if (this.q.testBit(1)) { |
||||
|
// z = g^(u+1) + p, p = 4u + 3
|
||||
|
var z = new ec.FieldElementFp(this.q, this.x.modPow(this.q.shiftRight(2).add(BigInteger.ONE), this.q)); |
||||
|
return z.square().equals(this) ? z : null; |
||||
|
} |
||||
|
|
||||
|
// p mod 4 == 1
|
||||
|
var qMinusOne = this.q.subtract(BigInteger.ONE); |
||||
|
var legendreExponent = qMinusOne.shiftRight(1); |
||||
|
if (!(this.x.modPow(legendreExponent, this.q).equals(BigInteger.ONE))) return null; |
||||
|
var u = qMinusOne.shiftRight(2); |
||||
|
var k = u.shiftLeft(1).add(BigInteger.ONE); |
||||
|
var Q = this.x; |
||||
|
var fourQ = Q.shiftLeft(2).mod(this.q); |
||||
|
var U, V; |
||||
|
|
||||
|
do { |
||||
|
var rand = new SecureRandom(); |
||||
|
var P; |
||||
|
do { |
||||
|
P = new BigInteger(this.q.bitLength(), rand); |
||||
|
} |
||||
|
while (P.compareTo(this.q) >= 0 || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, this.q).equals(qMinusOne))); |
||||
|
|
||||
|
var result = ec.FieldElementFp.fastLucasSequence(this.q, P, Q, k); |
||||
|
|
||||
|
U = result[0]; |
||||
|
V = result[1]; |
||||
|
if (V.multiply(V).mod(this.q).equals(fourQ)) { |
||||
|
// Integer division by 2, mod q
|
||||
|
if (V.testBit(0)) { |
||||
|
V = V.add(this.q); |
||||
|
} |
||||
|
V = V.shiftRight(1); |
||||
|
return new ec.FieldElementFp(this.q, V); |
||||
|
} |
||||
|
} |
||||
|
while (U.equals(BigInteger.ONE) || U.equals(qMinusOne)); |
||||
|
|
||||
|
return null; |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||||
|
* Ported to JavaScript by bitaddress.org |
||||
|
*/ |
||||
|
ec.FieldElementFp.fastLucasSequence = function (p, P, Q, k) { |
||||
|
// TODO Research and apply "common-multiplicand multiplication here"
|
||||
|
|
||||
|
var n = k.bitLength(); |
||||
|
var s = k.getLowestSetBit(); |
||||
|
var Uh = BigInteger.ONE; |
||||
|
var Vl = BigInteger.TWO; |
||||
|
var Vh = P; |
||||
|
var Ql = BigInteger.ONE; |
||||
|
var Qh = BigInteger.ONE; |
||||
|
|
||||
|
for (var j = n - 1; j >= s + 1; --j) { |
||||
|
Ql = Ql.multiply(Qh).mod(p); |
||||
|
if (k.testBit(j)) { |
||||
|
Qh = Ql.multiply(Q).mod(p); |
||||
|
Uh = Uh.multiply(Vh).mod(p); |
||||
|
Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); |
||||
|
Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p); |
||||
|
} |
||||
|
else { |
||||
|
Qh = Ql; |
||||
|
Uh = Uh.multiply(Vl).subtract(Ql).mod(p); |
||||
|
Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); |
||||
|
Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Ql = Ql.multiply(Qh).mod(p); |
||||
|
Qh = Ql.multiply(Q).mod(p); |
||||
|
Uh = Uh.multiply(Vl).subtract(Ql).mod(p); |
||||
|
Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); |
||||
|
Ql = Ql.multiply(Qh).mod(p); |
||||
|
|
||||
|
for (var j = 1; j <= s; ++j) { |
||||
|
Uh = Uh.multiply(Vl).mod(p); |
||||
|
Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); |
||||
|
Ql = Ql.multiply(Ql).mod(p); |
||||
|
} |
||||
|
|
||||
|
return [Uh, Vl]; |
||||
|
}; |
||||
|
|
||||
|
// ----------------
|
||||
|
// ECPointFp constructor
|
||||
|
ec.PointFp = function (curve, x, y, z, compressed) { |
||||
|
this.curve = curve; |
||||
|
this.x = x; |
||||
|
this.y = y; |
||||
|
// Projective coordinates: either zinv == null or z * zinv == 1
|
||||
|
// z and zinv are just BigIntegers, not fieldElements
|
||||
|
if (z == null) { |
||||
|
this.z = BigInteger.ONE; |
||||
|
} |
||||
|
else { |
||||
|
this.z = z; |
||||
|
} |
||||
|
this.zinv = null; |
||||
|
// compression flag
|
||||
|
this.compressed = !!compressed; |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.getX = function () { |
||||
|
if (this.zinv == null) { |
||||
|
this.zinv = this.z.modInverse(this.curve.q); |
||||
|
} |
||||
|
var r = this.x.toBigInteger().multiply(this.zinv); |
||||
|
this.curve.reduce(r); |
||||
|
return this.curve.fromBigInteger(r); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.getY = function () { |
||||
|
if (this.zinv == null) { |
||||
|
this.zinv = this.z.modInverse(this.curve.q); |
||||
|
} |
||||
|
var r = this.y.toBigInteger().multiply(this.zinv); |
||||
|
this.curve.reduce(r); |
||||
|
return this.curve.fromBigInteger(r); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.equals = function (other) { |
||||
|
if (other == this) return true; |
||||
|
if (this.isInfinity()) return other.isInfinity(); |
||||
|
if (other.isInfinity()) return this.isInfinity(); |
||||
|
var u, v; |
||||
|
// u = Y2 * Z1 - Y1 * Z2
|
||||
|
u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q); |
||||
|
if (!u.equals(BigInteger.ZERO)) return false; |
||||
|
// v = X2 * Z1 - X1 * Z2
|
||||
|
v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q); |
||||
|
return v.equals(BigInteger.ZERO); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.isInfinity = function () { |
||||
|
if ((this.x == null) && (this.y == null)) return true; |
||||
|
return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.negate = function () { |
||||
|
return new ec.PointFp(this.curve, this.x, this.y.negate(), this.z); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.add = function (b) { |
||||
|
if (this.isInfinity()) return b; |
||||
|
if (b.isInfinity()) return this; |
||||
|
|
||||
|
// u = Y2 * Z1 - Y1 * Z2
|
||||
|
var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q); |
||||
|
// v = X2 * Z1 - X1 * Z2
|
||||
|
var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q); |
||||
|
|
||||
|
|
||||
|
if (BigInteger.ZERO.equals(v)) { |
||||
|
if (BigInteger.ZERO.equals(u)) { |
||||
|
return this.twice(); // this == b, so double
|
||||
|
} |
||||
|
return this.curve.getInfinity(); // this = -b, so infinity
|
||||
|
} |
||||
|
|
||||
|
var THREE = new BigInteger("3"); |
||||
|
var x1 = this.x.toBigInteger(); |
||||
|
var y1 = this.y.toBigInteger(); |
||||
|
var x2 = b.x.toBigInteger(); |
||||
|
var y2 = b.y.toBigInteger(); |
||||
|
|
||||
|
var v2 = v.square(); |
||||
|
var v3 = v2.multiply(v); |
||||
|
var x1v2 = x1.multiply(v2); |
||||
|
var zu2 = u.square().multiply(this.z); |
||||
|
|
||||
|
// x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
|
||||
|
var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q); |
||||
|
// y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
|
||||
|
var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q); |
||||
|
// z3 = v^3 * z1 * z2
|
||||
|
var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q); |
||||
|
|
||||
|
return new ec.PointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.twice = function () { |
||||
|
if (this.isInfinity()) return this; |
||||
|
if (this.y.toBigInteger().signum() == 0) return this.curve.getInfinity(); |
||||
|
|
||||
|
// TODO: optimized handling of constants
|
||||
|
var THREE = new BigInteger("3"); |
||||
|
var x1 = this.x.toBigInteger(); |
||||
|
var y1 = this.y.toBigInteger(); |
||||
|
|
||||
|
var y1z1 = y1.multiply(this.z); |
||||
|
var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q); |
||||
|
var a = this.curve.a.toBigInteger(); |
||||
|
|
||||
|
// w = 3 * x1^2 + a * z1^2
|
||||
|
var w = x1.square().multiply(THREE); |
||||
|
if (!BigInteger.ZERO.equals(a)) { |
||||
|
w = w.add(this.z.square().multiply(a)); |
||||
|
} |
||||
|
w = w.mod(this.curve.q); |
||||
|
//this.curve.reduce(w);
|
||||
|
// x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
|
||||
|
var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q); |
||||
|
// y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
|
||||
|
var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q); |
||||
|
// z3 = 8 * (y1 * z1)^3
|
||||
|
var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q); |
||||
|
|
||||
|
return new ec.PointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3); |
||||
|
}; |
||||
|
|
||||
|
// Simple NAF (Non-Adjacent Form) multiplication algorithm
|
||||
|
// TODO: modularize the multiplication algorithm
|
||||
|
ec.PointFp.prototype.multiply = function (k) { |
||||
|
if (this.isInfinity()) return this; |
||||
|
if (k.signum() == 0) return this.curve.getInfinity(); |
||||
|
|
||||
|
var e = k; |
||||
|
var h = e.multiply(new BigInteger("3")); |
||||
|
|
||||
|
var neg = this.negate(); |
||||
|
var R = this; |
||||
|
|
||||
|
var i; |
||||
|
for (i = h.bitLength() - 2; i > 0; --i) { |
||||
|
R = R.twice(); |
||||
|
|
||||
|
var hBit = h.testBit(i); |
||||
|
var eBit = e.testBit(i); |
||||
|
|
||||
|
if (hBit != eBit) { |
||||
|
R = R.add(hBit ? this : neg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return R; |
||||
|
}; |
||||
|
|
||||
|
// Compute this*j + x*k (simultaneous multiplication)
|
||||
|
ec.PointFp.prototype.multiplyTwo = function (j, x, k) { |
||||
|
var i; |
||||
|
if (j.bitLength() > k.bitLength()) |
||||
|
i = j.bitLength() - 1; |
||||
|
else |
||||
|
i = k.bitLength() - 1; |
||||
|
|
||||
|
var R = this.curve.getInfinity(); |
||||
|
var both = this.add(x); |
||||
|
while (i >= 0) { |
||||
|
R = R.twice(); |
||||
|
if (j.testBit(i)) { |
||||
|
if (k.testBit(i)) { |
||||
|
R = R.add(both); |
||||
|
} |
||||
|
else { |
||||
|
R = R.add(this); |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
if (k.testBit(i)) { |
||||
|
R = R.add(x); |
||||
|
} |
||||
|
} |
||||
|
--i; |
||||
|
} |
||||
|
|
||||
|
return R; |
||||
|
}; |
||||
|
|
||||
|
// patched by bitaddress.org and Casascius for use with Bitcoin.ECKey
|
||||
|
// patched by coretechs to support compressed public keys
|
||||
|
ec.PointFp.prototype.getEncoded = function (compressed) { |
||||
|
var x = this.getX().toBigInteger(); |
||||
|
var y = this.getY().toBigInteger(); |
||||
|
var len = 32; // integerToBytes will zero pad if integer is less than 32 bytes. 32 bytes length is required by the Bitcoin protocol.
|
||||
|
var enc = ec.integerToBytes(x, len); |
||||
|
|
||||
|
// when compressed prepend byte depending if y point is even or odd
|
||||
|
if (compressed) { |
||||
|
if (y.isEven()) { |
||||
|
enc.unshift(0x02); |
||||
|
} |
||||
|
else { |
||||
|
enc.unshift(0x03); |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
enc.unshift(0x04); |
||||
|
enc = enc.concat(ec.integerToBytes(y, len)); // uncompressed public key appends the bytes of the y point
|
||||
|
} |
||||
|
return enc; |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.decodeFrom = function (curve, enc) { |
||||
|
var type = enc[0]; |
||||
|
var dataLen = enc.length - 1; |
||||
|
|
||||
|
// Extract x and y as byte arrays
|
||||
|
var xBa = enc.slice(1, 1 + dataLen / 2); |
||||
|
var yBa = enc.slice(1 + dataLen / 2, 1 + dataLen); |
||||
|
|
||||
|
// Prepend zero byte to prevent interpretation as negative integer
|
||||
|
xBa.unshift(0); |
||||
|
yBa.unshift(0); |
||||
|
|
||||
|
// Convert to BigIntegers
|
||||
|
var x = new BigInteger(xBa); |
||||
|
var y = new BigInteger(yBa); |
||||
|
|
||||
|
// Return point
|
||||
|
return new ec.PointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y)); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.add2D = function (b) { |
||||
|
if (this.isInfinity()) return b; |
||||
|
if (b.isInfinity()) return this; |
||||
|
|
||||
|
if (this.x.equals(b.x)) { |
||||
|
if (this.y.equals(b.y)) { |
||||
|
// this = b, i.e. this must be doubled
|
||||
|
return this.twice(); |
||||
|
} |
||||
|
// this = -b, i.e. the result is the point at infinity
|
||||
|
return this.curve.getInfinity(); |
||||
|
} |
||||
|
|
||||
|
var x_x = b.x.subtract(this.x); |
||||
|
var y_y = b.y.subtract(this.y); |
||||
|
var gamma = y_y.divide(x_x); |
||||
|
|
||||
|
var x3 = gamma.square().subtract(this.x).subtract(b.x); |
||||
|
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); |
||||
|
|
||||
|
return new ec.PointFp(this.curve, x3, y3); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.twice2D = function () { |
||||
|
if (this.isInfinity()) return this; |
||||
|
if (this.y.toBigInteger().signum() == 0) { |
||||
|
// if y1 == 0, then (x1, y1) == (x1, -y1)
|
||||
|
// and hence this = -this and thus 2(x1, y1) == infinity
|
||||
|
return this.curve.getInfinity(); |
||||
|
} |
||||
|
|
||||
|
var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2)); |
||||
|
var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3)); |
||||
|
var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO)); |
||||
|
|
||||
|
var x3 = gamma.square().subtract(this.x.multiply(TWO)); |
||||
|
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); |
||||
|
|
||||
|
return new ec.PointFp(this.curve, x3, y3); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.multiply2D = function (k) { |
||||
|
if (this.isInfinity()) return this; |
||||
|
if (k.signum() == 0) return this.curve.getInfinity(); |
||||
|
|
||||
|
var e = k; |
||||
|
var h = e.multiply(new BigInteger("3")); |
||||
|
|
||||
|
var neg = this.negate(); |
||||
|
var R = this; |
||||
|
|
||||
|
var i; |
||||
|
for (i = h.bitLength() - 2; i > 0; --i) { |
||||
|
R = R.twice(); |
||||
|
|
||||
|
var hBit = h.testBit(i); |
||||
|
var eBit = e.testBit(i); |
||||
|
|
||||
|
if (hBit != eBit) { |
||||
|
R = R.add2D(hBit ? this : neg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return R; |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.isOnCurve = function () { |
||||
|
var x = this.getX().toBigInteger(); |
||||
|
var y = this.getY().toBigInteger(); |
||||
|
var a = this.curve.getA().toBigInteger(); |
||||
|
var b = this.curve.getB().toBigInteger(); |
||||
|
var n = this.curve.getQ(); |
||||
|
var lhs = y.multiply(y).mod(n); |
||||
|
var rhs = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(n); |
||||
|
return lhs.equals(rhs); |
||||
|
}; |
||||
|
|
||||
|
ec.PointFp.prototype.toString = function () { |
||||
|
return '(' + this.getX().toBigInteger().toString() + ',' + this.getY().toBigInteger().toString() + ')'; |
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* Validate an elliptic curve point. |
||||
|
* |
||||
|
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive |
||||
|
*/ |
||||
|
ec.PointFp.prototype.validate = function () { |
||||
|
var n = this.curve.getQ(); |
||||
|
|
||||
|
// Check Q != O
|
||||
|
if (this.isInfinity()) { |
||||
|
throw new Error("Point is at infinity."); |
||||
|
} |
||||
|
|
||||
|
// Check coordinate bounds
|
||||
|
var x = this.getX().toBigInteger(); |
||||
|
var y = this.getY().toBigInteger(); |
||||
|
if (x.compareTo(BigInteger.ONE) < 0 || x.compareTo(n.subtract(BigInteger.ONE)) > 0) { |
||||
|
throw new Error('x coordinate out of bounds'); |
||||
|
} |
||||
|
if (y.compareTo(BigInteger.ONE) < 0 || y.compareTo(n.subtract(BigInteger.ONE)) > 0) { |
||||
|
throw new Error('y coordinate out of bounds'); |
||||
|
} |
||||
|
|
||||
|
// Check y^2 = x^3 + ax + b (mod n)
|
||||
|
if (!this.isOnCurve()) { |
||||
|
throw new Error("Point is not on the curve."); |
||||
|
} |
||||
|
|
||||
|
// Check nQ = 0 (Q is a scalar multiple of G)
|
||||
|
if (this.multiply(n).isInfinity()) { |
||||
|
// TODO: This check doesn't work - fix.
|
||||
|
throw new Error("Point is not a scalar multiple of G."); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
// ----------------
|
||||
|
// ECCurveFp constructor
|
||||
|
ec.CurveFp = function (q, a, b) { |
||||
|
this.q = q; |
||||
|
this.a = this.fromBigInteger(a); |
||||
|
this.b = this.fromBigInteger(b); |
||||
|
this.infinity = new ec.PointFp(this, null, null); |
||||
|
this.reducer = new Barrett(this.q); |
||||
|
} |
||||
|
|
||||
|
ec.CurveFp.prototype.getQ = function () { |
||||
|
return this.q; |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.getA = function () { |
||||
|
return this.a; |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.getB = function () { |
||||
|
return this.b; |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.equals = function (other) { |
||||
|
if (other == this) return true; |
||||
|
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b)); |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.getInfinity = function () { |
||||
|
return this.infinity; |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.fromBigInteger = function (x) { |
||||
|
return new ec.FieldElementFp(this.q, x); |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.reduce = function (x) { |
||||
|
this.reducer.reduce(x); |
||||
|
}; |
||||
|
|
||||
|
// for now, work with hex strings because they're easier in JS
|
||||
|
// compressed support added by bitaddress.org
|
||||
|
ec.CurveFp.prototype.decodePointHex = function (s) { |
||||
|
var firstByte = parseInt(s.substr(0, 2), 16); |
||||
|
switch (firstByte) { // first byte
|
||||
|
case 0: |
||||
|
return this.infinity; |
||||
|
case 2: // compressed
|
||||
|
case 3: // compressed
|
||||
|
var yTilde = firstByte & 1; |
||||
|
var xHex = s.substr(2, s.length - 2); |
||||
|
var X1 = new BigInteger(xHex, 16); |
||||
|
return this.decompressPoint(yTilde, X1); |
||||
|
case 4: // uncompressed
|
||||
|
case 6: // hybrid
|
||||
|
case 7: // hybrid
|
||||
|
var len = (s.length - 2) / 2; |
||||
|
var xHex = s.substr(2, len); |
||||
|
var yHex = s.substr(len + 2, len); |
||||
|
|
||||
|
return new ec.PointFp(this, |
||||
|
this.fromBigInteger(new BigInteger(xHex, 16)), |
||||
|
this.fromBigInteger(new BigInteger(yHex, 16))); |
||||
|
|
||||
|
default: // unsupported
|
||||
|
return null; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
ec.CurveFp.prototype.encodePointHex = function (p) { |
||||
|
if (p.isInfinity()) return "00"; |
||||
|
var xHex = p.getX().toBigInteger().toString(16); |
||||
|
var yHex = p.getY().toBigInteger().toString(16); |
||||
|
var oLen = this.getQ().toString(16).length; |
||||
|
if ((oLen % 2) != 0) oLen++; |
||||
|
while (xHex.length < oLen) { |
||||
|
xHex = "0" + xHex; |
||||
|
} |
||||
|
while (yHex.length < oLen) { |
||||
|
yHex = "0" + yHex; |
||||
|
} |
||||
|
return "04" + xHex + yHex; |
||||
|
}; |
||||
|
|
||||
|
/* |
||||
|
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||||
|
* Ported to JavaScript by bitaddress.org |
||||
|
* |
||||
|
* Number yTilde |
||||
|
* BigInteger X1 |
||||
|
*/ |
||||
|
ec.CurveFp.prototype.decompressPoint = function (yTilde, X1) { |
||||
|
var x = this.fromBigInteger(X1); |
||||
|
var alpha = x.multiply(x.square().add(this.getA())).add(this.getB()); |
||||
|
var beta = alpha.sqrt(); |
||||
|
// if we can't find a sqrt we haven't got a point on the curve - run!
|
||||
|
if (beta == null) throw new Error("Invalid point compression"); |
||||
|
var betaValue = beta.toBigInteger(); |
||||
|
var bit0 = betaValue.testBit(0) ? 1 : 0; |
||||
|
if (bit0 != yTilde) { |
||||
|
// Use the other root
|
||||
|
beta = this.fromBigInteger(this.getQ().subtract(betaValue)); |
||||
|
} |
||||
|
return new ec.PointFp(this, x, beta, null, true); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
ec.fromHex = function (s) { return new BigInteger(s, 16); }; |
||||
|
|
||||
|
ec.integerToBytes = function (i, len) { |
||||
|
var bytes = i.toByteArrayUnsigned(); |
||||
|
if (len < bytes.length) { |
||||
|
bytes = bytes.slice(bytes.length - len); |
||||
|
} else while (len > bytes.length) { |
||||
|
bytes.unshift(0); |
||||
|
} |
||||
|
return bytes; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// Named EC curves
|
||||
|
// ----------------
|
||||
|
// X9ECParameters constructor
|
||||
|
ec.X9Parameters = function (curve, g, n, h) { |
||||
|
this.curve = curve; |
||||
|
this.g = g; |
||||
|
this.n = n; |
||||
|
this.h = h; |
||||
|
} |
||||
|
ec.X9Parameters.prototype.getCurve = function () { return this.curve; }; |
||||
|
ec.X9Parameters.prototype.getG = function () { return this.g; }; |
||||
|
ec.X9Parameters.prototype.getN = function () { return this.n; }; |
||||
|
ec.X9Parameters.prototype.getH = function () { return this.h; }; |
||||
|
|
||||
|
// secp256k1 is the Curve used by Bitcoin
|
||||
|
ec.secNamedCurves = { |
||||
|
// used by Bitcoin
|
||||
|
"secp256k1": function () { |
||||
|
// p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
|
||||
|
var p = ec.fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); |
||||
|
var a = BigInteger.ZERO; |
||||
|
var b = ec.fromHex("7"); |
||||
|
var n = ec.fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); |
||||
|
var h = BigInteger.ONE; |
||||
|
var curve = new ec.CurveFp(p, a, b); |
||||
|
var G = curve.decodePointHex("04" |
||||
|
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" |
||||
|
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); |
||||
|
return new ec.X9Parameters(curve, G, n, h); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// secp256k1 called by Bitcoin's ECKEY
|
||||
|
ec.getSECCurveByName = function (name) { |
||||
|
if (ec.secNamedCurves[name] == undefined) return null; |
||||
|
return ec.secNamedCurves[name](); |
||||
|
} |
||||
|
})(); |
@ -0,0 +1,187 @@ |
|||||
|
/*! |
||||
|
* Random number generator with ArcFour PRNG |
||||
|
* |
||||
|
* NOTE: For best results, put code like |
||||
|
* <body onclick='SecureRandom.seedTime();' onkeypress='SecureRandom.seedTime();'> |
||||
|
* in your main HTML document. |
||||
|
* |
||||
|
* Copyright Tom Wu, bitaddress.org BSD License. |
||||
|
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
|
||||
|
*/ |
||||
|
(function () { |
||||
|
|
||||
|
// Constructor function of Global SecureRandom object
|
||||
|
var sr = window.SecureRandom = function () { }; |
||||
|
|
||||
|
// Properties
|
||||
|
sr.state; |
||||
|
sr.pool; |
||||
|
sr.pptr; |
||||
|
|
||||
|
// Pool size must be a multiple of 4 and greater than 32.
|
||||
|
// An array of bytes the size of the pool will be passed to init()
|
||||
|
sr.poolSize = 256; |
||||
|
|
||||
|
// --- object methods ---
|
||||
|
|
||||
|
// public method
|
||||
|
// ba: byte array
|
||||
|
sr.prototype.nextBytes = function (ba) { |
||||
|
var i; |
||||
|
if (window.crypto && window.crypto.getRandomValues && window.Uint8Array) { |
||||
|
try { |
||||
|
var rvBytes = new Uint8Array(ba.length); |
||||
|
window.crypto.getRandomValues(rvBytes); |
||||
|
for (i = 0; i < ba.length; ++i) |
||||
|
ba[i] = sr.getByte() ^ rvBytes[i]; |
||||
|
return; |
||||
|
} catch (e) { |
||||
|
alert(e); |
||||
|
} |
||||
|
} |
||||
|
for (i = 0; i < ba.length; ++i) ba[i] = sr.getByte(); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// --- static methods ---
|
||||
|
|
||||
|
// Mix in the current time (w/milliseconds) into the pool
|
||||
|
// NOTE: this method should be called from body click/keypress event handlers to increase entropy
|
||||
|
sr.seedTime = function () { |
||||
|
sr.seedInt(new Date().getTime()); |
||||
|
} |
||||
|
|
||||
|
sr.getByte = function () { |
||||
|
/*if(!ninja.seeder.isDone()) { |
||||
|
alert("Premature initialisation of the random generator. Something is really wrong, do not generate wallets."); |
||||
|
return NaN; |
||||
|
}*/ |
||||
|
|
||||
|
if (sr.state == null) { |
||||
|
sr.seedTime(); |
||||
|
sr.state = sr.ArcFour(); // Plug in your RNG constructor here
|
||||
|
sr.state.init(sr.pool); |
||||
|
sr.pptr = 0; |
||||
|
} |
||||
|
// TODO: allow reseeding after first request
|
||||
|
return sr.state.next(); |
||||
|
} |
||||
|
|
||||
|
// Mix in a 32-bit integer into the pool
|
||||
|
sr.seedInt = function (x) { |
||||
|
sr.seedInt8(x); |
||||
|
sr.seedInt8((x >> 8)); |
||||
|
sr.seedInt8((x >> 16)); |
||||
|
sr.seedInt8((x >> 24)); |
||||
|
} |
||||
|
|
||||
|
// Mix in a 16-bit integer into the pool
|
||||
|
sr.seedInt16 = function (x) { |
||||
|
sr.seedInt8(x); |
||||
|
sr.seedInt8((x >> 8)); |
||||
|
} |
||||
|
|
||||
|
// Mix in a 8-bit integer into the pool
|
||||
|
sr.seedInt8 = function (x) { |
||||
|
sr.pool[sr.pptr++] ^= x & 255; |
||||
|
if (sr.pptr >= sr.poolSize) sr.pptr -= sr.poolSize; |
||||
|
} |
||||
|
|
||||
|
// Arcfour is a PRNG
|
||||
|
sr.ArcFour = function () { |
||||
|
function Arcfour() { |
||||
|
this.i = 0; |
||||
|
this.j = 0; |
||||
|
this.S = new Array(); |
||||
|
} |
||||
|
|
||||
|
// Initialize arcfour context from key, an array of ints, each from [0..255]
|
||||
|
function ARC4init(key) { |
||||
|
var i, j, t; |
||||
|
for (i = 0; i < 256; ++i) |
||||
|
this.S[i] = i; |
||||
|
j = 0; |
||||
|
for (i = 0; i < 256; ++i) { |
||||
|
j = (j + this.S[i] + key[i % key.length]) & 255; |
||||
|
t = this.S[i]; |
||||
|
this.S[i] = this.S[j]; |
||||
|
this.S[j] = t; |
||||
|
} |
||||
|
this.i = 0; |
||||
|
this.j = 0; |
||||
|
} |
||||
|
|
||||
|
function ARC4next() { |
||||
|
var t; |
||||
|
this.i = (this.i + 1) & 255; |
||||
|
this.j = (this.j + this.S[this.i]) & 255; |
||||
|
t = this.S[this.i]; |
||||
|
this.S[this.i] = this.S[this.j]; |
||||
|
this.S[this.j] = t; |
||||
|
return this.S[(t + this.S[this.i]) & 255]; |
||||
|
} |
||||
|
|
||||
|
Arcfour.prototype.init = ARC4init; |
||||
|
Arcfour.prototype.next = ARC4next; |
||||
|
|
||||
|
return new Arcfour(); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// Initialize the pool with junk if needed.
|
||||
|
if (sr.pool == null) { |
||||
|
sr.pool = new Array(); |
||||
|
sr.pptr = 0; |
||||
|
var t; |
||||
|
if (window.crypto && window.crypto.getRandomValues && window.Uint8Array) { |
||||
|
try { |
||||
|
// Use webcrypto if available
|
||||
|
var ua = new Uint8Array(sr.poolSize); |
||||
|
window.crypto.getRandomValues(ua); |
||||
|
for (t = 0; t < sr.poolSize; ++t) |
||||
|
sr.pool[sr.pptr++] = ua[t]; |
||||
|
} catch (e) { alert(e); } |
||||
|
} |
||||
|
while (sr.pptr < sr.poolSize) { // extract some randomness from Math.random()
|
||||
|
t = Math.floor(65536 * Math.random()); |
||||
|
sr.pool[sr.pptr++] = t >>> 8; |
||||
|
sr.pool[sr.pptr++] = t & 255; |
||||
|
} |
||||
|
sr.pptr = Math.floor(sr.poolSize * Math.random()); |
||||
|
sr.seedTime(); |
||||
|
// entropy
|
||||
|
var entropyStr = ""; |
||||
|
// screen size and color depth: ~4.8 to ~5.4 bits
|
||||
|
entropyStr += (window.screen.height * window.screen.width * window.screen.colorDepth); |
||||
|
entropyStr += (window.screen.availHeight * window.screen.availWidth * window.screen.pixelDepth); |
||||
|
// time zone offset: ~4 bits
|
||||
|
var dateObj = new Date(); |
||||
|
var timeZoneOffset = dateObj.getTimezoneOffset(); |
||||
|
entropyStr += timeZoneOffset; |
||||
|
// user agent: ~8.3 to ~11.6 bits
|
||||
|
entropyStr += navigator.userAgent; |
||||
|
// browser plugin details: ~16.2 to ~21.8 bits
|
||||
|
var pluginsStr = ""; |
||||
|
for (var i = 0; i < navigator.plugins.length; i++) { |
||||
|
pluginsStr += navigator.plugins[i].name + " " + navigator.plugins[i].filename + " " + navigator.plugins[i].description + " " + navigator.plugins[i].version + ", "; |
||||
|
} |
||||
|
var mimeTypesStr = ""; |
||||
|
for (var i = 0; i < navigator.mimeTypes.length; i++) { |
||||
|
mimeTypesStr += navigator.mimeTypes[i].description + " " + navigator.mimeTypes[i].type + " " + navigator.mimeTypes[i].suffixes + ", "; |
||||
|
} |
||||
|
entropyStr += pluginsStr + mimeTypesStr; |
||||
|
// cookies and storage: 1 bit
|
||||
|
entropyStr += navigator.cookieEnabled + typeof (sessionStorage) + typeof (localStorage); |
||||
|
// language: ~7 bit
|
||||
|
entropyStr += navigator.language; |
||||
|
// history: ~2 bit
|
||||
|
entropyStr += window.history.length; |
||||
|
// location
|
||||
|
entropyStr += window.location; |
||||
|
|
||||
|
var entropyBytes = Crypto.SHA256(entropyStr, { asBytes: true }); |
||||
|
for (var i = 0 ; i < entropyBytes.length ; i++) { |
||||
|
sr.seedInt8(entropyBytes[i]); |
||||
|
} |
||||
|
} |
||||
|
})(); |
Loading…
Reference in new issue