refactor: 抽取symm通用加解密分发并统一hashx未知算法错误语义

This commit is contained in:
2026-03-18 14:32:55 +08:00
parent 4fa79744e8
commit 8d0f32015c
7 changed files with 341 additions and 564 deletions
+25 -243
View File
@@ -2,12 +2,10 @@ package symm
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io"
"b612.me/starcrypto/ccm"
"b612.me/starcrypto/paddingx"
)
@@ -28,306 +26,90 @@ const (
aeadCCMNonceSize = 12
)
func EncryptAes(data, key, iv []byte, mode, paddingType string) ([]byte, error) {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return EncryptAesGCM(data, key, iv, nil)
}
if normalizedMode == MODECCM {
return EncryptAesCCM(data, key, iv, nil)
}
var (
aesGCMFactory = newGCMFactory(aes.NewCipher)
aesCCMFactory = newCCMFactory(aes.NewCipher)
)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return encryptWithBlockMode(block, data, iv, normalizedMode, paddingType, PKCS7PADDING)
func EncryptAes(data, key, iv []byte, mode, paddingType string) ([]byte, error) {
return encryptBlockCipher(data, key, iv, mode, paddingType, PKCS7PADDING, aes.NewCipher, EncryptAesGCM, EncryptAesCCM)
}
func DecryptAes(src, key, iv []byte, mode, paddingType string) ([]byte, error) {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return DecryptAesGCM(src, key, iv, nil)
}
if normalizedMode == MODECCM {
return DecryptAesCCM(src, key, iv, nil)
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return decryptWithBlockMode(block, src, iv, normalizedMode, paddingType, PKCS7PADDING)
return decryptBlockCipher(src, key, iv, mode, paddingType, PKCS7PADDING, aes.NewCipher, DecryptAesGCM, DecryptAesCCM)
}
func EncryptAesStream(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType string) error {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return EncryptAesGCMStream(dst, src, key, iv, nil)
}
if normalizedMode == MODECCM {
return EncryptAesCCMStream(dst, src, key, iv, nil)
}
block, err := aes.NewCipher(key)
if err != nil {
return err
}
return encryptWithBlockModeStream(block, dst, src, iv, normalizedMode, paddingType, PKCS7PADDING)
return encryptBlockCipherStream(dst, src, key, iv, mode, paddingType, PKCS7PADDING, aes.NewCipher, EncryptAesGCMStream, EncryptAesCCMStream)
}
func DecryptAesStream(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType string) error {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return DecryptAesGCMStream(dst, src, key, iv, nil)
}
if normalizedMode == MODECCM {
return DecryptAesCCMStream(dst, src, key, iv, nil)
}
block, err := aes.NewCipher(key)
if err != nil {
return err
}
return decryptWithBlockModeStream(block, dst, src, iv, normalizedMode, paddingType, PKCS7PADDING)
return decryptBlockCipherStream(dst, src, key, iv, mode, paddingType, PKCS7PADDING, aes.NewCipher, DecryptAesGCMStream, DecryptAesCCMStream)
}
func EncryptAesWithOptions(data, key []byte, opts *CipherOptions) ([]byte, error) {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return EncryptAesGCM(data, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return EncryptAesCCM(data, key, nonceFromOptions(cfg), cfg.AAD)
}
return EncryptAes(data, key, cfg.IV, mode, cfg.Padding)
return encryptBlockWithOptions(data, key, opts, EncryptAesGCM, EncryptAesCCM, EncryptAes)
}
func DecryptAesWithOptions(src, key []byte, opts *CipherOptions) ([]byte, error) {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return DecryptAesGCM(src, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return DecryptAesCCM(src, key, nonceFromOptions(cfg), cfg.AAD)
}
return DecryptAes(src, key, cfg.IV, mode, cfg.Padding)
return decryptBlockWithOptions(src, key, opts, DecryptAesGCM, DecryptAesCCM, DecryptAes)
}
func EncryptAesStreamWithOptions(dst io.Writer, src io.Reader, key []byte, opts *CipherOptions) error {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return EncryptAesGCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return EncryptAesCCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
return EncryptAesStream(dst, src, key, cfg.IV, mode, cfg.Padding)
return encryptBlockStreamWithOptions(dst, src, key, opts, EncryptAesGCMStream, EncryptAesCCMStream, EncryptAesStream)
}
func DecryptAesStreamWithOptions(dst io.Writer, src io.Reader, key []byte, opts *CipherOptions) error {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return DecryptAesGCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return DecryptAesCCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
return DecryptAesStream(dst, src, key, cfg.IV, mode, cfg.Padding)
return decryptBlockStreamWithOptions(dst, src, key, opts, DecryptAesGCMStream, DecryptAesCCMStream, DecryptAesStream)
}
func EncryptAesGCM(plain, key, nonce, aad []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return gcm.Seal(nil, nonce, plain, aad), nil
return encryptAEAD(aesGCMFactory, plain, key, nonce, aad, ErrInvalidGCMNonceLength)
}
func DecryptAesGCM(ciphertext, key, nonce, aad []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return gcm.Open(nil, nonce, ciphertext, aad)
}
func newAesCCM(key []byte) (cipher.AEAD, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return ccm.NewCCM(block, aeadCCMTagSize, aeadCCMNonceSize)
return decryptAEAD(aesGCMFactory, ciphertext, key, nonce, aad, ErrInvalidGCMNonceLength)
}
func EncryptAesCCM(plain, key, nonce, aad []byte) ([]byte, error) {
aead, err := newAesCCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return aead.Seal(nil, nonce, plain, aad), nil
return encryptAEAD(aesCCMFactory, plain, key, nonce, aad, ErrInvalidCCMNonceLength)
}
func DecryptAesCCM(ciphertext, key, nonce, aad []byte) ([]byte, error) {
aead, err := newAesCCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return aead.Open(nil, nonce, ciphertext, aad)
return decryptAEAD(aesCCMFactory, ciphertext, key, nonce, aad, ErrInvalidCCMNonceLength)
}
func EncryptAesCCMChunk(plain, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
aead, err := newAesCCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return encryptCCMChunk(aead, plain, nonce, aad, chunkIndex), nil
return encryptAEADChunk(aesCCMFactory, plain, key, nonce, aad, chunkIndex, ErrInvalidCCMNonceLength, encryptCCMChunk)
}
func DecryptAesCCMChunk(ciphertext, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
aead, err := newAesCCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return decryptCCMChunk(aead, ciphertext, nonce, aad, chunkIndex)
return decryptAEADChunk(aesCCMFactory, ciphertext, key, nonce, aad, chunkIndex, ErrInvalidCCMNonceLength, decryptCCMChunk)
}
func EncryptAesCCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
aead, err := newAesCCM(key)
if err != nil {
return err
}
if len(nonce) != aead.NonceSize() {
return ErrInvalidCCMNonceLength
}
return encryptCCMChunkedStream(dst, src, aead, nonce, aad)
return encryptAEADStream(aesCCMFactory, dst, src, key, nonce, aad, ErrInvalidCCMNonceLength, encryptCCMChunkedStream)
}
func DecryptAesCCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
aead, err := newAesCCM(key)
if err != nil {
return err
}
if len(nonce) != aead.NonceSize() {
return ErrInvalidCCMNonceLength
}
return decryptCCMChunkedOrLegacyStream(dst, src, aead, nonce, aad)
return decryptAEADStream(aesCCMFactory, dst, src, key, nonce, aad, ErrInvalidCCMNonceLength, decryptCCMChunkedOrLegacyStream)
}
func EncryptAesGCMChunk(plain, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return encryptGCMChunk(gcm, plain, nonce, aad, chunkIndex), nil
return encryptAEADChunk(aesGCMFactory, plain, key, nonce, aad, chunkIndex, ErrInvalidGCMNonceLength, encryptGCMChunk)
}
func DecryptAesGCMChunk(ciphertext, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return decryptGCMChunk(gcm, ciphertext, nonce, aad, chunkIndex)
return decryptAEADChunk(aesGCMFactory, ciphertext, key, nonce, aad, chunkIndex, ErrInvalidGCMNonceLength, decryptGCMChunk)
}
func EncryptAesGCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
block, err := aes.NewCipher(key)
if err != nil {
return err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return err
}
if len(nonce) != gcm.NonceSize() {
return ErrInvalidGCMNonceLength
}
return encryptGCMChunkedStream(dst, src, gcm, nonce, aad)
return encryptAEADStream(aesGCMFactory, dst, src, key, nonce, aad, ErrInvalidGCMNonceLength, encryptGCMChunkedStream)
}
func DecryptAesGCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
block, err := aes.NewCipher(key)
if err != nil {
return err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return err
}
if len(nonce) != gcm.NonceSize() {
return ErrInvalidGCMNonceLength
}
return decryptGCMChunkedOrLegacyStream(dst, src, gcm, nonce, aad)
return decryptAEADStream(aesGCMFactory, dst, src, key, nonce, aad, ErrInvalidGCMNonceLength, decryptGCMChunkedOrLegacyStream)
}
func EncryptAesECB(data, key []byte, paddingType string) ([]byte, error) {
return EncryptAes(data, key, nil, MODEECB, paddingType)
}
+223
View File
@@ -0,0 +1,223 @@
package symm
import (
"crypto/cipher"
"io"
"b612.me/starcrypto/ccm"
)
type blockCipherFactory func(key []byte) (cipher.Block, error)
type aeadFactory func(key []byte) (cipher.AEAD, error)
type aeadBytesFunc func(data, key, nonce, aad []byte) ([]byte, error)
type aeadStreamFunc func(dst io.Writer, src io.Reader, key, nonce, aad []byte) error
type blockModeBytesFunc func(data, key, iv []byte, mode, paddingType string) ([]byte, error)
type blockModeStreamFunc func(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType string) error
type aeadChunkEncryptFunc func(aead cipher.AEAD, plain, nonce, aad []byte, chunkIndex uint64) []byte
type aeadChunkDecryptFunc func(aead cipher.AEAD, ciphertext, nonce, aad []byte, chunkIndex uint64) ([]byte, error)
type aeadStreamCodec func(dst io.Writer, src io.Reader, aead cipher.AEAD, nonce, aad []byte) error
func newGCMFactory(newBlock blockCipherFactory) aeadFactory {
return func(key []byte) (cipher.AEAD, error) {
block, err := newBlock(key)
if err != nil {
return nil, err
}
return cipher.NewGCM(block)
}
}
func newCCMFactory(newBlock blockCipherFactory) aeadFactory {
return func(key []byte) (cipher.AEAD, error) {
block, err := newBlock(key)
if err != nil {
return nil, err
}
return ccm.NewCCM(block, aeadCCMTagSize, aeadCCMNonceSize)
}
}
func normalizeModeOrDefaultAEAD(mode string) string {
mode = normalizeCipherMode(mode)
if mode == "" {
mode = MODEGCM
}
return mode
}
func encryptBlockCipher(data, key, iv []byte, mode, paddingType, defaultPadding string, newBlock blockCipherFactory, encryptGCM, encryptCCM aeadBytesFunc) ([]byte, error) {
mode = normalizeModeOrDefaultAEAD(mode)
switch mode {
case MODEGCM:
return encryptGCM(data, key, iv, nil)
case MODECCM:
return encryptCCM(data, key, iv, nil)
default:
block, err := newBlock(key)
if err != nil {
return nil, err
}
return encryptWithBlockMode(block, data, iv, mode, paddingType, defaultPadding)
}
}
func decryptBlockCipher(src, key, iv []byte, mode, paddingType, defaultPadding string, newBlock blockCipherFactory, decryptGCM, decryptCCM aeadBytesFunc) ([]byte, error) {
mode = normalizeModeOrDefaultAEAD(mode)
switch mode {
case MODEGCM:
return decryptGCM(src, key, iv, nil)
case MODECCM:
return decryptCCM(src, key, iv, nil)
default:
block, err := newBlock(key)
if err != nil {
return nil, err
}
return decryptWithBlockMode(block, src, iv, mode, paddingType, defaultPadding)
}
}
func encryptBlockCipherStream(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType, defaultPadding string, newBlock blockCipherFactory, encryptGCMStream, encryptCCMStream aeadStreamFunc) error {
mode = normalizeModeOrDefaultAEAD(mode)
switch mode {
case MODEGCM:
return encryptGCMStream(dst, src, key, iv, nil)
case MODECCM:
return encryptCCMStream(dst, src, key, iv, nil)
default:
block, err := newBlock(key)
if err != nil {
return err
}
return encryptWithBlockModeStream(block, dst, src, iv, mode, paddingType, defaultPadding)
}
}
func decryptBlockCipherStream(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType, defaultPadding string, newBlock blockCipherFactory, decryptGCMStream, decryptCCMStream aeadStreamFunc) error {
mode = normalizeModeOrDefaultAEAD(mode)
switch mode {
case MODEGCM:
return decryptGCMStream(dst, src, key, iv, nil)
case MODECCM:
return decryptCCMStream(dst, src, key, iv, nil)
default:
block, err := newBlock(key)
if err != nil {
return err
}
return decryptWithBlockModeStream(block, dst, src, iv, mode, paddingType, defaultPadding)
}
}
func encryptBlockWithOptions(data, key []byte, opts *CipherOptions, encryptGCM, encryptCCM aeadBytesFunc, encryptBlock blockModeBytesFunc) ([]byte, error) {
cfg := normalizeCipherOptions(opts)
mode := normalizeModeOrDefaultAEAD(cfg.Mode)
switch mode {
case MODEGCM:
return encryptGCM(data, key, nonceFromOptions(cfg), cfg.AAD)
case MODECCM:
return encryptCCM(data, key, nonceFromOptions(cfg), cfg.AAD)
default:
return encryptBlock(data, key, cfg.IV, mode, cfg.Padding)
}
}
func decryptBlockWithOptions(data, key []byte, opts *CipherOptions, decryptGCM, decryptCCM aeadBytesFunc, decryptBlock blockModeBytesFunc) ([]byte, error) {
cfg := normalizeCipherOptions(opts)
mode := normalizeModeOrDefaultAEAD(cfg.Mode)
switch mode {
case MODEGCM:
return decryptGCM(data, key, nonceFromOptions(cfg), cfg.AAD)
case MODECCM:
return decryptCCM(data, key, nonceFromOptions(cfg), cfg.AAD)
default:
return decryptBlock(data, key, cfg.IV, mode, cfg.Padding)
}
}
func encryptBlockStreamWithOptions(dst io.Writer, src io.Reader, key []byte, opts *CipherOptions, encryptGCM, encryptCCM aeadStreamFunc, encryptBlockStream blockModeStreamFunc) error {
cfg := normalizeCipherOptions(opts)
mode := normalizeModeOrDefaultAEAD(cfg.Mode)
switch mode {
case MODEGCM:
return encryptGCM(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
case MODECCM:
return encryptCCM(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
default:
return encryptBlockStream(dst, src, key, cfg.IV, mode, cfg.Padding)
}
}
func decryptBlockStreamWithOptions(dst io.Writer, src io.Reader, key []byte, opts *CipherOptions, decryptGCM, decryptCCM aeadStreamFunc, decryptBlockStream blockModeStreamFunc) error {
cfg := normalizeCipherOptions(opts)
mode := normalizeModeOrDefaultAEAD(cfg.Mode)
switch mode {
case MODEGCM:
return decryptGCM(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
case MODECCM:
return decryptCCM(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
default:
return decryptBlockStream(dst, src, key, cfg.IV, mode, cfg.Padding)
}
}
func buildAEAD(factory aeadFactory, key, nonce []byte, errInvalidNonce error) (cipher.AEAD, error) {
aead, err := factory(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, errInvalidNonce
}
return aead, nil
}
func encryptAEAD(factory aeadFactory, plain, key, nonce, aad []byte, errInvalidNonce error) ([]byte, error) {
aead, err := buildAEAD(factory, key, nonce, errInvalidNonce)
if err != nil {
return nil, err
}
return aead.Seal(nil, nonce, plain, aad), nil
}
func decryptAEAD(factory aeadFactory, ciphertext, key, nonce, aad []byte, errInvalidNonce error) ([]byte, error) {
aead, err := buildAEAD(factory, key, nonce, errInvalidNonce)
if err != nil {
return nil, err
}
return aead.Open(nil, nonce, ciphertext, aad)
}
func encryptAEADChunk(factory aeadFactory, plain, key, nonce, aad []byte, chunkIndex uint64, errInvalidNonce error, encryptChunk aeadChunkEncryptFunc) ([]byte, error) {
aead, err := buildAEAD(factory, key, nonce, errInvalidNonce)
if err != nil {
return nil, err
}
return encryptChunk(aead, plain, nonce, aad, chunkIndex), nil
}
func decryptAEADChunk(factory aeadFactory, ciphertext, key, nonce, aad []byte, chunkIndex uint64, errInvalidNonce error, decryptChunk aeadChunkDecryptFunc) ([]byte, error) {
aead, err := buildAEAD(factory, key, nonce, errInvalidNonce)
if err != nil {
return nil, err
}
return decryptChunk(aead, ciphertext, nonce, aad, chunkIndex)
}
func encryptAEADStream(factory aeadFactory, dst io.Writer, src io.Reader, key, nonce, aad []byte, errInvalidNonce error, encryptStream aeadStreamCodec) error {
aead, err := buildAEAD(factory, key, nonce, errInvalidNonce)
if err != nil {
return err
}
return encryptStream(dst, src, aead, nonce, aad)
}
func decryptAEADStream(factory aeadFactory, dst io.Writer, src io.Reader, key, nonce, aad []byte, errInvalidNonce error, decryptStream aeadStreamCodec) error {
aead, err := buildAEAD(factory, key, nonce, errInvalidNonce)
if err != nil {
return err
}
return decryptStream(dst, src, aead, nonce, aad)
}
+25 -243
View File
@@ -1,315 +1,97 @@
package symm
import (
"crypto/cipher"
"crypto/rand"
"errors"
"io"
"b612.me/starcrypto/ccm"
"github.com/emmansun/gmsm/sm4"
)
func EncryptSM4(data, key, iv []byte, mode, paddingType string) ([]byte, error) {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return EncryptSM4GCM(data, key, iv, nil)
}
if normalizedMode == MODECCM {
return EncryptSM4CCM(data, key, iv, nil)
}
var (
sm4GCMFactory = newGCMFactory(sm4.NewCipher)
sm4CCMFactory = newCCMFactory(sm4.NewCipher)
)
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
return encryptWithBlockMode(block, data, iv, normalizedMode, paddingType, PKCS7PADDING)
func EncryptSM4(data, key, iv []byte, mode, paddingType string) ([]byte, error) {
return encryptBlockCipher(data, key, iv, mode, paddingType, PKCS7PADDING, sm4.NewCipher, EncryptSM4GCM, EncryptSM4CCM)
}
func DecryptSM4(src, key, iv []byte, mode, paddingType string) ([]byte, error) {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return DecryptSM4GCM(src, key, iv, nil)
}
if normalizedMode == MODECCM {
return DecryptSM4CCM(src, key, iv, nil)
}
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
return decryptWithBlockMode(block, src, iv, normalizedMode, paddingType, PKCS7PADDING)
return decryptBlockCipher(src, key, iv, mode, paddingType, PKCS7PADDING, sm4.NewCipher, DecryptSM4GCM, DecryptSM4CCM)
}
func EncryptSM4Stream(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType string) error {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return EncryptSM4GCMStream(dst, src, key, iv, nil)
}
if normalizedMode == MODECCM {
return EncryptSM4CCMStream(dst, src, key, iv, nil)
}
block, err := sm4.NewCipher(key)
if err != nil {
return err
}
return encryptWithBlockModeStream(block, dst, src, iv, normalizedMode, paddingType, PKCS7PADDING)
return encryptBlockCipherStream(dst, src, key, iv, mode, paddingType, PKCS7PADDING, sm4.NewCipher, EncryptSM4GCMStream, EncryptSM4CCMStream)
}
func DecryptSM4Stream(dst io.Writer, src io.Reader, key, iv []byte, mode, paddingType string) error {
normalizedMode := normalizeCipherMode(mode)
if normalizedMode == "" {
normalizedMode = MODEGCM
}
if normalizedMode == MODEGCM {
return DecryptSM4GCMStream(dst, src, key, iv, nil)
}
if normalizedMode == MODECCM {
return DecryptSM4CCMStream(dst, src, key, iv, nil)
}
block, err := sm4.NewCipher(key)
if err != nil {
return err
}
return decryptWithBlockModeStream(block, dst, src, iv, normalizedMode, paddingType, PKCS7PADDING)
return decryptBlockCipherStream(dst, src, key, iv, mode, paddingType, PKCS7PADDING, sm4.NewCipher, DecryptSM4GCMStream, DecryptSM4CCMStream)
}
func EncryptSM4WithOptions(data, key []byte, opts *CipherOptions) ([]byte, error) {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return EncryptSM4GCM(data, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return EncryptSM4CCM(data, key, nonceFromOptions(cfg), cfg.AAD)
}
return EncryptSM4(data, key, cfg.IV, mode, cfg.Padding)
return encryptBlockWithOptions(data, key, opts, EncryptSM4GCM, EncryptSM4CCM, EncryptSM4)
}
func DecryptSM4WithOptions(src, key []byte, opts *CipherOptions) ([]byte, error) {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return DecryptSM4GCM(src, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return DecryptSM4CCM(src, key, nonceFromOptions(cfg), cfg.AAD)
}
return DecryptSM4(src, key, cfg.IV, mode, cfg.Padding)
return decryptBlockWithOptions(src, key, opts, DecryptSM4GCM, DecryptSM4CCM, DecryptSM4)
}
func EncryptSM4StreamWithOptions(dst io.Writer, src io.Reader, key []byte, opts *CipherOptions) error {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return EncryptSM4GCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return EncryptSM4CCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
return EncryptSM4Stream(dst, src, key, cfg.IV, mode, cfg.Padding)
return encryptBlockStreamWithOptions(dst, src, key, opts, EncryptSM4GCMStream, EncryptSM4CCMStream, EncryptSM4Stream)
}
func DecryptSM4StreamWithOptions(dst io.Writer, src io.Reader, key []byte, opts *CipherOptions) error {
cfg := normalizeCipherOptions(opts)
mode := normalizeCipherMode(cfg.Mode)
if mode == "" {
mode = MODEGCM
}
if mode == MODEGCM {
return DecryptSM4GCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
if mode == MODECCM {
return DecryptSM4CCMStream(dst, src, key, nonceFromOptions(cfg), cfg.AAD)
}
return DecryptSM4Stream(dst, src, key, cfg.IV, mode, cfg.Padding)
return decryptBlockStreamWithOptions(dst, src, key, opts, DecryptSM4GCMStream, DecryptSM4CCMStream, DecryptSM4Stream)
}
func EncryptSM4GCM(plain, key, nonce, aad []byte) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return gcm.Seal(nil, nonce, plain, aad), nil
return encryptAEAD(sm4GCMFactory, plain, key, nonce, aad, ErrInvalidGCMNonceLength)
}
func DecryptSM4GCM(ciphertext, key, nonce, aad []byte) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return gcm.Open(nil, nonce, ciphertext, aad)
return decryptAEAD(sm4GCMFactory, ciphertext, key, nonce, aad, ErrInvalidGCMNonceLength)
}
func EncryptSM4GCMChunk(plain, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return encryptGCMChunk(gcm, plain, nonce, aad, chunkIndex), nil
return encryptAEADChunk(sm4GCMFactory, plain, key, nonce, aad, chunkIndex, ErrInvalidGCMNonceLength, encryptGCMChunk)
}
func DecryptSM4GCMChunk(ciphertext, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
if len(nonce) != gcm.NonceSize() {
return nil, ErrInvalidGCMNonceLength
}
return decryptGCMChunk(gcm, ciphertext, nonce, aad, chunkIndex)
return decryptAEADChunk(sm4GCMFactory, ciphertext, key, nonce, aad, chunkIndex, ErrInvalidGCMNonceLength, decryptGCMChunk)
}
func EncryptSM4GCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
block, err := sm4.NewCipher(key)
if err != nil {
return err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return err
}
if len(nonce) != gcm.NonceSize() {
return ErrInvalidGCMNonceLength
}
return encryptGCMChunkedStream(dst, src, gcm, nonce, aad)
return encryptAEADStream(sm4GCMFactory, dst, src, key, nonce, aad, ErrInvalidGCMNonceLength, encryptGCMChunkedStream)
}
func DecryptSM4GCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
block, err := sm4.NewCipher(key)
if err != nil {
return err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return err
}
if len(nonce) != gcm.NonceSize() {
return ErrInvalidGCMNonceLength
}
return decryptGCMChunkedOrLegacyStream(dst, src, gcm, nonce, aad)
}
func newSM4CCM(key []byte) (cipher.AEAD, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
return ccm.NewCCM(block, aeadCCMTagSize, aeadCCMNonceSize)
return decryptAEADStream(sm4GCMFactory, dst, src, key, nonce, aad, ErrInvalidGCMNonceLength, decryptGCMChunkedOrLegacyStream)
}
func EncryptSM4CCM(plain, key, nonce, aad []byte) ([]byte, error) {
aead, err := newSM4CCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return aead.Seal(nil, nonce, plain, aad), nil
return encryptAEAD(sm4CCMFactory, plain, key, nonce, aad, ErrInvalidCCMNonceLength)
}
func DecryptSM4CCM(ciphertext, key, nonce, aad []byte) ([]byte, error) {
aead, err := newSM4CCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return aead.Open(nil, nonce, ciphertext, aad)
return decryptAEAD(sm4CCMFactory, ciphertext, key, nonce, aad, ErrInvalidCCMNonceLength)
}
func EncryptSM4CCMChunk(plain, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
aead, err := newSM4CCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return encryptCCMChunk(aead, plain, nonce, aad, chunkIndex), nil
return encryptAEADChunk(sm4CCMFactory, plain, key, nonce, aad, chunkIndex, ErrInvalidCCMNonceLength, encryptCCMChunk)
}
func DecryptSM4CCMChunk(ciphertext, key, nonce, aad []byte, chunkIndex uint64) ([]byte, error) {
aead, err := newSM4CCM(key)
if err != nil {
return nil, err
}
if len(nonce) != aead.NonceSize() {
return nil, ErrInvalidCCMNonceLength
}
return decryptCCMChunk(aead, ciphertext, nonce, aad, chunkIndex)
return decryptAEADChunk(sm4CCMFactory, ciphertext, key, nonce, aad, chunkIndex, ErrInvalidCCMNonceLength, decryptCCMChunk)
}
func EncryptSM4CCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
aead, err := newSM4CCM(key)
if err != nil {
return err
}
if len(nonce) != aead.NonceSize() {
return ErrInvalidCCMNonceLength
}
return encryptCCMChunkedStream(dst, src, aead, nonce, aad)
return encryptAEADStream(sm4CCMFactory, dst, src, key, nonce, aad, ErrInvalidCCMNonceLength, encryptCCMChunkedStream)
}
func DecryptSM4CCMStream(dst io.Writer, src io.Reader, key, nonce, aad []byte) error {
aead, err := newSM4CCM(key)
if err != nil {
return err
}
if len(nonce) != aead.NonceSize() {
return ErrInvalidCCMNonceLength
}
return decryptCCMChunkedOrLegacyStream(dst, src, aead, nonce, aad)
return decryptAEADStream(sm4CCMFactory, dst, src, key, nonce, aad, ErrInvalidCCMNonceLength, decryptCCMChunkedOrLegacyStream)
}
func EncryptSM4CFB(origData, key []byte) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {