init: v1.0.0
This commit is contained in:
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Package sm3 implements the SM3 Hash algorithms
|
||||
*/
|
||||
package sm3
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
"xdx.jelly/xgcl/sm"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 注册sm.SM3、sm.SM3WithID到sm.hashs中去.
|
||||
sm.RegisterHash(sm.SM3, New)
|
||||
sm.RegisterHash(sm.SM3WithID, New)
|
||||
}
|
||||
|
||||
type digest struct {
|
||||
h [8]uint32
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
// NewDigest return a new digest type, void change `digest` to `Digest`.
|
||||
// 相比标准库,增加此函数。
|
||||
// 在上下文明确使用sm3的时候,可以显示用这个函数来获取sm3的digest实例,
|
||||
// 而不是通过New()得到Hash接口。
|
||||
func NewDigest() *digest {
|
||||
d := new(digest)
|
||||
d.Reset()
|
||||
return d
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash computing the SM3 checksum. The Hash also
|
||||
// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
|
||||
// marshal and unmarshal the internal state of the hash.
|
||||
func New() hash.Hash {
|
||||
return NewDigest()
|
||||
}
|
||||
|
||||
// Reset reset the states
|
||||
func (d *digest) Reset() {
|
||||
d.h[0] = init0
|
||||
d.h[1] = init1
|
||||
d.h[2] = init2
|
||||
d.h[3] = init3
|
||||
d.h[4] = init4
|
||||
d.h[5] = init5
|
||||
d.h[6] = init6
|
||||
d.h[7] = init7
|
||||
d.nx = 0
|
||||
d.len = 0
|
||||
}
|
||||
|
||||
/*
|
||||
MarshalBinary和UnmarshalBinary实现了encoding.BinaryMarshaler和
|
||||
encoding.BinaryMarshaler接口,可以对Sm3的中间状态转化为byte序列存储。
|
||||
比如kdf函数要计算SM3(z||cnt), cnt = 1,2,3,4...,可以先update(z),保存此时
|
||||
状态。
|
||||
|
||||
用法:
|
||||
dig := New()
|
||||
io.WriteString(dig, "a")
|
||||
// New 返回的是hash接口, 转换为BinaryMarshaler接口
|
||||
state, _ := dig.(encoding.BinaryMarshaler).MarshalBinary()
|
||||
// dig do something
|
||||
dig.(encoding.BinaryUnmarshaler).UnmarshalBinary(state)
|
||||
|
||||
补充:我们增加了NewDigest(), 返回*digest,因此可以直接用赋值保存。
|
||||
d1 := NewDigest()
|
||||
// ...
|
||||
*d2 := *d1
|
||||
*/
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface
|
||||
// marshal a digest to []byte to save
|
||||
// no error return.
|
||||
func (d *digest) MarshalBinary() ([]byte, error) {
|
||||
b := make([]byte, 0, marshaledSize)
|
||||
b = append(b, magic...)
|
||||
b = appendUint32(b, d.h[0])
|
||||
b = appendUint32(b, d.h[1])
|
||||
b = appendUint32(b, d.h[2])
|
||||
b = appendUint32(b, d.h[3])
|
||||
b = appendUint32(b, d.h[4])
|
||||
b = appendUint32(b, d.h[5])
|
||||
b = appendUint32(b, d.h[6])
|
||||
b = appendUint32(b, d.h[7])
|
||||
b = append(b, d.x[:]...)
|
||||
b = appendUint64(b, d.len)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryMarshaler interface
|
||||
// recover a digest from []byte
|
||||
func (d *digest) UnmarshalBinary(b []byte) error {
|
||||
if len(b) < marshaledSize || string(b[:len(magic)]) != magic {
|
||||
return ErrInvalidInput
|
||||
}
|
||||
|
||||
b = b[len(magic):]
|
||||
b, d.h[0] = consumeUint32(b)
|
||||
b, d.h[1] = consumeUint32(b)
|
||||
b, d.h[2] = consumeUint32(b)
|
||||
b, d.h[3] = consumeUint32(b)
|
||||
b, d.h[4] = consumeUint32(b)
|
||||
b, d.h[5] = consumeUint32(b)
|
||||
b, d.h[6] = consumeUint32(b)
|
||||
b, d.h[7] = consumeUint32(b)
|
||||
b = b[copy(d.x[:], b):]
|
||||
_, d.len = consumeUint64(b)
|
||||
d.nx = int(d.len) % chunk
|
||||
return nil
|
||||
}
|
||||
|
||||
// Size returns the size of hash digest
|
||||
func (d *digest) Size() int { return Size }
|
||||
|
||||
// BlockSize return the bytes of one block
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
func (d *digest) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
d.len += uint64(nn)
|
||||
// try to clear d.x
|
||||
if d.nx > 0 {
|
||||
n := copy(d.x[d.nx:], p)
|
||||
d.nx += n
|
||||
if d.nx == chunk {
|
||||
block(d, d.x[:])
|
||||
d.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
|
||||
if len(p) >= chunk {
|
||||
// n is multiple of chunk
|
||||
n := len(p) &^ (chunk - 1)
|
||||
block(d, p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
d.nx = copy(d.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Sum returns the digest without change the intenal states
|
||||
func (d *digest) Sum(in []byte) []byte {
|
||||
// make a copy
|
||||
d0 := *d
|
||||
hash := d0.checkSum()
|
||||
return append(in, hash[:]...)
|
||||
}
|
||||
|
||||
// Sum returns the SM3 checksum of the data.
|
||||
func Sum(data ...[]byte) [Size]byte {
|
||||
var d digest
|
||||
d.Reset()
|
||||
for _, x := range data {
|
||||
d.Write(x)
|
||||
}
|
||||
return d.checkSum()
|
||||
}
|
||||
Reference in New Issue
Block a user