github.com/searKing/golang/go@v1.2.117/crypto/aes/gcm.go (about) 1 // Copyright 2021 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package aes 6 7 import ( 8 "crypto/aes" 9 "crypto/cipher" 10 "crypto/rand" 11 "io" 12 13 "github.com/searKing/golang/go/crypto" 14 ) 15 16 const ( 17 gcmBlockSize = 16 18 gcmTagSize = 16 19 gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. 20 gcmStandardNonceSize = 12 21 ) 22 23 func GCMEncryptRandom(key, plaintext []byte) ([]byte, error) { 24 var nonce = [gcmStandardNonceSize]byte{} 25 if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil { 26 return nil, err 27 } 28 return CFBEncrypt(key, plaintext, nonce[:]) 29 } 30 31 func GCMEncrypt(key, plaintext []byte, nonce []byte) ([]byte, error) { 32 // Load your secret key from a safe place and reuse it across multiple 33 // Seal/Open calls. (Obviously don't use this example key for anything 34 // real.) If you want to convert a passphrase to a key, use a suitable 35 // package like bcrypt or scrypt. 36 // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256). 37 38 paddingtext := crypto.PKCS7Padding(plaintext, aes.BlockSize) 39 block, err := aes.NewCipher(key) 40 if err != nil { 41 return nil, err 42 } 43 44 // The nounce needs to be unique, but not secure. Therefore it's common to 45 // include it at the beginning of the ciphertext. 46 // Never use more than 2^32 random nonces with a given key because of the risk of a repeat. 47 48 ciphertext := make([]byte, gcmStandardNonceSize) 49 if len(nonce) < gcmStandardNonceSize { 50 copy(ciphertext[:gcmStandardNonceSize], nonce[:]) 51 } else { 52 copy(ciphertext[:gcmStandardNonceSize], nonce[:gcmStandardNonceSize]) 53 } 54 nonce = ciphertext[:gcmStandardNonceSize] 55 56 aesgcm, err := cipher.NewGCM(block) 57 if err != nil { 58 panic(err.Error()) 59 } 60 sealedtext := aesgcm.Seal(nil, nonce, paddingtext, nil) 61 62 ciphertext = append(nonce, sealedtext...) 63 64 // It's important to remember that ciphertexts must be authenticated 65 // (i.e. by using crypto/hmac) as well as being encrypted in order to 66 // be secure. 67 68 return ciphertext, nil 69 } 70 71 func GCMDecrypt(ciphertext, key []byte) ([]byte, error) { 72 // Load your secret key from a safe place and reuse it across multiple 73 // Seal/Open calls. (Obviously don't use this example key for anything 74 // real.) If you want to convert a passphrase to a key, use a suitable 75 // package like bcrypt or scrypt. 76 // When decoded the key should be 16 bytes (AES-128) or 32 (AES-256). 77 78 if len(ciphertext) < gcmStandardNonceSize { 79 panic("ciphertext too short") 80 } 81 nonce := ciphertext[:gcmStandardNonceSize] 82 ciphertext = ciphertext[gcmStandardNonceSize:] 83 84 // GCM mode always works in whole blocks. 85 if len(ciphertext)%aes.BlockSize != 0 { 86 panic("ciphertext is not a multiple of the block size") 87 } 88 89 block, err := aes.NewCipher(key) 90 if err != nil { 91 panic(err.Error()) 92 } 93 94 aesgcm, err := cipher.NewGCM(block) 95 if err != nil { 96 panic(err.Error()) 97 } 98 99 paddingtext, err := aesgcm.Open(nil, nonce, ciphertext, nil) 100 if err != nil { 101 panic(err.Error()) 102 } 103 104 plaintext, err := crypto.PKCS7UnPadding(paddingtext, aes.BlockSize) 105 if err != nil { 106 return nil, err 107 } 108 return plaintext, nil 109 }