Files
fanqie-go/internal/algos/sm3.go
T
chenxin 6981148727 🔧 chore: 初始化番茄小说 API 项目结构
新增项目基础框架,包含核心 API 实现、算法模块、HTTP 处理器等完整功能模块
2026-08-28 15:22:22 +08:00

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
}