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  }