github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric/bccsp/sw/sm4.go (about)

     1  package sw
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/cipher"
     6  	"crypto/rand"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  
    11  	"github.com/hellobchain/third_party/hyperledger/fabric/bccsp"
    12  	"github.com/hellobchain/newcryptosm/sm4"
    13  )
    14  
    15  // GetRandomBytes returns len random looking bytes
    16  func GetSM4RandomBytes(len int) ([]byte, error) {
    17  	if len < 0 {
    18  		return nil, errors.New("Len must be larger than 0")
    19  	}
    20  
    21  	buffer := make([]byte, len)
    22  
    23  	n, err := rand.Read(buffer)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	if n != len {
    28  		return nil, fmt.Errorf("Buffer not filled. Requested [%d], got [%d]", len, n)
    29  	}
    30  
    31  	return buffer, nil
    32  }
    33  
    34  func sm4Pkcs7Padding(src []byte) []byte {
    35  	padding := sm4.BlockSize - len(src)%sm4.BlockSize
    36  	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    37  	return append(src, padtext...)
    38  }
    39  
    40  func sm4Pkcs7UnPadding(src []byte) ([]byte, error) {
    41  	length := len(src)
    42  	unpadding := int(src[length-1])
    43  
    44  	if unpadding > sm4.BlockSize || unpadding == 0 {
    45  		return nil, errors.New("Invalid pkcs7 padding (unpadding > sm4.BlockSize || unpadding == 0)")
    46  	}
    47  
    48  	pad := src[len(src)-unpadding:]
    49  	for i := 0; i < unpadding; i++ {
    50  		if pad[i] != byte(unpadding) {
    51  			return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)")
    52  		}
    53  	}
    54  
    55  	return src[:(length - unpadding)], nil
    56  }
    57  
    58  func sm4CBCEncrypt(key, s []byte) ([]byte, error) {
    59  	if len(s)%sm4.BlockSize != 0 {
    60  		return nil, errors.New("Invalid plaintext. It must be a multiple of the block size")
    61  	}
    62  
    63  	block, err := sm4.NewCipher(key)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	ciphertext := make([]byte, sm4.BlockSize+len(s))
    69  	iv := ciphertext[:sm4.BlockSize]
    70  	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	mode := cipher.NewCBCEncrypter(block, iv)
    75  	mode.CryptBlocks(ciphertext[sm4.BlockSize:], s)
    76  
    77  	return ciphertext, nil
    78  }
    79  
    80  func sm4CBCDecrypt(key, src []byte) ([]byte, error) {
    81  	block, err := sm4.NewCipher(key)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	if len(src) < sm4.BlockSize {
    87  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
    88  	}
    89  	iv := src[:sm4.BlockSize]
    90  	src = src[sm4.BlockSize:]
    91  
    92  	if len(src)%sm4.BlockSize != 0 {
    93  		return nil, errors.New("Invalid ciphertext. It must be a multiple of the block size")
    94  	}
    95  
    96  	mode := cipher.NewCBCDecrypter(block, iv)
    97  
    98  	mode.CryptBlocks(src, src)
    99  
   100  	return src, nil
   101  }
   102  
   103  // SM4CBCPKCS7Encrypt combines CBC encryption and PKCS7 padding
   104  func SM4CBCPKCS7Encrypt(key, src []byte) ([]byte, error) {
   105  	// First pad
   106  	tmp := sm4Pkcs7Padding(src)
   107  
   108  	// Then encrypt
   109  	return sm4CBCEncrypt(key, tmp)
   110  }
   111  
   112  // SM4CBCPKCS7Decrypt combines CBC decryption and PKCS7 unpadding
   113  func SM4CBCPKCS7Decrypt(key, src []byte) ([]byte, error) {
   114  	// First decrypt
   115  	pt, err := sm4CBCDecrypt(key, src)
   116  	if err == nil {
   117  		return sm4Pkcs7UnPadding(pt)
   118  	}
   119  	return nil, err
   120  }
   121  
   122  type sm4cbcpkcs7Encryptor struct{}
   123  
   124  func (*sm4cbcpkcs7Encryptor) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) {
   125  	// switch opts.(type) {
   126  	// case *bccsp.SM4CBCPKCS7ModeOpts, bccsp.SM4CBCPKCS7ModeOpts:
   127  	// 	// SM4 in CBC mode with PKCS7 padding
   128  	// 	return SM4CBCPKCS7Encrypt(k.(*sm4PrivateKey).privKey, plaintext)
   129  	// default:
   130  	// 	return nil, fmt.Errorf("Mode not recognized [%s]", opts)
   131  	// }
   132  	return SM4CBCPKCS7Encrypt(k.(*symmetryPrivateKey).privKey, plaintext)
   133  }
   134  
   135  type sm4cbcpkcs7Decryptor struct{}
   136  
   137  func (*sm4cbcpkcs7Decryptor) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) {
   138  	// check for mode
   139  	// switch opts.(type) {
   140  	// case *bccsp.SM4CBCPKCS7ModeOpts, bccsp.SM4CBCPKCS7ModeOpts:
   141  	// 	// SM4 in CBC mode with PKCS7 padding
   142  	// 	return SM4CBCPKCS7Decrypt(k.(*sm4PrivateKey).privKey, ciphertext)
   143  	// default:
   144  	// 	return nil, fmt.Errorf("Mode not recognized [%s]", opts)
   145  	// }
   146  	return SM4CBCPKCS7Decrypt(k.(*symmetryPrivateKey).privKey, ciphertext)
   147  }