multi-cloud: github.com/opensds/multi-cloud/s3/pkg/datastore/yig/crypto Index | Files

package crypto

import "github.com/opensds/multi-cloud/s3/pkg/datastore/yig/crypto"

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.

1. 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

2. 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.

1. 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

2. 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:

1.       Generate(KeyID) -> (Key, EncKey)
2. Unseal(KeyID, EncKey) -> Key

1. 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

2. 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

Package Files

client.go config.go doc.go error.go header.go key.go kms.go metadata.go sse.go vault.go

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.

func IsETagSealed Uses

func IsETagSealed(etag []byte) bool

IsETagSealed returns true if the etag seems to be encrypted.

func RemoveSensitiveEntries Uses

func RemoveSensitiveEntries(metadata map[string]string)

RemoveSensitiveEntries removes confidential encryption information - e.g. the SSE-C key - from the metadata map. It has the same semantics as RemoveSensitiveHeaders.

func RemoveSensitiveHeaders Uses

func RemoveSensitiveHeaders(h http.Header)

RemoveSensitiveHeaders removes confidential encryption information - e.g. the SSE-C key - from the HTTP headers. It has the same semantics as RemoveSensitiveEntires.

type Context Uses

type Context map[string]string

Context is a list of key-value pairs cryptographically associated with a certain object.

func (Context) WriteTo Uses

func (c Context) WriteTo(w io.Writer) (n int64, err error)

WriteTo writes the context in a canonical from to w. It returns the number of bytes and the first error encounter during writing to w, if any.

WriteTo sorts the context keys and writes the sorted key-value pairs as canonical JSON object to w.

type Error Uses

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.

func (Error) Error Uses

func (e Error) Error() string

type KMS Uses

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.

func NewKMS Uses

func NewKMS() KMS

func NewVault Uses

func NewVault(kmsConf KMSConfig) (KMS, error)

NewVault initializes Hashicorp Vault KMS by authenticating to Vault with the credentials in KMSConfig, and gets a client token for future api calls.

type KMSConfig Uses

type KMSConfig struct {
    Vault VaultConfig
}

KMSConfig has the KMS config for hashicorp vault

func NewVaultConfig Uses

func NewVaultConfig() (KMSConfig, error)

NewVaultConfig sets KMSConfig from environment variables and performs validations.

type ObjectKey Uses

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 Uses

func GenerateKey(extKey [32]byte, random io.Reader) (key ObjectKey)

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 Uses

func (key ObjectKey) DerivePartKey(id uint32) (partKey [32]byte)

DerivePartKey derives an unique 256 bit key from an ObjectKey and the part index.

type SealedKey Uses

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 Uses

type VaultAppRole struct {
    ID     string `json:"id"`
    Secret string `json:"secret"`
}

VaultAppRole represents vault approle credentials

type VaultAuth Uses

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 Uses

type VaultConfig struct {
    Endpoint string    `json:"endpoint"`
    Auth     VaultAuth `json:"auth"`
    Key      VaultKey  `json:"key-id"`
}

VaultConfig holds config required to start vault service

type VaultKey Uses

type VaultKey struct {
    Name    string `json:"name"`
    Version int    `json:"version"`
}

VaultKey represents vault encryption key-id name & version

Package crypto imports 17 packages (graph) and is imported by 1 packages. Updated 2020-06-21. Refresh now. Tools for package owners.