155 lines
3.8 KiB
Go
155 lines
3.8 KiB
Go
package algos
|
|
|
|
// SM3 SM3哈希算法实现
|
|
type SM3 struct {
|
|
IV []uint32
|
|
TJ []uint32
|
|
}
|
|
|
|
// NewSM3 创建SM3实例
|
|
func NewSM3() *SM3 {
|
|
return &SM3{
|
|
IV: []uint32{1937774191, 1226093241, 388252375, 3666478592, 2842636476, 372324522, 3817729613, 2969243214},
|
|
TJ: []uint32{
|
|
2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
|
|
2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169, 2043430169,
|
|
2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
|
|
2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
|
|
2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
|
|
2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
|
|
2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
|
|
2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042, 2055708042,
|
|
},
|
|
}
|
|
}
|
|
|
|
// rotateLeft 循环左移
|
|
func (sm3 *SM3) rotateLeft(a uint32, k int) uint32 {
|
|
k = k % 32
|
|
return ((a << uint(k)) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> uint(32-k))
|
|
}
|
|
|
|
// FFJ FF函数
|
|
func (sm3 *SM3) FFJ(X, Y, Z uint32, j int) uint32 {
|
|
if j >= 0 && j < 16 {
|
|
return X ^ Y ^ Z
|
|
} else if j >= 16 && j < 64 {
|
|
return (X & Y) | (X & Z) | (Y & Z)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// GGJ GG函数
|
|
func (sm3 *SM3) GGJ(X, Y, Z uint32, j int) uint32 {
|
|
if j >= 0 && j < 16 {
|
|
return X ^ Y ^ Z
|
|
} else if j >= 16 && j < 64 {
|
|
return (X & Y) | ((^X) & Z)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// P0 压缩函数P0
|
|
func (sm3 *SM3) P0(X uint32) uint32 {
|
|
return X ^ sm3.rotateLeft(X, 9) ^ sm3.rotateLeft(X, 17)
|
|
}
|
|
|
|
// P1 压缩函数P1
|
|
func (sm3 *SM3) P1(X uint32) uint32 {
|
|
return X ^ sm3.rotateLeft(X, 15) ^ sm3.rotateLeft(X, 23)
|
|
}
|
|
|
|
// CF 压缩函数
|
|
func (sm3 *SM3) CF(Vi []uint32, Bi []byte) []uint32 {
|
|
W := make([]uint32, 68)
|
|
for i := 0; i < 16; i++ {
|
|
weight := uint32(0x1000000)
|
|
data := uint32(0)
|
|
for k := i * 4; k < (i+1)*4; k++ {
|
|
data = data + uint32(Bi[k])*weight
|
|
weight = weight / 0x100
|
|
}
|
|
W[i] = data
|
|
}
|
|
|
|
for j := 16; j < 68; j++ {
|
|
W[j] = sm3.P1(W[j-16]^W[j-9]^sm3.rotateLeft(W[j-3], 15)) ^ sm3.rotateLeft(W[j-13], 7) ^ W[j-6]
|
|
}
|
|
|
|
W1 := make([]uint32, 64)
|
|
for j := 0; j < 64; j++ {
|
|
W1[j] = W[j] ^ W[j+4]
|
|
}
|
|
|
|
A, B, C, D, E, F, G, H := Vi[0], Vi[1], Vi[2], Vi[3], Vi[4], Vi[5], Vi[6], Vi[7]
|
|
|
|
for j := 0; j < 64; j++ {
|
|
SS1 := sm3.rotateLeft((sm3.rotateLeft(A, 12)+E+sm3.rotateLeft(sm3.TJ[j], j%32))&0xFFFFFFFF, 7)
|
|
SS2 := SS1 ^ sm3.rotateLeft(A, 12)
|
|
TT1 := (sm3.FFJ(A, B, C, j) + D + SS2 + W1[j]) & 0xFFFFFFFF
|
|
TT2 := (sm3.GGJ(E, F, G, j) + H + SS1 + W[j]) & 0xFFFFFFFF
|
|
D = C
|
|
C = sm3.rotateLeft(B, 9)
|
|
B = A
|
|
A = TT1
|
|
H = G
|
|
G = sm3.rotateLeft(F, 19)
|
|
F = E
|
|
E = sm3.P0(TT2)
|
|
}
|
|
|
|
V := make([]uint32, 8)
|
|
V[0] = A ^ Vi[0]
|
|
V[1] = B ^ Vi[1]
|
|
V[2] = C ^ Vi[2]
|
|
V[3] = D ^ Vi[3]
|
|
V[4] = E ^ Vi[4]
|
|
V[5] = F ^ Vi[5]
|
|
V[6] = G ^ Vi[6]
|
|
V[7] = H ^ Vi[7]
|
|
|
|
return V
|
|
}
|
|
|
|
// Hash 计算SM3哈希
|
|
func (sm3 *SM3) Hash(msg []byte) []byte {
|
|
msgLen := len(msg)
|
|
reserve1 := msgLen % 64
|
|
paddingLen := 0
|
|
if reserve1 > 55 {
|
|
paddingLen = 64 - reserve1 + 64
|
|
} else {
|
|
paddingLen = 64 - reserve1
|
|
}
|
|
|
|
msgPadding := make([]byte, msgLen+paddingLen)
|
|
copy(msgPadding, msg)
|
|
msgPadding[msgLen] = 0x80
|
|
|
|
lengthBits := uint64(msgLen) * 8
|
|
for i := 0; i < 8; i++ {
|
|
msgPadding[len(msgPadding)-1-i] = byte(lengthBits >> uint(8*i))
|
|
}
|
|
|
|
groupCount := len(msgPadding) / 64
|
|
|
|
V := make([]uint32, len(sm3.IV))
|
|
copy(V, sm3.IV)
|
|
|
|
for i := 0; i < groupCount; i++ {
|
|
B := msgPadding[i*64 : (i+1)*64]
|
|
V = sm3.CF(V, B)
|
|
}
|
|
|
|
result := make([]byte, 32)
|
|
for i := 0; i < 8; i++ {
|
|
result[i*4] = byte((V[i] >> 24) & 0xFF)
|
|
result[i*4+1] = byte((V[i] >> 16) & 0xFF)
|
|
result[i*4+2] = byte((V[i] >> 8) & 0xFF)
|
|
result[i*4+3] = byte(V[i] & 0xFF)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|