Add a package for the Key interface
Created by: arussellsaw
ref RFC 310
We should implement a package for the Key interface, with all implementations living in subpackages.
a rough sketch of the interface is here:
// NewKMSKey creates a new Key instance
// for the configured key name
func NewKMSKey(ctx, keyname, options) (Key, error)
// Key combines the Encrypter & Decrypter interfaces.
type Key interface {
Encrypter
Decrypter
}
// Encrypter is anything that can encrypt a value
type Encrypter interface {
Encrypt(ctx context.Context, value string) (string, error)
}
// Decrypter is anything that can decrypt a value
type Decrypter interface {
Decrypt(ctx context.Context, cipherText string) (Secret, error)
}
// Secret is a utility type to make it harder to accidentally leak secret
// values in logs. The actual value is unexported inside a struct, making
// harder to leak via reflection, the string value is only ever returned
// on explicit Secret() calls, meaning we can statically analyse secret
// usage and statically detect leaks.
type Secret struct {
value string
}
// String implements stringer, obfuscating the value
func (s Secret) String() string {
return “********”
}
// Secret returns the unobfuscated value
func (s Secret) Secret() string {
return s.value
}
// MarshalJSON overrides the default JSON marshaling implementation, obfuscating
// the value in any marshaled JSON
func (s Secret) MarshalJSON() ([]byte, error) {
return []byte(“********”)
}
One consideration from this design is key rotation, the ciphertext returned by the Encrypt function will need to encode metadata about the key name and version alongside the ciphertext, as at least for Cloud KMS you must specify the key version you want to use when decrypting a value. This should be simple enough to do via a base64 encoded blob of json or something along those lines, but the important thing is that each backend implementation can pick it’s own way to represent that metadata as long as it is encoded within the ciphertext string returned by the Encrypt call.