hello world

golang sm3、sm4 加密

https://gitee.com/t115liyanpeng/license

sm3:

sm3.go

package sm3

import (
    "hash"
)

//Size The size of a SM3 checksum in bytes.
const Size = 32

//BlockSize The blocksize of SM3 in bytes.
const BlockSize = 64

const (
    chunk = 64
    init0 = 0x7380166F
    init1 = 0x4914B2B9
    init2 = 0x172442D7
    init3 = 0xDA8A0600
    init4 = 0xA96F30BC
    init5 = 0x163138AA
    init6 = 0xE38DEE4D
    init7 = 0xB0FB0E4E
)

// digest represents the partial evaluation of a checksum.
type digest struct {
    h   [8]uint32
    x   [chunk]byte
    nx  int
    len uint64
}

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
}

// New returns a new hash.Hash computing the SM3 checksum.
func New() hash.Hash {
    d := new(digest)
    d.Reset()
    return d
}

func (d *digest) Size() int { return Size }

func (d *digest) BlockSize() int { return BlockSize }

func (d *digest) Write(p []byte) (nn int, err error) {
    nn = len(p)
    d.len += uint64(nn)
    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 := len(p) &^ (chunk - 1)
        block(d, p[:n])
        p = p[n:]
    }
    if len(p) > 0 {
        d.nx = copy(d.x[:], p)
    }
    return
}

//Sum sum is add
func (d *digest) Sum(in []byte) []byte {
    // Make a copy of d0 so that caller can keep writing and summing.
    d1 := *d
    hash := d1.checkSum()
    return append(in, hash[:]...)
}

func (d *digest) checkSum() [Size]byte {
    len := d.len
    // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
    var tmp [64]byte
    tmp[0] = 0x80
    if len%64 < 56 {
        d.Write(tmp[0 : 56-len%64])
    } else {
        d.Write(tmp[0 : 64+56-len%64])
    }

    // Length in bits.
    len <<= 3
    for i := uint(0); i < 8; i++ {
        tmp[i] = byte(len >> (56 - 8*i))
    }
    d.Write(tmp[0:8])

    if d.nx != 0 {
        panic("d.nx != 0")
    }

    h := d.h[:]

    var digest [Size]byte
    for i, s := range h {
        digest[i*4] = byte(s >> 24)
        digest[i*4+1] = byte(s >> 16)
        digest[i*4+2] = byte(s >> 8)
        digest[i*4+3] = byte(s)
    }

    return digest
}

// Sum returns the SM3 checksum of the data.
func Sum(data []byte) [Size]byte {
    var d digest
    d.Reset()
    d.Write(data)
    return d.checkSum()
}

sm3block.go

package sm3

func block(dig *digest, p []byte) {
    blockGeneric(dig, p)
}

func blockGeneric(dig *digest, p []byte) {
    var w [68]uint32
    var w1 [64]uint32
    var ss1, ss2, tt1, tt2 uint32

    h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
    for len(p) >= chunk {
        for i := 0; i < 16; i++ {
            j := i * 4
            w[i] = uint32(p[j])<<24 | uint32(p[j+1])<<16 | uint32(p[j+2])<<8 | uint32(p[j+3])
        }
        for i := 16; i < 68; i++ {
            w[i] = sm3p1(w[i-16]^w[i-9]^sm3rotl(w[i-3], 15)) ^ sm3rotl(w[i-13], 7) ^ w[i-6]
        }

        for i := 0; i < 64; i++ {
            w1[i] = w[i] ^ w[i+4]
        }

        a, b, c, d, e, f, g, h := h0, h1, h2, h3, h4, h5, h6, h7

        for j := 0; j < 64; j++ {
            ss1 = sm3rotl(sm3rotl(a, 12)+e+sm3rotl(sm3t(j), uint32(j)), 7)
            ss2 = ss1 ^ sm3rotl(a, 12)
            tt1 = sm3ff(a, b, c, j) + d + ss2 + w1[j]
            tt2 = sm3gg(e, f, g, j) + h + ss1 + w[j]
            d = c
            c = sm3rotl(b, 9)
            b = a
            a = tt1
            h = g
            g = sm3rotl(f, 19)
            f = e
            e = sm3p0(tt2)
        }

        h0 ^= a
        h1 ^= b
        h2 ^= c
        h3 ^= d
        h4 ^= e
        h5 ^= f
        h6 ^= g
        h7 ^= h

        p = p[chunk:]
    }

    dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7] = h0, h1, h2, h3, h4, h5, h6, h7
}

