Files
Syngnat de8fb60a30 feat(highgo-sm3): 增加瀚高SM3专用驱动并解耦PostgreSQL连接链路
- 引入 third_party/highgo-pq 作为 HighGo 专用驱动实现
- 调整驱动注册与连接入口,避免覆盖 postgres 驱动
- 保持 PG 数据源行为不变并补充接入文档
2026-02-10 17:42:28 +08:00

310 lines
6.3 KiB
Go

package pq
import (
"encoding/binary"
"encoding/hex"
"fmt"
"hash"
"math/bits"
)
const (
DigestLength = 32
BlockSize = 16
)
var gT = []uint32{
0x79CC4519, 0xF3988A32, 0xE7311465, 0xCE6228CB, 0x9CC45197, 0x3988A32F, 0x7311465E, 0xE6228CBC,
0xCC451979, 0x988A32F3, 0x311465E7, 0x6228CBCE, 0xC451979C, 0x88A32F39, 0x11465E73, 0x228CBCE6,
0x9D8A7A87, 0x3B14F50F, 0x7629EA1E, 0xEC53D43C, 0xD8A7A879, 0xB14F50F3, 0x629EA1E7, 0xC53D43CE,
0x8A7A879D, 0x14F50F3B, 0x29EA1E76, 0x53D43CEC, 0xA7A879D8, 0x4F50F3B1, 0x9EA1E762, 0x3D43CEC5,
0x7A879D8A, 0xF50F3B14, 0xEA1E7629, 0xD43CEC53, 0xA879D8A7, 0x50F3B14F, 0xA1E7629E, 0x43CEC53D,
0x879D8A7A, 0x0F3B14F5, 0x1E7629EA, 0x3CEC53D4, 0x79D8A7A8, 0xF3B14F50, 0xE7629EA1, 0xCEC53D43,
0x9D8A7A87, 0x3B14F50F, 0x7629EA1E, 0xEC53D43C, 0xD8A7A879, 0xB14F50F3, 0x629EA1E7, 0xC53D43CE,
0x8A7A879D, 0x14F50F3B, 0x29EA1E76, 0x53D43CEC, 0xA7A879D8, 0x4F50F3B1, 0x9EA1E762, 0x3D43CEC5}
type sm3Digest struct {
v [DigestLength / 4]uint32
inWords [BlockSize]uint32
xOff int32
w [68]uint32
xBuf [4]byte
xBufOff int32
byteCount int64
}
func New() hash.Hash {
digest := new(sm3Digest)
digest.Reset()
return digest
}
func (digest *sm3Digest) Sum(b []byte) []byte {
d1 := digest
h := d1.checkSum()
return append(b, h[:]...)
}
// Size returns the number of bytes Sum will return.
func (digest *sm3Digest) Size() int {
return DigestLength
}
// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all writes
// are a multiple of the block size.
func (digest *sm3Digest) BlockSize() int {
return BlockSize
}
func (digest *sm3Digest) Reset() {
digest.byteCount = 0
digest.xBufOff = 0
for i := 0; i < len(digest.xBuf); i++ {
digest.xBuf[i] = 0
}
for i := 0; i < len(digest.inWords); i++ {
digest.inWords[i] = 0
}
for i := 0; i < len(digest.w); i++ {
digest.w[i] = 0
}
digest.v[0] = 0x7380166F
digest.v[1] = 0x4914B2B9
digest.v[2] = 0x172442D7
digest.v[3] = 0xDA8A0600
digest.v[4] = 0xA96F30BC
digest.v[5] = 0x163138AA
digest.v[6] = 0xE38DEE4D
digest.v[7] = 0xB0FB0E4E
digest.xOff = 0
}
func (digest *sm3Digest) Write(p []byte) (n int, err error) {
_ = p[0]
inLen := len(p)
i := 0
if digest.xBufOff != 0 {
for i < inLen {
digest.xBuf[digest.xBufOff] = p[i]
digest.xBufOff++
i++
if digest.xBufOff == 4 {
digest.processWord(digest.xBuf[:], 0)
digest.xBufOff = 0
break
}
}
}
limit := ((inLen - i) & ^3) + i
for ; i < limit; i += 4 {
digest.processWord(p, int32(i))
}
for i < inLen {
digest.xBuf[digest.xBufOff] = p[i]
digest.xBufOff++
i++
}
digest.byteCount += int64(inLen)
n = inLen
return
}
func (digest *sm3Digest) finish() {
bitLength := digest.byteCount << 3
digest.Write([]byte{128})
for digest.xBufOff != 0 {
digest.Write([]byte{0})
}
digest.processLength(bitLength)
digest.processBlock()
}
func (digest *sm3Digest) checkSum() [DigestLength]byte {
digest.finish()
vlen := len(digest.v)
var out [DigestLength]byte
for i := 0; i < vlen; i++ {
binary.BigEndian.PutUint32(out[i*4:(i+1)*4], digest.v[i])
}
return out
}
func (digest *sm3Digest) processBlock() {
for j := 0; j < 16; j++ {
digest.w[j] = digest.inWords[j]
}
for j := 16; j < 68; j++ {
wj3 := digest.w[j-3]
r15 := (wj3 << 15) | (wj3 >> (32 - 15))
wj13 := digest.w[j-13]
r7 := (wj13 << 7) | (wj13 >> (32 - 7))
digest.w[j] = p1(digest.w[j-16]^digest.w[j-9]^r15) ^ r7 ^ digest.w[j-6]
}
A := digest.v[0]
B := digest.v[1]
C := digest.v[2]
D := digest.v[3]
E := digest.v[4]
F := digest.v[5]
G := digest.v[6]
H := digest.v[7]
for j := 0; j < 16; j++ {
a12 := (A << 12) | (A >> (32 - 12))
s1 := a12 + E + gT[j]
SS1 := (s1 << 7) | (s1 >> (32 - 7))
SS2 := SS1 ^ a12
Wj := digest.w[j]
W1j := Wj ^ digest.w[j+4]
TT1 := ff0(A, B, C) + D + SS2 + W1j
TT2 := gg0(E, F, G) + H + SS1 + Wj
D = C
C = (B << 9) | (B >> (32 - 9))
B = A
A = TT1
H = G
G = (F << 19) | (F >> (32 - 19))
F = E
E = p0(TT2)
}
for j := 16; j < 64; j++ {
a12 := (A << 12) | (A >> (32 - 12))
s1 := a12 + E + gT[j]
SS1 := (s1 << 7) | (s1 >> (32 - 7))
SS2 := SS1 ^ a12
Wj := digest.w[j]
W1j := Wj ^ digest.w[j+4]
TT1 := ff1(A, B, C) + D + SS2 + W1j
TT2 := gg1(E, F, G) + H + SS1 + Wj
D = C
C = (B << 9) | (B >> (32 - 9))
B = A
A = TT1
H = G
G = (F << 19) | (F >> (32 - 19))
F = E
E = p0(TT2)
}
digest.v[0] ^= A
digest.v[1] ^= B
digest.v[2] ^= C
digest.v[3] ^= D
digest.v[4] ^= E
digest.v[5] ^= F
digest.v[6] ^= G
digest.v[7] ^= H
digest.xOff = 0
}
func (digest *sm3Digest) processWord(in []byte, inOff int32) {
n := binary.BigEndian.Uint32(in[inOff : inOff+4])
digest.inWords[digest.xOff] = n
digest.xOff++
if digest.xOff >= 16 {
digest.processBlock()
}
}
func (digest *sm3Digest) processLength(bitLength int64) {
if digest.xOff > (BlockSize - 2) {
digest.inWords[digest.xOff] = 0
digest.xOff++
digest.processBlock()
}
for ; digest.xOff < (BlockSize - 2); digest.xOff++ {
digest.inWords[digest.xOff] = 0
}
digest.inWords[digest.xOff] = uint32(bitLength >> 32)
digest.xOff++
digest.inWords[digest.xOff] = uint32(bitLength)
digest.xOff++
}
func p0(x uint32) uint32 {
r9 := bits.RotateLeft32(x, 9)
r17 := bits.RotateLeft32(x, 17)
return x ^ r9 ^ r17
}
func p1(x uint32) uint32 {
r15 := bits.RotateLeft32(x, 15)
r23 := bits.RotateLeft32(x, 23)
return x ^ r15 ^ r23
}
func ff0(x uint32, y uint32, z uint32) uint32 {
return x ^ y ^ z
}
func ff1(x uint32, y uint32, z uint32) uint32 {
return (x & y) | (x & z) | (y & z)
}
func gg0(x uint32, y uint32, z uint32) uint32 {
return x ^ y ^ z
}
func gg1(x uint32, y uint32, z uint32) uint32 {
return (x & y) | ((^x) & z)
}
func Sum(data []byte) [DigestLength]byte {
var d sm3Digest
d.Reset()
d.Write(data)
return d.checkSum()
}
func PrintT() {
var T [64]uint32
fmt.Print("{")
for j := 0; j < 16; j++ {
T[j] = 0x79CC4519
Tj := (T[j] << uint32(j)) | (T[j] >> (32 - uint32(j)))
fmt.Printf("0x%08X, ", Tj)
}
for j := 16; j < 64; j++ {
n := j % 32
T[j] = 0x7A879D8A
Tj := (T[j] << uint32(n)) | (T[j] >> (32 - uint32(n)))
if j == 63 {
fmt.Printf("0x%08X}\n", Tj)
} else {
fmt.Printf("0x%08X, ", Tj)
}
}
}
func Sm3ToString(context string) string {
sm3 := New()
sm3.Write([]byte(context))
result := sm3.Sum(nil)
return hex.EncodeToString(result)
}