Documentation ¶
Overview ¶
Package crypto implements AWS S3 related cryptographic building blocks for implementing Server-Side-Encryption (SSE-S3) and Server-Side-Encryption with customer provided keys (SSE-C).
All objects are encrypted with an unique and randomly generated 'ObjectKey'. The ObjectKey itself is never stored in plaintext. Instead it is only stored in a sealed from. The sealed 'ObjectKey' is created by encrypting the 'ObjectKey' with an unique key-encryption-key. Given the correct key-encryption-key the sealed 'ObjectKey' can be unsealed and the object can be decrypted.
## SSE-C
SSE-C computes the key-encryption-key from the client-provided key, an initialization vector (IV) and the bucket/object path.
- Encrypt: Input: ClientKey, bucket, object, metadata, object_data - IV := Random({0,1}²⁵⁶) - ObjectKey := SHA256(ClientKey || Random({0,1}²⁵⁶)) - KeyEncKey := HMAC-SHA256(ClientKey, IV || 'SSE-C' || 'DAREv2-HMAC-SHA256' || bucket || '/' || object) - SealedKey := DAREv2_Enc(KeyEncKey, ObjectKey) - enc_object_data := DAREv2_Enc(ObjectKey, object_data) - metadata <- IV - metadata <- SealedKey Output: enc_object_data, metadata
- Decrypt: Input: ClientKey, bucket, object, metadata, enc_object_data - IV <- metadata - SealedKey <- metadata - KeyEncKey := HMAC-SHA256(ClientKey, IV || 'SSE-C' || 'DAREv2-HMAC-SHA256' || bucket || '/' || object) - ObjectKey := DAREv2_Dec(KeyEncKey, SealedKey) - object_data := DAREv2_Dec(ObjectKey, enc_object_data) Output: object_data
## SSE-S3
SSE-S3 can use either a master key or a KMS as root-of-trust. The en/decryption slightly depens upon which root-of-trust is used.
### SSE-S3 and single master key
The master key is used to derive unique object- and key-encryption-keys. SSE-S3 with a single master key works as SSE-C where the master key is used as the client-provided key.
- Encrypt: Input: MasterKey, bucket, object, metadata, object_data - IV := Random({0,1}²⁵⁶) - ObjectKey := SHA256(MasterKey || Random({0,1}²⁵⁶)) - KeyEncKey := HMAC-SHA256(MasterKey, IV || 'SSE-S3' || 'DAREv2-HMAC-SHA256' || bucket || '/' || object) - SealedKey := DAREv2_Enc(KeyEncKey, ObjectKey) - enc_object_data := DAREv2_Enc(ObjectKey, object_data) - metadata <- IV - metadata <- SealedKey Output: enc_object_data, metadata
- Decrypt: Input: MasterKey, bucket, object, metadata, enc_object_data - IV <- metadata - SealedKey <- metadata - KeyEncKey := HMAC-SHA256(MasterKey, IV || 'SSE-S3' || 'DAREv2-HMAC-SHA256' || bucket || '/' || object) - ObjectKey := DAREv2_Dec(KeyEncKey, SealedKey) - object_data := DAREv2_Dec(ObjectKey, enc_object_data) Output: object_data
### SSE-S3 and KMS
SSE-S3 requires that the KMS provides two functions:
- Generate(KeyID) -> (Key, EncKey)
- Unseal(KeyID, EncKey) -> Key
- Encrypt: Input: KeyID, bucket, object, metadata, object_data - Key, EncKey := Generate(KeyID) - IV := Random({0,1}²⁵⁶) - ObjectKey := SHA256(Key, Random({0,1}²⁵⁶)) - KeyEncKey := HMAC-SHA256(Key, IV || 'SSE-S3' || 'DAREv2-HMAC-SHA256' || bucket || '/' || object) - SealedKey := DAREv2_Enc(KeyEncKey, ObjectKey) - enc_object_data := DAREv2_Enc(ObjectKey, object_data) - metadata <- IV - metadata <- KeyID - metadata <- EncKey - metadata <- SealedKey Output: enc_object_data, metadata
- Decrypt: Input: bucket, object, metadata, enc_object_data - KeyID <- metadata - EncKey <- metadata - IV <- metadata - SealedKey <- metadata - Key := Unseal(KeyID, EncKey) - KeyEncKey := HMAC-SHA256(Key, IV || 'SSE-S3' || 'DAREv2-HMAC-SHA256' || bucket || '/' || object) - ObjectKey := DAREv2_Dec(KeyEncKey, SealedKey) - object_data := DAREv2_Dec(ObjectKey, enc_object_data) Output: object_data
Index ¶
Constants ¶
const ( // SSEKmsID is the HTTP header key referencing the SSE-KMS // key ID. SSEKmsID = SSEHeader + "-Aws-Kms-Key-Id" // SSEKmsContext is the HTTP header key referencing the // SSE-KMS encryption context. SSEKmsContext = SSEHeader + "-Context" )
const ( // SSECAlgorithm is the HTTP header key referencing // the SSE-C algorithm. SSECAlgorithm = SSEHeader + "-Customer-Algorithm" // SSECKey is the HTTP header key referencing the // SSE-C client-provided key.. SSECKey = SSEHeader + "-Customer-Key" // SSECKeyMD5 is the HTTP header key referencing // the MD5 sum of the client-provided key. SSECKeyMD5 = SSEHeader + "-Customer-Key-Md5" )
const ( // SSECopyAlgorithm is the HTTP header key referencing // the SSE-C algorithm for SSE-C copy requests. SSECopyAlgorithm = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm" // SSECopyKey is the HTTP header key referencing the SSE-C // client-provided key for SSE-C copy requests. SSECopyKey = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key" // SSECopyKeyMD5 is the HTTP header key referencing the // MD5 sum of the client key for SSE-C copy requests. SSECopyKeyMD5 = "X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5" )
const ( // SSEAlgorithmAES256 is the only supported value for the SSE-S3 or SSE-C algorithm header. // For SSE-S3 see: https://docs.aws.amazon.com/AmazonS3/latest/dev/SSEUsingRESTAPI.html // For SSE-C see: https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html SSEAlgorithmAES256 = "AES256" // SSEAlgorithmKMS is the value of 'X-Amz-Server-Side-Encryption' for SSE-KMS. // See: https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html SSEAlgorithmKMS = "aws:kms" )
const ( DEBUG_ROOT_TOKEN = "myroot" DEBUG_LEASE_DURATION = 60 * 60 * 24 * 30 // 30 days )
const SSEHeader = "X-Amz-Server-Side-Encryption"
SSEHeader is the general AWS SSE HTTP header key.
Variables ¶
var ( // ErrInvalidEncryptionMethod indicates that the specified SSE encryption method // is not supported. ErrInvalidEncryptionMethod = errors.New("The encryption method is not supported") // ErrInvalidCustomerAlgorithm indicates that the specified SSE-C algorithm // is not supported. ErrInvalidCustomerAlgorithm = errors.New("The SSE-C algorithm is not supported") // ErrMissingCustomerKey indicates that the HTTP headers contains no SSE-C client key. ErrMissingCustomerKey = errors.New("The SSE-C request is missing the customer key") // ErrMissingCustomerKeyMD5 indicates that the HTTP headers contains no SSE-C client key // MD5 checksum. ErrMissingCustomerKeyMD5 = errors.New("The SSE-C request is missing the customer key MD5") // ErrInvalidCustomerKey indicates that the SSE-C client key is not valid - e.g. not a // base64-encoded string or not 256 bits long. ErrInvalidCustomerKey = errors.New("The SSE-C client key is invalid") // ErrSecretKeyMismatch indicates that the provided secret key (SSE-C client key / SSE-S3 KMS key) // does not match the secret key used during encrypting the object. ErrSecretKeyMismatch = errors.New("The secret key does not match the secret key used during upload") // ErrCustomerKeyMD5Mismatch indicates that the SSE-C key MD5 does not match the // computed MD5 sum. This means that the client provided either the wrong key for // a certain MD5 checksum or the wrong MD5 for a certain key. ErrCustomerKeyMD5Mismatch = errors.New("The provided SSE-C key MD5 does not match the computed MD5 of the SSE-C key") // ErrIncompatibleEncryptionMethod indicates that both SSE-C headers and SSE-S3 headers were specified, and are incompatible // The client needs to remove the SSE-S3 header or the SSE-C headers ErrIncompatibleEncryptionMethod = errors.New("Server side encryption specified with both SSE-C and SSE-S3 headers") )
var ( // SSEC represents AWS SSE-C. It provides functionality to handle // SSE-C requests. SSEC = ssec{} // SSECopy represents AWS SSE-C for copy requests. It provides // functionality to handle SSE-C copy requests. SSECopy = ssecCopy{} )
var ( //ErrKMSAuthLogin is raised when there is a failure authenticating to KMS ErrKMSAuthLogin = errors.New("Vault service did not return auth info") )
var S3 = s3{}
S3 represents AWS SSE-S3. It provides functionality to handle SSE-S3 requests.
var S3KMS = s3KMS{}
S3KMS represents AWS SSE-KMS. It provides functionality to handle SSE-KMS requests.
Functions ¶
func IsETagSealed ¶
IsETagSealed returns true if the etag seems to be encrypted.
func RemoveSensitiveEntries ¶
RemoveSensitiveEntries removes confidential encryption information - e.g. the SSE-C key - from the metadata map. It has the same semantics as RemoveSensitiveHeaders.
func RemoveSensitiveHeaders ¶
RemoveSensitiveHeaders removes confidential encryption information - e.g. the SSE-C key - from the HTTP headers. It has the same semantics as RemoveSensitiveEntires.
Types ¶
type Context ¶
Context is a list of key-value pairs cryptographically associated with a certain object.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error is the generic type for any error happening during decrypting an object. It indicates that the object itself or its metadata was modified accidentally or maliciously.
type KMS ¶
type KMS interface { // GenerateKey generates a new random data key using // the master key referenced by the keyID. It returns // the plaintext key and the sealed plaintext key // on success. // // The context is cryptographically bound to the // generated key. The same context must be provided // again to unseal the generated key. GenerateKey(keyID string, context Context) (key [32]byte, sealedKey []byte, err error) // UnsealKey unseals the sealedKey using the master key // referenced by the keyID. The provided context must // match the context used to generate the sealed key. UnsealKey(keyID string, sealedKey []byte, context Context) (key [32]byte, err error) GetKeyID() string }
KMS represents an active and authenticted connection to a Key-Management-Service. It supports generating data key generation and unsealing of KMS-generated data keys.
type KMSConfig ¶
type KMSConfig struct {
Vault VaultConfig
}
KMSConfig has the KMS config for hashicorp vault
func NewVaultConfig ¶
NewVaultConfig sets KMSConfig from environment variables and performs validations.
type ObjectKey ¶
type ObjectKey [32]byte
ObjectKey is a 256 bit secret key used to encrypt the object. It must never be stored in plaintext.
func GenerateKey ¶
GenerateKey generates a unique ObjectKey from a 256 bit external key and a source of randomness. If random is nil the default PRNG of the system (crypto/rand) is used.
func (ObjectKey) DerivePartKey ¶
DerivePartKey derives an unique 256 bit key from an ObjectKey and the part index.
type SealedKey ¶
type SealedKey struct { Key [64]byte // The encrypted and authenticted object-key. IV [32]byte // The random IV used to encrypt the object-key. Algorithm string // The sealing algorithm used to encrypt the object key. }
SealedKey represents a sealed object key. It can be stored at an untrusted location.
type VaultAppRole ¶
VaultAppRole represents vault approle credentials
type VaultAuth ¶
type VaultAuth struct { Type string `json:"type"` AppRole VaultAppRole `json:"approle"` }
VaultAuth represents vault auth type to use. For now, AppRole is the only supported auth type.
type VaultConfig ¶
type VaultConfig struct { Endpoint string `json:"endpoint"` Auth VaultAuth `json:"auth"` Key VaultKey `json:"key-id"` }
VaultConfig holds config required to start vault service