• golang sm3、sm4 加密


    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)))
  • 相关阅读:
    web页面静态化与伪静态化
    mysql 优化之空间换时间
    QPS、PV、UV、RT 之间的关系
    接口
    MySQL 索引
    名词解释
    go 语言标识符
    Git版本控制与工作流
    Maven安装与配置
    IDEA工具使用说明
  • 原文地址:https://www.cnblogs.com/wuyaxiansheng/p/15873902.html
Copyright © 2020-2023  润新知