git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/crypto/aead.go (about) 1 package crypto 2 3 import ( 4 "crypto/aes" 5 "crypto/cipher" 6 "errors" 7 ) 8 9 const ( 10 // AEADKeySize is the size of the key used by this AEAD, in bytes. 11 AEADKeySize = KeySize256 12 13 // AEADNonceSize is the size of the nonce used with the AES-256-GCM 14 // variant of this AEAD, in bytes. 15 AEADNonceSize = 12 16 ) 17 18 // NewAEADKey generates a new random secret key. 19 func NewAEADKey() ([]byte, error) { 20 return RandBytes(AEADKeySize) 21 } 22 23 // NewAEADNonce generates a new random nonce. 24 func NewAEADNonce() ([]byte, error) { 25 return RandBytes(AEADNonceSize) 26 } 27 28 // NewAEAD returns a AES-256-GCM AEAD that uses the given 256-bit key. 29 func NewAEAD(key []byte) (aeadCipher cipher.AEAD, err error) { 30 blockCipher, err := aes.NewCipher(key) 31 if err != nil { 32 return 33 } 34 35 aeadCipher, err = cipher.NewGCM(blockCipher) 36 if err != nil { 37 return 38 } 39 return 40 } 41 42 // Encrypt is an helper function to symetrically encrypt a piece of data using AES-256-GCM 43 // returning the nonce separatly 44 func EncryptWithNonce(key, plaintext, additionalData []byte) (ciphertext, nonce []byte, err error) { 45 nonce, err = NewAEADNonce() 46 if err != nil { 47 return 48 } 49 cipher, err := NewAEAD(key) 50 if err != nil { 51 return 52 } 53 ciphertext = cipher.Seal(nil, nonce, plaintext, additionalData) 54 return 55 } 56 57 // DecryptWithNonce is an helper function to symetrically decrypt a piece of data using AES-256-GCM 58 // taking the nonce as a separate piece of input 59 func DecryptWithNonce(key, nonce, ciphertext, additionalData []byte) (plaintext []byte, err error) { 60 cipher, err := NewAEAD(key) 61 if err != nil { 62 return 63 } 64 plaintext, err = cipher.Open(nil, nonce, ciphertext, additionalData) 65 return 66 } 67 68 // Encrypt is an helper function to symetrically encrypt a piece of data using AES-256-GCM 69 // the nonce is prepended to the ciphertext in the returned buffer 70 func Encrypt(key, plaintext, additionalData []byte) (ciphertext []byte, err error) { 71 nonce, err := NewAEADNonce() 72 if err != nil { 73 return 74 } 75 cipher, err := NewAEAD(key) 76 if err != nil { 77 return 78 } 79 ciphertext = cipher.Seal(nil, nonce, plaintext, additionalData) 80 ciphertext = append(nonce, ciphertext...) 81 return 82 } 83 84 // DecryptWithNonce is an helper function to symetrically decrypt a piece of data using AES-256-GCM 85 // The nonce should be at the begining of the ciphertext 86 func Decrypt(key, ciphertext, additionalData []byte) (plaintext []byte, err error) { 87 cipher, err := NewAEAD(key) 88 if err != nil { 89 return 90 } 91 92 if len(ciphertext) < AEADNonceSize { 93 err = errors.New("crypto.Decrypt: len(ciphertext) < NonceSize") 94 return 95 } 96 nonce := ciphertext[:AEADNonceSize] 97 ciphertext = ciphertext[AEADNonceSize:] 98 99 plaintext, err = cipher.Open(nil, nonce, ciphertext, additionalData) 100 return 101 }