github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/crypto/sm/sm3/sm3hash.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 SPDX-License-Identifier: Apache-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 package sm3 17 18 func leftRotate(x uint32, r uint32) uint32 { return (x<<(r%32) | x>>(32-r%32)) } 19 20 func ff0(X uint32, Y uint32, Z uint32) uint32 { return X ^ Y ^ Z } 21 func ff1(X uint32, Y uint32, Z uint32) uint32 { return (X & Y) | (X & Z) | (Y & Z) } 22 23 func gg0(X uint32, Y uint32, Z uint32) uint32 { return X ^ Y ^ Z } 24 func gg1(X uint32, Y uint32, Z uint32) uint32 { return (X & Y) | ((^X) & Z) } 25 26 func p0(X uint32) uint32 { return X ^ leftRotate(X, 9) ^ leftRotate(X, 17) } 27 28 func p1(X uint32) uint32 { return X ^ leftRotate(X, 15) ^ leftRotate(X, 23) } 29 30 func msgPadding(message []byte) []byte { 31 // Pre-processing: 32 chunk := message 33 34 // Pre-processing: adding a single 1 bit 35 chunk = append(chunk, byte(0x80)) 36 37 // Pre-processing: padding with zeros 38 padding := 56 - len(chunk)%64 39 for i := 0; i < padding; i++ { 40 chunk = append(chunk, 0x00) 41 } 42 var l uint64 43 l = uint64(len(message) * 8) 44 45 // l := byte((len(message) * 8))() 46 chunk = append(chunk, byte((l>>56)&0xff)) 47 chunk = append(chunk, byte((l>>48)&0xff)) 48 chunk = append(chunk, byte((l>>40)&0xff)) 49 chunk = append(chunk, byte((l>>32)&0xff)) 50 chunk = append(chunk, byte((l>>24)&0xff)) 51 chunk = append(chunk, byte((l>>16)&0xff)) 52 chunk = append(chunk, byte((l>>8)&0xff)) 53 chunk = append(chunk, byte(l&0xff)) 54 55 // hstr := biu.BytesToHexString(chunk) 56 // fmt.Println(len(hstr)) 57 // fmt.Println("test" + hstr) 58 59 // return hstr 60 return chunk 61 } 62 63 type W struct { 64 W1 [68]uint32 65 W2 [64]uint32 66 } 67 68 func msgExp(x [16]uint32) W { 69 var i int 70 var wtmp W 71 for i = 0; i < 16; i++ { 72 wtmp.W1[i] = x[i] 73 } 74 for i = 16; i < 68; i++ { 75 wtmp.W1[i] = p1(wtmp.W1[i-16]^wtmp.W1[i-9]^leftRotate(wtmp.W1[i-3], 15)) ^ leftRotate(wtmp.W1[i-13], 7) ^ wtmp.W1[i-6] 76 } 77 for i = 0; i < 64; i++ { 78 wtmp.W2[i] = wtmp.W1[i] ^ wtmp.W1[i+4] 79 } 80 return wtmp 81 } 82 83 func cF(V [8]uint32, Bmsg [16]uint32) [8]uint32 { 84 var j int 85 var A, B, C, D, E, F, G, H uint32 86 A = V[0] 87 B = V[1] 88 C = V[2] 89 D = V[3] 90 E = V[4] 91 F = V[5] 92 G = V[6] 93 H = V[7] 94 wtmp := msgExp(Bmsg) 95 for j = 0; j < 16; j++ { 96 var jj int 97 if j < 33 { 98 jj = j 99 } else { 100 jj = j - 32 101 } 102 SS1 := leftRotate(leftRotate(A, 12)+E+leftRotate(0x79cc4519, uint32(jj)), 7) 103 SS2 := SS1 ^ leftRotate(A, 12) 104 TT1 := ff0(A, B, C) + D + SS2 + wtmp.W2[j] 105 TT2 := gg0(E, F, G) + H + SS1 + wtmp.W1[j] 106 D = C 107 C = leftRotate(B, 9) 108 B = A 109 A = TT1 110 H = G 111 G = leftRotate(F, 19) 112 F = E 113 E = p0(TT2) 114 } 115 for j = 16; j < 64; j++ { 116 var jj int 117 if j < 33 { 118 jj = j 119 } else { 120 jj = j - 32 121 } 122 SS1 := leftRotate(leftRotate(A, 12)+E+leftRotate(0x7a879d8a, uint32(jj)), 7) 123 SS2 := SS1 ^ leftRotate(A, 12) 124 TT1 := ff1(A, B, C) + D + SS2 + wtmp.W2[j] 125 TT2 := gg1(E, F, G) + H + SS1 + wtmp.W1[j] 126 D = C 127 C = leftRotate(B, 9) 128 B = A 129 A = TT1 130 H = G 131 G = leftRotate(F, 19) 132 F = E 133 E = p0(TT2) 134 } 135 136 V[0] = A ^ V[0] 137 V[1] = B ^ V[1] 138 V[2] = C ^ V[2] 139 V[3] = D ^ V[3] 140 V[4] = E ^ V[4] 141 V[5] = F ^ V[5] 142 V[6] = G ^ V[6] 143 V[7] = H ^ V[7] 144 145 return V 146 } 147 148 func Block(dig *digest, p []byte) { 149 var V [8]uint32 150 for i := 0; i < 8; i++ { 151 V[i] = dig.h[i] 152 } 153 for len(p) >= 64 { 154 m := [16]uint32{} 155 x := p[:64] 156 xi := 0 157 mi := 0 158 for mi < 16 { 159 m[mi] = (uint32(x[xi+3]) | 160 (uint32(x[xi+2]) << 8) | 161 (uint32(x[xi+1]) << 16) | 162 (uint32(x[xi]) << 24)) 163 mi += 1 164 xi += 4 165 } 166 V = cF(V, m) 167 p = p[64:] 168 } 169 for i := 0; i < 8; i++ { 170 dig.h[i] = V[i] 171 } 172 }