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) { // //字符串转为UTF8的16进制字WordArray对象 // var msgData = CryptoJS.enc.Utf8.parse(text); // //16进制字符串转为二进制数组 // 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); }; }