gitee.com/lh-her-team/common@v1.5.1/crypto/sym/aes/aes.go (about) 1 package aes 2 3 import ( 4 "crypto/aes" 5 "crypto/cipher" 6 "crypto/rand" 7 "encoding/asn1" 8 "encoding/hex" 9 "fmt" 10 11 "gitee.com/lh-her-team/common/crypto" 12 "gitee.com/lh-her-team/common/crypto/sym/modes" 13 "gitee.com/lh-her-team/common/crypto/sym/util" 14 ) 15 16 const ( 17 AES_GCM_IV_LENGTH = 12 18 AES_GCM_TAG_LENGTH = 16 19 ) 20 21 var defaultAESOpts = &crypto.EncOpts{ 22 EncodingType: modes.PADDING_NONE, 23 BlockMode: modes.BLOCK_MODE_GCM, 24 EnableMAC: true, 25 Hash: 0, 26 Label: nil, 27 EnableASN1: true, 28 } 29 30 type AESKey struct { 31 Key []byte 32 } 33 34 type aesCiphertext struct { 35 IV []byte 36 Ciphertext []byte 37 Tag []byte 38 } 39 40 func (aesKey *AESKey) Bytes() ([]byte, error) { 41 return aesKey.Key, nil 42 } 43 44 func (aesKey *AESKey) String() (string, error) { 45 return hex.EncodeToString(aesKey.Key), nil 46 } 47 48 /* 49 The ciphertext returned by Encrypt() and EncryptWithOpts can be ASN1 encoded, 50 or of the form: 51 nonce + ciphertext + tag (can be nil) 52 */ 53 func (aesKey *AESKey) Encrypt(plain []byte) ([]byte, error) { 54 return aesKey.EncryptWithOpts(plain, defaultAESOpts) 55 } 56 57 func (aesKey *AESKey) EncryptWithOpts(plain []byte, opts *crypto.EncOpts) ([]byte, error) { 58 block, err := aes.NewCipher(aesKey.Key) 59 if err != nil { 60 return nil, fmt.Errorf("AES encryption fails: %v", err) 61 } 62 var ciphertext aesCiphertext 63 switch opts.BlockMode { 64 case modes.BLOCK_MODE_CBC: 65 var msg []byte 66 switch opts.EncodingType { 67 case modes.PADDING_PKCS5: 68 msg = util.PKCS5Padding(plain, block.BlockSize()) 69 default: 70 return nil, fmt.Errorf("AES CBC encryption fails: invalid padding scheme [%s]", opts.EncodingType) 71 } 72 ciphertext.IV = make([]byte, block.BlockSize()) 73 if _, err := rand.Read(ciphertext.IV); err != nil { 74 return nil, fmt.Errorf("AES CBC encryption fails: %v", err) 75 } 76 blockMode := cipher.NewCBCEncrypter(block, ciphertext.IV) 77 ciphertext.Ciphertext = make([]byte, len(msg)) 78 blockMode.CryptBlocks(ciphertext.Ciphertext[0:], msg) 79 ciphertext.Tag = nil 80 case modes.BLOCK_MODE_GCM: 81 gcmMode, err := cipher.NewGCM(block) 82 if err != nil { 83 return nil, fmt.Errorf("AES GCM encryption fails: %v", err) 84 } 85 ivLength := gcmMode.NonceSize() 86 ciphertext.IV = make([]byte, ivLength) 87 if _, err := rand.Read(ciphertext.IV); err != nil { 88 return nil, fmt.Errorf("AES GCM encryption fails: %v", err) 89 } 90 cipherWithTag := gcmMode.Seal(nil, ciphertext.IV, plain, nil) 91 tagLength := gcmMode.Overhead() 92 ciphertext.Ciphertext = cipherWithTag[0 : len(cipherWithTag)-tagLength] 93 ciphertext.Tag = cipherWithTag[len(cipherWithTag)-tagLength:] 94 default: 95 return nil, fmt.Errorf("AES encryption fails: unknown cipher block mode [%s]", opts.BlockMode) 96 } 97 if opts.EnableASN1 { 98 return asn1.Marshal(ciphertext) 99 } 100 ret := append(ciphertext.IV, ciphertext.Ciphertext...) 101 ret = append(ret, ciphertext.Tag...) 102 return ret, nil 103 } 104 105 /* 106 The input ciphertext can be ASN1 encoded, 107 or of the form: 108 nonce + ciphertext + tag (can be nil) 109 */ 110 func (aesKey *AESKey) Decrypt(crypted []byte) ([]byte, error) { 111 return aesKey.DecryptWithOpts(crypted, defaultAESOpts) 112 } 113 114 func (aesKey *AESKey) DecryptWithOpts(crypted []byte, opts *crypto.EncOpts) ([]byte, error) { 115 var ciphertext aesCiphertext 116 if opts.EnableASN1 { 117 _, err := asn1.Unmarshal(crypted, &ciphertext) 118 if err != nil { 119 return nil, fmt.Errorf("AES decryption fails: %v", err) 120 } 121 } 122 block, err := aes.NewCipher(aesKey.Key) 123 if err != nil { 124 return nil, fmt.Errorf("AES decryption fails: %v", err) 125 } 126 switch opts.BlockMode { 127 case modes.BLOCK_MODE_CBC: 128 if !opts.EnableASN1 { 129 ciphertext.IV = crypted[0:block.BlockSize()] 130 ciphertext.Ciphertext = crypted[block.BlockSize():] 131 ciphertext.Tag = nil 132 } 133 blockMode := cipher.NewCBCDecrypter(block, ciphertext.IV) 134 orig := make([]byte, len(ciphertext.Ciphertext)) 135 blockMode.CryptBlocks(orig, ciphertext.Ciphertext) 136 switch opts.EncodingType { 137 case modes.PADDING_PKCS5: 138 orig, err = util.PKCS5UnPadding(orig) 139 if err != nil { 140 return nil, fmt.Errorf("AES CBC decryption fails: %v", err) 141 } 142 return orig, nil 143 default: 144 return nil, fmt.Errorf("AES CBC decryption fails: invalid padding scheme [%s]", opts.EncodingType) 145 } 146 case modes.BLOCK_MODE_GCM: 147 gcmMode, err := cipher.NewGCM(block) 148 if err != nil { 149 return nil, fmt.Errorf("AES GCM decryption fails: %v", err) 150 } 151 if !opts.EnableASN1 { 152 ciphertext.IV = crypted[0:gcmMode.NonceSize()] 153 ciphertext.Ciphertext = crypted[gcmMode.NonceSize() : len(crypted)-gcmMode.Overhead()] 154 ciphertext.Tag = crypted[len(crypted)-gcmMode.Overhead():] 155 } 156 cipherWithTag := append(ciphertext.Ciphertext, ciphertext.Tag...) 157 return gcmMode.Open(nil, ciphertext.IV, cipherWithTag, nil) 158 default: 159 return nil, fmt.Errorf("AES decryption fails: unknown cipher block mode [%s]", opts.BlockMode) 160 } 161 } 162 163 func (aesKey *AESKey) Type() crypto.KeyType { 164 return crypto.AES 165 }