1package aead 2 3import ( 4 "context" 5 "crypto/aes" 6 "crypto/cipher" 7 "errors" 8 9 wrapping "github.com/hashicorp/go-kms-wrapping" 10 "github.com/hashicorp/go-uuid" 11) 12 13// Wrapper implements the wrapping.Wrapper interface for Shamir 14type Wrapper struct { 15 keyBytes []byte 16 aead cipher.AEAD 17} 18 19// Ensure that we are implementing AutoSealAccess 20var _ wrapping.Wrapper = (*Wrapper)(nil) 21 22// NewWrapper creates a new Wrapper with the provided logger 23func NewWrapper(opts *wrapping.WrapperOptions) *Wrapper { 24 if opts == nil { 25 opts = new(wrapping.WrapperOptions) 26 } 27 seal := new(Wrapper) 28 return seal 29} 30 31func (s *Wrapper) GetKeyBytes() []byte { 32 return s.keyBytes 33} 34 35func (s *Wrapper) SetAEAD(aead cipher.AEAD) { 36 s.aead = aead 37} 38 39// SetAESGCMKeyBytes takes in a byte slice and constucts an AES-GCM AEAD from it 40func (s *Wrapper) SetAESGCMKeyBytes(key []byte) error { 41 aesCipher, err := aes.NewCipher(key) 42 if err != nil { 43 return err 44 } 45 46 aead, err := cipher.NewGCM(aesCipher) 47 if err != nil { 48 return err 49 } 50 51 s.keyBytes = key 52 s.aead = aead 53 return nil 54} 55 56// Init is a no-op at the moment 57func (s *Wrapper) Init(_ context.Context) error { 58 return nil 59} 60 61// Finalize is called during shutdown. This is a no-op since 62// Wrapper doesn't require any cleanup. 63func (s *Wrapper) Finalize(_ context.Context) error { 64 return nil 65} 66 67// Type returns the seal type for this particular Wrapper implementation 68func (s *Wrapper) Type() string { 69 return wrapping.Shamir 70} 71 72// KeyID returns the last known key id 73func (s *Wrapper) KeyID() string { 74 return "" 75} 76 77// HMACKeyID returns the last known HMAC key id 78func (s *Wrapper) HMACKeyID() string { 79 return "" 80} 81 82// Encrypt is used to encrypt the plaintext using the aead held by the seal. 83func (s *Wrapper) Encrypt(_ context.Context, plaintext, aad []byte) (*wrapping.EncryptedBlobInfo, error) { 84 if plaintext == nil { 85 return nil, errors.New("given plaintext for encryption is nil") 86 } 87 88 if s.aead == nil { 89 return nil, errors.New("aead is not configured in the seal") 90 } 91 92 iv, err := uuid.GenerateRandomBytes(12) 93 if err != nil { 94 return nil, err 95 } 96 97 ciphertext := s.aead.Seal(nil, iv, plaintext, aad) 98 99 return &wrapping.EncryptedBlobInfo{ 100 Ciphertext: append(iv, ciphertext...), 101 }, nil 102} 103 104func (s *Wrapper) Decrypt(_ context.Context, in *wrapping.EncryptedBlobInfo, aad []byte) ([]byte, error) { 105 if in == nil { 106 return nil, errors.New("given plaintext for encryption is nil") 107 } 108 109 if s.aead == nil { 110 return nil, errors.New("aead is not configured in the seal") 111 } 112 113 iv, ciphertext := in.Ciphertext[:12], in.Ciphertext[12:] 114 115 plaintext, err := s.aead.Open(nil, iv, ciphertext, aad) 116 if err != nil { 117 return nil, err 118 } 119 120 return plaintext, nil 121} 122