func sm3t(j int) uint32 {
    if j >= 16 {
        return 0x7A879D8A
    }
    return 0x79CC4519

}

func sm3ff(x, y, z uint32, j int) uint32 {
    if j >= 16 {
        return ((x | y) & (x | z) & (y | z))
    }
    return x ^ y ^ z

}

func sm3gg(x, y, z uint32, j int) uint32 {
    if j >= 16 {
        return ((x & y) | ((^x) & z))
    }
    return x ^ y ^ z

}

func sm3rotl(x, n uint32) uint32 {
    return (x << (n % 32)) | (x >> (32 - (n % 32)))
}

func sm3p0(x uint32) uint32 {
    return x ^ sm3rotl(x, 9) ^ sm3rotl(x, 17)
}

func sm3p1(x uint32) uint32 {
    return x ^ sm3rotl(x, 15) ^ sm3rotl(x, 23)
}

sm4:

block.go

package sm4


func (c *sm4Cipher) generateSubkeys(keyBytes []byte) {
    var key = make([]uint32, 4)
    var k = make([]uint32, 4)
    key[0] = (uint32(keyBytes[0]) << 24) | (uint32(keyBytes[1]) << 16) | (uint32(keyBytes[2]) << 8) | (uint32(keyBytes[3]))
    key[1] = (uint32(keyBytes[4]) << 24) | (uint32(keyBytes[5]) << 16) | (uint32(keyBytes[6]) << 8) | (uint32(keyBytes[7]))
    key[2] = (uint32(keyBytes[8]) << 24) | (uint32(keyBytes[9]) << 16) | (uint32(keyBytes[10]) << 8) | (uint32(keyBytes[11]))
    key[3] = (uint32(keyBytes[12]) << 24) | (uint32(keyBytes[13]) << 16) | (uint32(keyBytes[14]) << 8) | (uint32(keyBytes[15]))

    k[0] = key[0] ^ sm4fk[0]
    k[1] = key[1] ^ sm4fk[1]
    k[2] = key[2] ^ sm4fk[2]
    k[3] = key[3] ^ sm4fk[3]

    for i := 0; i < 32; i++ {
        c.subkeys[i] = k[0] ^ sm4kt(k[1]^k[2]^k[3]^sm4ck[i])
        k[0] = k[1]
        k[1] = k[2]
        k[2] = k[3]
        k[3] = c.subkeys[i]
    }
}

func encryptBlock(subkeys []uint32, dst, src []byte) {
    cryptBlock(subkeys, dst, src, false)
}
func decryptBlock(subkeys []uint32, dst, src []byte) {
    cryptBlock(subkeys, dst, src, true)
}

func cryptBlock(subkeys []uint32, dst, src []byte, decrypt bool) {
    var m = make([]uint32, 4)
    var o = make([]uint32, 4)
    m[0] = (uint32(src[0]) << 24) | (uint32(src[1]) << 16) | (uint32(src[2]) << 8) | (uint32(src[3]))
    m[1] = (uint32(src[4]) << 24) | (uint32(src[5]) << 16) | (uint32(src[6]) << 8) | (uint32(src[7]))
    m[2] = (uint32(src[8]) << 24) | (uint32(src[9]) << 16) | (uint32(src[10]) << 8) | (uint32(src[11]))
    m[3] = (uint32(src[12]) << 24) | (uint32(src[13]) << 16) | (uint32(src[14]) << 8) | (uint32(src[15]))

    if decrypt {
        for j := 32; j > 0; j-- {
            tmp := sm4f(m[0], m[1], m[2], m[3], subkeys[j-1])
            m[0] = m[1]
            m[1] = m[2]
            m[2] = m[3]
            m[3] = tmp
        }
    } else {
        for j := 0; j < 32; j++ {
            tmp := sm4f(m[0], m[1], m[2], m[3], subkeys[j])
            m[0] = m[1]
            m[1] = m[2]
            m[2] = m[3]
            m[3] = tmp
        }
    }

    sm4r(o, m)

    for j := 0; j < 4; j++ {
        dst[j*4] = uint8((o[j] >> 24))
        dst[j*4+1] = uint8((o[j] >> 16))
        dst[j*4+2] = uint8((o[j] >> 8))
        dst[j*4+3] = uint8((o[j]))
    }
}

