init: v1.0.0
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
package sm1
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
var sbox = []byte{
|
||||
0xb1, 0x08, 0x19, 0x39, 0x51, 0xe5, 0x23, 0x7d, 0x01, 0x46, 0x9c, 0x13, 0x87, 0xe7, 0x48, 0x67,
|
||||
0xc8, 0xfd, 0x95, 0x0b, 0x3a, 0xc5, 0x7a, 0x2a, 0x6f, 0x02, 0xf9, 0x3b, 0x64, 0x44, 0xff, 0x49,
|
||||
0x4e, 0x57, 0x78, 0x06, 0x2e, 0xb6, 0x88, 0xda, 0xb7, 0x8d, 0x17, 0xc3, 0x98, 0x4d, 0x24, 0x6b,
|
||||
0xf5, 0xf7, 0xcd, 0x4c, 0x60, 0x8e, 0x81, 0xfe, 0xfa, 0x03, 0x14, 0x1b, 0x5e, 0x41, 0x99, 0x50,
|
||||
0x97, 0x3d, 0x5b, 0xcf, 0x1d, 0xaa, 0x09, 0xca, 0x0e, 0x1f, 0xa7, 0xf4, 0x33, 0x2d, 0x20, 0x83,
|
||||
0x3f, 0x04, 0xf2, 0xce, 0x8b, 0x9b, 0xc4, 0x21, 0xf1, 0xa5, 0x84, 0x42, 0xaf, 0xc9, 0x3c, 0x79,
|
||||
0x34, 0xbc, 0x7e, 0xb5, 0x1c, 0x9f, 0xd8, 0x0f, 0xb9, 0xe6, 0x93, 0x2f, 0xe4, 0xef, 0x70, 0x18,
|
||||
0x6e, 0xa2, 0xbd, 0x91, 0xb3, 0xeb, 0xa4, 0xed, 0x22, 0x5f, 0x16, 0xea, 0xa6, 0x07, 0x62, 0x8f,
|
||||
0xb2, 0x36, 0x92, 0x4f, 0x5a, 0xe1, 0x90, 0x0c, 0x26, 0xa0, 0xb4, 0x54, 0xd3, 0x29, 0x35, 0x7f,
|
||||
0x86, 0x73, 0x82, 0x6a, 0xdd, 0x12, 0xbb, 0x40, 0x2c, 0x3e, 0xd9, 0x55, 0x0a, 0xad, 0xd5, 0x65,
|
||||
0x89, 0xe3, 0x71, 0xde, 0x76, 0x59, 0x7c, 0x4a, 0xe0, 0xe8, 0x45, 0xf6, 0xae, 0x9d, 0xac, 0x5c,
|
||||
0xc0, 0x00, 0x80, 0x74, 0x8a, 0x63, 0x25, 0x28, 0xbe, 0x68, 0xd6, 0x96, 0x61, 0x72, 0xb8, 0xec,
|
||||
0xb0, 0xcc, 0xf3, 0x2b, 0x56, 0x15, 0xdb, 0xf0, 0x10, 0x5d, 0x47, 0xd1, 0xc1, 0x32, 0x53, 0x43,
|
||||
0xdc, 0xcb, 0xee, 0x8c, 0xe2, 0x9e, 0xba, 0xdf, 0x66, 0x9a, 0x27, 0xc6, 0xd0, 0x94, 0xa3, 0xd7,
|
||||
0xa8, 0x85, 0xd4, 0xa1, 0x6c, 0x05, 0x69, 0x0d, 0xa9, 0xfc, 0x7b, 0x75, 0xbf, 0x77, 0xd2, 0x6d,
|
||||
0xc7, 0x58, 0x52, 0xc2, 0x4b, 0x30, 0xab, 0x31, 0xfb, 0x1a, 0x38, 0xf8, 0xe9, 0x11, 0x37, 0x1e,
|
||||
}
|
||||
|
||||
const mask = 0xffffffff
|
||||
|
||||
func rol(x, i uint32) uint32 {
|
||||
return (x << i) | (x >> (32 - i))
|
||||
}
|
||||
|
||||
func ror(x, i uint32) uint32 {
|
||||
return (x >> i) | (x << (32 - i))
|
||||
}
|
||||
|
||||
// x,y int[4]
|
||||
func r(y, x []uint32) {
|
||||
y[0] = rol(x[0], 1)
|
||||
y[1] = rol(x[1], 9)
|
||||
y[2] = rol(x[2], 17)
|
||||
y[3] = rol(x[3], 25)
|
||||
}
|
||||
|
||||
// x,y int[4]
|
||||
func rr(y, x []uint32) {
|
||||
y[0] = ror(x[0], 1)
|
||||
y[1] = ror(x[1], 9)
|
||||
y[2] = ror(x[2], 17)
|
||||
y[3] = ror(x[3], 25)
|
||||
}
|
||||
|
||||
// x,y,rk int[4]
|
||||
func j(y, x, rk []uint32) {
|
||||
y[0] = x[0] ^ rk[0]
|
||||
y[1] = x[1] ^ rk[1]
|
||||
y[2] = x[2] ^ rk[2]
|
||||
y[3] = x[3] ^ rk[3]
|
||||
}
|
||||
|
||||
// x,y are [4]byte
|
||||
func l(y []uint32, x []uint32) {
|
||||
y[0] = x[1] ^ x[2] ^ x[3]
|
||||
y[1] = x[1] ^ x[2] ^ x[0]
|
||||
y[2] = x[1] ^ x[0] ^ x[3]
|
||||
y[3] = x[0] ^ x[2] ^ x[3]
|
||||
}
|
||||
|
||||
func s(y []uint32, x []uint32) {
|
||||
xBuf := make([]byte, 4)
|
||||
for i, u := range x {
|
||||
binary.LittleEndian.PutUint32(xBuf, u)
|
||||
for i := range xBuf {
|
||||
xBuf[i] = sbox[xBuf[i]]
|
||||
}
|
||||
y[i] = binary.LittleEndian.Uint32(xBuf)
|
||||
}
|
||||
}
|
||||
|
||||
//enc = 1 for enc and 0 for dec
|
||||
func round(out, m []uint32, rk []uint32, r func([]uint32, []uint32)) {
|
||||
y := make([]uint32, 4)
|
||||
j(out, m, rk)
|
||||
l(y, out)
|
||||
s(y, y) // L(S(y)) can do in one sbox change?
|
||||
l(out, y)
|
||||
r(out, out)
|
||||
}
|
||||
|
||||
// input 16bytes to 4 uint32 in bigendian
|
||||
func bytes2ints(out []uint32, in []byte) {
|
||||
out[0] = binary.BigEndian.Uint32(in[:4])
|
||||
out[1] = binary.BigEndian.Uint32(in[4:8])
|
||||
out[2] = binary.BigEndian.Uint32(in[8:12])
|
||||
out[3] = binary.BigEndian.Uint32(in[12:])
|
||||
}
|
||||
|
||||
func ints2bytes(out []byte, in []uint32) {
|
||||
binary.BigEndian.PutUint32(out, in[0])
|
||||
binary.BigEndian.PutUint32(out[4:], in[1])
|
||||
binary.BigEndian.PutUint32(out[8:], in[2])
|
||||
binary.BigEndian.PutUint32(out[12:], in[3])
|
||||
}
|
||||
|
||||
func block(out []byte, in []byte, key roundKey, r func([]uint32, []uint32)) {
|
||||
x := make([]uint32, 4)
|
||||
bytes2ints(x, in)
|
||||
r(x, x)
|
||||
for i := 0; i < numOfRound; i++ {
|
||||
round(x, x, key[4*i:], r)
|
||||
}
|
||||
|
||||
j(x, x, key[4*numOfRound:])
|
||||
ints2bytes(out, x)
|
||||
}
|
||||
|
||||
func encryptBlock(dst, src []byte, key []uint32) {
|
||||
block(dst, src, key, r)
|
||||
}
|
||||
func decryptBlock(dst, src []byte, key []uint32) {
|
||||
block(dst, src, key, rr)
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package sm1
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
)
|
||||
|
||||
// BlockSize is the SM1 block size in bytes.
|
||||
const (
|
||||
BlockSize = 16
|
||||
numOfRound = 8
|
||||
)
|
||||
|
||||
// sm1Cipher is an instance of cipher.Block interface
|
||||
type sm1Cipher struct {
|
||||
encKey [4 * (numOfRound + 1)]uint32
|
||||
decKey [4 * (numOfRound + 1)]uint32
|
||||
}
|
||||
|
||||
// NewCipher creates and returns a new cipher.Block.
|
||||
func NewCipher(key []byte) (cipher.Block, error) {
|
||||
if len(key) != BlockSize {
|
||||
return nil, gerrors.WithAnnotatingf(ErrInvalidInputLength, "key should be %d bytes", BlockSize)
|
||||
}
|
||||
|
||||
cp := new(sm1Cipher)
|
||||
// gen keys
|
||||
keyexpand_enc(cp.encKey[:], key)
|
||||
keyexpand_dec(cp.decKey[:], key)
|
||||
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
// Clear implements the gmath.Clearable interface
|
||||
func (c *sm1Cipher) Clear() {
|
||||
for i := 0; i < len(c.decKey); i++ {
|
||||
c.decKey[i] = 0
|
||||
c.encKey[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (c *sm1Cipher) BlockSize() int { return BlockSize }
|
||||
|
||||
// 调用前应保证输入一个block
|
||||
func (c *sm1Cipher) Encrypt(dst, src []byte) {
|
||||
if len(src) < BlockSize {
|
||||
panic("xdx.jelly/xgcl/sm/sm1/Encrypt: input not full block")
|
||||
}
|
||||
if len(dst) < BlockSize {
|
||||
panic("xdx.jelly/xgcl/sm/sm1/Encrypt: output not full block")
|
||||
}
|
||||
encryptBlock(dst, src, c.encKey[:])
|
||||
}
|
||||
|
||||
func (c *sm1Cipher) Decrypt(dst, src []byte) {
|
||||
if len(src) < BlockSize {
|
||||
panic("xdx.jelly/xgcl/sm/sm1/Decrypt: input not full block")
|
||||
}
|
||||
if len(dst) < BlockSize {
|
||||
panic("xdx.jelly/xgcl/sm/sm1/Decrypt: output not full block")
|
||||
}
|
||||
decryptBlock(dst, src, c.decKey[:])
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Package sm1 is the implementation of SM1 block cipher.
|
||||
|
||||
The SM1 works as follows, There are three keys:
|
||||
- systems key SK
|
||||
- auxiliary key AK
|
||||
- key
|
||||
|
||||
# Enecryption
|
||||
|
||||
PT key SK
|
||||
| | |
|
||||
v +---v------v----+
|
||||
R(·) <---- |rk |
|
||||
| | |
|
||||
| | key expand |
|
||||
v | |
|
||||
round f(·) <---|rk |
|
||||
| +---------------+
|
||||
v
|
||||
J(·)
|
||||
|
|
||||
v
|
||||
CT
|
||||
|
||||
# Decryption
|
||||
|
||||
CT key SK
|
||||
| | |
|
||||
v +---v------v----+
|
||||
R⁻¹(·) <--- |rk |
|
||||
| | |
|
||||
| | key expand |
|
||||
v | |
|
||||
round f(·) <---|rk |
|
||||
| +---------------+
|
||||
v
|
||||
J(·)
|
||||
|
|
||||
v
|
||||
PT
|
||||
|
||||
# R Transformation
|
||||
|
||||
The input of R is 128 bits, and denotes as X0, X1, X2, X3 from left to right.
|
||||
The output of R is 128 bits, and denotes as Y0, Y1, Y2, Y3 from left to right..
|
||||
|
||||
Y0 = X0 << 1
|
||||
Y1 = X1 << 9
|
||||
Y2 = X2 << 17
|
||||
Y3 = X3 << 25
|
||||
|
||||
# R⁻¹ Transformation
|
||||
|
||||
The R⁻¹ Transformation is the reverse of R transformation.
|
||||
|
||||
Y0 = X0 >> 1
|
||||
Y1 = X1 >> 9
|
||||
Y2 = X2 >> 17
|
||||
Y3 = X3 >> 25
|
||||
*/
|
||||
package sm1
|
||||
@@ -0,0 +1,15 @@
|
||||
package sm1
|
||||
|
||||
import "xdx.jelly/xgcl/gerrors"
|
||||
|
||||
//go:generate stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go
|
||||
type ErrorCode gerrors.ErrorCode
|
||||
|
||||
func (e ErrorCode) Error() string {
|
||||
return gerrors.Format(uint32(e), e.String())
|
||||
}
|
||||
|
||||
// error codes
|
||||
const (
|
||||
ErrInvalidInputLength ErrorCode = 0x01001000 + iota //输入长度不合法
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
// Code generated by "stringer -type=ErrorCode -linecomment -output=errors_string.go errors.go"; DO NOT EDIT.
|
||||
|
||||
package sm1
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[ErrInvalidInputLength-16781312]
|
||||
}
|
||||
|
||||
const _ErrorCode_name = "输入长度不合法"
|
||||
|
||||
var _ErrorCode_index = [...]uint8{0, 21}
|
||||
|
||||
func (i ErrorCode) String() string {
|
||||
i -= 16781312
|
||||
if i >= ErrorCode(len(_ErrorCode_index)-1) {
|
||||
return "ErrorCode(" + strconv.FormatInt(int64(i+16781312), 10) + ")"
|
||||
}
|
||||
return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]]
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
package sm1
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// type roundKey = [4 * (numOfRound + 1)]uint32
|
||||
type roundKey []uint32
|
||||
|
||||
// // func newRoundKey() AC_SM1_KEY {
|
||||
// // return make([]uint32, 4*(numOfRound+1))
|
||||
// // }
|
||||
// func (k AC_SM1_KEY) clear() {
|
||||
// for i := range k {
|
||||
// k[i] = 0
|
||||
// }
|
||||
// }
|
||||
|
||||
func sbox2(sbox1, sbox2 []byte, x byte) byte {
|
||||
return ((sbox1[(x>>4)&0x0f] << 4) | sbox2[x&0x0f])
|
||||
}
|
||||
|
||||
func g(out, inX, inY []uint32) {
|
||||
var sbox = [][]byte{
|
||||
{0x5, 0xd, 0x9, 0x1, 0x0, 0x2, 0xa, 0xf, 0x6, 0x7, 0xc, 0x8, 0xe, 0x3, 0xb, 0x4},
|
||||
{0x2, 0x4, 0xf, 0x6, 0x8, 0xb, 0xe, 0x5, 0xa, 0xd, 0x3, 0xc, 0x9, 0x7, 0x1, 0x0},
|
||||
{0x4, 0x3, 0x5, 0xd, 0xf, 0x0, 0x8, 0x9, 0xb, 0x2, 0x6, 0xe, 0xa, 0x1, 0xc, 0x7},
|
||||
{0xf, 0xe, 0x0, 0xa, 0x1, 0x7, 0x3, 0xd, 0x4, 0xc, 0x8, 0x5, 0xb, 0x9, 0x6, 0x2},
|
||||
{0x4, 0xc, 0x8, 0x0, 0x1, 0x3, 0xb, 0xe, 0x7, 0x6, 0xd, 0x9, 0xf, 0x2, 0xa, 0x5},
|
||||
{0x1, 0x7, 0xc, 0x5, 0xb, 0x8, 0xd, 0x6, 0x9, 0xe, 0x0, 0xf, 0xa, 0x4, 0x2, 0x3},
|
||||
{0xd, 0xa, 0xc, 0x4, 0x6, 0x9, 0x1, 0x0, 0x2, 0xb, 0xf, 0x7, 0x3, 0x8, 0x5, 0xe},
|
||||
{0x9, 0x8, 0x6, 0xc, 0x7, 0x1, 0x5, 0xb, 0x2, 0xa, 0xe, 0x3, 0xd, 0xf, 0x0, 0x4}}
|
||||
xx := make([]uint32, 4)
|
||||
xxx := make([]uint32, 4)
|
||||
xx[0] = inX[0] ^ inX[2] ^ inX[3]
|
||||
xx[1] = inX[0] ^ inX[1] ^ inX[3]
|
||||
xx[2] = inX[0] ^ inX[2] ^ inX[1]
|
||||
xx[3] = inX[0] ^ inX[1] ^ inX[2] ^ inX[3]
|
||||
|
||||
xxx[0] = xx[0] ^ inY[0]
|
||||
xxx[1] = xx[1] ^ inY[1]
|
||||
xxx[2] = xx[2] ^ inY[2]
|
||||
s := make([]byte, 4)
|
||||
// int2bytes(s, xx[3])
|
||||
binary.BigEndian.PutUint32(s, xx[3])
|
||||
// printf("s[0-3]=%02x%02x%02x%02x\n", s[0], s[1], s[2], s[3]);
|
||||
s[0] = sbox2(sbox[0], sbox[1], s[0])
|
||||
s[1] = sbox2(sbox[2], sbox[3], s[1])
|
||||
// printf("s[0-3]=%02x%02x%02x%02x\n", s[0], s[1], s[2], s[3]);
|
||||
s[2] = sbox2(sbox[4], sbox[5], s[2])
|
||||
// printf("s[0-3]=%02x%02x%02x%02x\n", s[0], s[1], s[2], s[3]);
|
||||
s[3] = sbox2(sbox[6], sbox[7], s[3])
|
||||
// printf("s[0-3]=%02x%02x%02x%02x\n", s[0], s[1], s[2], s[3]);
|
||||
xxx[3] = binary.BigEndian.Uint32(s) // bytes2int(s);
|
||||
|
||||
out[0] = rol(xxx[3], 1) ^ inY[3]
|
||||
out[1] = rol(xxx[0], 8) ^ rol(xxx[3], 17)
|
||||
out[2] = rol(xxx[1], 7) ^ rol(xxx[3], 25)
|
||||
out[3] = rol(xxx[2], 1) ^ rol(xxx[3], 9)
|
||||
}
|
||||
|
||||
func gg(out, inX, inY []uint32) {
|
||||
var sbox = [][]byte{
|
||||
{0x4, 0x3, 0x5, 0xd, 0xf, 0x0, 0x8, 0x9, 0xb, 0x2, 0x6, 0xe, 0xa, 0x1, 0xc, 0x7},
|
||||
{0xf, 0xe, 0x0, 0xa, 0x1, 0x7, 0x3, 0xd, 0x4, 0xc, 0x8, 0x5, 0xb, 0x9, 0x6, 0x2},
|
||||
{0x5, 0xd, 0x9, 0x1, 0x0, 0x2, 0xa, 0xf, 0x6, 0x7, 0xc, 0x8, 0xe, 0x3, 0xb, 0x4},
|
||||
{0x2, 0x4, 0xf, 0x6, 0x8, 0xb, 0xe, 0x5, 0xa, 0xd, 0x3, 0xc, 0x9, 0x7, 0x1, 0x0},
|
||||
{0x3, 0x4, 0xd, 0x5, 0x0, 0xf, 0x9, 0x8, 0x2, 0xb, 0xe, 0x6, 0x1, 0xa, 0x7, 0xc},
|
||||
{0xa, 0x0, 0xe, 0xf, 0xd, 0x3, 0x7, 0x1, 0x5, 0x8, 0xc, 0x4, 0x2, 0x6, 0x9, 0xb},
|
||||
{0x7, 0x6, 0x8, 0xc, 0x3, 0xe, 0x4, 0xb, 0xd, 0x5, 0x1, 0x9, 0x2, 0x0, 0xf, 0xa},
|
||||
{0xe, 0x5, 0x8, 0xb, 0xf, 0x6, 0x2, 0x4, 0x1, 0x0, 0x9, 0x7, 0x3, 0xc, 0xa, 0xd},
|
||||
}
|
||||
xx := make([]uint32, 4)
|
||||
xxx := make([]uint32, 4)
|
||||
xx[3] = ror(inX[0]^inY[3], 1)
|
||||
xx[2] = ror(rol(xx[3], 9)^inX[3], 1)
|
||||
xx[1] = ror(rol(xx[3], 25)^inX[2], 7)
|
||||
xx[0] = ror(rol(xx[3], 17)^inX[1], 8)
|
||||
|
||||
xxx[0] = xx[0] ^ inY[0]
|
||||
xxx[1] = xx[1] ^ inY[1]
|
||||
xxx[2] = xx[2] ^ inY[2]
|
||||
s := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(s, xx[3])
|
||||
s[0] = sbox2(sbox[0], sbox[1], s[0])
|
||||
s[1] = sbox2(sbox[2], sbox[3], s[1])
|
||||
s[2] = sbox2(sbox[4], sbox[5], s[2])
|
||||
s[3] = sbox2(sbox[6], sbox[7], s[3])
|
||||
xxx[3] = binary.BigEndian.Uint32(s)
|
||||
|
||||
out[0] = xxx[0] ^ xxx[1] ^ xxx[2]
|
||||
out[1] = xxx[0] ^ xxx[3]
|
||||
out[2] = xxx[3] ^ xxx[1]
|
||||
out[3] = xxx[2] ^ xxx[3]
|
||||
}
|
||||
|
||||
func xor(c, a, b []uint32) {
|
||||
for i := range a {
|
||||
c[i] = a[i] ^ b[i]
|
||||
}
|
||||
}
|
||||
|
||||
func keyexpand(A, B [][]uint32, ek []byte) {
|
||||
// static const unsigned char sk[AC_SM1_KEY_LENGTH_IN_BYTE] = {0x19, 0x1a, 0x4e, 0xf3, 0x67, 0xec, 0xe2, 0x81, 0xc9, 0x03, 0xc4, 0x6c, 0x23, 0x33, 0x3c, 0x2a};
|
||||
// static const unsigned char ak[AC_SM1_KEY_LENGTH_IN_BYTE] = {0};
|
||||
EK := make([]uint32, 4)
|
||||
|
||||
// 辅助密钥AK为全0
|
||||
// uint32_t AK[4] = {0};
|
||||
|
||||
// 系统密钥
|
||||
SK := []uint32{0x191a4ef3, 0x67ece281, 0xc903c46c, 0x23333c2a}
|
||||
|
||||
bytes2ints(EK, ek)
|
||||
a := make([]uint32, 4)
|
||||
b := make([]uint32, 4)
|
||||
xor(SK, EK, SK)
|
||||
a[0] = SK[1] ^ SK[2] ^ SK[3]
|
||||
a[1] = SK[1] ^ SK[2] ^ SK[0]
|
||||
a[2] = SK[1] ^ SK[0] ^ SK[3]
|
||||
a[3] = SK[0] ^ SK[2] ^ SK[3]
|
||||
// a[0] = a[0];
|
||||
a[1] = rol(a[1], 8)
|
||||
a[2] = rol(a[2], 16)
|
||||
a[3] = rol(a[3], 23)
|
||||
|
||||
// xor(i, EK, AK, 4);
|
||||
b[0] = EK[1] ^ EK[2] ^ EK[3]
|
||||
b[1] = EK[1] ^ EK[2] ^ EK[0]
|
||||
b[2] = EK[1] ^ EK[0] ^ EK[3]
|
||||
b[3] = EK[0] ^ EK[2] ^ EK[3]
|
||||
b[0] = rol(b[0], 8)
|
||||
b[1] = rol(b[1], 16)
|
||||
b[2] = rol(b[2], 24)
|
||||
// b[3] = b[3];
|
||||
|
||||
g(A[0], a, b)
|
||||
gg(B[0], b, a)
|
||||
for i := 1; i < numOfRound/2+1; i++ {
|
||||
g(A[i], A[i-1], b)
|
||||
gg(B[i], B[i-1], a)
|
||||
}
|
||||
for i := numOfRound/2 + 1; i < numOfRound+1; i++ {
|
||||
gg(A[i], A[i-1], b)
|
||||
g(B[i], B[i-1], a)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func keyexpand_enc(rkey []uint32, ek []byte) {
|
||||
A := make([][]uint32, numOfRound+1)
|
||||
for i := range A {
|
||||
A[i] = make([]uint32, 4)
|
||||
}
|
||||
B := make([][]uint32, numOfRound+1)
|
||||
for i := range B {
|
||||
B[i] = make([]uint32, 4)
|
||||
}
|
||||
|
||||
keyexpand(A, B, ek)
|
||||
j := 0
|
||||
for ; j < numOfRound/2+1; j++ {
|
||||
rkey[4*j+0] = A[j][0]
|
||||
rkey[4*j+1] = A[j][1]
|
||||
rkey[4*j+2] = A[j][2]
|
||||
rkey[4*j+3] = A[j][3]
|
||||
}
|
||||
for ; j < numOfRound+1; j++ {
|
||||
rkey[4*j+0] = B[j][0]
|
||||
rkey[4*j+1] = B[j][1]
|
||||
rkey[4*j+2] = B[j][2]
|
||||
rkey[4*j+3] = B[j][3]
|
||||
}
|
||||
}
|
||||
func keyexpand_dec(rkey []uint32, ek []byte) {
|
||||
A := make([][]uint32, numOfRound+1)
|
||||
for i := range A {
|
||||
A[i] = make([]uint32, 4)
|
||||
}
|
||||
B := make([][]uint32, numOfRound+1)
|
||||
for i := range B {
|
||||
B[i] = make([]uint32, 4)
|
||||
}
|
||||
|
||||
keyexpand(A, B, ek)
|
||||
j := 0
|
||||
for ; j < numOfRound/2; j++ {
|
||||
rkey[4*j+0] = B[j][0]
|
||||
rkey[4*j+1] = B[j][1]
|
||||
rkey[4*j+2] = B[j][2]
|
||||
rkey[4*j+3] = B[j][3]
|
||||
}
|
||||
for ; j < numOfRound+1; j++ {
|
||||
rkey[4*j+0] = A[j][0]
|
||||
rkey[4*j+1] = A[j][1]
|
||||
rkey[4*j+2] = A[j][2]
|
||||
rkey[4*j+3] = A[j][3]
|
||||
}
|
||||
for j = 0; j < numOfRound+1; j++ {
|
||||
rr(rkey[4*j:], rkey[4*j:])
|
||||
}
|
||||
}
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
package sm1
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
"xdx.jelly/xgcl/gerrors"
|
||||
"xdx.jelly/xgcl/internal/modes"
|
||||
"xdx.jelly/xgcl/utils"
|
||||
)
|
||||
|
||||
// EncryptECB len(encData) must exactly equal to len(data)
|
||||
// or return error
|
||||
// we not realloc memory for encData!!!
|
||||
// data和encData要么完全重叠,要么完全不重叠!!!
|
||||
//
|
||||
// @param dst[out] 密文预分配空间,可以为nil
|
||||
// @param key[in] 16字节密钥
|
||||
// @param src[in] 明文,长度必须是16的倍数,函数不负责padding
|
||||
// @return []byte 输入密文。
|
||||
// @note 如果输入dst的空间(cap)比src小,则可能引起内存地址得变化。
|
||||
// @usage dst = ECBEncrypt(dst, key, src)
|
||||
func EncryptECB(dst, key, src []byte) ([]byte, error) {
|
||||
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be a multiple of %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := modes.NewECBEncrypter(block)
|
||||
blockMode.CryptBlocks(dst, src)
|
||||
block.(utils.Clearable).Clear()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// DecryptECB 解密
|
||||
// params:
|
||||
//
|
||||
// dst[in] 明文
|
||||
// src[in] 密文,长度必须是16的倍数,函数不负责解padding
|
||||
// key[in] 16字节密钥
|
||||
func DecryptECB(dst, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be a multiple of %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := modes.NewECBDecrypter(block)
|
||||
blockMode.CryptBlocks(dst, src)
|
||||
block.(utils.Clearable).Clear()
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// EncryptCBC cbc加密
|
||||
// 函数返回时iv保存最后一个分组密文,因此对大包数据可以分组多次调用进行加密。
|
||||
// params:
|
||||
//
|
||||
// dst[out] 密文,输入时分配好长度,必须和data的长度相等
|
||||
// iv[in/out] 初始向量, 16字节,返回时是最后一个分组密文
|
||||
// key[in] 16字节密钥
|
||||
// src[in] 明文,长度必须是16的倍数,函数不负责padding
|
||||
func EncryptCBC(dst, iv, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
if len(iv) != BlockSize {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input iv must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := cipher.NewCBCEncrypter(block, iv)
|
||||
blockMode.CryptBlocks(dst, src)
|
||||
|
||||
// The last dst block is the return iv
|
||||
if len(dst) > 0 {
|
||||
copy(iv, dst[len(dst)-BlockSize:])
|
||||
}
|
||||
block.(utils.Clearable).Clear()
|
||||
return dst, nil
|
||||
|
||||
}
|
||||
|
||||
// DecryptCBC cbc解密
|
||||
// 函数返回时iv保存最后一个分组密文,因此对大包数据可以分组多次调用进行加密。
|
||||
// params:
|
||||
//
|
||||
// dst[out] 密文,输入时分配好长度,必须和data的长度相等
|
||||
// iv[in/out] 初始向量, 16字节,返回时是最后一个分组
|
||||
// key[in] 16字节密钥
|
||||
// src[in] 明文,长度必须是16的倍数,函数不负责padding
|
||||
func DecryptCBC(dst, iv, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
if len(iv) != BlockSize {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input iv must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := cipher.NewCBCDecrypter(block, iv)
|
||||
blockMode.CryptBlocks(dst, src)
|
||||
|
||||
// The last src block is the return iv
|
||||
if len(src) > 0 {
|
||||
copy(iv, src[len(src)-block.BlockSize():])
|
||||
}
|
||||
if block, ok := block.(utils.Clearable); ok {
|
||||
block.Clear()
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// EncryptCFB cfb加密
|
||||
// params:
|
||||
//
|
||||
// dst[out] 密文,输入时分配好长度,必须和data的长度相等
|
||||
// iv[in/out] 初始向量, 16字节
|
||||
// key[in] 16字节密钥
|
||||
// src[in] 明文,长度必须是16的倍数,函数不负责padding
|
||||
func EncryptCFB(dst, iv, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, gerrors.WithStack(err)
|
||||
}
|
||||
|
||||
if len(iv) != BlockSize {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input iv must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := cipher.NewCFBEncrypter(block, iv)
|
||||
blockMode.XORKeyStream(dst, src)
|
||||
if block, ok := block.(utils.Clearable); ok {
|
||||
block.Clear()
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// DecryptCFB ...
|
||||
func DecryptCFB(dst, iv, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
if len(iv) != BlockSize {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input iv must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := cipher.NewCFBDecrypter(block, iv)
|
||||
blockMode.XORKeyStream(dst, src)
|
||||
if block, ok := block.(utils.Clearable); ok {
|
||||
block.Clear()
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// EncryptOFB ofb加密
|
||||
func EncryptOFB(dst, iv, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
if len(iv) != BlockSize {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input iv must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := cipher.NewOFB(block, iv)
|
||||
blockMode.XORKeyStream(dst, src)
|
||||
if block, ok := block.(utils.Clearable); ok {
|
||||
block.Clear()
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// DecryptOFB ofb解密
|
||||
func DecryptOFB(dst, iv, key, src []byte) ([]byte, error) {
|
||||
block, err := NewCipher(key)
|
||||
if err != nil {
|
||||
return dst, err
|
||||
}
|
||||
|
||||
if len(iv) != BlockSize {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input iv must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if len(src)%BlockSize != 0 {
|
||||
return dst, gerrors.WithAnnotatingf(ErrInvalidInputLength,
|
||||
"the length of input must be %d", BlockSize)
|
||||
}
|
||||
|
||||
if dst == nil || cap(dst) < len(src) {
|
||||
dst = make([]byte, len(src))
|
||||
}
|
||||
dst = dst[:len(src)]
|
||||
|
||||
blockMode := cipher.NewOFB(block, iv)
|
||||
blockMode.XORKeyStream(dst, src)
|
||||
if block, ok := block.(utils.Clearable); ok {
|
||||
block.Clear()
|
||||
}
|
||||
return dst, nil
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package sm1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSm1Block(t *testing.T) {
|
||||
key := []byte{0x40, 0xbb, 0x12, 0xdd, 0x6a, 0x82, 0x73, 0x86, 0x7f, 0x35, 0x29, 0xd3, 0x54, 0xb4, 0xa0, 0x26}
|
||||
msg := []byte{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}
|
||||
encMsg := []byte{0x6d, 0x7f, 0x45, 0xb0, 0x8b, 0xc4, 0xd9, 0x66, 0x44, 0x4c, 0x86, 0xc2, 0xb0, 0x7d, 0x29, 0x93}
|
||||
|
||||
buf, _ := EncryptECB(nil, key, msg)
|
||||
if !bytes.Equal(encMsg, buf) {
|
||||
t.Fatal()
|
||||
}
|
||||
|
||||
buf, _ = DecryptECB(nil, key, encMsg)
|
||||
if !bytes.Equal(msg, buf) {
|
||||
t.Fatal()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user