321 lines
12 KiB
JavaScript
321 lines
12 KiB
JavaScript
function SM3Digest() {
|
||
this.BYTE_LENGTH = 64;
|
||
this.xBuf = new Array();
|
||
this.xBufOff = 0;
|
||
this.byteCount = 0;
|
||
this.DIGEST_LENGTH = 32;
|
||
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e];
|
||
this.v0 = [0x7380166f, 0x4914b2b9, 0x172442d7, -628488704, -1452330820, 0x163138aa, -477237683, -1325724082];
|
||
this.v = new Array(8);
|
||
this.v_ = new Array(8);
|
||
this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||
this.X = new Array(68);
|
||
this.xOff = 0;
|
||
this.T_00_15 = 0x79cc4519;
|
||
this.T_16_63 = 0x7a879d8a;
|
||
if (arguments.length > 0) {
|
||
this.InitDigest(arguments[0])
|
||
} else {
|
||
this.Init()
|
||
}
|
||
}
|
||
SM3Digest.prototype = {
|
||
Init: function() {
|
||
this.xBuf = new Array(4);
|
||
this.Reset()
|
||
},
|
||
InitDigest: function(t) {
|
||
this.xBuf = new Array(t.xBuf.length);
|
||
copyArray(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
|
||
this.xBufOff = t.xBufOff;
|
||
this.byteCount = t.byteCount;
|
||
copyArray(t.X, 0, this.X, 0, t.X.length);
|
||
this.xOff = t.xOff;
|
||
copyArray(t.v, 0, this.v, 0, t.v.length)
|
||
},
|
||
GetDigestSize: function() {
|
||
return this.DIGEST_LENGTH
|
||
},
|
||
Reset: function() {
|
||
this.byteCount = 0;
|
||
this.xBufOff = 0;
|
||
clearArray(this.xBuf, 0, this.xBuf.length);
|
||
copyArray(this.v0, 0, this.v, 0, this.v0.length);
|
||
this.xOff = 0;
|
||
copyArray(this.X0, 0, this.X, 0, this.X0.length)
|
||
},
|
||
GetByteLength: function() {
|
||
return this.BYTE_LENGTH
|
||
},
|
||
ProcessBlock: function() {
|
||
var i;
|
||
var ww = this.X;
|
||
var ww_ = new Array(64);
|
||
for (i = 16; i < 68; i++) {
|
||
ww[i] = this.P1(ww[i - 16] ^ ww[i - 9] ^ (this.ROTATE(ww[i - 3], 15))) ^ (this.ROTATE(ww[i - 13], 7)) ^ ww[i - 6]
|
||
}
|
||
for (i = 0; i < 64; i++) {
|
||
ww_[i] = ww[i] ^ ww[i + 4]
|
||
}
|
||
var vv = this.v;
|
||
var vv_ = this.v_;
|
||
copyArray(vv, 0, vv_, 0, this.v0.length);
|
||
var SS1, SS2, TT1, TT2, aaa;
|
||
for (i = 0; i < 16; i++) {
|
||
aaa = this.ROTATE(vv_[0], 12);
|
||
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.ROTATE(this.T_00_15, i));
|
||
SS1 = this.ROTATE(SS1, 7);
|
||
SS2 = SS1 ^ aaa;
|
||
TT1 = Int32.parse(Int32.parse(this.FF_00_15(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i];
|
||
TT2 = Int32.parse(Int32.parse(this.GG_00_15(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i];
|
||
vv_[3] = vv_[2];
|
||
vv_[2] = this.ROTATE(vv_[1], 9);
|
||
vv_[1] = vv_[0];
|
||
vv_[0] = TT1;
|
||
vv_[7] = vv_[6];
|
||
vv_[6] = this.ROTATE(vv_[5], 19);
|
||
vv_[5] = vv_[4];
|
||
vv_[4] = this.P0(TT2)
|
||
}
|
||
for (i = 16; i < 64; i++) {
|
||
aaa = this.ROTATE(vv_[0], 12);
|
||
SS1 = Int32.parse(Int32.parse(aaa + vv_[4]) + this.ROTATE(this.T_16_63, i));
|
||
SS1 = this.ROTATE(SS1, 7);
|
||
SS2 = SS1 ^ aaa;
|
||
TT1 = Int32.parse(Int32.parse(this.FF_16_63(vv_[0], vv_[1], vv_[2]) + vv_[3]) + SS2) + ww_[i];
|
||
TT2 = Int32.parse(Int32.parse(this.GG_16_63(vv_[4], vv_[5], vv_[6]) + vv_[7]) + SS1) + ww[i];
|
||
vv_[3] = vv_[2];
|
||
vv_[2] = this.ROTATE(vv_[1], 9);
|
||
vv_[1] = vv_[0];
|
||
vv_[0] = TT1;
|
||
vv_[7] = vv_[6];
|
||
vv_[6] = this.ROTATE(vv_[5], 19);
|
||
vv_[5] = vv_[4];
|
||
vv_[4] = this.P0(TT2)
|
||
}
|
||
for (i = 0; i < 8; i++) {
|
||
vv[i] ^= Int32.parse(vv_[i])
|
||
}
|
||
this.xOff = 0;
|
||
copyArray(this.X0, 0, this.X, 0, this.X0.length)
|
||
},
|
||
ProcessWord: function(in_Renamed, inOff) {
|
||
var n = in_Renamed[inOff] << 24;
|
||
n |= (in_Renamed[++inOff] & 0xff) << 16;
|
||
n |= (in_Renamed[++inOff] & 0xff) << 8;
|
||
n |= (in_Renamed[++inOff] & 0xff);
|
||
this.X[this.xOff] = n;
|
||
if (++this.xOff == 16) {
|
||
this.ProcessBlock()
|
||
}
|
||
},
|
||
ProcessLength: function(bitLength) {
|
||
if (this.xOff > 14) {
|
||
this.ProcessBlock()
|
||
}
|
||
this.X[14] = (this.URShiftLong(bitLength, 32));
|
||
this.X[15] = (bitLength & (0xffffffff))
|
||
},
|
||
IntToBigEndian: function(n, bs, off) {
|
||
bs[off] = Int32.parseByte(this.URShift(n, 24));
|
||
bs[++off] = Int32.parseByte(this.URShift(n, 16));
|
||
bs[++off] = Int32.parseByte(this.URShift(n, 8));
|
||
bs[++off] = Int32.parseByte(n)
|
||
},
|
||
DoFinal: function(out_Renamed, outOff) {
|
||
this.Finish();
|
||
for (var i = 0; i < 8; i++) {
|
||
this.IntToBigEndian(this.v[i], out_Renamed, outOff + i * 4)
|
||
}
|
||
this.Reset();
|
||
return this.DIGEST_LENGTH
|
||
},
|
||
Update: function(input) {
|
||
this.xBuf[this.xBufOff++] = input;
|
||
if (this.xBufOff == this.xBuf.length) {
|
||
this.ProcessWord(this.xBuf, 0);
|
||
this.xBufOff = 0
|
||
}
|
||
this.byteCount++
|
||
},
|
||
BlockUpdate: function(input, inOff, length) {
|
||
while ((this.xBufOff != 0) && (length > 0)) {
|
||
this.Update(input[inOff]);
|
||
inOff++;
|
||
length--
|
||
}
|
||
while (length > this.xBuf.length) {
|
||
this.ProcessWord(input, inOff);
|
||
inOff += this.xBuf.length;
|
||
length -= this.xBuf.length;
|
||
this.byteCount += this.xBuf.length
|
||
}
|
||
while (length > 0) {
|
||
this.Update(input[inOff]);
|
||
inOff++;
|
||
length--
|
||
}
|
||
},
|
||
Finish: function() {
|
||
var bitLength = (this.byteCount << 3);
|
||
this.Update((128));
|
||
while (this.xBufOff != 0) this.Update((0));
|
||
this.ProcessLength(bitLength);
|
||
this.ProcessBlock()
|
||
},
|
||
ROTATE: function(x, n) {
|
||
return (x << n) | (this.URShift(x, (32 - n)))
|
||
},
|
||
P0: function(X) {
|
||
return ((X) ^ this.ROTATE((X), 9) ^ this.ROTATE((X), 17))
|
||
},
|
||
P1: function(X) {
|
||
return ((X) ^ this.ROTATE((X), 15) ^ this.ROTATE((X), 23))
|
||
},
|
||
FF_00_15: function(X, Y, Z) {
|
||
return (X ^ Y ^ Z)
|
||
},
|
||
FF_16_63: function(X, Y, Z) {
|
||
return ((X & Y) | (X & Z) | (Y & Z))
|
||
},
|
||
GG_00_15: function(X, Y, Z) {
|
||
return (X ^ Y ^ Z)
|
||
},
|
||
GG_16_63: function(X, Y, Z) {
|
||
return ((X & Y) | (~X & Z))
|
||
},
|
||
URShift: function(number, bits) {
|
||
if (number > Int32.maxValue || number < Int32.minValue) {
|
||
number = Int32.parse(number)
|
||
}
|
||
if (number >= 0) {
|
||
return number >> bits
|
||
} else {
|
||
return (number >> bits) + (2 << ~bits)
|
||
}
|
||
},
|
||
URShiftLong: function(number, bits) {
|
||
var returnV;
|
||
var big = new BigInteger();
|
||
big.fromInt(number);
|
||
if (big.signum() >= 0) {
|
||
returnV = big.shiftRight(bits).intValue()
|
||
} else {
|
||
var bigAdd = new BigInteger();
|
||
bigAdd.fromInt(2);
|
||
var shiftLeftBits = ~bits;
|
||
var shiftLeftNumber = '';
|
||
if (shiftLeftBits < 0) {
|
||
var shiftRightBits = 64 + shiftLeftBits;
|
||
for (var i = 0; i < shiftRightBits; i++) {
|
||
shiftLeftNumber += '0'
|
||
}
|
||
var shiftLeftNumberBigAdd = new BigInteger();
|
||
shiftLeftNumberBigAdd.fromInt(number >> bits);
|
||
var shiftLeftNumberBig = new BigInteger("10" + shiftLeftNumber, 2);
|
||
shiftLeftNumber = shiftLeftNumberBig.toRadix(10);
|
||
var r = shiftLeftNumberBig.add(shiftLeftNumberBigAdd);
|
||
returnV = r.toRadix(10)
|
||
} else {
|
||
shiftLeftNumber = bigAdd.shiftLeft((~bits)).intValue();
|
||
returnV = (number >> bits) + shiftLeftNumber
|
||
}
|
||
}
|
||
return returnV
|
||
},
|
||
GetZ: function(g, pubKeyHex) {
|
||
// var userId = CryptoJS.enc.Utf8.parse("1234567812345678");
|
||
// var len = userId.words.length * 4 * 8;
|
||
var userIdWords = strToUtf8Bytes("1234567812345678");
|
||
var len = userIdWords.length * 8;
|
||
this.Update((len >> 8 & 0x00ff));
|
||
this.Update((len & 0x00ff));
|
||
this.BlockUpdate(userIdWords, 0, userIdWords.length);
|
||
var aWords = hexToBytes(g.curve.a.toBigInteger().toRadix(16));
|
||
var bWords = hexToBytes(g.curve.b.toBigInteger().toRadix(16));
|
||
var gxWords = hexToBytes(g.getX().toBigInteger().toRadix(16));
|
||
var gyWords = hexToBytes(g.getY().toBigInteger().toRadix(16));
|
||
var pxWords = hexToBytes(pubKeyHex.substr(0, 64));
|
||
var pyWords = hexToBytes(pubKeyHex.substr(64, 64));
|
||
this.BlockUpdate(aWords, 0, aWords.length);
|
||
this.BlockUpdate(bWords, 0, bWords.length);
|
||
this.BlockUpdate(gxWords, 0, gxWords.length);
|
||
this.BlockUpdate(gyWords, 0, gyWords.length);
|
||
this.BlockUpdate(pxWords, 0, pxWords.length);
|
||
this.BlockUpdate(pyWords, 0, pyWords.length);
|
||
var md = new Array(this.GetDigestSize());
|
||
this.DoFinal(md, 0);
|
||
return md
|
||
}
|
||
};
|
||
|
||
window.Int32 = {
|
||
minValue: -parseInt('10000000000000000000000000000000', 2),
|
||
maxValue: parseInt('1111111111111111111111111111111', 2),
|
||
parse: function(n) {
|
||
if (n < this.minValue) {
|
||
var bigInteger = new Number(-n);
|
||
var bigIntegerRadix = bigInteger.toString(2);
|
||
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31);
|
||
var reBigIntegerRadix = '';
|
||
for (var i = 0; i < subBigIntegerRadix.length; i++) {
|
||
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
|
||
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
|
||
}
|
||
var result = parseInt(reBigIntegerRadix, 2);
|
||
return (result + 1)
|
||
} else if (n > this.maxValue) {
|
||
var bigInteger = Number(n);
|
||
var bigIntegerRadix = bigInteger.toString(2);
|
||
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 31, 31);
|
||
var reBigIntegerRadix = '';
|
||
for (var i = 0; i < subBigIntegerRadix.length; i++) {
|
||
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
|
||
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
|
||
}
|
||
var result = parseInt(reBigIntegerRadix, 2);
|
||
return -(result + 1)
|
||
} else {
|
||
return n
|
||
}
|
||
},
|
||
parseByte: function(n) {
|
||
if (n < 0) {
|
||
var bigInteger = new Number(-n);
|
||
var bigIntegerRadix = bigInteger.toString(2);
|
||
var subBigIntegerRadix = bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8);
|
||
var reBigIntegerRadix = '';
|
||
for (var i = 0; i < subBigIntegerRadix.length; i++) {
|
||
var subBigIntegerRadixItem = subBigIntegerRadix.substr(i, 1);
|
||
reBigIntegerRadix += subBigIntegerRadixItem == '0' ? '1' : '0'
|
||
}
|
||
var result = parseInt(reBigIntegerRadix, 2);
|
||
return (result + 1)
|
||
} else if (n > 255) {
|
||
var bigInteger = Number(n);
|
||
var bigIntegerRadix = bigInteger.toString(2);
|
||
return parseInt(bigIntegerRadix.substr(bigIntegerRadix.length - 8, 8), 2)
|
||
} else {
|
||
return n
|
||
}
|
||
}
|
||
};
|
||
|
||
function SM3Util() {
|
||
var sm3Digest = new SM3Digest();
|
||
this.sm3Hash = function(text) {
|
||
// //<2F>ַ<EFBFBD><D6B7><EFBFBD>תΪUTF8<46><38>16<31><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD>WordArray<61><79><EFBFBD><EFBFBD>
|
||
// var msgData = CryptoJS.enc.Utf8.parse(text);
|
||
// //16<31><36><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>תΪ<D7AA><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
// msgData = this.GetWords(msgData.toString());
|
||
var msgData = strToUtf8Bytes(text);
|
||
var outBytes = new Array(32);
|
||
sm3Digest.BlockUpdate(msgData, 0, msgData.length);
|
||
sm3Digest.DoFinal(outBytes, 0);
|
||
return bytesToHex(outBytes);
|
||
};
|
||
this.sm3verify = function(text, hash) {
|
||
return hash == this.sm3Hash(text);
|
||
};
|
||
}
|