func sm4rotl(x uint32, i uint8) uint32 {
    return (x << (i % 32)) | (x >> (32 - (i % 32)))
}

func sm4tao(a uint32) uint32 {
    return sm4sbox[uint8(a)] | (sm4sbox[uint8(a>>8)] << 8) | (sm4sbox[uint8(a>>16)] << 16) | (sm4sbox[uint8(a>>24)] << 24)
}

func sm4l(b uint32) uint32 {
    return b ^ sm4rotl(b, 2) ^ sm4rotl(b, 10) ^ sm4rotl(b, 18) ^ sm4rotl(b, 24)
}

func sm4t(x uint32) uint32 {
    return sm4l(sm4tao(x))
}

func sm4f(x0, x1, x2, x3, rk uint32) uint32 {
    return x0 ^ sm4t(x1^x2^x3^rk)
}

func sm4r(o, i []uint32) {
    o[0] = i[3]
    o[1] = i[2]
    o[2] = i[1]
    o[3] = i[0]
}

func sm4kl(b uint32) uint32 {
    return b ^ sm4rotl(b, 13) ^ sm4rotl(b, 23)
}

func sm4kt(x uint32) uint32 {
    return sm4kl(sm4tao(x))
}

cipher.go

package sm4

import (
    "crypto/cipher"
    "strconv"
)

//BlockSize The SM4 block size in bytes.
const BlockSize = 16

// KeySizeError key error
type KeySizeError int

func (k KeySizeError) Error() string {
    return "sm4: invalid key size " + strconv.Itoa(int(k))
}

// sm4Cipher is an instance of SM4 encryption.
type sm4Cipher struct {
    subkeys [32]uint32
}

// NewCipher creates and returns a new cipher.Block.
func NewCipher(key []byte) (cipher.Block, error) {
    if len(key) != 16 {
        return nil, KeySizeError(len(key))
    }

    c := new(sm4Cipher)
    c.generateSubkeys(key)
    return c, nil
}

func (c *sm4Cipher) BlockSize() int {
    return BlockSize
}

func (c *sm4Cipher) Encrypt(dst, src []byte) {
    encryptBlock(c.subkeys[:], dst, src)
}

func (c *sm4Cipher) Decrypt(dst, src []byte) {
    decryptBlock(c.subkeys[:], dst, src)
}

const.go

package sm4

var sm4fk = [4]uint32{
    0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,
}

var sm4ck = [32]uint32{
    0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
    0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
    0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
    0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
    0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
    0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
    0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
    0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,
}

var sm4sbox = [256]uint32{
    0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
    0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
    0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
    0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
    0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
    0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
    0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
    0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
    0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
    0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
    0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
    0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
    0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
    0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
    0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
    0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
}

 

使用方法

//sm3 sm4 加解密示例
        hash := sm3.New()

        hash.Write([]byte("123456"))

        result := hash.Sum(nil)

        println("sm3 hash = ", hex.EncodeToString(result))

        a := []byte("123456")
        key := []byte("abc.123")
        decrypto := SM4Encrypt(a, key)
        fmt.Println("sm4加密后:", hex.EncodeToString(decrypto))
        i := SM4Decrypto(decrypto, key)
        fmt.Println("sm4解密后:", string(i))

补充获取 sm3 hmac 方法

 

secret := []byte("abc.123")
    message := []byte("123456")

    hash := hmac.New(sm3.New, secret)
    hash.Write(message)

    // to lowercase hexits

    fmt.Printf("sm3 hmac:%s\n", hex.EncodeToString(hash.Sum(nil)))

 

posted @ 2022-02-09 10:16  我是刹那、  阅读(3393)  评论(0编辑  收藏  举报