зеркало из https://github.com/mozilla/pluotsorbet.git
225 строки
6.8 KiB
JavaScript
225 строки
6.8 KiB
JavaScript
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
|
|
|
|
'use strict';
|
|
|
|
Native["com/sun/midp/crypto/PRand.getRandomBytes.([BI)Z"] = function(b, nbytes) {
|
|
window.crypto.getRandomValues(b.subarray(0, nbytes));
|
|
return 1;
|
|
};
|
|
|
|
MIDP.hashers = new Map();
|
|
|
|
/**
|
|
* A constructor for a SHA-1 hasher. To create a new hasher:
|
|
*
|
|
* var hasher = new MIDP.SHA1Hasher();
|
|
*/
|
|
MIDP.SHA1Hasher = function() {
|
|
this.input = new Int8Array(0);
|
|
};
|
|
|
|
/**
|
|
* Add data to the hasher. Does not implement true progressive hashing,
|
|
* but simulates it well enough for the Java API that uses these natives.
|
|
*/
|
|
MIDP.SHA1Hasher.prototype.update = function(newInput) {
|
|
var oldInput = this.input;
|
|
this.input = new Int8Array(oldInput.length + newInput.length);
|
|
this.input.set(oldInput, 0);
|
|
this.input.set(newInput, oldInput.length);
|
|
};
|
|
|
|
/**
|
|
* Clone this hasher.
|
|
*
|
|
* @returns {MIDP.SHA1Hasher} the cloned hasher
|
|
*/
|
|
MIDP.SHA1Hasher.prototype.clone = function() {
|
|
var hasher = new MIDP.SHA1Hasher();
|
|
hasher.update(this.input);
|
|
return hasher;
|
|
};
|
|
|
|
MIDP.SHA1Hasher.prototype.digest = function() {
|
|
var hash = new Rusha().rawDigest(this.input);
|
|
return hash;
|
|
};
|
|
|
|
/**
|
|
* A 16-byte Int32Array whose values are all initialized to zero.
|
|
* Useful for comparing with other such arrays to determine whether or not
|
|
* they've been populated with other values. Also useful for resetting
|
|
* data arrays back to their initial state.
|
|
*/
|
|
MIDP.emptyDataArray = new Int32Array(16);
|
|
|
|
MIDP.getSHA1Hasher = function(data) {
|
|
if (!util.compareTypedArrays(data, MIDP.emptyDataArray)) {
|
|
return MIDP.hashers.get(data);
|
|
}
|
|
|
|
var hasher = new MIDP.SHA1Hasher();
|
|
window.crypto.getRandomValues(data);
|
|
MIDP.hashers.set(data, hasher);
|
|
return hasher;
|
|
};
|
|
|
|
MIDP.getMD5Hasher = function(data) {
|
|
if (!util.compareTypedArrays(data, MIDP.emptyDataArray)) {
|
|
return MIDP.hashers.get(data);
|
|
}
|
|
|
|
var hasher = forge.md.md5.create();
|
|
window.crypto.getRandomValues(data);
|
|
MIDP.hashers.set(data, hasher);
|
|
return hasher;
|
|
};
|
|
|
|
MIDP.bin2String = function(array) {
|
|
var result = "";
|
|
for (var i = 0; i < array.length; i++) {
|
|
result += String.fromCharCode(array[i] & 0xff);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/SHA.nativeUpdate.([BII[I[I[I[I)V"] = function(inBuf, inOff, inLen, state, num, count, data) {
|
|
MIDP.getSHA1Hasher(data).update(inBuf.subarray(inOff, inOff + inLen));
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/SHA.nativeFinal.([BII[BI[I[I[I[I)V"] = function(inBuf, inOff, inLen, outBuf, outOff, state, num, count, data) {
|
|
var hasher = MIDP.getSHA1Hasher(data);
|
|
|
|
if (inBuf) {
|
|
// digest passes `null` for inBuf, and there are no other callers,
|
|
// so this should never happen; but I'm including it for completeness
|
|
// (and in case a subclass ever uses it).
|
|
hasher.update(inBuf.subarray(inOff, inOff + inLen));
|
|
}
|
|
|
|
var hash = hasher.digest();
|
|
outBuf.set(new Int8Array(hash.buffer), outOff);
|
|
|
|
// XXX Call the reset method instead to completely reset the object.
|
|
data.set(MIDP.emptyDataArray);
|
|
|
|
MIDP.hashers.delete(data);
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/SHA.nativeClone.([I)V"] = function(data) {
|
|
for (var key of MIDP.hashers.keys()) {
|
|
if (util.compareTypedArrays(key, data)) {
|
|
var value = MIDP.hashers.get(key);
|
|
var hasher = value.clone();
|
|
window.crypto.getRandomValues(data);
|
|
MIDP.hashers.set(data, hasher);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/MD5.nativeUpdate.([BII[I[I[I[I)V"] = function(inBuf, inOff, inLen, state, num, count, data) {
|
|
MIDP.getMD5Hasher(data).update(MIDP.bin2String(new Int8Array(inBuf.subarray(inOff, inOff + inLen))));
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/MD5.nativeFinal.([BII[BI[I[I[I[I)V"] = function(inBuf, inOff, inLen, outBuf, outOff, state, num, count, data) {
|
|
var hasher = MIDP.getMD5Hasher(data);
|
|
|
|
if (inBuf) {
|
|
// digest passes `null` for inBuf, and there are no other callers,
|
|
// so this should never happen; but I'm including it for completeness
|
|
// (and in case a subclass ever uses it).
|
|
hasher.update(MIDP.bin2String(inBuf.subarray(inOff, inOff + inLen)));
|
|
}
|
|
|
|
var hash = hasher.digest();
|
|
|
|
for (var i = 0; i < hash.length(); i++) {
|
|
outBuf[outOff + i] = hash.at(i);
|
|
}
|
|
|
|
// XXX Call the reset method instead to completely reset the object.
|
|
data.set(MIDP.emptyDataArray);
|
|
|
|
MIDP.hashers.delete(data);
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/MD5.nativeClone.([I)V"] = function(data) {
|
|
for (var key of MIDP.hashers.keys()) {
|
|
if (util.compareTypedArrays(key, data)) {
|
|
var value = MIDP.hashers.get(key);
|
|
var hasher = value.clone();
|
|
window.crypto.getRandomValues(data);
|
|
MIDP.hashers.set(data, hasher);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
var hexEncodeArray = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', ];
|
|
|
|
function bytesToHexString(array) {
|
|
var s = '';
|
|
for (var i = 0; i < array.length; i++) {
|
|
var code = array[i] & 0xFF;
|
|
s += hexEncodeArray[code >>> 4];
|
|
s += hexEncodeArray[code & 0x0F];
|
|
}
|
|
return s;
|
|
}
|
|
|
|
function hexStringToBytes(hex) {
|
|
// The jsbn library (that provides BigInteger support) produces a
|
|
// hexadecimal string that doesn't contain a leading 0 (e.g. "010010" would
|
|
// be "10010").
|
|
var length = hex.length / 2;
|
|
if (length % 1 !== 0) {
|
|
hex = "0" + hex;
|
|
}
|
|
|
|
var bytes = new Int8Array(hex.length / 2);
|
|
|
|
for (var i = 0; i < hex.length; i += 2) {
|
|
bytes[i/2] = parseInt(hex.substr(i, 2), 16);
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
Native["com/sun/midp/crypto/RSA.modExp.([B[B[B[B)I"] = function(data, exponent, modulus, result) {
|
|
// The jsbn library doesn't work well with typed arrays, so we're using this
|
|
// hack of translating the numbers to hexadecimal strings before handing
|
|
// them to jsbn (and we're getting the result back in a hex string).
|
|
|
|
var bnBase = new BigInteger(bytesToHexString(data), 16);
|
|
var bnExponent = new BigInteger(bytesToHexString(exponent), 16);
|
|
var bnModulus = new BigInteger(bytesToHexString(modulus), 16);
|
|
var bnRemainder = bnBase.modPow(bnExponent, bnModulus);
|
|
var remainder = hexStringToBytes(bnRemainder.toString(16));
|
|
|
|
result.set(remainder);
|
|
return remainder.length;
|
|
};
|
|
|
|
Native["com/sun/midp/crypto/ARC4.nativetx.([B[I[I[BII[BI)V"] = function(S, X, Y, inbuf, inoff, inlen, outbuf, outoff) {
|
|
var x = X[0];
|
|
var y = Y[0];
|
|
|
|
for (var i = 0; i < inlen; i++) {
|
|
x = (x + 1) & 0xff;
|
|
y = (y + S[x]) & 0xff;
|
|
|
|
var tx = S[x];
|
|
S[x] = S[y];
|
|
S[y] = tx;
|
|
|
|
var ty = S[x] + S[y] & 0xff;
|
|
|
|
outbuf[i+outoff] = S[ty] ^ inbuf[i+inoff];
|
|
}
|
|
|
|
X[0] = x;
|
|
Y[0] = y;
|
|
};
|