forked from hashicorp/go-kms-wrapping
-
Notifications
You must be signed in to change notification settings - Fork 0
/
envelope.go
63 lines (53 loc) · 1.57 KB
/
envelope.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package wrapping
import (
"crypto/aes"
"crypto/cipher"
"errors"
fmt "fmt"
uuid "github.com/hashicorp/go-uuid"
)
// NewEnvelope retuns an Envelope that is ready to use for use. It is valid to pass nil EnvelopeOptions.
func NewEnvelope(opts *EnvelopeOptions) *Envelope {
return &Envelope{}
}
// Encrypt takes in plaintext and envelope encrypts it, generating an EnvelopeInfo value
func (e *Envelope) Encrypt(plaintext []byte, aad []byte) (*EnvelopeInfo, error) {
// Generate DEK
key, err := uuid.GenerateRandomBytes(32)
if err != nil {
return nil, err
}
iv, err := uuid.GenerateRandomBytes(12)
if err != nil {
return nil, err
}
aead, err := e.aeadEncrypter(key)
if err != nil {
return nil, err
}
return &EnvelopeInfo{
Ciphertext: aead.Seal(nil, iv, plaintext, aad),
Key: key,
IV: iv,
}, nil
}
// Decrypt takes in EnvelopeInfo and potentially additional data and decrypts. Additional data is separate from the encrypted blob info as it is expected that will be sourced from a separate location.
func (e *Envelope) Decrypt(data *EnvelopeInfo, aad []byte) ([]byte, error) {
aead, err := e.aeadEncrypter(data.Key)
if err != nil {
return nil, err
}
return aead.Open(nil, data.IV, data.Ciphertext, aad)
}
func (e *Envelope) aeadEncrypter(key []byte) (cipher.AEAD, error) {
aesCipher, err := aes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("failed to create cipher: %w", err)
}
// Create the GCM mode AEAD
gcm, err := cipher.NewGCM(aesCipher)
if err != nil {
return nil, errors.New("failed to initialize GCM mode")
}
return gcm, nil
}