/// /// Copyright (c) 2018 xdx. All rights reserved. /// /// \file: cipher.go /// /// \brief: SM4's Block interface and its implements /// /// \author: xdx /// package sm4 import ( "crypto/cipher" "xdx.jelly/xgcl/gerrors" ) // BlockSize is the SM4 block size in bytes. const BlockSize = 16 // NewCipher creates and returns a new cipher.Block. // it call the newCipher of each platform func NewCipher(key []byte) (cipher.Block, error) { if len(key) < BlockSize { return nil, gerrors.WithAnnotatingf(ErrInvalidInput, "input key size is %d, want %d", len(key), BlockSize) } // newCipher is defined on different arch. return newCipher(key) } // newCipherGeneric creates and returns a new cipher.Block. func newCipherGeneric(key []byte) (cipher.Block, error) { cp := new(sm4Cipher) // gen keys expandKey(key, cp.encKey[:], cp.decKey[:]) return cp, nil } // sm4Cipher is an instance of cipher.Block interface type sm4Cipher struct { encKey [32]uint32 decKey [32]uint32 } // Clear implements the Clearable interface func (c *sm4Cipher) Clear() { for i := 0; i < len(c.decKey); i++ { c.decKey[i] = 0 c.encKey[i] = 0 } } func (c *sm4Cipher) BlockSize() int { return BlockSize } // 调用前应保证输入一个block func (c *sm4Cipher) Encrypt(dst, src []byte) { if len(src) < BlockSize { panic("xdx.jelly/xgcl/sm/sm4/Encrypt: input not full block") } if len(dst) < BlockSize { panic("xdx.jelly/xgcl/sm/sm4/Encrypt: output not full block") } encryptBlockGo(c.encKey[:], dst, src) } func (c *sm4Cipher) Decrypt(dst, src []byte) { if len(src) < BlockSize { panic("xdx.jelly/xgcl/sm/sm4/Decrypt: input not full block") } if len(dst) < BlockSize { panic("xdx.jelly/xgcl/sm/sm4/Decrypt: output not full block") } decryptBlockGo(c.decKey[:], dst, src) }