mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-22 10:16:18 +08:00
support zuc eia 256 bits
This commit is contained in:
parent
7632ebf376
commit
eb56eac42a
17
zuc/core.go
17
zuc/core.go
@ -1,4 +1,4 @@
|
||||
// Package zuc handle shangmi zuc stream cipher
|
||||
// Package zuc handle shangmi zuc stream cipher, experimental/poc implementation.
|
||||
package zuc
|
||||
|
||||
import (
|
||||
@ -57,6 +57,21 @@ var zuc256_d0 = [16]byte{
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30,
|
||||
}
|
||||
|
||||
var zuc256_d = [][16]byte{
|
||||
{
|
||||
0x22, 0x2F, 0x25, 0x2A, 0x6D, 0x40, 0x40, 0x40,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30,
|
||||
},
|
||||
{
|
||||
0x23, 0x2F, 0x24, 0x2A, 0x6D, 0x40, 0x40, 0x40,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30,
|
||||
},
|
||||
{
|
||||
0x23, 0x2F, 0x25, 0x2A, 0x6D, 0x40, 0x40, 0x40,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x52, 0x10, 0x30,
|
||||
},
|
||||
}
|
||||
|
||||
type zucState32 struct {
|
||||
lfsr [16]uint32 // linear feedback shift register
|
||||
r1 uint32
|
||||
|
@ -23,7 +23,6 @@ type ZUC128Mac struct {
|
||||
}
|
||||
|
||||
// NewHash create hash for zuc-128 eia, with arguments key and iv.
|
||||
// Hash byte (8 bits) level.
|
||||
func NewHash(key, iv []byte) (*ZUC128Mac, error) {
|
||||
k := len(key)
|
||||
ivLen := len(iv)
|
||||
|
191
zuc/eia256.go
Normal file
191
zuc/eia256.go
Normal file
@ -0,0 +1,191 @@
|
||||
package zuc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ZUC256Mac struct {
|
||||
zucState32
|
||||
initState zucState32
|
||||
tagSize int
|
||||
k0 []uint32
|
||||
t []uint32
|
||||
x [chunk]byte
|
||||
nx int
|
||||
len uint64
|
||||
}
|
||||
|
||||
// NewHash create hash for zuc-128 eia, with arguments key, iv and tagSize.
|
||||
// The larger the tag size, the worse the performance.
|
||||
func NewHash256(key, iv []byte, tagSize int) (*ZUC256Mac, error) {
|
||||
k := len(key)
|
||||
ivLen := len(iv)
|
||||
mac := &ZUC256Mac{}
|
||||
var d []byte
|
||||
switch tagSize {
|
||||
default:
|
||||
return nil, fmt.Errorf("zuc/eia: invalid tag size %d, support 4/8/16 in bytes", tagSize)
|
||||
case 4:
|
||||
d = zuc256_d[0][:]
|
||||
case 8:
|
||||
d = zuc256_d[1][:]
|
||||
case 16:
|
||||
d = zuc256_d[2][:]
|
||||
}
|
||||
mac.tagSize = tagSize
|
||||
mac.t = make([]uint32, mac.tagSize/4)
|
||||
mac.k0 = make([]uint32, mac.tagSize/4)
|
||||
switch k {
|
||||
default:
|
||||
return nil, fmt.Errorf("zuc/eia: invalid key size %d, expect 32 in bytes", k)
|
||||
case 32: // ZUC-256
|
||||
if ivLen != 23 {
|
||||
return nil, fmt.Errorf("zuc/eia: invalid iv size %d, expect 23 in bytes", ivLen)
|
||||
}
|
||||
mac.loadKeyIV32(key, iv, d)
|
||||
}
|
||||
// initialization
|
||||
for i := 0; i < 32; i++ {
|
||||
x := mac.bitReconstruction()
|
||||
w := mac.f32(x[0], x[1], x[2])
|
||||
mac.enterInitMode(w >> 1)
|
||||
}
|
||||
|
||||
// work state
|
||||
x := mac.bitReconstruction()
|
||||
mac.f32(x[0], x[1], x[2])
|
||||
mac.enterWorkMode()
|
||||
|
||||
mac.initState.r1 = mac.r1
|
||||
mac.initState.r2 = mac.r2
|
||||
|
||||
copy(mac.initState.lfsr[:], mac.lfsr[:])
|
||||
mac.Reset()
|
||||
return mac, nil
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) Size() int {
|
||||
return m.tagSize
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) BlockSize() int {
|
||||
return chunk
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) Reset() {
|
||||
m.nx = 0
|
||||
m.len = 0
|
||||
m.r1 = m.initState.r1
|
||||
m.r2 = m.initState.r2
|
||||
copy(m.lfsr[:], m.initState.lfsr[:])
|
||||
m.genKeywords(m.t)
|
||||
m.genKeywords(m.k0)
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) block(p []byte) {
|
||||
for len(p) >= chunk {
|
||||
w := binary.BigEndian.Uint32(p)
|
||||
k1 := m.genKeyword()
|
||||
|
||||
for i := 0; i < 32; i++ {
|
||||
if w&0x80000000 == 0x80000000 {
|
||||
for j := 0; j < m.tagSize/4; j++ {
|
||||
m.t[j] ^= m.k0[j]
|
||||
}
|
||||
}
|
||||
w <<= 1
|
||||
var j int
|
||||
for j = 0; j < m.tagSize/4-1; j++ {
|
||||
m.k0[j] = (m.k0[j] << 1) | (m.k0[j+1] >> 31)
|
||||
}
|
||||
m.k0[j] = (m.k0[j] << 1) | (k1 >> 31)
|
||||
k1 <<= 1
|
||||
}
|
||||
|
||||
p = p[chunk:]
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) Write(p []byte) (nn int, err error) {
|
||||
nn = len(p)
|
||||
m.len += uint64(nn)
|
||||
if m.nx > 0 {
|
||||
n := copy(m.x[m.nx:], p)
|
||||
m.nx += n
|
||||
if m.nx == chunk {
|
||||
m.block(m.x[:])
|
||||
m.nx = 0
|
||||
}
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) >= chunk {
|
||||
n := len(p) &^ (chunk - 1)
|
||||
m.block(p[:n])
|
||||
p = p[n:]
|
||||
}
|
||||
if len(p) > 0 {
|
||||
m.nx = copy(m.x[:], p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) checkSum(additionalBits int, b byte) []byte {
|
||||
if m.nx >= 4 {
|
||||
panic("m.nx >= 4")
|
||||
}
|
||||
if m.nx > 0 || additionalBits > 0 {
|
||||
m.x[m.nx] = b
|
||||
w := binary.BigEndian.Uint32(m.x[:])
|
||||
k1 := m.genKeyword()
|
||||
|
||||
for i := 0; i < 8*m.nx+additionalBits; i++ {
|
||||
if w&0x80000000 == 0x80000000 {
|
||||
for j := 0; j < m.tagSize/4; j++ {
|
||||
m.t[j] ^= m.k0[j]
|
||||
}
|
||||
}
|
||||
w <<= 1
|
||||
var j int
|
||||
for j = 0; j < m.tagSize/4-1; j++ {
|
||||
m.k0[j] = (m.k0[j] << 1) | (m.k0[j+1] >> 31)
|
||||
}
|
||||
m.k0[j] = (m.k0[j] << 1) | (k1 >> 31)
|
||||
k1 <<= 1
|
||||
}
|
||||
}
|
||||
|
||||
digest := make([]byte, m.tagSize)
|
||||
for j := 0; j < m.tagSize/4; j++ {
|
||||
m.t[j] ^= m.k0[j]
|
||||
binary.BigEndian.PutUint32(digest[j*4:], m.t[j])
|
||||
}
|
||||
|
||||
return digest
|
||||
}
|
||||
|
||||
// Finish this function hash nbits data in p and return mac value
|
||||
// In general, we will use byte level function, this is just for test/verify.
|
||||
func (m *ZUC256Mac) Finish(p []byte, nbits int) []byte {
|
||||
if len(p) < (nbits+7)/8 {
|
||||
panic("invalid p length")
|
||||
}
|
||||
nbytes := nbits / 8
|
||||
nRemainBits := nbits - nbytes*8
|
||||
if nbytes > 0 {
|
||||
m.Write(p[:nbytes])
|
||||
}
|
||||
var b byte
|
||||
if nRemainBits > 0 {
|
||||
b = p[nbytes]
|
||||
}
|
||||
digest := m.checkSum(nRemainBits, b)
|
||||
return digest[:]
|
||||
}
|
||||
|
||||
func (m *ZUC256Mac) Sum(in []byte) []byte {
|
||||
// Make a copy of d so that caller can keep writing and summing.
|
||||
d0 := *m
|
||||
hash := d0.checkSum(0, 0)
|
||||
return append(in, hash[:]...)
|
||||
}
|
253
zuc/eia256_test.go
Normal file
253
zuc/eia256_test.go
Normal file
@ -0,0 +1,253 @@
|
||||
package zuc
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var zucEIA256Tests = []struct {
|
||||
key []byte
|
||||
iv []byte
|
||||
msg []byte
|
||||
nMsgs int
|
||||
mac32 string
|
||||
mac64 string
|
||||
mac128 string
|
||||
}{
|
||||
{
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
1,
|
||||
"9b972a74",
|
||||
"673e54990034d38c",
|
||||
"d85e54bbcb9600967084c952a1654b26",
|
||||
},
|
||||
{
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
[]byte{
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
},
|
||||
10,
|
||||
"8754f5cf",
|
||||
"130dc225e72240cc",
|
||||
"df1e8307b31cc62beca1ac6f8190c22f",
|
||||
},
|
||||
{
|
||||
[]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
},
|
||||
[]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
},
|
||||
[]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
},
|
||||
1,
|
||||
"1f3079b4",
|
||||
"8c71394d39957725",
|
||||
"a35bb274b567c48b28319f111af34fbd",
|
||||
},
|
||||
{
|
||||
[]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
},
|
||||
[]byte{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
},
|
||||
[]byte{
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
},
|
||||
10,
|
||||
"5c7c8b88",
|
||||
"ea1dee544bb6223b",
|
||||
"3a83b554be408ca5494124ed9d473205",
|
||||
},
|
||||
}
|
||||
|
||||
func Test_Finish256_32(t *testing.T) {
|
||||
for i, test := range zucEIA256Tests {
|
||||
h, err := NewHash256(test.key, test.iv, 4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
for j := 0; j < test.nMsgs; j++ {
|
||||
_, err = h.Write(test.msg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
digest := h.Sum(nil)
|
||||
if hex.EncodeToString(digest) != test.mac32 {
|
||||
t.Errorf("case %d, expected=%s, result=%s\n", i+1, test.mac32, hex.EncodeToString(digest))
|
||||
}
|
||||
h.Reset()
|
||||
for j := 0; j < test.nMsgs; j++ {
|
||||
_, err = h.Write(test.msg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
digest = h.Sum(nil)
|
||||
if hex.EncodeToString(digest) != test.mac32 {
|
||||
t.Errorf("case %d, expected=%s, result=%s\n", i+1, test.mac32, hex.EncodeToString(digest))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Finish256_64(t *testing.T) {
|
||||
for i, test := range zucEIA256Tests {
|
||||
h, err := NewHash256(test.key, test.iv, 8)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
for j := 0; j < test.nMsgs; j++ {
|
||||
_, err = h.Write(test.msg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
digest := h.Sum(nil)
|
||||
if hex.EncodeToString(digest) != test.mac64 {
|
||||
t.Errorf("case %d, expected=%s, result=%s\n", i+1, test.mac64, hex.EncodeToString(digest))
|
||||
}
|
||||
h.Reset()
|
||||
for j := 0; j < test.nMsgs; j++ {
|
||||
_, err = h.Write(test.msg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
digest = h.Sum(nil)
|
||||
if hex.EncodeToString(digest) != test.mac64 {
|
||||
t.Errorf("case %d, expected=%s, result=%s\n", i+1, test.mac64, hex.EncodeToString(digest))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Finish256_128(t *testing.T) {
|
||||
for i, test := range zucEIA256Tests {
|
||||
h, err := NewHash256(test.key, test.iv, 16)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
for j := 0; j < test.nMsgs; j++ {
|
||||
_, err = h.Write(test.msg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
digest := h.Sum(nil)
|
||||
if hex.EncodeToString(digest) != test.mac128 {
|
||||
t.Errorf("case %d, expected=%s, result=%s\n", i+1, test.mac128, hex.EncodeToString(digest))
|
||||
}
|
||||
h.Reset()
|
||||
for j := 0; j < test.nMsgs; j++ {
|
||||
_, err = h.Write(test.msg)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
digest = h.Sum(nil)
|
||||
if hex.EncodeToString(digest) != test.mac128 {
|
||||
t.Errorf("case %d, expected=%s, result=%s\n", i+1, test.mac128, hex.EncodeToString(digest))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchmark256Size(b *testing.B, size, tagSize int) {
|
||||
var key [32]byte
|
||||
var iv [23]byte
|
||||
var buf = make([]byte, 8192)
|
||||
bench, _ := NewHash256(key[:], iv[:], tagSize)
|
||||
b.SetBytes(int64(size))
|
||||
sum := make([]byte, bench.Size())
|
||||
for i := 0; i < b.N; i++ {
|
||||
bench.Reset()
|
||||
bench.Write(buf[:size])
|
||||
bench.Sum(sum[:0])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHash8Bytes_Tag32(b *testing.B) {
|
||||
benchmark256Size(b, 8, 4)
|
||||
}
|
||||
|
||||
func BenchmarkHash8Bytes_Tag64(b *testing.B) {
|
||||
benchmark256Size(b, 8, 8)
|
||||
}
|
||||
|
||||
func BenchmarkHash8Bytes_Tag128(b *testing.B) {
|
||||
benchmark256Size(b, 8, 16)
|
||||
}
|
||||
|
||||
func BenchmarkHash1K_Tag32(b *testing.B) {
|
||||
benchmark256Size(b, 1024, 4)
|
||||
}
|
||||
|
||||
func BenchmarkHash1K_Tag64(b *testing.B) {
|
||||
benchmark256Size(b, 1024, 8)
|
||||
}
|
||||
|
||||
func BenchmarkHash1K_Tag128(b *testing.B) {
|
||||
benchmark256Size(b, 1024, 16)
|
||||
}
|
||||
|
||||
func BenchmarkHash8K_Tag32(b *testing.B) {
|
||||
benchmark256Size(b, 8192, 4)
|
||||
}
|
||||
|
||||
func BenchmarkHash8K_Tag64(b *testing.B) {
|
||||
benchmark256Size(b, 8192, 8)
|
||||
}
|
||||
|
||||
func BenchmarkHash8K_Tag128(b *testing.B) {
|
||||
benchmark256Size(b, 8192, 16)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user