From 33cd35d2402b0ee5bfeb28206d772d139f2e96cd Mon Sep 17 00:00:00 2001 From: wobondar Date: Wed, 13 Mar 2024 23:00:27 +0200 Subject: [PATCH 01/30] docs: module, client, clientconfig Go documentation --- doc.go | 69 ++++++++++++++++++++++++++ pkg/client/doc.go | 5 ++ pkg/client/options.go | 11 ++-- pkg/clientconfig/client_config.go | 31 ++++++++++-- pkg/clientconfig/client_config_test.go | 4 +- pkg/clientconfig/client_defaults.go | 8 ++- pkg/clientconfig/doc.go | 5 ++ pkg/crypto/config.go | 2 + pkg/crypto/doc.go | 5 ++ pkg/doc.go | 5 ++ pkg/version.go | 1 + 11 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 pkg/client/doc.go create mode 100644 pkg/clientconfig/doc.go create mode 100644 pkg/crypto/doc.go create mode 100644 pkg/doc.go diff --git a/doc.go b/doc.go index 6508b42a..3a28059d 100644 --- a/doc.go +++ b/doc.go @@ -1,4 +1,73 @@ // Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +// Package sdk is the Unofficial Go SDK implementation of the AWS Encryption SDK. +// +// # Getting started +// +// To install the AWS Encryption SDK for Go, use the following command: +// +// go get github.com/chainifynet/aws-encryption-sdk-go@latest +// +// # Usage +// +// The following example demonstrates how to use SDK to encrypt and decrypt data using a static key. +// +// package main +// +// import ( +// "context" +// "fmt" +// +// "github.com/chainifynet/aws-encryption-sdk-go/pkg/client" +// "github.com/chainifynet/aws-encryption-sdk-go/pkg/materials" +// "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/rawprovider" +// ) +// +// func main() { +// // static key to use for encryption and decryption +// staticKey1 := []byte("superSecureKeySecureKey32bytes32") +// +// // data to encrypt +// secretData := []byte("secret data to encrypt") +// +// // setup Encryption SDK client with default configuration +// sdkClient := client.NewClient() +// +// // setup Raw Key provider +// rawKeyProvider, err := rawprovider.NewWithOpts( +// "raw", +// rawprovider.WithStaticKey("static1", staticKey1), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// // setup crypto materials manager +// cmm, err := materials.NewDefault(rawKeyProvider) +// if err != nil { +// panic(err) // handle error +// } +// +// // encrypt data without encryption context passing nil as the third argument +// encrypted, header, err := sdkClient.Encrypt(context.TODO(), secretData, nil, cmm) +// if err != nil { +// panic(err) // handle error +// } +// +// fmt.Printf("encrypted encryption context: %v\n", header.AADData().EncryptionContext()) +// +// // decrypt "encrypted" data +// decrypted, _, err := sdkClient.Decrypt(context.TODO(), encrypted, cmm) +// if err != nil { +// panic(err) // handle error +// } +// +// fmt.Printf("decrypted data: %s\n", decrypted) +// +// // verify that "decrypted" plaintext is identical to the original secret data +// if string(decrypted) != string(secretData) { +// panic("decrypted data does not match with the original data") +// } +// } package sdk diff --git a/pkg/client/doc.go b/pkg/client/doc.go new file mode 100644 index 00000000..a62824f5 --- /dev/null +++ b/pkg/client/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package client provides the entrypoint for using AWS Encryption SDK for Go. +package client diff --git a/pkg/client/options.go b/pkg/client/options.go index 5018555d..8cae0312 100644 --- a/pkg/client/options.go +++ b/pkg/client/options.go @@ -12,7 +12,8 @@ import ( ) const ( - DefaultFrameLength = int(4096) // default frame size for encryption + // DefaultFrameLength default frame length for encryption. + DefaultFrameLength = int(4096) ) // EncryptOptions defines the configuration options for the encryption process. @@ -25,9 +26,12 @@ const ( // - Handler: Specifies a function that creates [model.EncryptionHandler] encryption handler. // If not set, a default [encrypter.New] function is used. type EncryptOptions struct { - Algorithm *suite.AlgorithmSuite + // Algorithm that defines the encryption algorithm to be used. + Algorithm *suite.AlgorithmSuite + // FrameLength specifies the frame length for encryption. FrameLength int - Handler func(config crypto.EncrypterConfig, cmm model.CryptoMaterialsManager) model.EncryptionHandler + // Handler specifies a function that creates model.EncryptionHandler encryption handler. + Handler func(config crypto.EncrypterConfig, cmm model.CryptoMaterialsManager) model.EncryptionHandler } // DecryptOptions defines the configuration options for the decryption process. @@ -36,6 +40,7 @@ type EncryptOptions struct { // - Handler: Specifies a function that creates [model.DecryptionHandler] decryption handler. // If not set, a default [decrypter.New] function is used. type DecryptOptions struct { + // Handler specifies a function that creates model.DecryptionHandler decryption handler. Handler func(config crypto.DecrypterConfig, cmm model.CryptoMaterialsManager) model.DecryptionHandler } diff --git a/pkg/clientconfig/client_config.go b/pkg/clientconfig/client_config.go index 1154443a..86d3fbcb 100644 --- a/pkg/clientconfig/client_config.go +++ b/pkg/clientconfig/client_config.go @@ -10,34 +10,56 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// ConfigOptions is a holder of the configuration options for the client. type ConfigOptions struct { - CommitmentPolicy suite.CommitmentPolicy + // CommitmentPolicy is the commitment policy for the client. + CommitmentPolicy suite.CommitmentPolicy + + // MaxEncryptedDataKeys is the maximum number of encrypted data keys that can be used in a single message. MaxEncryptedDataKeys int } +// ConfigOptionFunc is a function that sets a configuration option. type ConfigOptionFunc func(o *ConfigOptions) error +// ClientConfig is the configuration for the client. type ClientConfig struct { commitmentPolicy suite.CommitmentPolicy maxEncryptedDataKeys int } +// CommitmentPolicy returns the commitment policy for the client. func (c ClientConfig) CommitmentPolicy() suite.CommitmentPolicy { return c.commitmentPolicy } +// MaxEncryptedDataKeys returns the maximum number of encrypted data keys that can be used in a single message. func (c ClientConfig) MaxEncryptedDataKeys() int { return c.maxEncryptedDataKeys } +// NewConfig returns a new client configuration with the default options. func NewConfig() (*ClientConfig, error) { return NewConfigWithOpts() } +// NewConfigWithOpts returns a new client configuration with the provided options. +// The options are passed as [ConfigOptionFunc] functions, which modify the [ConfigOptions] struct. +// +// The default values for the configuration options are as follows: +// - CommitmentPolicy: [DefaultCommitment] +// - MaxEncryptedDataKeys: [DefaultMaxEDK] +// +// Example usage: +// +// cfg, err := NewConfigWithOpts( +// WithCommitmentPolicy(suite.CommitmentPolicyRequireEncryptAllowDecrypt), +// WithMaxEncryptedDataKeys(5), +// ) func NewConfigWithOpts(optFns ...ConfigOptionFunc) (*ClientConfig, error) { opts := ConfigOptions{ - CommitmentPolicy: defaultCommitment, - MaxEncryptedDataKeys: defaultMaxEDK, + CommitmentPolicy: DefaultCommitment, + MaxEncryptedDataKeys: DefaultMaxEDK, } for _, optFn := range optFns { if err := optFn(&opts); err != nil { @@ -50,6 +72,7 @@ func NewConfigWithOpts(optFns ...ConfigOptionFunc) (*ClientConfig, error) { }, nil } +// WithCommitmentPolicy returns a [ConfigOptionFunc] that sets the commitment policy for the client. func WithCommitmentPolicy(policy suite.CommitmentPolicy) ConfigOptionFunc { return func(o *ConfigOptions) error { if err := suite.ValidateCommitmentPolicy(policy); err != nil { @@ -60,6 +83,8 @@ func WithCommitmentPolicy(policy suite.CommitmentPolicy) ConfigOptionFunc { } } +// WithMaxEncryptedDataKeys returns a [ConfigOptionFunc] that sets the maximum +// number of encrypted data keys that can be used in a single message. func WithMaxEncryptedDataKeys(maxEncryptedDataKeys int) ConfigOptionFunc { return func(o *ConfigOptions) error { if maxEncryptedDataKeys > math.MaxUint8 { diff --git a/pkg/clientconfig/client_config_test.go b/pkg/clientconfig/client_config_test.go index d4b6bbca..37bef283 100644 --- a/pkg/clientconfig/client_config_test.go +++ b/pkg/clientconfig/client_config_test.go @@ -15,8 +15,8 @@ func TestNewConfig(t *testing.T) { defaultCfg, err := NewConfig() assert.NoError(t, err) - assert.Equal(t, defaultCommitment, defaultCfg.CommitmentPolicy()) - assert.Equal(t, defaultMaxEDK, defaultCfg.MaxEncryptedDataKeys()) + assert.Equal(t, DefaultCommitment, defaultCfg.CommitmentPolicy()) + assert.Equal(t, DefaultMaxEDK, defaultCfg.MaxEncryptedDataKeys()) } func TestNewConfigWithOpts(t *testing.T) { diff --git a/pkg/clientconfig/client_defaults.go b/pkg/clientconfig/client_defaults.go index 45714d62..652d2521 100644 --- a/pkg/clientconfig/client_defaults.go +++ b/pkg/clientconfig/client_defaults.go @@ -6,6 +6,10 @@ package clientconfig import "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" const ( - defaultCommitment = suite.CommitmentPolicyRequireEncryptRequireDecrypt - defaultMaxEDK = 10 + // DefaultCommitment is the default commitment policy for the client. + DefaultCommitment = suite.CommitmentPolicyRequireEncryptRequireDecrypt + + // DefaultMaxEDK is the default maximum number of encrypted data keys that can be + // used to encrypt or decrypt a single message. + DefaultMaxEDK = 10 ) diff --git a/pkg/clientconfig/doc.go b/pkg/clientconfig/doc.go new file mode 100644 index 00000000..faf0ad5c --- /dev/null +++ b/pkg/clientconfig/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package clientconfig provides a way to configure SDK client. +package clientconfig diff --git a/pkg/crypto/config.go b/pkg/crypto/config.go index 504cb106..f7f7b80f 100644 --- a/pkg/crypto/config.go +++ b/pkg/crypto/config.go @@ -8,12 +8,14 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// EncrypterConfig is the configuration for the encrypter. type EncrypterConfig struct { ClientCfg clientconfig.ClientConfig Algorithm *suite.AlgorithmSuite FrameLength int } +// DecrypterConfig is the configuration for the decrypter. type DecrypterConfig struct { ClientCfg clientconfig.ClientConfig } diff --git a/pkg/crypto/doc.go b/pkg/crypto/doc.go new file mode 100644 index 00000000..0fdbde21 --- /dev/null +++ b/pkg/crypto/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package crypto provides common errors and encryption configuration. +package crypto diff --git a/pkg/doc.go b/pkg/doc.go new file mode 100644 index 00000000..2ae6b247 --- /dev/null +++ b/pkg/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package pkg provides the core SDK packages. +package pkg diff --git a/pkg/version.go b/pkg/version.go index 2eab8c8a..c64d6fa4 100644 --- a/pkg/version.go +++ b/pkg/version.go @@ -3,4 +3,5 @@ package pkg +// Version is the current version of the SDK. const Version = "0.3.2" From 44393ef2a82e3926d6c214ae9816314654a7fbb8 Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 03:07:05 +0200 Subject: [PATCH 02/30] docs: types documentation --- pkg/model/types/doc.go | 5 +++++ pkg/model/types/provider.go | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 pkg/model/types/doc.go diff --git a/pkg/model/types/doc.go b/pkg/model/types/doc.go new file mode 100644 index 00000000..1b9aaca1 --- /dev/null +++ b/pkg/model/types/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package types contains a basic types used in SDK. +package types diff --git a/pkg/model/types/provider.go b/pkg/model/types/provider.go index 2ef5765f..11cea073 100644 --- a/pkg/model/types/provider.go +++ b/pkg/model/types/provider.go @@ -4,9 +4,11 @@ package types const ( + // KmsProviderID is the ID of the AWS KMS key provider. KmsProviderID = "aws-kms" ) +// ProviderKind represents the kind of key provider. type ProviderKind int8 const ( From 797b2c09fd971a6efd6b4974acd3bd736f4cd016 Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 03:08:14 +0200 Subject: [PATCH 03/30] docs: format package documentation, minor fixes --- .../pkg/model/format/Deserializer_mock.go | 50 ++++++++-------- pkg/internal/crypto/decrypter/decrypt.go | 2 +- pkg/internal/serialization/deserializer.go | 6 +- .../serialization/deserializer_test.go | 8 +-- pkg/model/format/body.go | 16 +++++ pkg/model/format/doc.go | 5 ++ pkg/model/format/footer.go | 5 ++ pkg/model/format/header.go | 60 ++++++++++++++++--- pkg/model/format/serialization.go | 31 +++++++++- 9 files changed, 141 insertions(+), 42 deletions(-) create mode 100644 pkg/model/format/doc.go diff --git a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/Deserializer_mock.go b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/Deserializer_mock.go index a152f696..4969e7f4 100644 --- a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/Deserializer_mock.go +++ b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/Deserializer_mock.go @@ -26,9 +26,9 @@ func (_m *MockDeserializer) EXPECT() *MockDeserializer_Expecter { return &MockDeserializer_Expecter{mock: &_m.Mock} } -// DeserializeBody provides a mock function with given fields: buf, algorithm, frameLen -func (_m *MockDeserializer) DeserializeBody(buf *bytes.Buffer, algorithm *suite.AlgorithmSuite, frameLen int) (format.MessageBody, error) { - ret := _m.Called(buf, algorithm, frameLen) +// DeserializeBody provides a mock function with given fields: buf, alg, frameLen +func (_m *MockDeserializer) DeserializeBody(buf *bytes.Buffer, alg *suite.AlgorithmSuite, frameLen int) (format.MessageBody, error) { + ret := _m.Called(buf, alg, frameLen) if len(ret) == 0 { panic("no return value specified for DeserializeBody") @@ -37,10 +37,10 @@ func (_m *MockDeserializer) DeserializeBody(buf *bytes.Buffer, algorithm *suite. var r0 format.MessageBody var r1 error if rf, ok := ret.Get(0).(func(*bytes.Buffer, *suite.AlgorithmSuite, int) (format.MessageBody, error)); ok { - return rf(buf, algorithm, frameLen) + return rf(buf, alg, frameLen) } if rf, ok := ret.Get(0).(func(*bytes.Buffer, *suite.AlgorithmSuite, int) format.MessageBody); ok { - r0 = rf(buf, algorithm, frameLen) + r0 = rf(buf, alg, frameLen) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(format.MessageBody) @@ -48,7 +48,7 @@ func (_m *MockDeserializer) DeserializeBody(buf *bytes.Buffer, algorithm *suite. } if rf, ok := ret.Get(1).(func(*bytes.Buffer, *suite.AlgorithmSuite, int) error); ok { - r1 = rf(buf, algorithm, frameLen) + r1 = rf(buf, alg, frameLen) } else { r1 = ret.Error(1) } @@ -63,13 +63,13 @@ type MockDeserializer_DeserializeBody_Call struct { // DeserializeBody is a helper method to define mock.On call // - buf *bytes.Buffer -// - algorithm *suite.AlgorithmSuite +// - alg *suite.AlgorithmSuite // - frameLen int -func (_e *MockDeserializer_Expecter) DeserializeBody(buf interface{}, algorithm interface{}, frameLen interface{}) *MockDeserializer_DeserializeBody_Call { - return &MockDeserializer_DeserializeBody_Call{Call: _e.mock.On("DeserializeBody", buf, algorithm, frameLen)} +func (_e *MockDeserializer_Expecter) DeserializeBody(buf interface{}, alg interface{}, frameLen interface{}) *MockDeserializer_DeserializeBody_Call { + return &MockDeserializer_DeserializeBody_Call{Call: _e.mock.On("DeserializeBody", buf, alg, frameLen)} } -func (_c *MockDeserializer_DeserializeBody_Call) Run(run func(buf *bytes.Buffer, algorithm *suite.AlgorithmSuite, frameLen int)) *MockDeserializer_DeserializeBody_Call { +func (_c *MockDeserializer_DeserializeBody_Call) Run(run func(buf *bytes.Buffer, alg *suite.AlgorithmSuite, frameLen int)) *MockDeserializer_DeserializeBody_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(*bytes.Buffer), args[1].(*suite.AlgorithmSuite), args[2].(int)) }) @@ -86,9 +86,9 @@ func (_c *MockDeserializer_DeserializeBody_Call) RunAndReturn(run func(*bytes.Bu return _c } -// DeserializeFooter provides a mock function with given fields: alg, buf -func (_m *MockDeserializer) DeserializeFooter(alg *suite.AlgorithmSuite, buf *bytes.Buffer) (format.MessageFooter, error) { - ret := _m.Called(alg, buf) +// DeserializeFooter provides a mock function with given fields: buf, alg +func (_m *MockDeserializer) DeserializeFooter(buf *bytes.Buffer, alg *suite.AlgorithmSuite) (format.MessageFooter, error) { + ret := _m.Called(buf, alg) if len(ret) == 0 { panic("no return value specified for DeserializeFooter") @@ -96,19 +96,19 @@ func (_m *MockDeserializer) DeserializeFooter(alg *suite.AlgorithmSuite, buf *by var r0 format.MessageFooter var r1 error - if rf, ok := ret.Get(0).(func(*suite.AlgorithmSuite, *bytes.Buffer) (format.MessageFooter, error)); ok { - return rf(alg, buf) + if rf, ok := ret.Get(0).(func(*bytes.Buffer, *suite.AlgorithmSuite) (format.MessageFooter, error)); ok { + return rf(buf, alg) } - if rf, ok := ret.Get(0).(func(*suite.AlgorithmSuite, *bytes.Buffer) format.MessageFooter); ok { - r0 = rf(alg, buf) + if rf, ok := ret.Get(0).(func(*bytes.Buffer, *suite.AlgorithmSuite) format.MessageFooter); ok { + r0 = rf(buf, alg) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(format.MessageFooter) } } - if rf, ok := ret.Get(1).(func(*suite.AlgorithmSuite, *bytes.Buffer) error); ok { - r1 = rf(alg, buf) + if rf, ok := ret.Get(1).(func(*bytes.Buffer, *suite.AlgorithmSuite) error); ok { + r1 = rf(buf, alg) } else { r1 = ret.Error(1) } @@ -122,15 +122,15 @@ type MockDeserializer_DeserializeFooter_Call struct { } // DeserializeFooter is a helper method to define mock.On call -// - alg *suite.AlgorithmSuite // - buf *bytes.Buffer -func (_e *MockDeserializer_Expecter) DeserializeFooter(alg interface{}, buf interface{}) *MockDeserializer_DeserializeFooter_Call { - return &MockDeserializer_DeserializeFooter_Call{Call: _e.mock.On("DeserializeFooter", alg, buf)} +// - alg *suite.AlgorithmSuite +func (_e *MockDeserializer_Expecter) DeserializeFooter(buf interface{}, alg interface{}) *MockDeserializer_DeserializeFooter_Call { + return &MockDeserializer_DeserializeFooter_Call{Call: _e.mock.On("DeserializeFooter", buf, alg)} } -func (_c *MockDeserializer_DeserializeFooter_Call) Run(run func(alg *suite.AlgorithmSuite, buf *bytes.Buffer)) *MockDeserializer_DeserializeFooter_Call { +func (_c *MockDeserializer_DeserializeFooter_Call) Run(run func(buf *bytes.Buffer, alg *suite.AlgorithmSuite)) *MockDeserializer_DeserializeFooter_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*suite.AlgorithmSuite), args[1].(*bytes.Buffer)) + run(args[0].(*bytes.Buffer), args[1].(*suite.AlgorithmSuite)) }) return _c } @@ -140,7 +140,7 @@ func (_c *MockDeserializer_DeserializeFooter_Call) Return(_a0 format.MessageFoot return _c } -func (_c *MockDeserializer_DeserializeFooter_Call) RunAndReturn(run func(*suite.AlgorithmSuite, *bytes.Buffer) (format.MessageFooter, error)) *MockDeserializer_DeserializeFooter_Call { +func (_c *MockDeserializer_DeserializeFooter_Call) RunAndReturn(run func(*bytes.Buffer, *suite.AlgorithmSuite) (format.MessageFooter, error)) *MockDeserializer_DeserializeFooter_Call { _c.Call.Return(run) return _c } diff --git a/pkg/internal/crypto/decrypter/decrypt.go b/pkg/internal/crypto/decrypter/decrypt.go index 6ce8bab5..4a48dbc1 100644 --- a/pkg/internal/crypto/decrypter/decrypt.go +++ b/pkg/internal/crypto/decrypter/decrypt.go @@ -81,7 +81,7 @@ func (d *Decrypter) decryptData(ctx context.Context, ciphertext []byte) ([]byte, } if d.verifier != nil { - footer, errFooter := d.deser.DeserializeFooter(d.header.AlgorithmSuite(), buf) + footer, errFooter := d.deser.DeserializeFooter(buf, d.header.AlgorithmSuite()) if errFooter != nil { return nil, nil, errFooter } diff --git a/pkg/internal/serialization/deserializer.go b/pkg/internal/serialization/deserializer.go index 57da5674..43e20e93 100644 --- a/pkg/internal/serialization/deserializer.go +++ b/pkg/internal/serialization/deserializer.go @@ -34,10 +34,10 @@ func (d *Deserializer) DeserializeHeader(buf *bytes.Buffer, maxEDK int) (format. return header, authData, nil } -func (d *Deserializer) DeserializeBody(buf *bytes.Buffer, algorithm *suite.AlgorithmSuite, frameLen int) (format.MessageBody, error) { - return deserializeBody(algorithm, frameLen, buf) +func (d *Deserializer) DeserializeBody(buf *bytes.Buffer, alg *suite.AlgorithmSuite, frameLen int) (format.MessageBody, error) { + return deserializeBody(alg, frameLen, buf) } -func (d *Deserializer) DeserializeFooter(alg *suite.AlgorithmSuite, buf *bytes.Buffer) (format.MessageFooter, error) { +func (d *Deserializer) DeserializeFooter(buf *bytes.Buffer, alg *suite.AlgorithmSuite) (format.MessageFooter, error) { return deserializeFooter(alg, buf) } diff --git a/pkg/internal/serialization/deserializer_test.go b/pkg/internal/serialization/deserializer_test.go index 659bcf37..4e76de0c 100644 --- a/pkg/internal/serialization/deserializer_test.go +++ b/pkg/internal/serialization/deserializer_test.go @@ -202,8 +202,8 @@ func TestDeserializer_DeserializeBody(t *testing.T) { func TestDeserializer_DeserializeFooter(t *testing.T) { type args struct { - alg *suite.AlgorithmSuite buf *bytes.Buffer + alg *suite.AlgorithmSuite } tests := []struct { name string @@ -214,8 +214,8 @@ func TestDeserializer_DeserializeFooter(t *testing.T) { { name: "Nil Buffer", args: args{ - alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, buf: nil, + alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, }, want: nil, wantErr: true, @@ -223,8 +223,8 @@ func TestDeserializer_DeserializeFooter(t *testing.T) { { name: "Valid Footer Deserialize", args: args{ - alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, buf: bytes.NewBuffer(concatSlices([]byte{0x0, 0x67}, make([]byte, 103))), + alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, }, want: &footer{ algorithmSuite: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, @@ -237,7 +237,7 @@ func TestDeserializer_DeserializeFooter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d := &Deserializer{} - got, err := d.DeserializeFooter(tt.args.alg, tt.args.buf) + got, err := d.DeserializeFooter(tt.args.buf, tt.args.alg) if tt.wantErr { assert.Error(t, err) assert.Nil(t, got) diff --git a/pkg/model/format/body.go b/pkg/model/format/body.go index 5cbe22e6..625f2fc7 100644 --- a/pkg/model/format/body.go +++ b/pkg/model/format/body.go @@ -3,17 +3,33 @@ package format +// BodyFrame contains information about the body frame. type BodyFrame interface { Serializable + + // IsFinal indicates true if the frame is final. IsFinal() bool + + // SequenceNumber returns the frame sequence number. SequenceNumber() int + + // IV returns the frame IV. IV() []byte + + // EncryptedContent returns the frame encrypted content. EncryptedContent() []byte + + // AuthenticationTag returns the frame authentication tag. AuthenticationTag() []byte } +// MessageBody contains information about the message body. type MessageBody interface { Serializable + + // Frames returns the body frames. Frames() []BodyFrame + + // AddFrame adds new BodyFrame to the body. AddFrame(final bool, seqNum int, IV []byte, contentLength int, ciphertext, authTag []byte) error } diff --git a/pkg/model/format/doc.go b/pkg/model/format/doc.go new file mode 100644 index 00000000..17233f7e --- /dev/null +++ b/pkg/model/format/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package format provides set of interfaces for SDK message format. +package format diff --git a/pkg/model/format/footer.go b/pkg/model/format/footer.go index 465adace..4929aaa7 100644 --- a/pkg/model/format/footer.go +++ b/pkg/model/format/footer.go @@ -3,8 +3,13 @@ package format +// MessageFooter contains information about the message footer. type MessageFooter interface { Serializable + + // SignLen returns the length of the signature. SignLen() int + + // Signature returns the signature. Signature() []byte } diff --git a/pkg/model/format/header.go b/pkg/model/format/header.go index 85d7eb1a..61427cdc 100644 --- a/pkg/model/format/header.go +++ b/pkg/model/format/header.go @@ -7,50 +7,96 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// Serializable is an interface for objects that can be serialized to bytes. type Serializable interface { + // Len returns the length of the serialized object. Len() int + // Bytes returns the serialized object. Bytes() []byte } -type messageHeaderBase interface { +// MessageHeaderBase is the common interface for the message header. +type MessageHeaderBase interface { + // Version returns the message format version. Version() suite.MessageFormatVersion + + // AlgorithmSuite returns the algorithm suite used with the message. AlgorithmSuite() *suite.AlgorithmSuite + + // MessageID returns the message ID. MessageID() []byte + + // AADLength returns the length of the additional authenticated data. AADLength() int + + // AADData returns the additional authenticated data. AADData() MessageAAD + + // EncryptedDataKeyCount returns the number of encrypted data keys. EncryptedDataKeyCount() int + + // EncryptedDataKeys returns the encrypted data keys. EncryptedDataKeys() []MessageEDK + + // ContentType returns the content type. ContentType() suite.ContentType + + // FrameLength returns the frame length. FrameLength() int } +// MessageHeader contains information about the message header. type MessageHeader interface { Serializable - messageHeaderBase - Type() suite.MessageType // present only in V1 - Reserved() []byte // present only in V1 - IVLength() int // present only in V1 - AlgorithmSuiteData() []byte // present only in V2 + MessageHeaderBase + + // Type returns the message type. Present only in V1. + Type() suite.MessageType + + // Reserved returns the reserved bytes. Present only in V1. + Reserved() []byte + + // IVLength returns the length of the IV. Present only in V1. + IVLength() int + + // AlgorithmSuiteData returns the algorithm suite data. Present only in V2. + AlgorithmSuiteData() []byte } +// MessageEDK contains information about the encrypted data key. type MessageEDK interface { Serializable + + // ProviderID returns the provider ID. ProviderID() string + + // ProviderInfo returns the provider info. ProviderInfo() string + + // EncryptedDataKey returns the encrypted data key. EncryptedDataKey() []byte } +// MessageAAD contains information about the additional authenticated data. type MessageAAD interface { Serializable + + // EncryptionContext returns the encryption context. EncryptionContext() suite.EncryptionContext } +// MessageHeaderAuth contains information about the message header authentication. type MessageHeaderAuth interface { Serializable + + // AuthData returns the authentication data. AuthData() []byte - IV() []byte // present only in V1 + + // IV returns the IV. Present only in V1. + IV() []byte } +// HeaderParams contains the parameters to be used to create [MessageHeader]. type HeaderParams struct { AlgorithmSuite *suite.AlgorithmSuite MessageID []byte diff --git a/pkg/model/format/serialization.go b/pkg/model/format/serialization.go index 4e8d9450..71782fce 100644 --- a/pkg/model/format/serialization.go +++ b/pkg/model/format/serialization.go @@ -9,15 +9,42 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// Deserializer defines methods for deserializing encrypted message components. type Deserializer interface { + // DeserializeHeader deserializes a message header from a buffer. + // It takes a buffer and a maximum number of encrypted data keys as input. + // It returns a MessageHeader, MessageHeaderAuth, and an error if any. DeserializeHeader(buf *bytes.Buffer, maxEncryptedDataKeys int) (MessageHeader, MessageHeaderAuth, error) - DeserializeBody(buf *bytes.Buffer, algorithm *suite.AlgorithmSuite, frameLen int) (MessageBody, error) - DeserializeFooter(alg *suite.AlgorithmSuite, buf *bytes.Buffer) (MessageFooter, error) + + // DeserializeBody deserializes a message body from a buffer. + // It takes a buffer, an algorithm suite, and a frame length as input. + // It returns a MessageBody and an error if any. + DeserializeBody(buf *bytes.Buffer, alg *suite.AlgorithmSuite, frameLen int) (MessageBody, error) + + // DeserializeFooter deserializes a message footer from a buffer. + // It takes a buffer and an algorithm suite as input. + // It returns a MessageFooter and an error if any. + DeserializeFooter(buf *bytes.Buffer, alg *suite.AlgorithmSuite) (MessageFooter, error) } +// Serializer defines methods for serializing encrypted message components. type Serializer interface { + // SerializeHeader serializes a message header. + // It takes header parameters as input and returns a MessageHeader and an error if any. SerializeHeader(p HeaderParams) (MessageHeader, error) + + // SerializeHeaderAuth serializes a message header authentication data. + // It takes a message format version, an initialization vector, and authentication data as input. + // It returns a MessageHeaderAuth and an error if any. SerializeHeaderAuth(v suite.MessageFormatVersion, iv, authData []byte) (MessageHeaderAuth, error) + + // SerializeBody serializes a message body. + // It takes an algorithm suite and a frame length as input. + // It returns a MessageBody and an error if any. SerializeBody(alg *suite.AlgorithmSuite, frameLength int) (MessageBody, error) + + // SerializeFooter serializes a message footer. + // It takes an algorithm suite and a signature as input. + // It returns a MessageFooter and an error if any. SerializeFooter(alg *suite.AlgorithmSuite, signature []byte) (MessageFooter, error) } From 7e7c73ed58f1c079dc978c2c3b7f5a4b8ae3a50e Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 20:23:46 +0200 Subject: [PATCH 04/30] docs: SDK model package documentation --- pkg/model/doc.go | 5 ++++ pkg/model/edk.go | 11 ++++++++ pkg/model/encryption.go | 15 +++++++++++ pkg/model/encryption_material.go | 31 ++++++++++++++++++++--- pkg/model/key.go | 26 ++++++++++++++----- pkg/model/kms.go | 2 ++ pkg/model/masterkey.go | 16 ++++++++++++ pkg/model/materialsmgr.go | 28 ++++++++++++++++++++- pkg/model/provider.go | 43 ++++++++++++++++++++++++++++---- pkg/model/wrappingkey.go | 8 ++++++ 10 files changed, 170 insertions(+), 15 deletions(-) create mode 100644 pkg/model/doc.go diff --git a/pkg/model/doc.go b/pkg/model/doc.go new file mode 100644 index 00000000..b7db08b5 --- /dev/null +++ b/pkg/model/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package model contains SDK data model. +package model diff --git a/pkg/model/edk.go b/pkg/model/edk.go index f6c67593..36cd5933 100644 --- a/pkg/model/edk.go +++ b/pkg/model/edk.go @@ -3,6 +3,7 @@ package model +// DataKey contains unencrypted data key and its encrypted version. type DataKey struct { provider KeyMeta dataKey []byte @@ -11,26 +12,32 @@ type DataKey struct { var _ DataKeyI = (*DataKey)(nil) +// NewDataKey returns a new [DataKey] with the given provider, dataKey, and encryptedDataKey. func NewDataKey(provider KeyMeta, dataKey, encryptedDataKey []byte) *DataKey { return &DataKey{provider: provider, dataKey: dataKey, encryptedDataKey: encryptedDataKey} } +// KeyProvider returns the [KeyMeta] of the key. func (dk DataKey) KeyProvider() KeyMeta { return dk.provider } +// KeyID returns the ID of the key. func (dk DataKey) KeyID() string { return dk.provider.KeyID } +// EncryptedDataKey returns the encrypted data key of data key. func (dk DataKey) EncryptedDataKey() []byte { return dk.encryptedDataKey } +// DataKey returns unencrypted data key. func (dk DataKey) DataKey() []byte { return dk.dataKey } +// EncryptedDataKey contains the encrypted data key and its provider. type EncryptedDataKey struct { provider KeyMeta encryptedDataKey []byte @@ -38,6 +45,7 @@ type EncryptedDataKey struct { var _ EncryptedDataKeyI = (*EncryptedDataKey)(nil) +// NewEncryptedDataKey returns a new [EncryptedDataKey] with the given provider and encryptedDataKey. func NewEncryptedDataKey(provider KeyMeta, encryptedDataKey []byte) *EncryptedDataKey { return &EncryptedDataKey{ provider: provider, @@ -45,14 +53,17 @@ func NewEncryptedDataKey(provider KeyMeta, encryptedDataKey []byte) *EncryptedDa } } +// KeyProvider returns the [KeyMeta] of the key. func (edk EncryptedDataKey) KeyProvider() KeyMeta { return edk.provider } +// KeyID returns the ID of the key. func (edk EncryptedDataKey) KeyID() string { return edk.provider.KeyID } +// EncryptedDataKey returns the encrypted data key of data key. func (edk EncryptedDataKey) EncryptedDataKey() []byte { return edk.encryptedDataKey } diff --git a/pkg/model/encryption.go b/pkg/model/encryption.go index d76ca4cc..6fd8069e 100644 --- a/pkg/model/encryption.go +++ b/pkg/model/encryption.go @@ -11,17 +11,32 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// DecryptionHandler is an interface for decryption handler implementations. type DecryptionHandler interface { + // Decrypt decrypts ciphertext encrypted message and returns the decrypted + // plaintext and associated message header. Decrypt(ctx context.Context, ciphertext []byte) ([]byte, format.MessageHeader, error) } +// EncryptionHandler is an interface for encryption handler implementations. type EncryptionHandler interface { + // Encrypt encrypts the plaintext and returns the encrypted ciphertext and + // associated message header. Encrypt(ctx context.Context, source []byte, ec suite.EncryptionContext) ([]byte, format.MessageHeader, error) } +// EncryptionBuffer is an interface to be used as a buffer for encryption. See +// [bytes.Buffer] for more details on Bytes, Len and Reset methods. type EncryptionBuffer interface { io.ReadWriter + + // Bytes returns a slice of buffer length holding the unread portion of the + // buffer. Bytes() []byte + + // Len returns the number of bytes of the unread portion of the buffer. Len() int + + // Reset resets the buffer to be empty. Reset() } diff --git a/pkg/model/encryption_material.go b/pkg/model/encryption_material.go index 2bfb3ee5..259c4a51 100644 --- a/pkg/model/encryption_material.go +++ b/pkg/model/encryption_material.go @@ -9,12 +9,20 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// EncryptionMaterialsRequest is a request to get [EncryptionMaterial] from a [CryptoMaterialsManager]. type EncryptionMaterialsRequest struct { + // EncryptionContext is a map of key-value pairs that will be used to generate + // primary data key, and encrypt other data keys. EncryptionContext suite.EncryptionContext - Algorithm *suite.AlgorithmSuite - PlaintextLength int + + // Algorithm is the algorithm to be used for encryption. + Algorithm *suite.AlgorithmSuite + + // PlaintextLength is the length of the plaintext to be encrypted. + PlaintextLength int } +// EncryptionMaterials contains the encryption materials produced by a [CryptoMaterialsManager]. type EncryptionMaterials struct { dataEncryptionKey DataKeyI encryptedDataKeys []EncryptedDataKeyI @@ -22,45 +30,62 @@ type EncryptionMaterials struct { signingKey *ecdsa.PrivateKey } +// NewEncryptionMaterials returns a new instance of [EncryptionMaterials]. func NewEncryptionMaterials(dataEncryptionKey DataKeyI, encryptedDataKeys []EncryptedDataKeyI, ec suite.EncryptionContext, signingKey *ecdsa.PrivateKey) *EncryptionMaterials { return &EncryptionMaterials{dataEncryptionKey: dataEncryptionKey, encryptedDataKeys: encryptedDataKeys, encryptionContext: ec, signingKey: signingKey} } +// DataEncryptionKey returns the data encryption key to be used for encryption. func (e EncryptionMaterials) DataEncryptionKey() DataKeyI { return e.dataEncryptionKey } +// EncryptedDataKeys returns the encrypted data keys encrypted with primary master key provider data key. func (e EncryptionMaterials) EncryptedDataKeys() []EncryptedDataKeyI { return e.encryptedDataKeys } +// EncryptionContext returns the encryption context associated with the encryption. func (e EncryptionMaterials) EncryptionContext() suite.EncryptionContext { return e.encryptionContext } +// SigningKey returns the signing key used to sign the footer. It returns nil if +// non-signing algorithm is used. func (e EncryptionMaterials) SigningKey() *ecdsa.PrivateKey { return e.signingKey } +// DecryptionMaterialsRequest is a request to get [DecryptionMaterial] from a [CryptoMaterialsManager]. type DecryptionMaterialsRequest struct { - Algorithm *suite.AlgorithmSuite + // Algorithm is the algorithm to be used for decryption. + Algorithm *suite.AlgorithmSuite + + // EncryptedDataKeys is a list of encrypted data keys to decrypt data key. EncryptedDataKeys []EncryptedDataKeyI + + // EncryptionContext is a map of key-value pairs that will be used to decrypt data keys. EncryptionContext suite.EncryptionContext } +// DecryptionMaterials contains the decryption materials produced by a [CryptoMaterialsManager]. type DecryptionMaterials struct { dataKey DataKeyI verificationKey []byte } +// NewDecryptionMaterials returns a new instance of [DecryptionMaterial]. func NewDecryptionMaterials(dataKey DataKeyI, verificationKey []byte) *DecryptionMaterials { return &DecryptionMaterials{dataKey: dataKey, verificationKey: verificationKey} } +// DataKey returns the data encryption key to be used for decryption. func (d DecryptionMaterials) DataKey() DataKeyI { return d.dataKey } +// VerificationKey returns a verification key used to verify footer signature. It +// returns nil if non-signing algorithm is used. func (d DecryptionMaterials) VerificationKey() []byte { return d.verificationKey } diff --git a/pkg/model/key.go b/pkg/model/key.go index ec9c11da..9a7fb2ff 100644 --- a/pkg/model/key.go +++ b/pkg/model/key.go @@ -3,32 +3,44 @@ package model -type KeyBase interface { +// Key is a base interface for both [DataKey] and [EncryptedDataKey]. +type Key interface { + // KeyProvider returns the KeyMeta of the key. KeyProvider() KeyMeta - KeyID() string -} -type Key interface { - KeyBase + // KeyID returns the ID of the key. + KeyID() string } +// DataKeyI is an interface for [DataKey]. type DataKeyI interface { Key + // EncryptedDataKey returns the encrypted data key of data key. EncryptedDataKey() []byte + + // DataKey returns unencrypted data key. DataKey() []byte } +// EncryptedDataKeyI is an interface for [EncryptedDataKey]. type EncryptedDataKeyI interface { Key + + // EncryptedDataKey returns the encrypted data key of data key. EncryptedDataKey() []byte } +// KeyMeta is a struct that holds metadata of a [Key]. type KeyMeta struct { + // ProviderID is the ID of the key provider. ProviderID string - KeyID string + + // KeyID is the ID of the key. + KeyID string } +// WithKeyMeta returns a new [KeyMeta] with the given providerID and keyID. func WithKeyMeta(providerID, keyID string) KeyMeta { return KeyMeta{ ProviderID: providerID, @@ -36,6 +48,7 @@ func WithKeyMeta(providerID, keyID string) KeyMeta { } } +// Equal returns true if the given [KeyMeta] is equal to the current [KeyMeta]. func (km KeyMeta) Equal(other KeyMeta) bool { if km.ProviderID != other.ProviderID || km.KeyID != other.KeyID { return false @@ -43,6 +56,7 @@ func (km KeyMeta) Equal(other KeyMeta) bool { return true } +// String returns a string representation of the [KeyMeta]. func (km KeyMeta) String() string { return km.ProviderID + "__" + km.KeyID } diff --git a/pkg/model/kms.go b/pkg/model/kms.go index 3379d933..ee44c999 100644 --- a/pkg/model/kms.go +++ b/pkg/model/kms.go @@ -10,12 +10,14 @@ import ( "github.com/aws/aws-sdk-go-v2/service/kms" ) +// KMSClient is an interface for the AWS KMS client. type KMSClient interface { GenerateDataKey(ctx context.Context, params *kms.GenerateDataKeyInput, optFns ...func(*kms.Options)) (*kms.GenerateDataKeyOutput, error) Encrypt(ctx context.Context, params *kms.EncryptInput, optFns ...func(*kms.Options)) (*kms.EncryptOutput, error) Decrypt(ctx context.Context, params *kms.DecryptInput, optFns ...func(*kms.Options)) (*kms.DecryptOutput, error) } +// KMSClientFactory is an interface for the AWS KMS client factory. type KMSClientFactory interface { NewFromConfig(cfg aws.Config, optFns ...func(options *kms.Options)) KMSClient } diff --git a/pkg/model/masterkey.go b/pkg/model/masterkey.go index 2b726aad..efdefa1e 100644 --- a/pkg/model/masterkey.go +++ b/pkg/model/masterkey.go @@ -9,19 +9,35 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// MasterKeyBase is the base interface for all master keys. type MasterKeyBase interface { + // KeyID returns the key ID of the master key. KeyID() string + + // Metadata returns the metadata of the master key. Metadata() KeyMeta + + // OwnsDataKey returns true if key is owned by the master key. In other words, + // the key was encrypted with the master key. OwnsDataKey(key Key) bool } +// MasterKey is an interface for master key implementations. type MasterKey interface { MasterKeyBase + + // GenerateDataKey generates a new data key and returns it. GenerateDataKey(ctx context.Context, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (DataKeyI, error) + + // EncryptDataKey encrypts the data key and returns the encrypted data key. EncryptDataKey(ctx context.Context, dataKey DataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (EncryptedDataKeyI, error) + + // DecryptDataKey decrypts the encrypted data key and returns the data key. DecryptDataKey(ctx context.Context, encryptedDataKey EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (DataKeyI, error) } +// MasterKeyFactory is an interface for master key factory. type MasterKeyFactory interface { + // NewMasterKey returns a new instance of master key. NewMasterKey(args ...interface{}) (MasterKey, error) } diff --git a/pkg/model/materialsmgr.go b/pkg/model/materialsmgr.go index ce7e2927..6db1c751 100644 --- a/pkg/model/materialsmgr.go +++ b/pkg/model/materialsmgr.go @@ -10,20 +10,46 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// CryptoMaterialsManager is an interface for crypto materials manager implementations. type CryptoMaterialsManager interface { + // GetEncryptionMaterials returns the encryption materials for the given request. + // Used during encryption process to get the encryption materials from registered + // master key providers. GetEncryptionMaterials(ctx context.Context, request EncryptionMaterialsRequest) (EncryptionMaterial, error) + + // DecryptMaterials returns the decryption materials for the given request. Used + // during decryption process to get the decryption materials from registered + // master key providers. DecryptMaterials(ctx context.Context, request DecryptionMaterialsRequest) (DecryptionMaterial, error) - GetInstance() CryptoMaterialsManager // TODO research and test + + // GetInstance returns a new instance of the crypto materials manager to interact + // within encryption/decryption process. + GetInstance() CryptoMaterialsManager } +// DecryptionMaterial is an interface for decryption material. type DecryptionMaterial interface { + // DataKey returns the data key used for decryption. DataKey() DataKeyI + + // VerificationKey returns a verification key used to verify footer signature. It + // returns nil if non-signing algorithm is used. VerificationKey() []byte } +// EncryptionMaterial is an interface for encryption material. type EncryptionMaterial interface { + // DataEncryptionKey returns the data encryption key to be used for encryption. DataEncryptionKey() DataKeyI + + // EncryptedDataKeys returns the encrypted data keys encrypted with primary + // master key provider data key. EncryptedDataKeys() []EncryptedDataKeyI + + // EncryptionContext returns the encryption context associated with the encryption. EncryptionContext() suite.EncryptionContext + + // SigningKey returns the signing key used to sign the footer. It returns nil if + // non-signing algorithm is used. SigningKey() *ecdsa.PrivateKey } diff --git a/pkg/model/provider.go b/pkg/model/provider.go index 9b3f21d2..981f1d44 100644 --- a/pkg/model/provider.go +++ b/pkg/model/provider.go @@ -10,29 +10,62 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// BaseKeyProvider is the base interface for key provider. It responsible for a +// logic of decrypting encrypted data keys for an abstract [MasterKeyProvider]. type BaseKeyProvider interface { + // ID returns the ID of the key provider. ID() string + + // Kind returns the kind of the key provider. Kind() types.ProviderKind + + // VendOnDecrypt returns true if the key provider indicates that it can decrypt + // encrypted data keys that is not registered with master key provider. VendOnDecrypt() bool + + // DecryptDataKey attempts to decrypt the encrypted data key and returns the data + // key. DecryptDataKey(ctx context.Context, MKP MasterKeyProvider, encryptedDataKey EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (DataKeyI, error) + + // DecryptDataKeyFromList attempts to decrypt the encrypted data keys and returns + // the data key. DecryptDataKeyFromList(ctx context.Context, MKP MasterKeyProvider, encryptedDataKeys []EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (DataKeyI, error) } -type ProviderBase interface { +// MasterKeyProvider is an interface for master key provider implementations. +type MasterKeyProvider interface { //nolint:interfacebloat + // ProviderKind returns the kind of the master key provider. ProviderKind() types.ProviderKind + + // ProviderID returns the ID of the master key provider. ProviderID() string - ValidateProviderID(otherID string) error -} -type MasterKeyProvider interface { - ProviderBase + // ValidateProviderID validates master key provider ID matches the given provider ID. + ValidateProviderID(otherID string) error + // AddMasterKey creates a new master key and adds it to the master key provider. AddMasterKey(keyID string) (MasterKey, error) + + // NewMasterKey returns a new instance of master key. NewMasterKey(ctx context.Context, keyID string) (MasterKey, error) + + // MasterKeysForEncryption returns the primary master key and a list of master + // keys for encryption. MasterKeysForEncryption(ctx context.Context, ec suite.EncryptionContext) (MasterKey, []MasterKey, error) + + // MasterKeyForDecrypt returns the master key for the given metadata. MasterKeyForDecrypt(ctx context.Context, metadata KeyMeta) (MasterKey, error) + + // DecryptDataKey attempts to decrypt the encrypted data key with a KeyProvider. DecryptDataKey(ctx context.Context, encryptedDataKey EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (DataKeyI, error) + + // DecryptDataKeyFromList attempts to decrypt the encrypted data keys with a + // KeyProvider. DecryptDataKeyFromList(ctx context.Context, encryptedDataKeys []EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (DataKeyI, error) + + // ValidateMasterKey validates the master key with the given key ID. ValidateMasterKey(keyID string) error + + // MasterKeysForDecryption returns the list of master keys for decryption. MasterKeysForDecryption() []MasterKey } diff --git a/pkg/model/wrappingkey.go b/pkg/model/wrappingkey.go index 4264066d..8595af2c 100644 --- a/pkg/model/wrappingkey.go +++ b/pkg/model/wrappingkey.go @@ -3,8 +3,16 @@ package model +// Wrapper is an interface for wrapping key implementations. type Wrapper interface { + // SerializeEncryptedDataKey serializes the encrypted data key and returns the + // serialized form. SerializeEncryptedDataKey(encryptedKey, tag, iv []byte) []byte + + // DeserializeEncryptedDataKey deserializes the encrypted data key and returns + // the encrypted data key, tag and IV. DeserializeEncryptedDataKey(b []byte, iVLen int) (encryptedData, iv []byte) + + // SerializeKeyInfoPrefix serializes the key ID and returns the serialized form. SerializeKeyInfoPrefix(keyID string) []byte } From 006146be711105cc7f876daa5aa75798c379e534 Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 20:40:13 +0200 Subject: [PATCH 05/30] refactor(suite): get rid of a global variable --- pkg/client/options.go | 2 +- pkg/internal/serialization/messageheader.go | 4 ++-- pkg/suite/algorithm.go | 10 +++------- pkg/suite/algorithm_test.go | 10 ++++------ 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/pkg/client/options.go b/pkg/client/options.go index 8cae0312..7d6de304 100644 --- a/pkg/client/options.go +++ b/pkg/client/options.go @@ -78,7 +78,7 @@ func WithAlgorithm(alg *suite.AlgorithmSuite) EncryptOptionFunc { if alg == nil { return fmt.Errorf("algorithm must not be nil") } - if _, err := suite.Algorithm.ByID(alg.AlgorithmID); err != nil { + if _, err := suite.ByID(alg.AlgorithmID); err != nil { return fmt.Errorf("algorithm error: %w", err) } o.Algorithm = alg diff --git a/pkg/internal/serialization/messageheader.go b/pkg/internal/serialization/messageheader.go index 6b71479c..2e416980 100644 --- a/pkg/internal/serialization/messageheader.go +++ b/pkg/internal/serialization/messageheader.go @@ -58,7 +58,7 @@ func newHeader(p format.HeaderParams) (format.MessageHeader, error) { if p.AlgorithmSuite == nil { return nil, fmt.Errorf("invalid AlgorithmSuite: %v", p.AlgorithmSuite) } - _, err := suite.Algorithm.ByID(p.AlgorithmSuite.AlgorithmID) + _, err := suite.ByID(p.AlgorithmSuite.AlgorithmID) if err != nil { return nil, fmt.Errorf("unsupported AlgorithmID: %w", err) } @@ -137,7 +137,7 @@ func deserializeHeader(buf *bytes.Buffer) (format.MessageHeader, error) { //noli algorithmID := buf.Next(algorithmIDFieldBytes) // AlgorithmID is 2 bytes, uint16 // validate AlgorithmID is supported - algorithmSuite, err := suite.Algorithm.FromBytes(algorithmID) + algorithmSuite, err := suite.FromBytes(algorithmID) if err != nil { return nil, err } diff --git a/pkg/suite/algorithm.go b/pkg/suite/algorithm.go index 49a945df..95335dd1 100644 --- a/pkg/suite/algorithm.go +++ b/pkg/suite/algorithm.go @@ -220,12 +220,8 @@ func newAlgorithmSuite(algorithmID uint16, encryptionSuite encryptionSuite, mess return alg } -var Algorithm algorithm - -type algorithm struct{} - // ByID returns proper AlgorithmSuite by its algorithmID 16-bit unsigned integer -func (algorithm) ByID(algorithmID uint16) (*AlgorithmSuite, error) { +func ByID(algorithmID uint16) (*AlgorithmSuite, error) { val, ok := algorithmLookup[algorithmID] if !ok { return nil, fmt.Errorf("%#v algorithm not supported: %w", algorithmID, ErrAlgorithmSuite) @@ -234,9 +230,9 @@ func (algorithm) ByID(algorithmID uint16) (*AlgorithmSuite, error) { } // FromBytes returns proper AlgorithmSuite from slice of bytes, slice must have a length of 2 bytes -func (alg algorithm) FromBytes(b []byte) (*AlgorithmSuite, error) { +func FromBytes(b []byte) (*AlgorithmSuite, error) { if len(b) != algorithmIDLen { return nil, fmt.Errorf("%#v algorithm size must be 2 bytes: %w", b, ErrAlgorithmSuite) } - return alg.ByID(conv.FromBytes.UUint16BigEndian(b)) + return ByID(conv.FromBytes.UUint16BigEndian(b)) } diff --git a/pkg/suite/algorithm_test.go b/pkg/suite/algorithm_test.go index bd9c8594..41f09727 100644 --- a/pkg/suite/algorithm_test.go +++ b/pkg/suite/algorithm_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_algorithm_ByID(t *testing.T) { +func Test_ByID(t *testing.T) { type args struct { algorithmID uint16 } @@ -37,8 +37,7 @@ func Test_algorithm_ByID(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - al := algorithm{} - got, err := al.ByID(tt.args.algorithmID) + got, err := ByID(tt.args.algorithmID) if (err != nil) != tt.wantErr { t.Errorf("ByID() error = %v, wantErr %v", err, tt.wantErr) return @@ -50,7 +49,7 @@ func Test_algorithm_ByID(t *testing.T) { } } -func Test_algorithm_FromBytes(t *testing.T) { +func Test_FromBytes(t *testing.T) { type args struct { b []byte } @@ -69,8 +68,7 @@ func Test_algorithm_FromBytes(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - alg := algorithm{} - got, err := alg.FromBytes(tt.args.b) + got, err := FromBytes(tt.args.b) if (err != nil) != tt.wantErr { t.Errorf("FromBytes() error = %v, wantErr %v", err, tt.wantErr) return From 3e517061d16994fbb0dd9ecf594e0a89b689c3cd Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 23:01:38 +0200 Subject: [PATCH 06/30] refactor(suite): move MessageType to format package --- .../pkg/model/format/MessageHeader_mock.go | 12 ++++++------ pkg/internal/serialization/messageheader.go | 14 +++++++------- pkg/internal/serialization/messageheader_test.go | 6 +++--- pkg/model/format/consts.go | 12 ++++++++++++ pkg/model/format/header.go | 2 +- 5 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 pkg/model/format/consts.go diff --git a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/MessageHeader_mock.go b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/MessageHeader_mock.go index ab31e8d2..7932bec2 100644 --- a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/MessageHeader_mock.go +++ b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format/MessageHeader_mock.go @@ -624,18 +624,18 @@ func (_c *MockMessageHeader_Reserved_Call) RunAndReturn(run func() []byte) *Mock } // Type provides a mock function with given fields: -func (_m *MockMessageHeader) Type() suite.MessageType { +func (_m *MockMessageHeader) Type() format.MessageType { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for Type") } - var r0 suite.MessageType - if rf, ok := ret.Get(0).(func() suite.MessageType); ok { + var r0 format.MessageType + if rf, ok := ret.Get(0).(func() format.MessageType); ok { r0 = rf() } else { - r0 = ret.Get(0).(suite.MessageType) + r0 = ret.Get(0).(format.MessageType) } return r0 @@ -658,12 +658,12 @@ func (_c *MockMessageHeader_Type_Call) Run(run func()) *MockMessageHeader_Type_C return _c } -func (_c *MockMessageHeader_Type_Call) Return(_a0 suite.MessageType) *MockMessageHeader_Type_Call { +func (_c *MockMessageHeader_Type_Call) Return(_a0 format.MessageType) *MockMessageHeader_Type_Call { _c.Call.Return(_a0) return _c } -func (_c *MockMessageHeader_Type_Call) RunAndReturn(run func() suite.MessageType) *MockMessageHeader_Type_Call { +func (_c *MockMessageHeader_Type_Call) RunAndReturn(run func() format.MessageType) *MockMessageHeader_Type_Call { _c.Call.Return(run) return _c } diff --git a/pkg/internal/serialization/messageheader.go b/pkg/internal/serialization/messageheader.go index 2e416980..67222e59 100644 --- a/pkg/internal/serialization/messageheader.go +++ b/pkg/internal/serialization/messageheader.go @@ -44,9 +44,9 @@ type messageHeader struct { type messageHeaderV1 struct { messageHeader - messageType suite.MessageType // 1, format.MessageType, present only in V1 - reserved []byte // 4, reserved, present only in V1, always 0x00,0x00,0x00,0x00 - ivLen int // 1, length of IV, present only in V1, always 12 + messageType format.MessageType // 1, format.MessageType, present only in V1 + reserved []byte // 4, reserved, present only in V1, always 0x00,0x00,0x00,0x00 + ivLen int // 1, length of IV, present only in V1, always 12 } type messageHeaderV2 struct { @@ -105,7 +105,7 @@ func newHeader(p format.HeaderParams) (format.MessageHeader, error) { return &messageHeaderV1{ messageHeader: header, - messageType: suite.CustomerAEData, + messageType: format.CustomerAEData, reserved: reservedField, ivLen: p.AlgorithmSuite.EncryptionSuite.IVLen, }, nil @@ -129,7 +129,7 @@ func deserializeHeader(buf *bytes.Buffer) (format.MessageHeader, error) { //noli if messageVersion == suite.V1 { messageType := fieldReader.ReadSingleField(buf) - if suite.MessageType(messageType) != suite.CustomerAEData { + if format.MessageType(messageType) != format.CustomerAEData { return nil, fmt.Errorf("invalid messageType %v not supported: %w", messageType, errHeaderDeserialize) } } @@ -341,7 +341,7 @@ func (h *messageHeader) FrameLength() int { return h.frameLength } -func (h *messageHeaderV1) Type() suite.MessageType { +func (h *messageHeaderV1) Type() format.MessageType { return h.messageType } @@ -357,7 +357,7 @@ func (h *messageHeaderV1) AlgorithmSuiteData() []byte { return nil } -func (h *messageHeaderV2) Type() suite.MessageType { +func (h *messageHeaderV2) Type() format.MessageType { return 0 } diff --git a/pkg/internal/serialization/messageheader_test.go b/pkg/internal/serialization/messageheader_test.go index f48c5e54..62d4e0b4 100644 --- a/pkg/internal/serialization/messageheader_test.go +++ b/pkg/internal/serialization/messageheader_test.go @@ -81,7 +81,7 @@ func TestNewHeader(t *testing.T) { contentType: suite.FramedContent, frameLength: 1024, }, - messageType: suite.CustomerAEData, + messageType: format.CustomerAEData, reserved: reservedField, ivLen: 12, } @@ -98,7 +98,7 @@ func TestNewHeader(t *testing.T) { contentType: suite.FramedContent, frameLength: 1024, }, - messageType: suite.CustomerAEData, + messageType: format.CustomerAEData, reserved: reservedField, ivLen: 12, } @@ -253,7 +253,7 @@ func Test_deserializeHeader(t *testing.T) { contentType: suite.FramedContent, frameLength: 1024, }, - messageType: suite.CustomerAEData, + messageType: format.CustomerAEData, reserved: reservedV1, ivLen: 12, } diff --git a/pkg/model/format/consts.go b/pkg/model/format/consts.go new file mode 100644 index 00000000..686ee637 --- /dev/null +++ b/pkg/model/format/consts.go @@ -0,0 +1,12 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package format + +// MessageType is the type of the message. The type indicates the kind of +// structure. The only supported type is [CustomerAEData]. +type MessageType int + +// CustomerAEData is a customer authenticated encrypted data. Its type value is +// 128, encoded as byte 80 in hexadecimal notation. +const CustomerAEData MessageType = 128 diff --git a/pkg/model/format/header.go b/pkg/model/format/header.go index 61427cdc..50d280a5 100644 --- a/pkg/model/format/header.go +++ b/pkg/model/format/header.go @@ -51,7 +51,7 @@ type MessageHeader interface { MessageHeaderBase // Type returns the message type. Present only in V1. - Type() suite.MessageType + Type() MessageType // Reserved returns the reserved bytes. Present only in V1. Reserved() []byte From fd76e8b9969ef828173e21cb38ea577b60d834bf Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 23:02:22 +0200 Subject: [PATCH 07/30] refactor(suite): move ContentAADString into bodyaad package --- pkg/internal/utils/bodyaad/bodyaad.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/internal/utils/bodyaad/bodyaad.go b/pkg/internal/utils/bodyaad/bodyaad.go index 3a9665f0..f7e8bf69 100644 --- a/pkg/internal/utils/bodyaad/bodyaad.go +++ b/pkg/internal/utils/bodyaad/bodyaad.go @@ -13,14 +13,21 @@ const ( lengthLen = int(8) // length as big-endian 64-bit unsigned integer ) +type contentAADString string + +const ( + contentAADFrame contentAADString = "AWSKMSEncryptionClient Frame" + contentAADFinalFrame contentAADString = "AWSKMSEncryptionClient Final Frame" +) + func ContentString(contentType suite.ContentType, finalFrame bool) ([]byte, error) { if err := suite.ValidateContentType(contentType); err != nil { return nil, err } if finalFrame { - return []byte(suite.ContentAADFinalFrame), nil + return []byte(contentAADFinalFrame), nil } - return []byte(suite.ContentAADFrame), nil + return []byte(contentAADFrame), nil } func ContentAADBytes(messageID, contentString []byte, seqNum, length int) []byte { From de1b7bc0bab8c30da9e5318179c89f972c1a182c Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 14 Mar 2024 23:03:12 +0200 Subject: [PATCH 08/30] docs: suite package documentation --- pkg/suite/algorithm.go | 72 ++++++++++++++++++++++++++++++------------ pkg/suite/consts.go | 38 ++++++++++++---------- pkg/suite/doc.go | 9 ++++++ pkg/suite/validate.go | 7 ++++ 4 files changed, 88 insertions(+), 38 deletions(-) create mode 100644 pkg/suite/doc.go diff --git a/pkg/suite/algorithm.go b/pkg/suite/algorithm.go index 95335dd1..d6c31db6 100644 --- a/pkg/suite/algorithm.go +++ b/pkg/suite/algorithm.go @@ -19,6 +19,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) +// ErrAlgorithmSuite is returned when algorithm suite is invalid or not supported. var ErrAlgorithmSuite = errors.New("algorithm suite error") type encAlgorithm string @@ -92,13 +93,14 @@ func newAuthenticationSuite(algorithm elliptic.Curve, hashFunc func() hash.Hash, return authenticationSuite{Algorithm: algorithm, HashFunc: hashFunc, SignatureLen: signatureLen} } +// AlgorithmSuite represents the algorithm suite used for encryption and decryption. type AlgorithmSuite struct { - AlgorithmID uint16 - name string - EncryptionSuite encryptionSuite - MessageFormatVersion MessageFormatVersion - KDFSuite kdfSuite - Authentication authenticationSuite + AlgorithmID uint16 // An identifier for the algorithm. It is a 2-byte value interpreted as a 16-bit unsigned integer. + EncryptionSuite encryptionSuite // Encryption of the algorithm suite + MessageFormatVersion MessageFormatVersion // Message format version + KDFSuite kdfSuite // Key Derivation Suite of the algorithm suite + Authentication authenticationSuite // Authentication Suite of the algorithm suite + name string // Name of the algorithm suite } func (as *AlgorithmSuite) GoString() string { @@ -138,33 +140,53 @@ func buildAlgorithmName(as *AlgorithmSuite) string { return sb.String() } +// Name returns the name of AlgorithmSuite. +// +// Example: +// +// AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 func (as *AlgorithmSuite) Name() string { - // format: AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 return as.name } +// String returns a string representation of AlgorithmSuite. +// +// Example: +// +// AlgID 0x0578: AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 func (as *AlgorithmSuite) String() string { - // format: AlgID 0x0578: AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 return fmt.Sprintf("AlgID 0x%04X: %s", as.AlgorithmID, as.Name()) } +// IDString returns the ID of AlgorithmSuite as a string. +// +// Example: +// +// 0578 func (as *AlgorithmSuite) IDString() string { // format: 0578 return fmt.Sprintf("%04X", as.AlgorithmID) } +// IDBytes returns the ID of AlgorithmSuite as a slice of bytes. func (as *AlgorithmSuite) IDBytes() []byte { return conv.FromInt.UUint16BigEndian(as.AlgorithmID) } +// IsSigning indicates whether the AlgorithmSuite is using ECDSA for signing over +// the ciphertext header and body. func (as *AlgorithmSuite) IsSigning() bool { return as.Authentication.Algorithm != nil } +// IsKDFSupported indicates whether the AlgorithmSuite is using key derivation to +// derive the data encryption key. func (as *AlgorithmSuite) IsKDFSupported() bool { return as.KDFSuite.KDFFunc != nil } +// IsCommitting indicates whether the AlgorithmSuite is using key commitment. +// Only [V2] message format version supports key commitment. func (as *AlgorithmSuite) IsCommitting() bool { if bytes.HasPrefix(as.IDBytes(), []byte{0x05}) || bytes.HasPrefix(as.IDBytes(), []byte{0x04}) { return true @@ -172,6 +194,7 @@ func (as *AlgorithmSuite) IsCommitting() bool { return false } +// MessageIDLen returns the length of the message ID. func (as *AlgorithmSuite) MessageIDLen() int { // all supported algorithmSuite MessageFormatVersion 1 has 16 bytes MessageID length if as.MessageFormatVersion == V1 { @@ -181,6 +204,7 @@ func (as *AlgorithmSuite) MessageIDLen() int { return messageIDLen } +// AlgorithmSuiteDataLen returns the length of the Algorithm Suite Data field. func (as *AlgorithmSuite) AlgorithmSuiteDataLen() int { if as.MessageFormatVersion == V1 { // Algorithm Suite Data field not present in MessageFormatVersion 1 @@ -190,24 +214,30 @@ func (as *AlgorithmSuite) AlgorithmSuiteDataLen() int { return algorithmSuiteDataLen } +// Supported [AlgorithmSuite] by AWS Encryption SDK. +// +// See [AWS Encryption SDK algorithms reference] for more information. +// +// [AWS Encryption SDK algorithms reference]: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/algorithms-reference.html +// //goland:noinspection GoSnakeCaseUsage,GoUnusedGlobalVariable var ( // MessageFormatVersion 1 algorithm suites - AES_128_GCM_IV12_TAG16 = newAlgorithmSuite(0x0014, aes_128_GCM_IV12_TAG16, V1, hkdf_NONE, authSuite_NONE) - AES_192_GCM_IV12_TAG16 = newAlgorithmSuite(0x0046, aes_192_GCM_IV12_TAG16, V1, hkdf_NONE, authSuite_NONE) - AES_256_GCM_IV12_TAG16 = newAlgorithmSuite(0x0078, aes_256_GCM_IV12_TAG16, V1, hkdf_NONE, authSuite_NONE) - AES_128_GCM_IV12_TAG16_HKDF_SHA256 = newAlgorithmSuite(0x0114, aes_128_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_NONE) - AES_192_GCM_IV12_TAG16_HKDF_SHA256 = newAlgorithmSuite(0x0146, aes_192_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_NONE) - AES_256_GCM_IV12_TAG16_HKDF_SHA256 = newAlgorithmSuite(0x0178, aes_256_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_NONE) - AES_128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256 = newAlgorithmSuite(0x0214, aes_128_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_SHA256_ECDSA_P256) - AES_192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 = newAlgorithmSuite(0x0346, aes_192_GCM_IV12_TAG16, V1, hkdf_SHA384, authSuite_SHA256_ECDSA_P384) - AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 = newAlgorithmSuite(0x0378, aes_256_GCM_IV12_TAG16, V1, hkdf_SHA384, authSuite_SHA256_ECDSA_P384) + AES_128_GCM_IV12_TAG16 = newAlgorithmSuite(0x0014, aes_128_GCM_IV12_TAG16, V1, hkdf_NONE, authSuite_NONE) // Algorithm ID: 00 14 + AES_192_GCM_IV12_TAG16 = newAlgorithmSuite(0x0046, aes_192_GCM_IV12_TAG16, V1, hkdf_NONE, authSuite_NONE) // Algorithm ID: 00 46 + AES_256_GCM_IV12_TAG16 = newAlgorithmSuite(0x0078, aes_256_GCM_IV12_TAG16, V1, hkdf_NONE, authSuite_NONE) // Algorithm ID: 00 78 + AES_128_GCM_IV12_TAG16_HKDF_SHA256 = newAlgorithmSuite(0x0114, aes_128_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_NONE) // Algorithm ID: 01 14 + AES_192_GCM_IV12_TAG16_HKDF_SHA256 = newAlgorithmSuite(0x0146, aes_192_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_NONE) // Algorithm ID: 01 46 + AES_256_GCM_IV12_TAG16_HKDF_SHA256 = newAlgorithmSuite(0x0178, aes_256_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_NONE) // Algorithm ID: 01 78 + AES_128_GCM_IV12_TAG16_HKDF_SHA256_ECDSA_P256 = newAlgorithmSuite(0x0214, aes_128_GCM_IV12_TAG16, V1, hkdf_SHA256, authSuite_SHA256_ECDSA_P256) // Algorithm ID: 02 14 + AES_192_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 = newAlgorithmSuite(0x0346, aes_192_GCM_IV12_TAG16, V1, hkdf_SHA384, authSuite_SHA256_ECDSA_P384) // Algorithm ID: 03 46 + AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384 = newAlgorithmSuite(0x0378, aes_256_GCM_IV12_TAG16, V1, hkdf_SHA384, authSuite_SHA256_ECDSA_P384) // Algorithm ID: 03 78 // MessageFormatVersion 2 algorithm suites with commitment - AES_256_GCM_HKDF_SHA512_COMMIT_KEY = newAlgorithmSuite(0x0478, aes_256_GCM_IV12_TAG16, V2, hkdf_SHA512, authSuite_NONE) - AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 = newAlgorithmSuite(0x0578, aes_256_GCM_IV12_TAG16, V2, hkdf_SHA512, authSuite_SHA256_ECDSA_P384) + AES_256_GCM_HKDF_SHA512_COMMIT_KEY = newAlgorithmSuite(0x0478, aes_256_GCM_IV12_TAG16, V2, hkdf_SHA512, authSuite_NONE) // Algorithm ID: 04 78 + AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384 = newAlgorithmSuite(0x0578, aes_256_GCM_IV12_TAG16, V2, hkdf_SHA512, authSuite_SHA256_ECDSA_P384) // Algorithm ID: 05 78 ) // Note: we are not accessing this map concurrently on write, so no need to use sync.Map. @@ -220,7 +250,7 @@ func newAlgorithmSuite(algorithmID uint16, encryptionSuite encryptionSuite, mess return alg } -// ByID returns proper AlgorithmSuite by its algorithmID 16-bit unsigned integer +// ByID returns [AlgorithmSuite] by its algorithmID 16-bit unsigned integer. func ByID(algorithmID uint16) (*AlgorithmSuite, error) { val, ok := algorithmLookup[algorithmID] if !ok { @@ -229,7 +259,7 @@ func ByID(algorithmID uint16) (*AlgorithmSuite, error) { return val, nil } -// FromBytes returns proper AlgorithmSuite from slice of bytes, slice must have a length of 2 bytes +// FromBytes returns [AlgorithmSuite] from slice of bytes, slice must have a length of 2 bytes. func FromBytes(b []byte) (*AlgorithmSuite, error) { if len(b) != algorithmIDLen { return nil, fmt.Errorf("%#v algorithm size must be 2 bytes: %w", b, ErrAlgorithmSuite) diff --git a/pkg/suite/consts.go b/pkg/suite/consts.go index 0bfdca3b..4a2636e5 100644 --- a/pkg/suite/consts.go +++ b/pkg/suite/consts.go @@ -13,22 +13,25 @@ const ( BlockSize = int(128) // BlockSize is aes.BlockSize in bits (16 * 8) ) +// ContentType is the type of encrypted data, either non-framed or framed. type ContentType uint8 +// Supported content types. const ( - NonFramedContent ContentType = 0x01 - FramedContent ContentType = 0x02 -) - -type ContentAADString string - -const ( - ContentAADFrame ContentAADString = "AWSKMSEncryptionClient Frame" - ContentAADFinalFrame ContentAADString = "AWSKMSEncryptionClient Final Frame" + NonFramedContent ContentType = 0x01 // Non-framed content is type 1, encoded as the byte 01 in hexadecimal notation. + FramedContent ContentType = 0x02 // Framed content is type 2, encoded as the byte 02 in hexadecimal notation. ) +// CommitmentPolicy is a configuration setting that determines whether your +// application encrypts and decrypts with [key commitment]. +// +// See [Commitment policy] for more information. +// +// [Commitment policy]: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#commitment-policy +// [key commitment]: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#key-commitment type CommitmentPolicy int8 +// Supported commitment policies. const ( _commitmentPolicyNone CommitmentPolicy = iota // 0 is NONE CommitmentPolicyForbidEncryptAllowDecrypt // 1 - FORBID_ENCRYPT_ALLOW_DECRYPT @@ -36,6 +39,7 @@ const ( CommitmentPolicyRequireEncryptRequireDecrypt // 3 - REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) +// String returns the string representation of the [CommitmentPolicy]. func (cp CommitmentPolicy) String() string { switch cp { case _commitmentPolicyNone: @@ -51,19 +55,19 @@ func (cp CommitmentPolicy) String() string { } } +// GoString returns the same as String(). func (cp CommitmentPolicy) GoString() string { return cp.String() } +// MessageFormatVersion is the version of the message format. type MessageFormatVersion uint8 +// Supported message format versions. +// +// - Algorithm suites without key commitment use message format version 1. +// - Algorithm suites with key commitment use message format version 2. const ( - V1 MessageFormatVersion = iota + 1 // 1 is V1 MessageFormatVersion - V2 // 2 is V2 MessageFormatVersion -) - -type MessageType int - -const ( - CustomerAEData MessageType = 128 // 128 is 80 in hex + V1 MessageFormatVersion = iota + 1 // Version 1 encoded as the byte 01 in hexadecimal notation. + V2 // Version 2 encoded as the byte 02 in hexadecimal notation. ) diff --git a/pkg/suite/doc.go b/pkg/suite/doc.go new file mode 100644 index 00000000..db25d6e5 --- /dev/null +++ b/pkg/suite/doc.go @@ -0,0 +1,9 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package suite provides the algorithm suites. +// +// See [AWS Encryption SDK algorithms reference] for more information. +// +// [AWS Encryption SDK algorithms reference]: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/algorithms-reference.html +package suite diff --git a/pkg/suite/validate.go b/pkg/suite/validate.go index 3ae218e1..bdb7c50f 100644 --- a/pkg/suite/validate.go +++ b/pkg/suite/validate.go @@ -5,6 +5,9 @@ package suite import "fmt" +// ValidateMessageVersion validates the message format version values. +// +// The only supported message format versions are [V1] and [V2]. func ValidateMessageVersion(v uint8) error { version := MessageFormatVersion(v) if version != V1 && version != V2 { @@ -13,6 +16,9 @@ func ValidateMessageVersion(v uint8) error { return nil } +// ValidateContentType validates the content type values. +// +// The only supported content type is [FramedContent]. func ValidateContentType(t ContentType) error { if t != FramedContent { return fmt.Errorf("ContentType %v not supported", t) @@ -20,6 +26,7 @@ func ValidateContentType(t ContentType) error { return nil } +// ValidateCommitmentPolicy validates the commitment policy values. func ValidateCommitmentPolicy(p CommitmentPolicy) error { if p < CommitmentPolicyForbidEncryptAllowDecrypt || p > CommitmentPolicyRequireEncryptRequireDecrypt { return fmt.Errorf("invalid CommitmentPolicy %v", p) From a349dfadf3e781f5140d1a761b85cc57687ae404 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 03:12:29 +0200 Subject: [PATCH 09/30] refactor(utils): move rand under internal package --- .mockery.yaml | 4 +++- .../pkg/{ => internal_}/utils/rand/RandomGenerator_mock.go | 0 pkg/internal/crypto/encrypter/encrypt.go | 2 +- pkg/internal/crypto/encrypter/encrypt_test.go | 4 ++-- pkg/internal/crypto/signature/signer.go | 2 +- pkg/internal/crypto/signature/signer_test.go | 2 +- pkg/{ => internal}/utils/rand/random.go | 0 pkg/{ => internal}/utils/rand/random_test.go | 0 pkg/keys/raw/raw.go | 2 +- pkg/keys/raw/raw_test.go | 7 +++---- pkg/materials/default.go | 2 +- pkg/materials/default_test.go | 2 +- pkg/providers/kmsprovider/kmsprovider.go | 2 +- pkg/providers/kmsprovider/kmsprovider_test.go | 2 +- pkg/providers/rawprovider/rawprovider.go | 2 +- pkg/providers/rawprovider/rawprovider_test.go | 2 +- 16 files changed, 18 insertions(+), 17 deletions(-) rename mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/{ => internal_}/utils/rand/RandomGenerator_mock.go (100%) rename pkg/{ => internal}/utils/rand/random.go (100%) rename pkg/{ => internal}/utils/rand/random_test.go (100%) diff --git a/.mockery.yaml b/.mockery.yaml index 209a1041..0d1fe4f3 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -58,7 +58,9 @@ packages: filename: "Encrypter_mock.go" AEADDecrypter: AEADEncrypter: - github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand: + github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand: + config: + dir: mocks/{{ replaceAll .PackagePath "internal" "internal_" }} interfaces: RandomGenerator: github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature: diff --git a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand/RandomGenerator_mock.go b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/utils/rand/RandomGenerator_mock.go similarity index 100% rename from mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand/RandomGenerator_mock.go rename to mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/utils/rand/RandomGenerator_mock.go diff --git a/pkg/internal/crypto/encrypter/encrypt.go b/pkg/internal/crypto/encrypter/encrypt.go index b418da1d..ff4460ec 100644 --- a/pkg/internal/crypto/encrypter/encrypt.go +++ b/pkg/internal/crypto/encrypter/encrypt.go @@ -15,12 +15,12 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/bodyaad" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/keyderivation" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" ) type Encrypter struct { diff --git a/pkg/internal/crypto/encrypter/encrypt_test.go b/pkg/internal/crypto/encrypter/encrypt_test.go index bd5c89ab..cd17a789 100644 --- a/pkg/internal/crypto/encrypter/encrypt_test.go +++ b/pkg/internal/crypto/encrypter/encrypt_test.go @@ -12,17 +12,17 @@ import ( "github.com/stretchr/testify/mock" signaturemock "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/crypto/signature" + randmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/utils/rand" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" formatmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" encryptionmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" - randmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/clientconfig" "github.com/chainifynet/aws-encryption-sdk-go/pkg/crypto" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" ) func TestEncrypter_reset(t *testing.T) { diff --git a/pkg/internal/crypto/signature/signer.go b/pkg/internal/crypto/signature/signer.go index 9fb05d40..c72d5bcc 100644 --- a/pkg/internal/crypto/signature/signer.go +++ b/pkg/internal/crypto/signature/signer.go @@ -11,7 +11,7 @@ import ( "hash" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/hasher" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" ) var ( diff --git a/pkg/internal/crypto/signature/signer_test.go b/pkg/internal/crypto/signature/signer_test.go index 29b5d60e..042376a1 100644 --- a/pkg/internal/crypto/signature/signer_test.go +++ b/pkg/internal/crypto/signature/signer_test.go @@ -15,7 +15,7 @@ import ( hashermocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/crypto/hasher" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/hasher" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" ) func TestNewECCSigner(t *testing.T) { diff --git a/pkg/utils/rand/random.go b/pkg/internal/utils/rand/random.go similarity index 100% rename from pkg/utils/rand/random.go rename to pkg/internal/utils/rand/random.go diff --git a/pkg/utils/rand/random_test.go b/pkg/internal/utils/rand/random_test.go similarity index 100% rename from pkg/utils/rand/random_test.go rename to pkg/internal/utils/rand/random_test.go diff --git a/pkg/keys/raw/raw.go b/pkg/keys/raw/raw.go index 2910c1b9..72082422 100644 --- a/pkg/keys/raw/raw.go +++ b/pkg/keys/raw/raw.go @@ -10,12 +10,12 @@ import ( "fmt" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization/wrappingkey" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/keyderivation" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" ) type KeyHandler interface { diff --git a/pkg/keys/raw/raw_test.go b/pkg/keys/raw/raw_test.go index 58c0020c..df8639e1 100644 --- a/pkg/keys/raw/raw_test.go +++ b/pkg/keys/raw/raw_test.go @@ -12,16 +12,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + mocksrand "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/utils/rand" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" - mocksrand "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" + mocksencryption "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization/wrappingkey" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" - - mocksencryption "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" ) func TestRawMasterKey_KeyID(t *testing.T) { diff --git a/pkg/materials/default.go b/pkg/materials/default.go index 72dbbd0c..ecd532df 100644 --- a/pkg/materials/default.go +++ b/pkg/materials/default.go @@ -12,11 +12,11 @@ import ( "fmt" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" ) type DefaultCryptoMaterialsManager struct { diff --git a/pkg/materials/default_test.go b/pkg/materials/default_test.go index f134bb60..002c5ad5 100644 --- a/pkg/materials/default_test.go +++ b/pkg/materials/default_test.go @@ -14,12 +14,12 @@ import ( "github.com/stretchr/testify/mock" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/materials" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/rand" ) type mockProvider struct { diff --git a/pkg/providers/kmsprovider/kmsprovider.go b/pkg/providers/kmsprovider/kmsprovider.go index 535fd7b8..ea67c2cb 100644 --- a/pkg/providers/kmsprovider/kmsprovider.go +++ b/pkg/providers/kmsprovider/kmsprovider.go @@ -12,11 +12,11 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) diff --git a/pkg/providers/kmsprovider/kmsprovider_test.go b/pkg/providers/kmsprovider/kmsprovider_test.go index dce2bfed..951c948c 100644 --- a/pkg/providers/kmsprovider/kmsprovider_test.go +++ b/pkg/providers/kmsprovider/kmsprovider_test.go @@ -14,10 +14,10 @@ import ( mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) diff --git a/pkg/providers/rawprovider/rawprovider.go b/pkg/providers/rawprovider/rawprovider.go index 9ad54968..25334fbc 100644 --- a/pkg/providers/rawprovider/rawprovider.go +++ b/pkg/providers/rawprovider/rawprovider.go @@ -9,11 +9,11 @@ import ( "fmt" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/raw" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) diff --git a/pkg/providers/rawprovider/rawprovider_test.go b/pkg/providers/rawprovider/rawprovider_test.go index f398a5c0..6719f5ed 100644 --- a/pkg/providers/rawprovider/rawprovider_test.go +++ b/pkg/providers/rawprovider/rawprovider_test.go @@ -11,10 +11,10 @@ import ( "github.com/stretchr/testify/mock" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) From c1de113b35f3811d479204753374917b7780b8da Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 03:13:19 +0200 Subject: [PATCH 10/30] refactor(providers): move providers common package under internal package --- pkg/{ => internal}/providers/common/key_entry.go | 0 pkg/{ => internal}/providers/common/key_entry_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename pkg/{ => internal}/providers/common/key_entry.go (100%) rename pkg/{ => internal}/providers/common/key_entry_test.go (100%) diff --git a/pkg/providers/common/key_entry.go b/pkg/internal/providers/common/key_entry.go similarity index 100% rename from pkg/providers/common/key_entry.go rename to pkg/internal/providers/common/key_entry.go diff --git a/pkg/providers/common/key_entry_test.go b/pkg/internal/providers/common/key_entry_test.go similarity index 100% rename from pkg/providers/common/key_entry_test.go rename to pkg/internal/providers/common/key_entry_test.go From d86de45fed112bfff7983dfd5a943a86ee66c623 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 04:19:18 +0200 Subject: [PATCH 11/30] refactor(utils): move itertools package under internal package --- pkg/{helpers => internal/utils}/itertools/comb.go | 1 - pkg/{helpers => internal/utils}/itertools/comb_test.go | 2 +- pkg/internal/utils/itertools/doc.go | 5 +++++ pkg/providers/kmsprovider/config.go | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) rename pkg/{helpers => internal/utils}/itertools/comb.go (92%) rename pkg/{helpers => internal/utils}/itertools/comb_test.go (96%) create mode 100644 pkg/internal/utils/itertools/doc.go diff --git a/pkg/helpers/itertools/comb.go b/pkg/internal/utils/itertools/comb.go similarity index 92% rename from pkg/helpers/itertools/comb.go rename to pkg/internal/utils/itertools/comb.go index 103eecfc..f98ea9d0 100644 --- a/pkg/helpers/itertools/comb.go +++ b/pkg/internal/utils/itertools/comb.go @@ -1,7 +1,6 @@ // Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Package itertools provides a method to generate all combinations out of a given string array. package itertools import "math/bits" diff --git a/pkg/helpers/itertools/comb_test.go b/pkg/internal/utils/itertools/comb_test.go similarity index 96% rename from pkg/helpers/itertools/comb_test.go rename to pkg/internal/utils/itertools/comb_test.go index c1d9aac9..d86ae617 100644 --- a/pkg/helpers/itertools/comb_test.go +++ b/pkg/internal/utils/itertools/comb_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/itertools" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/itertools" ) func BenchmarkCombinationsNew(b *testing.B) { diff --git a/pkg/internal/utils/itertools/doc.go b/pkg/internal/utils/itertools/doc.go new file mode 100644 index 00000000..5e234f4f --- /dev/null +++ b/pkg/internal/utils/itertools/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package itertools provides a method to generate all combinations out of a given generic type array. +package itertools diff --git a/pkg/providers/kmsprovider/config.go b/pkg/providers/kmsprovider/config.go index 782b0fcf..3496f797 100644 --- a/pkg/providers/kmsprovider/config.go +++ b/pkg/providers/kmsprovider/config.go @@ -13,10 +13,10 @@ import ( "github.com/aws/aws-sdk-go-v2/config" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/itertools" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/keyprovider" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/kmsclient" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/itertools" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" From 15d68d40db9fa69cb0653a20bbcd2f218657151d Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 04:25:38 +0200 Subject: [PATCH 12/30] docs: providers package documentation --- pkg/providers/doc.go | 5 +++++ pkg/providers/errors.go | 34 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 pkg/providers/doc.go diff --git a/pkg/providers/doc.go b/pkg/providers/doc.go new file mode 100644 index 00000000..5d20b1c3 --- /dev/null +++ b/pkg/providers/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package providers contains a generic provider errors. +package providers diff --git a/pkg/providers/errors.go b/pkg/providers/errors.go index 8ea84741..79fd22c1 100644 --- a/pkg/providers/errors.go +++ b/pkg/providers/errors.go @@ -5,12 +5,28 @@ package providers import "errors" -var ( - ErrMasterKeyProvider = errors.New("MKP error") - ErrMasterKeyProviderDecrypt = errors.New("MKP decrypt error") - ErrMasterKeyProviderDecryptForbidden = errors.New("MKP decrypt forbidden error") - ErrMasterKeyProviderEncrypt = errors.New("MKP encrypt error") - ErrMasterKeyProviderNoPrimaryKey = errors.New("MKP no primary key") - ErrConfig = errors.New("MKP config error") - ErrFilterKeyNotAllowed = errors.New("MKP key not allowed by filter") -) +// ErrMasterKeyProvider is a generic error for master key provider. +var ErrMasterKeyProvider = errors.New("MKP error") + +// ErrMasterKeyProviderDecrypt is returned when the master key provider fails to +// decrypt. +var ErrMasterKeyProviderDecrypt = errors.New("MKP decrypt error") + +// ErrMasterKeyProviderDecryptForbidden is returned when the master key provider +// fails to decrypt due to forbidden access or filtering. +var ErrMasterKeyProviderDecryptForbidden = errors.New("MKP decrypt forbidden error") + +// ErrMasterKeyProviderEncrypt is returned when the master key provider fails to +// encrypt. +var ErrMasterKeyProviderEncrypt = errors.New("MKP encrypt error") + +// ErrMasterKeyProviderNoPrimaryKey is returned when the master key provider has +// no primary key. +var ErrMasterKeyProviderNoPrimaryKey = errors.New("MKP no primary key") + +// ErrConfig is returned when the master key provider has a configuration error. +var ErrConfig = errors.New("MKP config error") + +// ErrFilterKeyNotAllowed is returned when the master key provider has a key that +// is not allowed by the filter. +var ErrFilterKeyNotAllowed = errors.New("MKP key not allowed by filter") From c019d354be879eeda48fa42fcdd062c244ecd649 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 04:25:57 +0200 Subject: [PATCH 13/30] docs: arn package documentation --- pkg/helpers/arn/arn.go | 5 ++++- pkg/helpers/arn/doc.go | 5 +++++ pkg/helpers/arn/filter.go | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 pkg/helpers/arn/doc.go diff --git a/pkg/helpers/arn/arn.go b/pkg/helpers/arn/arn.go index 8a358dbe..d2f0602f 100644 --- a/pkg/helpers/arn/arn.go +++ b/pkg/helpers/arn/arn.go @@ -17,8 +17,10 @@ const ( aliasResourceType = "alias" ) +// ErrMalformedArn is returned when the ARN is malformed. var ErrMalformedArn = errors.New("malformed Key ARN") +// KeyArn represents an AWS Key ARN. type KeyArn struct { Partition string // AWS partition, e.g. aws, aws-cn, aws-us-gov Service string // AWS service, kms @@ -57,7 +59,7 @@ func (a *KeyArn) IsMrk() bool { return a.ResourceType == KeyResourceType && strings.HasPrefix(a.ResourceID, mrkPrefix) } -// ParseArn Parses str string as an ARN (KeyArn). +// ParseArn parses str string as an ARN (KeyArn). func ParseArn(str string) (*KeyArn, error) { elements := strings.SplitN(str, delim, 6) @@ -126,6 +128,7 @@ func ParseArn(str string) (*KeyArn, error) { }, nil } +// ValidateKeyArn validates the keyID as an ARN. func ValidateKeyArn(keyID string) error { _, err := ParseArn(keyID) if err != nil { diff --git a/pkg/helpers/arn/doc.go b/pkg/helpers/arn/doc.go new file mode 100644 index 00000000..205deb19 --- /dev/null +++ b/pkg/helpers/arn/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package arn provides a set of utilities for working with Amazon Resource Names (ARNs). +package arn diff --git a/pkg/helpers/arn/filter.go b/pkg/helpers/arn/filter.go index 76c7d663..37a227b6 100644 --- a/pkg/helpers/arn/filter.go +++ b/pkg/helpers/arn/filter.go @@ -3,8 +3,13 @@ package arn +// FilterFunc is a function that filters a string. +// +// Examples: [IsValidMrkArn], [IsValidMrkIdentifier] type FilterFunc func(s string) (bool, error) +// FilterKeyIDs filters a list of key IDs using the given filter function. It +// returns a list of key IDs that pass the filter. func FilterKeyIDs(f FilterFunc, keyIDs []string) ([]string, error) { result := make([]string, 0, len(keyIDs)) for _, keyID := range keyIDs { @@ -19,6 +24,7 @@ func FilterKeyIDs(f FilterFunc, keyIDs []string) ([]string, error) { return result, nil } +// KeyResourceEqual checks if the given key ARNs refer to the same KMS MRK resourceID. func KeyResourceEqual(key1, key2 string) (bool, error) { arn1, err := ParseArn(key1) if err != nil { From 50b6d4122e190dde671c75724c789e5d20fecd9a Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 04:29:02 +0200 Subject: [PATCH 14/30] refactor(utils): move arn package --- example/discoveryFilterKmsProvider/main.go | 2 +- example/mrkAwareKmsProvider/main.go | 2 +- pkg/keys/kms/kms.go | 2 +- pkg/keys/kms/kms_mrk.go | 2 +- pkg/keys/kms/kms_test.go | 2 +- pkg/providers/kmsprovider/config.go | 10 +++++----- pkg/providers/kmsprovider/kmsprovider.go | 2 +- pkg/providers/kmsprovider/options.go | 2 +- pkg/{helpers => utils}/arn/arn.go | 0 pkg/{helpers => utils}/arn/arn_test.go | 0 pkg/{helpers => utils}/arn/doc.go | 0 pkg/{helpers => utils}/arn/filter.go | 0 pkg/{helpers => utils}/arn/filter_test.go | 0 pkg/{helpers => utils}/arn/mrk.go | 0 pkg/{helpers => utils}/arn/mrk_test.go | 0 test/e2e/kms_discovery_test.go | 2 +- 16 files changed, 13 insertions(+), 13 deletions(-) rename pkg/{helpers => utils}/arn/arn.go (100%) rename pkg/{helpers => utils}/arn/arn_test.go (100%) rename pkg/{helpers => utils}/arn/doc.go (100%) rename pkg/{helpers => utils}/arn/filter.go (100%) rename pkg/{helpers => utils}/arn/filter_test.go (100%) rename pkg/{helpers => utils}/arn/mrk.go (100%) rename pkg/{helpers => utils}/arn/mrk_test.go (100%) diff --git a/example/discoveryFilterKmsProvider/main.go b/example/discoveryFilterKmsProvider/main.go index 1ef5c96d..3259ca17 100644 --- a/example/discoveryFilterKmsProvider/main.go +++ b/example/discoveryFilterKmsProvider/main.go @@ -9,10 +9,10 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/client" "github.com/chainifynet/aws-encryption-sdk-go/pkg/clientconfig" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/materials" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/kmsprovider" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) // encrypts and then decrypts a string using KMS key provider with discovery filter diff --git a/example/mrkAwareKmsProvider/main.go b/example/mrkAwareKmsProvider/main.go index e06ef6bd..90871bf2 100644 --- a/example/mrkAwareKmsProvider/main.go +++ b/example/mrkAwareKmsProvider/main.go @@ -9,10 +9,10 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/client" "github.com/chainifynet/aws-encryption-sdk-go/pkg/clientconfig" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/materials" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/kmsprovider" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) // encrypts and then decrypts a string using MRK-aware KMS key provider diff --git a/pkg/keys/kms/kms.go b/pkg/keys/kms/kms.go index adf6af9d..284bdb51 100644 --- a/pkg/keys/kms/kms.go +++ b/pkg/keys/kms/kms.go @@ -14,11 +14,11 @@ import ( "github.com/aws/smithy-go" "github.com/aws/smithy-go/transport/http" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) var ( diff --git a/pkg/keys/kms/kms_mrk.go b/pkg/keys/kms/kms_mrk.go index 8d0a504f..c796bbf1 100644 --- a/pkg/keys/kms/kms_mrk.go +++ b/pkg/keys/kms/kms_mrk.go @@ -7,11 +7,11 @@ import ( "context" "fmt" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) type MrkMasterKey struct { diff --git a/pkg/keys/kms/kms_test.go b/pkg/keys/kms/kms_test.go index a9bd83a9..dbccbeea 100644 --- a/pkg/keys/kms/kms_test.go +++ b/pkg/keys/kms/kms_test.go @@ -19,11 +19,11 @@ import ( "github.com/stretchr/testify/require" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) func TestKmsMasterKey_GenerateDataKey(t *testing.T) { diff --git a/pkg/providers/kmsprovider/config.go b/pkg/providers/kmsprovider/config.go index 3496f797..dab676a5 100644 --- a/pkg/providers/kmsprovider/config.go +++ b/pkg/providers/kmsprovider/config.go @@ -12,7 +12,6 @@ import ( "github.com/aws/aws-sdk-go-v2/config" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/keyprovider" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/kmsclient" @@ -20,6 +19,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" + arn2 "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) func resolveProviderType(opts *Options) ProviderType { @@ -89,7 +89,7 @@ func resolveDefaultRegion(keyIDs []string, opts *Options) { var region string if len(keyIDs) > 0 { for _, keyID := range keyIDs { - keyArn, err := arn.ParseArn(keyID) + keyArn, err := arn2.ParseArn(keyID) if err != nil { // try next keyID in case of invalid ARN continue @@ -176,7 +176,7 @@ func validateConfig(t ProviderType, keyIDs []string, options *Options) error { / func validateKeyArns(keyIDs []string) error { for _, keyID := range keyIDs { - if _, err := arn.ParseArn(keyID); err != nil { + if _, err := arn2.ParseArn(keyID); err != nil { return fmt.Errorf("%q keyID is not a valid ARN: %w", keyID, err) } } @@ -213,7 +213,7 @@ func validateAccountID(accountID string) error { } func validateUniqueMrks(keyIDs []string) error { - mrkKeyIDs, err := arn.FilterKeyIDs(arn.IsValidMrkIdentifier, keyIDs) + mrkKeyIDs, err := arn2.FilterKeyIDs(arn2.IsValidMrkIdentifier, keyIDs) if err != nil { return err } @@ -223,7 +223,7 @@ func validateUniqueMrks(keyIDs []string) error { if structs.MapContains(duplicateIDs, key1) && structs.MapContains(duplicateIDs, key2) { continue } - ok, _ := arn.KeyResourceEqual(key1, key2) + ok, _ := arn2.KeyResourceEqual(key1, key2) // error ignored because ARN is already validated IsValidMrkIdentifier // or filtered out by FilterKeyIDs if ok { diff --git a/pkg/providers/kmsprovider/kmsprovider.go b/pkg/providers/kmsprovider/kmsprovider.go index ea67c2cb..e0a56e74 100644 --- a/pkg/providers/kmsprovider/kmsprovider.go +++ b/pkg/providers/kmsprovider/kmsprovider.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/config" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" @@ -18,6 +17,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) type KmsProvider interface { diff --git a/pkg/providers/kmsprovider/options.go b/pkg/providers/kmsprovider/options.go index 868a35f1..a77c55fa 100644 --- a/pkg/providers/kmsprovider/options.go +++ b/pkg/providers/kmsprovider/options.go @@ -6,8 +6,8 @@ package kmsprovider import ( "github.com/aws/aws-sdk-go-v2/config" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) type Options struct { diff --git a/pkg/helpers/arn/arn.go b/pkg/utils/arn/arn.go similarity index 100% rename from pkg/helpers/arn/arn.go rename to pkg/utils/arn/arn.go diff --git a/pkg/helpers/arn/arn_test.go b/pkg/utils/arn/arn_test.go similarity index 100% rename from pkg/helpers/arn/arn_test.go rename to pkg/utils/arn/arn_test.go diff --git a/pkg/helpers/arn/doc.go b/pkg/utils/arn/doc.go similarity index 100% rename from pkg/helpers/arn/doc.go rename to pkg/utils/arn/doc.go diff --git a/pkg/helpers/arn/filter.go b/pkg/utils/arn/filter.go similarity index 100% rename from pkg/helpers/arn/filter.go rename to pkg/utils/arn/filter.go diff --git a/pkg/helpers/arn/filter_test.go b/pkg/utils/arn/filter_test.go similarity index 100% rename from pkg/helpers/arn/filter_test.go rename to pkg/utils/arn/filter_test.go diff --git a/pkg/helpers/arn/mrk.go b/pkg/utils/arn/mrk.go similarity index 100% rename from pkg/helpers/arn/mrk.go rename to pkg/utils/arn/mrk.go diff --git a/pkg/helpers/arn/mrk_test.go b/pkg/utils/arn/mrk_test.go similarity index 100% rename from pkg/helpers/arn/mrk_test.go rename to pkg/utils/arn/mrk_test.go diff --git a/test/e2e/kms_discovery_test.go b/test/e2e/kms_discovery_test.go index ed504ef3..1688cdce 100644 --- a/test/e2e/kms_discovery_test.go +++ b/test/e2e/kms_discovery_test.go @@ -13,9 +13,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/arn" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers/kmsprovider" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) func Test_Integration_KmsDiscovery(t *testing.T) { From ba880e390d631137ab6179f2b03968cf598611b1 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 04:32:40 +0200 Subject: [PATCH 15/30] fix(utils): lint issues with arn pkg --- .golangci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index f0e75da8..46c8508e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -127,7 +127,7 @@ linters-settings: ignored-files: - 'algorithm\.go' - 'pkg/utils/conv/conv\.go' - - 'pkg/helpers/arn/arn\.go' + - 'pkg/utils/arn/arn\.go' ignored-functions: - '^math\.' - '^http\.StatusText$' From 1626bb18fcf096e23dec2a614739a30da3bd42ca Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 17:22:43 +0200 Subject: [PATCH 16/30] refactor(utils): move structs package, documentation --- .golangci.yml | 3 +++ pkg/internal/providers/keyprovider/keyprovider.go | 2 +- pkg/internal/serialization/aad.go | 2 +- pkg/internal/utils/structs/doc.go | 5 +++++ pkg/{helpers => internal/utils}/structs/maps.go | 10 ++++++++++ pkg/{helpers => internal/utils}/structs/maps_test.go | 0 pkg/{helpers => internal/utils}/structs/slices.go | 3 +++ pkg/materials/default.go | 2 +- pkg/providers/kmsprovider/config.go | 2 +- pkg/providers/kmsprovider/kmsprovider.go | 2 +- pkg/providers/kmsprovider/kmsprovider_test.go | 2 +- pkg/providers/rawprovider/rawprovider.go | 2 +- 12 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 pkg/internal/utils/structs/doc.go rename pkg/{helpers => internal/utils}/structs/maps.go (57%) rename pkg/{helpers => internal/utils}/structs/maps_test.go (100%) rename pkg/{helpers => internal/utils}/structs/slices.go (56%) diff --git a/.golangci.yml b/.golangci.yml index 46c8508e..be64faba 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -56,6 +56,9 @@ linters: - wrapcheck - gofmt - zerologlint +# enable these on the next golangci-lint release: +# - copyloopvar +# - intrange linters-settings: errorlint: diff --git a/pkg/internal/providers/keyprovider/keyprovider.go b/pkg/internal/providers/keyprovider/keyprovider.go index 61094f26..72bab740 100644 --- a/pkg/internal/providers/keyprovider/keyprovider.go +++ b/pkg/internal/providers/keyprovider/keyprovider.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" diff --git a/pkg/internal/serialization/aad.go b/pkg/internal/serialization/aad.go index d2ba6670..94d36920 100644 --- a/pkg/internal/serialization/aad.go +++ b/pkg/internal/serialization/aad.go @@ -10,7 +10,7 @@ import ( "math" "sort" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) diff --git a/pkg/internal/utils/structs/doc.go b/pkg/internal/utils/structs/doc.go new file mode 100644 index 00000000..b9d976ce --- /dev/null +++ b/pkg/internal/utils/structs/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package structs provides utility functions for working with structs. +package structs diff --git a/pkg/helpers/structs/maps.go b/pkg/internal/utils/structs/maps.go similarity index 57% rename from pkg/helpers/structs/maps.go rename to pkg/internal/utils/structs/maps.go index e417b394..74ab64d3 100644 --- a/pkg/helpers/structs/maps.go +++ b/pkg/internal/utils/structs/maps.go @@ -5,6 +5,9 @@ package structs import "sort" +// MapContains checks if a map contains a specific key. +// It takes a map and a key as parameters. +// It returns true if the key is found in the map, otherwise it returns false. func MapContains[K comparable, V any](m map[K]V, k K) bool { for key := range m { if key == k { @@ -14,6 +17,9 @@ func MapContains[K comparable, V any](m map[K]V, k K) bool { return false } +// MapKeys returns all keys from a map. +// It takes a map as a parameter. +// It returns a slice containing all keys from the map. func MapKeys[K comparable, V any](m map[K]V) []K { keys := make([]K, 0, len(m)) for k := range m { @@ -22,6 +28,10 @@ func MapKeys[K comparable, V any](m map[K]V) []K { return keys } +// MapSort sorts a map by its keys. +// It takes a map as a parameter. +// It returns a new map with the same key-value pairs, but sorted by keys. +// The sorting is only applicable for maps with string or integer keys. func MapSort[K ~string | ~int, V any](m map[K]V) map[K]V { keys := make([]K, 0, len(m)) for k := range m { diff --git a/pkg/helpers/structs/maps_test.go b/pkg/internal/utils/structs/maps_test.go similarity index 100% rename from pkg/helpers/structs/maps_test.go rename to pkg/internal/utils/structs/maps_test.go diff --git a/pkg/helpers/structs/slices.go b/pkg/internal/utils/structs/slices.go similarity index 56% rename from pkg/helpers/structs/slices.go rename to pkg/internal/utils/structs/slices.go index 496b3753..7874d3d1 100644 --- a/pkg/helpers/structs/slices.go +++ b/pkg/internal/utils/structs/slices.go @@ -3,6 +3,9 @@ package structs +// Contains checks if a slice contains a specific element. +// It takes a slice and an element as parameters. +// It returns true if the element is found in the slice, otherwise it returns false. func Contains[T comparable](s []T, e T) bool { for _, v := range s { if v == e { diff --git a/pkg/materials/default.go b/pkg/materials/default.go index ecd532df..cdb2a77a 100644 --- a/pkg/materials/default.go +++ b/pkg/materials/default.go @@ -11,8 +11,8 @@ import ( "errors" "fmt" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" diff --git a/pkg/providers/kmsprovider/config.go b/pkg/providers/kmsprovider/config.go index dab676a5..c6d3213c 100644 --- a/pkg/providers/kmsprovider/config.go +++ b/pkg/providers/kmsprovider/config.go @@ -12,10 +12,10 @@ import ( "github.com/aws/aws-sdk-go-v2/config" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/keyprovider" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/kmsclient" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/itertools" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" diff --git a/pkg/providers/kmsprovider/kmsprovider.go b/pkg/providers/kmsprovider/kmsprovider.go index e0a56e74..d02d9c40 100644 --- a/pkg/providers/kmsprovider/kmsprovider.go +++ b/pkg/providers/kmsprovider/kmsprovider.go @@ -10,8 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/config" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" diff --git a/pkg/providers/kmsprovider/kmsprovider_test.go b/pkg/providers/kmsprovider/kmsprovider_test.go index 951c948c..5dd56ca9 100644 --- a/pkg/providers/kmsprovider/kmsprovider_test.go +++ b/pkg/providers/kmsprovider/kmsprovider_test.go @@ -13,8 +13,8 @@ import ( "github.com/stretchr/testify/mock" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" diff --git a/pkg/providers/rawprovider/rawprovider.go b/pkg/providers/rawprovider/rawprovider.go index 25334fbc..c1b2972c 100644 --- a/pkg/providers/rawprovider/rawprovider.go +++ b/pkg/providers/rawprovider/rawprovider.go @@ -8,8 +8,8 @@ import ( "errors" "fmt" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/helpers/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/common" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/raw" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" From eb7fc1af4e57b0d05b4275842ed7ed88b735de0a Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 18:34:55 +0200 Subject: [PATCH 17/30] docs: materials package documentation --- pkg/materials/cache_entry.go | 2 ++ pkg/materials/caching.go | 6 ++++++ pkg/materials/consts.go | 6 +++--- pkg/materials/default.go | 19 ++++++++++++++++++ pkg/materials/doc.go | 29 ++++++++++++++++++++++++++++ pkg/materials/{base.go => errors.go} | 5 ++--- pkg/materials/memory_cache.go | 1 + 7 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 pkg/materials/doc.go rename pkg/materials/{base.go => errors.go} (61%) diff --git a/pkg/materials/cache_entry.go b/pkg/materials/cache_entry.go index e57d5b3c..e0670ecf 100644 --- a/pkg/materials/cache_entry.go +++ b/pkg/materials/cache_entry.go @@ -9,6 +9,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" ) +// CacheEntry CachingCryptoMaterialsManager still under development. type CacheEntry[V model.EncryptionMaterials | model.DecryptionMaterials] struct { key []byte value V @@ -19,6 +20,7 @@ type CacheEntry[V model.EncryptionMaterials | model.DecryptionMaterials] struct valid bool } +// NewCacheEntry CachingCryptoMaterialsManager still under development. func NewCacheEntry[V model.EncryptionMaterials | model.DecryptionMaterials](key []byte, value V, lifetime time.Duration) *CacheEntry[V] { return &CacheEntry[V]{ key: key, diff --git a/pkg/materials/caching.go b/pkg/materials/caching.go index ecee1522..0eba932a 100644 --- a/pkg/materials/caching.go +++ b/pkg/materials/caching.go @@ -10,6 +10,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" ) +// BaseCache CachingCryptoMaterialsManager still under development. type BaseCache interface { PutEncryptionEntry(cacheKey []byte, m model.EncryptionMaterials, n int) (*CacheEntry[model.EncryptionMaterials], error) PutDecryptionEntry(cacheKey []byte, m model.DecryptionMaterials) (*CacheEntry[model.DecryptionMaterials], error) @@ -17,6 +18,7 @@ type BaseCache interface { GetDecryptionEntry(cacheKey []byte) (*CacheEntry[model.DecryptionMaterials], error) } +// CachingCryptoMaterialsManager still under development. type CachingCryptoMaterialsManager struct { // TODO probably add DefaultCryptoMaterialsManager cache BaseCache @@ -25,6 +27,7 @@ type CachingCryptoMaterialsManager struct { maxBytes int } +// NewCaching CachingCryptoMaterialsManager still under development. func NewCaching(cache BaseCache, _ model.MasterKeyProvider, _ ...model.MasterKeyProvider) (*CachingCryptoMaterialsManager, error) { return &CachingCryptoMaterialsManager{ cache: cache, @@ -37,14 +40,17 @@ func NewCaching(cache BaseCache, _ model.MasterKeyProvider, _ ...model.MasterKey // compile checking that CachingCryptoMaterialsManager implements CryptoMaterialsManager interface var _ model.CryptoMaterialsManager = (*CachingCryptoMaterialsManager)(nil) +// GetEncryptionMaterials CachingCryptoMaterialsManager still under development. func (cm *CachingCryptoMaterialsManager) GetEncryptionMaterials(_ context.Context, _ model.EncryptionMaterialsRequest) (model.EncryptionMaterial, error) { return nil, nil } +// DecryptMaterials CachingCryptoMaterialsManager still under development. func (cm *CachingCryptoMaterialsManager) DecryptMaterials(_ context.Context, _ model.DecryptionMaterialsRequest) (model.DecryptionMaterial, error) { return nil, nil } +// GetInstance CachingCryptoMaterialsManager still under development. func (cm *CachingCryptoMaterialsManager) GetInstance() model.CryptoMaterialsManager { return &CachingCryptoMaterialsManager{ cache: cm.cache, diff --git a/pkg/materials/consts.go b/pkg/materials/consts.go index 27e4b901..9aaa8444 100644 --- a/pkg/materials/consts.go +++ b/pkg/materials/consts.go @@ -3,6 +3,6 @@ package materials -const ( - EcPublicKeyField = "aws-crypto-public-key" -) +// EcPublicKeyField is the reserved field name in encryption context that +// represents the public verification key. +const EcPublicKeyField = "aws-crypto-public-key" diff --git a/pkg/materials/default.go b/pkg/materials/default.go index cdb2a77a..88b8ffe4 100644 --- a/pkg/materials/default.go +++ b/pkg/materials/default.go @@ -19,6 +19,8 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// DefaultCryptoMaterialsManager is a default implementation of [model.CryptoMaterialsManager]. +// It interacts directly with your Master Key Providers without any caching. type DefaultCryptoMaterialsManager struct { primaryKeyProvider model.MasterKeyProvider masterKeyProviders []model.MasterKeyProvider @@ -27,6 +29,15 @@ type DefaultCryptoMaterialsManager struct { // compile checking that DefaultCryptoMaterialsManager implements CryptoMaterialsManager interface var _ model.CryptoMaterialsManager = (*DefaultCryptoMaterialsManager)(nil) +// NewDefault creates a new instance of DefaultCryptoMaterialsManager. +// +// It takes a primary [model.MasterKeyProvider] and an optional list of extra +// MasterKeyProviders as parameters. If the primary MasterKeyProvider is nil, it +// returns an error. +// +// Parameters: +// - primary: The primary [model.MasterKeyProvider]. Must not be nil. +// - extra: Optional additional [model.MasterKeyProvider] providers. Duplicates are not allowed. func NewDefault(primary model.MasterKeyProvider, extra ...model.MasterKeyProvider) (*DefaultCryptoMaterialsManager, error) { if primary == nil { return nil, fmt.Errorf("primary MasterKeyProvider nil : %w", ErrCMM) @@ -50,6 +61,9 @@ func NewDefault(primary model.MasterKeyProvider, extra ...model.MasterKeyProvide }, nil } +// GetEncryptionMaterials returns the encryption materials for the given request. +// Used during encryption process to get the encryption materials from registered +// master key providers. func (dm *DefaultCryptoMaterialsManager) GetEncryptionMaterials(ctx context.Context, encReq model.EncryptionMaterialsRequest) (model.EncryptionMaterial, error) { // copy encryption context map var encryptionContext suite.EncryptionContext @@ -95,6 +109,9 @@ func (dm *DefaultCryptoMaterialsManager) GetEncryptionMaterials(ctx context.Cont } +// DecryptMaterials returns the decryption materials for the given request. Used +// during decryption process to get the decryption materials from registered +// master key providers. func (dm *DefaultCryptoMaterialsManager) DecryptMaterials(ctx context.Context, decReq model.DecryptionMaterialsRequest) (model.DecryptionMaterial, error) { var dataKey model.DataKeyI var errDecryptDataKey error @@ -149,6 +166,8 @@ func (dm *DefaultCryptoMaterialsManager) DecryptMaterials(ctx context.Context, d return model.NewDecryptionMaterials(dataKey, verificationKey), nil } +// GetInstance returns a new instance of the crypto materials manager to interact +// within encryption/decryption process. func (dm *DefaultCryptoMaterialsManager) GetInstance() model.CryptoMaterialsManager { return &DefaultCryptoMaterialsManager{ primaryKeyProvider: dm.primaryKeyProvider, diff --git a/pkg/materials/doc.go b/pkg/materials/doc.go new file mode 100644 index 00000000..faf7a896 --- /dev/null +++ b/pkg/materials/doc.go @@ -0,0 +1,29 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package materials provides CryptoMaterialsManager implementations. +// +// The cryptographic materials manager (CMM) assembles the cryptographic +// materials that are used to encrypt and decrypt data. +// +// # Supported Cryptographic Materials Managers +// +// - [DefaultCryptoMaterialsManager]: A default interacts with your Master Key +// Providers without any caching. +// - [CachingCryptoMaterialsManager]: A caching CMM that uses a cache to store +// cryptographic materials. Not implemented yet. +// +// # Usage +// +// The following example demonstrates how to use the DefaultCryptoMaterialsManager. +// +// // Set up your key provider. +// cmm, err := materials.NewDefault(keyProvider) +// if err != nil { +// panic("materials manager setup failed") // handle error +// } +// +// Check [example] for more advanced usage. +// +// [example]: https://github.com/chainifynet/aws-encryption-sdk-go/blob/main/example/multipleKeyProvider/main.go +package materials diff --git a/pkg/materials/base.go b/pkg/materials/errors.go similarity index 61% rename from pkg/materials/base.go rename to pkg/materials/errors.go index 72adec42..3014e01d 100644 --- a/pkg/materials/base.go +++ b/pkg/materials/errors.go @@ -7,6 +7,5 @@ import ( "errors" ) -var ( - ErrCMM = errors.New("CMM error") -) +// ErrCMM is a generic [model.CryptoMaterialsManager] error. +var ErrCMM = errors.New("CMM error") diff --git a/pkg/materials/memory_cache.go b/pkg/materials/memory_cache.go index f36df238..a275ce22 100644 --- a/pkg/materials/memory_cache.go +++ b/pkg/materials/memory_cache.go @@ -10,6 +10,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" ) +// MemoryCache CachingCryptoMaterialsManager still under development. type MemoryCache struct { cache sync.Map } From ef714bb89f5687c6f1a8105632a1ba4a245e14ef Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 18:43:51 +0200 Subject: [PATCH 18/30] refactor(utils): conv package moved under internal packages, documentation --- pkg/internal/serialization/aad.go | 2 +- pkg/internal/serialization/aad_test.go | 2 +- pkg/internal/serialization/encrypteddatakey.go | 2 +- pkg/internal/serialization/encrypteddatakey_test.go | 2 +- pkg/internal/serialization/messagebody.go | 2 +- pkg/internal/serialization/messagebody_test.go | 2 +- pkg/internal/serialization/messagefooter.go | 2 +- pkg/internal/serialization/messageheader.go | 2 +- pkg/internal/serialization/reader.go | 2 +- pkg/internal/serialization/wrappingkey/wrapping.go | 4 +++- pkg/internal/utils/bodyaad/bodyaad.go | 2 +- pkg/{ => internal}/utils/conv/conv.go | 0 pkg/{ => internal}/utils/conv/conv_test.go | 0 pkg/internal/utils/conv/doc.go | 5 +++++ pkg/suite/algorithm.go | 2 +- pkg/utils/encryption/gcm.go | 2 +- pkg/utils/keyderivation/key_derivation.go | 2 +- 17 files changed, 21 insertions(+), 14 deletions(-) rename pkg/{ => internal}/utils/conv/conv.go (100%) rename pkg/{ => internal}/utils/conv/conv_test.go (100%) create mode 100644 pkg/internal/utils/conv/doc.go diff --git a/pkg/internal/serialization/aad.go b/pkg/internal/serialization/aad.go index 94d36920..afc48911 100644 --- a/pkg/internal/serialization/aad.go +++ b/pkg/internal/serialization/aad.go @@ -10,9 +10,9 @@ import ( "math" "sort" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/structs" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) const aadLenFields = int(2) diff --git a/pkg/internal/serialization/aad_test.go b/pkg/internal/serialization/aad_test.go index 0ed1061b..b5616886 100644 --- a/pkg/internal/serialization/aad_test.go +++ b/pkg/internal/serialization/aad_test.go @@ -10,8 +10,8 @@ import ( "github.com/stretchr/testify/assert" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) func Test_newAAD(t *testing.T) { diff --git a/pkg/internal/serialization/encrypteddatakey.go b/pkg/internal/serialization/encrypteddatakey.go index 75c55792..ee6b285c 100644 --- a/pkg/internal/serialization/encrypteddatakey.go +++ b/pkg/internal/serialization/encrypteddatakey.go @@ -10,9 +10,9 @@ import ( "math" "strings" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) const edkLenFields = int(3) diff --git a/pkg/internal/serialization/encrypteddatakey_test.go b/pkg/internal/serialization/encrypteddatakey_test.go index 0e9c890b..9f26ae11 100644 --- a/pkg/internal/serialization/encrypteddatakey_test.go +++ b/pkg/internal/serialization/encrypteddatakey_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/assert" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) func Test_edk_validateMinMaxEDKs(t *testing.T) { diff --git a/pkg/internal/serialization/messagebody.go b/pkg/internal/serialization/messagebody.go index 0b083f26..a6c6d873 100644 --- a/pkg/internal/serialization/messagebody.go +++ b/pkg/internal/serialization/messagebody.go @@ -8,9 +8,9 @@ import ( "errors" "fmt" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) var ( diff --git a/pkg/internal/serialization/messagebody_test.go b/pkg/internal/serialization/messagebody_test.go index 5ebbef78..f92cb89c 100644 --- a/pkg/internal/serialization/messagebody_test.go +++ b/pkg/internal/serialization/messagebody_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) func Test_frame_len(t *testing.T) { diff --git a/pkg/internal/serialization/messagefooter.go b/pkg/internal/serialization/messagefooter.go index ac797d8d..31704f5c 100644 --- a/pkg/internal/serialization/messagefooter.go +++ b/pkg/internal/serialization/messagefooter.go @@ -8,8 +8,8 @@ import ( "errors" "fmt" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) var ( diff --git a/pkg/internal/serialization/messageheader.go b/pkg/internal/serialization/messageheader.go index 67222e59..c3e40e6e 100644 --- a/pkg/internal/serialization/messageheader.go +++ b/pkg/internal/serialization/messageheader.go @@ -8,9 +8,9 @@ import ( "errors" "fmt" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) var ( diff --git a/pkg/internal/serialization/reader.go b/pkg/internal/serialization/reader.go index 33cb4440..bafca4df 100644 --- a/pkg/internal/serialization/reader.go +++ b/pkg/internal/serialization/reader.go @@ -7,7 +7,7 @@ import ( "bytes" "fmt" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" ) var fieldReader bufReader //nolint:gochecknoglobals diff --git a/pkg/internal/serialization/wrappingkey/wrapping.go b/pkg/internal/serialization/wrappingkey/wrapping.go index 65d25f8b..c7aa4041 100644 --- a/pkg/internal/serialization/wrappingkey/wrapping.go +++ b/pkg/internal/serialization/wrappingkey/wrapping.go @@ -3,7 +3,9 @@ package wrappingkey -import "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" +import ( + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" +) const ( tagLen = 16 diff --git a/pkg/internal/utils/bodyaad/bodyaad.go b/pkg/internal/utils/bodyaad/bodyaad.go index f7e8bf69..1a328e6c 100644 --- a/pkg/internal/utils/bodyaad/bodyaad.go +++ b/pkg/internal/utils/bodyaad/bodyaad.go @@ -4,8 +4,8 @@ package bodyaad import ( + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) const ( diff --git a/pkg/utils/conv/conv.go b/pkg/internal/utils/conv/conv.go similarity index 100% rename from pkg/utils/conv/conv.go rename to pkg/internal/utils/conv/conv.go diff --git a/pkg/utils/conv/conv_test.go b/pkg/internal/utils/conv/conv_test.go similarity index 100% rename from pkg/utils/conv/conv_test.go rename to pkg/internal/utils/conv/conv_test.go diff --git a/pkg/internal/utils/conv/doc.go b/pkg/internal/utils/conv/doc.go new file mode 100644 index 00000000..a2b9457c --- /dev/null +++ b/pkg/internal/utils/conv/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package conv provides utilities for converting types to big endian and vice versa. +package conv diff --git a/pkg/suite/algorithm.go b/pkg/suite/algorithm.go index d6c31db6..da2e3bc5 100644 --- a/pkg/suite/algorithm.go +++ b/pkg/suite/algorithm.go @@ -16,7 +16,7 @@ import ( "golang.org/x/crypto/hkdf" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" ) // ErrAlgorithmSuite is returned when algorithm suite is invalid or not supported. diff --git a/pkg/utils/encryption/gcm.go b/pkg/utils/encryption/gcm.go index 603af695..c6412e24 100644 --- a/pkg/utils/encryption/gcm.go +++ b/pkg/utils/encryption/gcm.go @@ -9,7 +9,7 @@ import ( "errors" "fmt" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" ) const ( diff --git a/pkg/utils/keyderivation/key_derivation.go b/pkg/utils/keyderivation/key_derivation.go index e9258629..b7fe5684 100644 --- a/pkg/utils/keyderivation/key_derivation.go +++ b/pkg/utils/keyderivation/key_derivation.go @@ -8,8 +8,8 @@ import ( "fmt" "io" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/conv" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/conv" ) var errKeyDerivation = errors.New("key derivation error") From 87c67b2a9b8b3a3e0bebd48eb0739a39b46feb6f Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 19:11:35 +0200 Subject: [PATCH 19/30] refactor(utils): keyderivation moved under internal packages, documentation --- pkg/internal/crypto/decrypter/decrypt.go | 2 +- pkg/internal/crypto/encrypter/encrypt.go | 2 +- pkg/internal/utils/keyderivation/doc.go | 5 +++++ pkg/{ => internal}/utils/keyderivation/key_derivation.go | 0 .../utils/keyderivation/key_derivation_test.go | 0 pkg/keys/raw/raw.go | 2 +- 6 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 pkg/internal/utils/keyderivation/doc.go rename pkg/{ => internal}/utils/keyderivation/key_derivation.go (100%) rename pkg/{ => internal}/utils/keyderivation/key_derivation_test.go (100%) diff --git a/pkg/internal/crypto/decrypter/decrypt.go b/pkg/internal/crypto/decrypter/decrypt.go index 4a48dbc1..5080fd3c 100644 --- a/pkg/internal/crypto/decrypter/decrypt.go +++ b/pkg/internal/crypto/decrypter/decrypt.go @@ -15,10 +15,10 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/bodyaad" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/keyderivation" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/keyderivation" ) // ErrInvalidMessage is returned when the message format is invalid. diff --git a/pkg/internal/crypto/encrypter/encrypt.go b/pkg/internal/crypto/encrypter/encrypt.go index ff4460ec..b0f2e568 100644 --- a/pkg/internal/crypto/encrypter/encrypt.go +++ b/pkg/internal/crypto/encrypter/encrypt.go @@ -15,12 +15,12 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/bodyaad" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/keyderivation" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/keyderivation" ) type Encrypter struct { diff --git a/pkg/internal/utils/keyderivation/doc.go b/pkg/internal/utils/keyderivation/doc.go new file mode 100644 index 00000000..d228863f --- /dev/null +++ b/pkg/internal/utils/keyderivation/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package keyderivation provides a set of functions for deriving cryptographic keys. +package keyderivation diff --git a/pkg/utils/keyderivation/key_derivation.go b/pkg/internal/utils/keyderivation/key_derivation.go similarity index 100% rename from pkg/utils/keyderivation/key_derivation.go rename to pkg/internal/utils/keyderivation/key_derivation.go diff --git a/pkg/utils/keyderivation/key_derivation_test.go b/pkg/internal/utils/keyderivation/key_derivation_test.go similarity index 100% rename from pkg/utils/keyderivation/key_derivation_test.go rename to pkg/internal/utils/keyderivation/key_derivation_test.go diff --git a/pkg/keys/raw/raw.go b/pkg/keys/raw/raw.go index 72082422..cab4959f 100644 --- a/pkg/keys/raw/raw.go +++ b/pkg/keys/raw/raw.go @@ -10,12 +10,12 @@ import ( "fmt" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization/wrappingkey" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/keyderivation" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/keyderivation" ) type KeyHandler interface { From 977473a30997b240f82da6e8a75f9a3bf96d0025 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 20:54:57 +0200 Subject: [PATCH 20/30] refactor(utils): move GCM encryption under internal packages, documentation --- .golangci.yml | 4 +- .mockery.yaml | 11 +-- .../AEADDecrypter_mock.go | 2 +- .../AEADEncrypter_mock.go | 2 +- .../GcmCrypter_mock.go} | 52 ++++++------ pkg/internal/crypto/decrypter/decrypt.go | 4 +- pkg/internal/crypto/decrypter/decrypt_test.go | 85 +++++++++---------- pkg/internal/crypto/encrypter/encrypt.go | 4 +- pkg/internal/crypto/encrypter/encrypt_test.go | 27 +++--- pkg/internal/utils/encryption/doc.go | 5 ++ pkg/{ => internal}/utils/encryption/gcm.go | 24 ------ .../utils/encryption/gcm_test.go | 0 pkg/keys/raw/raw.go | 4 +- pkg/keys/raw/raw_test.go | 13 ++- pkg/model/encryption.go | 24 ++++++ 15 files changed, 129 insertions(+), 132 deletions(-) rename mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/{utils/encryption => model}/AEADDecrypter_mock.go (99%) rename mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/{utils/encryption => model}/AEADEncrypter_mock.go (99%) rename mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/{utils/encryption/Encrypter_mock.go => model/GcmCrypter_mock.go} (54%) create mode 100644 pkg/internal/utils/encryption/doc.go rename pkg/{ => internal}/utils/encryption/gcm.go (89%) rename pkg/{ => internal}/utils/encryption/gcm_test.go (100%) diff --git a/.golangci.yml b/.golangci.yml index be64faba..94449eea 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -129,7 +129,7 @@ linters-settings: - assign ignored-files: - 'algorithm\.go' - - 'pkg/utils/conv/conv\.go' + - 'pkg/internal/utils/conv/conv\.go' - 'pkg/utils/arn/arn\.go' ignored-functions: - '^math\.' @@ -183,7 +183,7 @@ issues: - path: 'pkg/suite/algorithm.go' linters: - gochecknoglobals - - path: 'pkg/utils/conv/conv.go' + - path: 'pkg/internal/utils/conv/conv.go' linters: - gochecknoglobals - linters: diff --git a/.mockery.yaml b/.mockery.yaml index 0d1fe4f3..f30dbbc6 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -39,6 +39,9 @@ packages: config: mockname: "MockEncrypter" filename: "Encrypter_mock.go" + GcmCrypter: + AEADEncrypter: + AEADDecrypter: github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format: interfaces: MessageAAD: @@ -50,14 +53,6 @@ packages: MessageFooter: Deserializer: Serializer: - github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption: - interfaces: - GcmBase: - config: - mockname: "MockEncrypter" - filename: "Encrypter_mock.go" - AEADDecrypter: - AEADEncrypter: github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand: config: dir: mocks/{{ replaceAll .PackagePath "internal" "internal_" }} diff --git a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/AEADDecrypter_mock.go b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/AEADDecrypter_mock.go similarity index 99% rename from mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/AEADDecrypter_mock.go rename to mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/AEADDecrypter_mock.go index f2bf343a..9b696e2a 100644 --- a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/AEADDecrypter_mock.go +++ b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/AEADDecrypter_mock.go @@ -2,7 +2,7 @@ //go:build mocks -package encryption +package model import mock "github.com/stretchr/testify/mock" diff --git a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/AEADEncrypter_mock.go b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/AEADEncrypter_mock.go similarity index 99% rename from mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/AEADEncrypter_mock.go rename to mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/AEADEncrypter_mock.go index 1597c6ee..28ded160 100644 --- a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/AEADEncrypter_mock.go +++ b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/AEADEncrypter_mock.go @@ -2,7 +2,7 @@ //go:build mocks -package encryption +package model import mock "github.com/stretchr/testify/mock" diff --git a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/Encrypter_mock.go b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/GcmCrypter_mock.go similarity index 54% rename from mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/Encrypter_mock.go rename to mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/GcmCrypter_mock.go index e48b198a..4ffa30f9 100644 --- a/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption/Encrypter_mock.go +++ b/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/GcmCrypter_mock.go @@ -2,25 +2,25 @@ //go:build mocks -package encryption +package model import mock "github.com/stretchr/testify/mock" -// MockEncrypter is an autogenerated mock type for the GcmBase type -type MockEncrypter struct { +// MockGcmCrypter is an autogenerated mock type for the GcmCrypter type +type MockGcmCrypter struct { mock.Mock } -type MockEncrypter_Expecter struct { +type MockGcmCrypter_Expecter struct { mock *mock.Mock } -func (_m *MockEncrypter) EXPECT() *MockEncrypter_Expecter { - return &MockEncrypter_Expecter{mock: &_m.Mock} +func (_m *MockGcmCrypter) EXPECT() *MockGcmCrypter_Expecter { + return &MockGcmCrypter_Expecter{mock: &_m.Mock} } // Decrypt provides a mock function with given fields: key, iv, ciphertext, tag, aadData -func (_m *MockEncrypter) Decrypt(key []byte, iv []byte, ciphertext []byte, tag []byte, aadData []byte) ([]byte, error) { +func (_m *MockGcmCrypter) Decrypt(key []byte, iv []byte, ciphertext []byte, tag []byte, aadData []byte) ([]byte, error) { ret := _m.Called(key, iv, ciphertext, tag, aadData) if len(ret) == 0 { @@ -49,8 +49,8 @@ func (_m *MockEncrypter) Decrypt(key []byte, iv []byte, ciphertext []byte, tag [ return r0, r1 } -// MockEncrypter_Decrypt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Decrypt' -type MockEncrypter_Decrypt_Call struct { +// MockGcmCrypter_Decrypt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Decrypt' +type MockGcmCrypter_Decrypt_Call struct { *mock.Call } @@ -60,29 +60,29 @@ type MockEncrypter_Decrypt_Call struct { // - ciphertext []byte // - tag []byte // - aadData []byte -func (_e *MockEncrypter_Expecter) Decrypt(key interface{}, iv interface{}, ciphertext interface{}, tag interface{}, aadData interface{}) *MockEncrypter_Decrypt_Call { - return &MockEncrypter_Decrypt_Call{Call: _e.mock.On("Decrypt", key, iv, ciphertext, tag, aadData)} +func (_e *MockGcmCrypter_Expecter) Decrypt(key interface{}, iv interface{}, ciphertext interface{}, tag interface{}, aadData interface{}) *MockGcmCrypter_Decrypt_Call { + return &MockGcmCrypter_Decrypt_Call{Call: _e.mock.On("Decrypt", key, iv, ciphertext, tag, aadData)} } -func (_c *MockEncrypter_Decrypt_Call) Run(run func(key []byte, iv []byte, ciphertext []byte, tag []byte, aadData []byte)) *MockEncrypter_Decrypt_Call { +func (_c *MockGcmCrypter_Decrypt_Call) Run(run func(key []byte, iv []byte, ciphertext []byte, tag []byte, aadData []byte)) *MockGcmCrypter_Decrypt_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].([]byte), args[1].([]byte), args[2].([]byte), args[3].([]byte), args[4].([]byte)) }) return _c } -func (_c *MockEncrypter_Decrypt_Call) Return(_a0 []byte, _a1 error) *MockEncrypter_Decrypt_Call { +func (_c *MockGcmCrypter_Decrypt_Call) Return(_a0 []byte, _a1 error) *MockGcmCrypter_Decrypt_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *MockEncrypter_Decrypt_Call) RunAndReturn(run func([]byte, []byte, []byte, []byte, []byte) ([]byte, error)) *MockEncrypter_Decrypt_Call { +func (_c *MockGcmCrypter_Decrypt_Call) RunAndReturn(run func([]byte, []byte, []byte, []byte, []byte) ([]byte, error)) *MockGcmCrypter_Decrypt_Call { _c.Call.Return(run) return _c } // Encrypt provides a mock function with given fields: key, iv, plaintext, aadData -func (_m *MockEncrypter) Encrypt(key []byte, iv []byte, plaintext []byte, aadData []byte) ([]byte, []byte, error) { +func (_m *MockGcmCrypter) Encrypt(key []byte, iv []byte, plaintext []byte, aadData []byte) ([]byte, []byte, error) { ret := _m.Called(key, iv, plaintext, aadData) if len(ret) == 0 { @@ -120,8 +120,8 @@ func (_m *MockEncrypter) Encrypt(key []byte, iv []byte, plaintext []byte, aadDat return r0, r1, r2 } -// MockEncrypter_Encrypt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Encrypt' -type MockEncrypter_Encrypt_Call struct { +// MockGcmCrypter_Encrypt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Encrypt' +type MockGcmCrypter_Encrypt_Call struct { *mock.Call } @@ -130,34 +130,34 @@ type MockEncrypter_Encrypt_Call struct { // - iv []byte // - plaintext []byte // - aadData []byte -func (_e *MockEncrypter_Expecter) Encrypt(key interface{}, iv interface{}, plaintext interface{}, aadData interface{}) *MockEncrypter_Encrypt_Call { - return &MockEncrypter_Encrypt_Call{Call: _e.mock.On("Encrypt", key, iv, plaintext, aadData)} +func (_e *MockGcmCrypter_Expecter) Encrypt(key interface{}, iv interface{}, plaintext interface{}, aadData interface{}) *MockGcmCrypter_Encrypt_Call { + return &MockGcmCrypter_Encrypt_Call{Call: _e.mock.On("Encrypt", key, iv, plaintext, aadData)} } -func (_c *MockEncrypter_Encrypt_Call) Run(run func(key []byte, iv []byte, plaintext []byte, aadData []byte)) *MockEncrypter_Encrypt_Call { +func (_c *MockGcmCrypter_Encrypt_Call) Run(run func(key []byte, iv []byte, plaintext []byte, aadData []byte)) *MockGcmCrypter_Encrypt_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].([]byte), args[1].([]byte), args[2].([]byte), args[3].([]byte)) }) return _c } -func (_c *MockEncrypter_Encrypt_Call) Return(_a0 []byte, _a1 []byte, _a2 error) *MockEncrypter_Encrypt_Call { +func (_c *MockGcmCrypter_Encrypt_Call) Return(_a0 []byte, _a1 []byte, _a2 error) *MockGcmCrypter_Encrypt_Call { _c.Call.Return(_a0, _a1, _a2) return _c } -func (_c *MockEncrypter_Encrypt_Call) RunAndReturn(run func([]byte, []byte, []byte, []byte) ([]byte, []byte, error)) *MockEncrypter_Encrypt_Call { +func (_c *MockGcmCrypter_Encrypt_Call) RunAndReturn(run func([]byte, []byte, []byte, []byte) ([]byte, []byte, error)) *MockGcmCrypter_Encrypt_Call { _c.Call.Return(run) return _c } -// NewMockEncrypter creates a new instance of MockEncrypter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// NewMockGcmCrypter creates a new instance of MockGcmCrypter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewMockEncrypter(t interface { +func NewMockGcmCrypter(t interface { mock.TestingT Cleanup(func()) -}) *MockEncrypter { - mock := &MockEncrypter{} +}) *MockGcmCrypter { + mock := &MockGcmCrypter{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/internal/crypto/decrypter/decrypt.go b/pkg/internal/crypto/decrypter/decrypt.go index 5080fd3c..85732668 100644 --- a/pkg/internal/crypto/decrypter/decrypt.go +++ b/pkg/internal/crypto/decrypter/decrypt.go @@ -15,10 +15,10 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/bodyaad" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/keyderivation" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" ) // ErrInvalidMessage is returned when the message format is invalid. @@ -27,7 +27,7 @@ var ErrInvalidMessage = errors.New("invalid message format") type Decrypter struct { cmm model.CryptoMaterialsManager cfg crypto.DecrypterConfig - aeadDecrypter encryption.AEADDecrypter + aeadDecrypter model.AEADDecrypter deser format.Deserializer header format.MessageHeader verifier signature.Verifier diff --git a/pkg/internal/crypto/decrypter/decrypt_test.go b/pkg/internal/crypto/decrypter/decrypt_test.go index 21a08d5a..0e31b56a 100644 --- a/pkg/internal/crypto/decrypter/decrypt_test.go +++ b/pkg/internal/crypto/decrypter/decrypt_test.go @@ -16,7 +16,6 @@ import ( signaturemock "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/crypto/signature" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" formatmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" - encryptionmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/clientconfig" "github.com/chainifynet/aws-encryption-sdk-go/pkg/crypto" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" @@ -126,7 +125,7 @@ func TestDecrypter_Decrypt(t *testing.T) { name string clientCfgOpts []clientconfig.ConfigOptionFunc ciphertext []byte - setupMocks func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) + setupMocks func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) want []byte wantErr bool wantErrType error @@ -135,7 +134,7 @@ func TestDecrypter_Decrypt(t *testing.T) { { name: "Valid Decrypt", ciphertext: []byte{0x02, 0x00}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { // header header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384).Times(10) @@ -200,7 +199,7 @@ func TestDecrypter_Decrypt(t *testing.T) { { name: "Decrypt Error", ciphertext: nil, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { }, want: nil, wantErr: true, @@ -215,7 +214,7 @@ func TestDecrypter_Decrypt(t *testing.T) { cmm := mocks.NewMockCryptoMaterialsManager(t) deser := formatmocks.NewMockDeserializer(t) verifier := signaturemock.NewMockVerifier(t) - aeadDecrypter := encryptionmocks.NewMockAEADDecrypter(t) + aeadDecrypter := mocks.NewMockAEADDecrypter(t) tt.setupMocks(t, cmm, verifier, aeadDecrypter, deser) @@ -265,7 +264,7 @@ func TestDecrypter_decryptData(t *testing.T) { name string clientCfgOpts []clientconfig.ConfigOptionFunc ciphertext []byte - setupMocks func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) + setupMocks func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) want []byte wantErr bool wantErrType error @@ -274,7 +273,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Valid Decrypt", ciphertext: []byte{0x02, 0x00}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { // header header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384).Times(10) @@ -339,7 +338,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Empty Ciphertext", ciphertext: nil, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { }, want: nil, @@ -349,7 +348,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Invalid Ciphertext First Bytes", ciphertext: []byte{0x03}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { }, want: nil, wantErr: true, @@ -359,7 +358,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Header Decrypt Error", ciphertext: []byte{0x02, 0x00}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { deser.EXPECT().DeserializeHeader(mock.Anything, mock.Anything).Return(nil, nil, assert.AnError).Once() }, want: nil, @@ -369,7 +368,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Body Decrypt Error", ciphertext: []byte{0x02, 0x00}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { // header header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite(). @@ -411,7 +410,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Footer Deserialize Error", ciphertext: []byte{0x02, 0x00}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { // header header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite(). @@ -473,7 +472,7 @@ func TestDecrypter_decryptData(t *testing.T) { { name: "Footer Signature Error", ciphertext: []byte{0x02, 0x00}, - setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, cmm *mocks.MockCryptoMaterialsManager, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { // header header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite(). @@ -545,7 +544,7 @@ func TestDecrypter_decryptData(t *testing.T) { cmm := mocks.NewMockCryptoMaterialsManager(t) deser := formatmocks.NewMockDeserializer(t) verifier := signaturemock.NewMockVerifier(t) - aeadDecrypter := encryptionmocks.NewMockAEADDecrypter(t) + aeadDecrypter := mocks.NewMockAEADDecrypter(t) tt.setupMocks(t, cmm, verifier, aeadDecrypter, deser) @@ -592,7 +591,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { name string clientCfgOpts []clientconfig.ConfigOptionFunc alg *suite.AlgorithmSuite - setupMocks func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) + setupMocks func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) wantErr bool wantErrType error wantErrStr string @@ -600,7 +599,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Valid Committing Signing", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(8) header.EXPECT().Bytes().Return([]byte("test")).Twice() @@ -633,7 +632,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Valid Committing NonSigning", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(6) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -664,7 +663,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { clientconfig.WithCommitmentPolicy(suite.CommitmentPolicyRequireEncryptAllowDecrypt), }, alg: suite.AES_256_GCM_IV12_TAG16_HKDF_SHA256, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(5) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -694,7 +693,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { clientconfig.WithCommitmentPolicy(suite.CommitmentPolicyForbidEncryptAllowDecrypt), }, alg: suite.AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(7) header.EXPECT().Bytes().Return([]byte("test")).Twice() @@ -726,7 +725,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Deserialize Header Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { deser.EXPECT().DeserializeHeader(mock.Anything, mock.Anything). Return(nil, nil, assert.AnError).Once() }, @@ -736,7 +735,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Policy Conflict Error", alg: suite.AES_256_GCM_IV12_TAG16_HKDF_SHA256, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(1) @@ -750,7 +749,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Verifier Update Header Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(4) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -767,7 +766,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Verifier Update Header Auth Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(4) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -786,7 +785,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "CMM DecryptMaterials Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(5) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -809,7 +808,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Verifier Elliptic Key Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(5) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -835,7 +834,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Derive DataKey Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(6) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -865,7 +864,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Commitment Key Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(8) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -896,7 +895,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Commitment Key Match Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(8) header.EXPECT().Bytes().Return([]byte("test")).Once() @@ -927,7 +926,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { { name: "Header Auth Error", alg: suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384, - setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *encryptionmocks.MockAEADDecrypter) { + setupMocks: func(t *testing.T, alg *suite.AlgorithmSuite, cmm *mocks.MockCryptoMaterialsManager, deser *formatmocks.MockDeserializer, verifier *signaturemock.MockVerifier, aeadDecrypter *mocks.MockAEADDecrypter) { header := formatmocks.NewMockMessageHeader(t) header.EXPECT().AlgorithmSuite().Return(alg).Times(8) header.EXPECT().Bytes().Return([]byte("test")).Twice() @@ -967,7 +966,7 @@ func TestDecrypter_decryptHeader(t *testing.T) { cmm := mocks.NewMockCryptoMaterialsManager(t) deser := formatmocks.NewMockDeserializer(t) verifier := signaturemock.NewMockVerifier(t) - aeadDecrypter := encryptionmocks.NewMockAEADDecrypter(t) + aeadDecrypter := mocks.NewMockAEADDecrypter(t) tt.setupMocks(t, tt.alg, cmm, deser, verifier, aeadDecrypter) @@ -1017,7 +1016,7 @@ func TestDecrypter_decryptBody(t *testing.T) { tests := []struct { name string derivedDataKey []byte - setupMocks func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) + setupMocks func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) want []byte wantErr bool wantErrType error @@ -1026,7 +1025,7 @@ func TestDecrypter_decryptBody(t *testing.T) { { name: "Valid Decrypt", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { header.EXPECT().AlgorithmSuite(). Return(suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY).Once() header.EXPECT().FrameLength().Return(1024).Once() @@ -1056,7 +1055,7 @@ func TestDecrypter_decryptBody(t *testing.T) { { name: "Valid Two Frames Decrypt", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { header.EXPECT().AlgorithmSuite(). Return(suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY).Once() header.EXPECT().FrameLength().Return(1024).Once() @@ -1095,7 +1094,7 @@ func TestDecrypter_decryptBody(t *testing.T) { { name: "Deserialize Body Error", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { header.EXPECT().AlgorithmSuite(). Return(suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY).Once() header.EXPECT().FrameLength().Return(1024).Once() @@ -1111,7 +1110,7 @@ func TestDecrypter_decryptBody(t *testing.T) { { name: "Decrypt Frame Error", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, deser *formatmocks.MockDeserializer) { header.EXPECT().AlgorithmSuite(). Return(suite.AES_256_GCM_HKDF_SHA512_COMMIT_KEY).Once() header.EXPECT().FrameLength().Return(1024).Once() @@ -1136,7 +1135,7 @@ func TestDecrypter_decryptBody(t *testing.T) { t.Run(tt.name, func(t *testing.T) { header := formatmocks.NewMockMessageHeader(t) deser := formatmocks.NewMockDeserializer(t) - aeadDecrypter := encryptionmocks.NewMockAEADDecrypter(t) + aeadDecrypter := mocks.NewMockAEADDecrypter(t) tt.setupMocks(t, header, aeadDecrypter, deser) @@ -1170,7 +1169,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { tests := []struct { name string derivedDataKey []byte - setupMocks func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier + setupMocks func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier want []byte wantErr bool wantErrType error @@ -1179,7 +1178,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { { name: "Valid Decrypt Final Frame", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { header.EXPECT().ContentType().Return(suite.FramedContent).Once() header.EXPECT().MessageID().Return([]byte("test-id")).Once() @@ -1203,7 +1202,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { { name: "Valid Decrypt NonFinal Frame", derivedDataKey: []byte("test-key2"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { header.EXPECT().ContentType().Return(suite.FramedContent).Once() header.EXPECT().MessageID().Return([]byte("test-id")).Once() @@ -1224,7 +1223,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { { name: "BodyAAD NonFramed Error", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { header.EXPECT().ContentType().Return(suite.NonFramedContent).Once() frame.EXPECT().IsFinal().Return(true).Once() @@ -1237,7 +1236,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { { name: "AEAD Decrypt Error", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { header.EXPECT().ContentType().Return(suite.FramedContent).Once() header.EXPECT().MessageID().Return([]byte("test-id")).Once() @@ -1260,7 +1259,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { { name: "Verifier Error", derivedDataKey: []byte("test-key"), - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *encryptionmocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadDecrypter *mocks.MockAEADDecrypter, frame *formatmocks.MockBodyFrame) signature.Verifier { header.EXPECT().ContentType().Return(suite.FramedContent).Once() header.EXPECT().MessageID().Return([]byte("test-id")).Once() @@ -1286,7 +1285,7 @@ func TestDecrypter_decryptFrame(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { header := formatmocks.NewMockMessageHeader(t) - aeadDecrypter := encryptionmocks.NewMockAEADDecrypter(t) + aeadDecrypter := mocks.NewMockAEADDecrypter(t) frame := formatmocks.NewMockBodyFrame(t) verifier := tt.setupMocks(t, header, aeadDecrypter, frame) diff --git a/pkg/internal/crypto/encrypter/encrypt.go b/pkg/internal/crypto/encrypter/encrypt.go index b0f2e568..4aeac541 100644 --- a/pkg/internal/crypto/encrypter/encrypt.go +++ b/pkg/internal/crypto/encrypter/encrypt.go @@ -15,18 +15,18 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/bodyaad" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/keyderivation" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" ) type Encrypter struct { cmm model.CryptoMaterialsManager cfg crypto.EncrypterConfig - aeadEncrypter encryption.AEADEncrypter + aeadEncrypter model.AEADEncrypter ser format.Serializer header format.MessageHeader _derivedDataKey []byte diff --git a/pkg/internal/crypto/encrypter/encrypt_test.go b/pkg/internal/crypto/encrypter/encrypt_test.go index cd17a789..e0a0941f 100644 --- a/pkg/internal/crypto/encrypter/encrypt_test.go +++ b/pkg/internal/crypto/encrypter/encrypt_test.go @@ -15,7 +15,6 @@ import ( randmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/utils/rand" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" formatmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model/format" - encryptionmocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/clientconfig" "github.com/chainifynet/aws-encryption-sdk-go/pkg/crypto" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/crypto/signature" @@ -439,7 +438,7 @@ func TestEncrypter_encryptFrame(t *testing.T) { name string derivedDataKey []byte args args - setupMocks func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *encryptionmocks.MockAEADEncrypter) + setupMocks func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *mocks.MockAEADEncrypter) wantCiphertext []byte wantAuthTag []byte wantErr bool @@ -450,7 +449,7 @@ func TestEncrypter_encryptFrame(t *testing.T) { name: "BodyAAD Error", derivedDataKey: []byte("derivedDataKey"), args: finalFrameMock, - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *encryptionmocks.MockAEADEncrypter) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *mocks.MockAEADEncrypter) { header.EXPECT().ContentType().Return(suite.NonFramedContent).Once() }, wantCiphertext: nil, @@ -462,7 +461,7 @@ func TestEncrypter_encryptFrame(t *testing.T) { name: "AEAD Encrypt Error", derivedDataKey: []byte("derivedDataKey"), args: frameMock, - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *encryptionmocks.MockAEADEncrypter) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *mocks.MockAEADEncrypter) { header.EXPECT().ContentType().Return(suite.FramedContent).Once() header.EXPECT().MessageID().Return([]byte("test-message-id")).Once() @@ -479,7 +478,7 @@ func TestEncrypter_encryptFrame(t *testing.T) { name: "Valid Frame Encrypt", derivedDataKey: []byte("derivedDataKey"), args: frameMock, - setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *encryptionmocks.MockAEADEncrypter) { + setupMocks: func(t *testing.T, header *formatmocks.MockMessageHeader, aeadEncrypter *mocks.MockAEADEncrypter) { header.EXPECT().ContentType().Return(suite.FramedContent).Once() header.EXPECT().MessageID().Return([]byte("test-message-id")).Once() @@ -494,7 +493,7 @@ func TestEncrypter_encryptFrame(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { header := formatmocks.NewMockMessageHeader(t) - aeadEncrypter := encryptionmocks.NewMockAEADEncrypter(t) + aeadEncrypter := mocks.NewMockAEADEncrypter(t) tt.setupMocks(t, header, aeadEncrypter) @@ -529,7 +528,7 @@ func TestEncrypter_encryptFrame(t *testing.T) { func TestEncrypter_encryptBody(t *testing.T) { type mocksParams struct { header *formatmocks.MockMessageHeader - aeadEncrypter *encryptionmocks.MockAEADEncrypter + aeadEncrypter *mocks.MockAEADEncrypter ser *formatmocks.MockSerializer ciphertextBuf *mocks.MockEncryptionBuffer } @@ -640,7 +639,7 @@ func TestEncrypter_encryptBody(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { header := formatmocks.NewMockMessageHeader(t) - aeadEncrypter := encryptionmocks.NewMockAEADEncrypter(t) + aeadEncrypter := mocks.NewMockAEADEncrypter(t) ser := formatmocks.NewMockSerializer(t) ciphertextBuf := mocks.NewMockEncryptionBuffer(t) @@ -683,7 +682,7 @@ func TestEncrypter_encryptBody(t *testing.T) { func TestEncrypter_generateHeaderAuth(t *testing.T) { type mocksParams struct { header *formatmocks.MockMessageHeader - aeadEncrypter *encryptionmocks.MockAEADEncrypter + aeadEncrypter *mocks.MockAEADEncrypter ser *formatmocks.MockSerializer ciphertextBuf *mocks.MockEncryptionBuffer } @@ -749,7 +748,7 @@ func TestEncrypter_generateHeaderAuth(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { header := formatmocks.NewMockMessageHeader(t) - aeadEncrypter := encryptionmocks.NewMockAEADEncrypter(t) + aeadEncrypter := mocks.NewMockAEADEncrypter(t) ser := formatmocks.NewMockSerializer(t) ciphertextBuf := mocks.NewMockEncryptionBuffer(t) @@ -1109,7 +1108,7 @@ func TestEncrypter_encryptData(t *testing.T) { type mocksParams struct { alg *suite.AlgorithmSuite cmm *mocks.MockCryptoMaterialsManager - aeadEncrypter *encryptionmocks.MockAEADEncrypter + aeadEncrypter *mocks.MockAEADEncrypter encMaterials *mocks.MockEncryptionMaterial ser *formatmocks.MockSerializer ciphertextBuf *mocks.MockEncryptionBuffer @@ -1664,7 +1663,7 @@ func TestEncrypter_encryptData(t *testing.T) { rand.CryptoRandGen = randomGen cmm := mocks.NewMockCryptoMaterialsManager(t) - aeadEncrypter := encryptionmocks.NewMockAEADEncrypter(t) + aeadEncrypter := mocks.NewMockAEADEncrypter(t) encMaterials := mocks.NewMockEncryptionMaterial(t) ser := formatmocks.NewMockSerializer(t) ciphertextBuf := mocks.NewMockEncryptionBuffer(t) @@ -1724,7 +1723,7 @@ func TestEncrypter_Encrypt(t *testing.T) { type mocksParams struct { alg *suite.AlgorithmSuite cmm *mocks.MockCryptoMaterialsManager - aeadEncrypter *encryptionmocks.MockAEADEncrypter + aeadEncrypter *mocks.MockAEADEncrypter encMaterials *mocks.MockEncryptionMaterial ser *formatmocks.MockSerializer ciphertextBuf *mocks.MockEncryptionBuffer @@ -1848,7 +1847,7 @@ func TestEncrypter_Encrypt(t *testing.T) { rand.CryptoRandGen = randomGen cmm := mocks.NewMockCryptoMaterialsManager(t) - aeadEncrypter := encryptionmocks.NewMockAEADEncrypter(t) + aeadEncrypter := mocks.NewMockAEADEncrypter(t) encMaterials := mocks.NewMockEncryptionMaterial(t) ser := formatmocks.NewMockSerializer(t) ciphertextBuf := mocks.NewMockEncryptionBuffer(t) diff --git a/pkg/internal/utils/encryption/doc.go b/pkg/internal/utils/encryption/doc.go new file mode 100644 index 00000000..73954cbb --- /dev/null +++ b/pkg/internal/utils/encryption/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package encryption provides a way to encrypt and decrypt with AES-GCM. +package encryption diff --git a/pkg/utils/encryption/gcm.go b/pkg/internal/utils/encryption/gcm.go similarity index 89% rename from pkg/utils/encryption/gcm.go rename to pkg/internal/utils/encryption/gcm.go index c6412e24..579dd825 100644 --- a/pkg/utils/encryption/gcm.go +++ b/pkg/internal/utils/encryption/gcm.go @@ -22,30 +22,6 @@ var ( ErrGcmEncrypt = errors.New("gcm encrypt error") ) -type Encrypter interface { - Encrypt(key, iv, plaintext, aadData []byte) ([]byte, []byte, error) -} - -type Decrypter interface { - Decrypt(key, iv, ciphertext, tag, aadData []byte) ([]byte, error) -} - -type GcmBase interface { - Encrypter - Decrypter -} - -type AEADEncrypter interface { - Encrypter - GenerateHeaderAuth(derivedDataKey, headerBytes []byte) ([]byte, []byte, error) - ConstructIV(seqNum int) []byte -} - -type AEADDecrypter interface { - Decrypter - ValidateHeaderAuth(derivedDataKey, headerAuthTag, headerBytes []byte) error -} - type Gcm struct{} // Decrypt data with AES-GCM AEAD, IV is nonce diff --git a/pkg/utils/encryption/gcm_test.go b/pkg/internal/utils/encryption/gcm_test.go similarity index 100% rename from pkg/utils/encryption/gcm_test.go rename to pkg/internal/utils/encryption/gcm_test.go diff --git a/pkg/keys/raw/raw.go b/pkg/keys/raw/raw.go index cab4959f..f6cbe85b 100644 --- a/pkg/keys/raw/raw.go +++ b/pkg/keys/raw/raw.go @@ -10,12 +10,12 @@ import ( "fmt" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization/wrappingkey" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/keyderivation" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" ) type KeyHandler interface { @@ -50,7 +50,7 @@ type MasterKey struct { keys.BaseKey keyInfoPrefix []byte derivedDataKey []byte - Encrypter encryption.GcmBase + Encrypter model.GcmCrypter keyWrapper model.Wrapper } diff --git a/pkg/keys/raw/raw_test.go b/pkg/keys/raw/raw_test.go index df8639e1..455812e4 100644 --- a/pkg/keys/raw/raw_test.go +++ b/pkg/keys/raw/raw_test.go @@ -14,13 +14,12 @@ import ( mocksrand "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/internal_/utils/rand" mocks "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/model" - mocksencryption "github.com/chainifynet/aws-encryption-sdk-go/mocks/github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/serialization/wrappingkey" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/encryption" "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/utils/rand" "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" - "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/encryption" ) func TestRawMasterKey_KeyID(t *testing.T) { @@ -202,7 +201,7 @@ func TestRawMasterKey_encryptDataKey(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockEncrypter := mocksencryption.NewMockEncrypter(t) + mockEncrypter := mocks.NewMockGcmCrypter(t) mockRandomGenerator := mocksrand.NewMockRandomGenerator(t) mockWrapper := mocks.NewMockWrapper(t) @@ -302,7 +301,7 @@ func TestRawMasterKey_GenerateDataKey(t *testing.T) { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() - mockEncrypter := mocksencryption.NewMockEncrypter(t) + mockEncrypter := mocks.NewMockGcmCrypter(t) mockRandomGenerator := mocksrand.NewMockRandomGenerator(t) mockWrapper := mocks.NewMockWrapper(t) @@ -402,7 +401,7 @@ func TestRawMasterKey_EncryptDataKey(t *testing.T) { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() - mockEncrypter := mocksencryption.NewMockEncrypter(t) + mockEncrypter := mocks.NewMockGcmCrypter(t) mockRandomGenerator := mocksrand.NewMockRandomGenerator(t) mockWrapper := mocks.NewMockWrapper(t) @@ -509,7 +508,7 @@ func TestRawMasterKey_decryptDataKey(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - mockEncrypter := mocksencryption.NewMockEncrypter(t) + mockEncrypter := mocks.NewMockGcmCrypter(t) mockRandomGenerator := mocksrand.NewMockRandomGenerator(t) mockWrapper := mocks.NewMockWrapper(t) @@ -652,7 +651,7 @@ func TestRawMasterKey_DecryptDataKey(t *testing.T) { t.Run(tt.name, func(t *testing.T) { ctx := context.Background() - mockEncrypter := mocksencryption.NewMockEncrypter(t) + mockEncrypter := mocks.NewMockGcmCrypter(t) mockRandomGenerator := mocksrand.NewMockRandomGenerator(t) mockWrapper := mocks.NewMockWrapper(t) diff --git a/pkg/model/encryption.go b/pkg/model/encryption.go index 6fd8069e..c5df9d16 100644 --- a/pkg/model/encryption.go +++ b/pkg/model/encryption.go @@ -40,3 +40,27 @@ type EncryptionBuffer interface { // Reset resets the buffer to be empty. Reset() } + +type GcmEncrypter interface { + Encrypt(key, iv, plaintext, aadData []byte) ([]byte, []byte, error) +} + +type GcmDecrypter interface { + Decrypt(key, iv, ciphertext, tag, aadData []byte) ([]byte, error) +} + +type GcmCrypter interface { + GcmEncrypter + GcmDecrypter +} + +type AEADEncrypter interface { + GcmEncrypter + GenerateHeaderAuth(derivedDataKey, headerBytes []byte) ([]byte, []byte, error) + ConstructIV(seqNum int) []byte +} + +type AEADDecrypter interface { + GcmDecrypter + ValidateHeaderAuth(derivedDataKey, headerAuthTag, headerBytes []byte) error +} From 7e53348ed4e53e03eb32a75c3cee29231c14ed7c Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 21:08:50 +0200 Subject: [PATCH 21/30] docs(model): GCM encryption documentation --- pkg/model/encryption.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pkg/model/encryption.go b/pkg/model/encryption.go index c5df9d16..1881fea3 100644 --- a/pkg/model/encryption.go +++ b/pkg/model/encryption.go @@ -41,26 +41,44 @@ type EncryptionBuffer interface { Reset() } +// GcmEncrypter is an interface for GCM encryption implementations. type GcmEncrypter interface { + // Encrypt is a method for encrypting data. It returns three values: the + // encrypted ciphertext, the authentication tag, and an error if any occurred + // during the encryption process. Encrypt(key, iv, plaintext, aadData []byte) ([]byte, []byte, error) } +// GcmDecrypter is an interface for GCM decryption implementations. type GcmDecrypter interface { + // Decrypt is a method for decrypting data. It returns the decrypted plaintext, + // and an error if any occurred. Decrypt(key, iv, ciphertext, tag, aadData []byte) ([]byte, error) } +// GcmCrypter is a combined interface for GCM encryption and decryption. type GcmCrypter interface { GcmEncrypter GcmDecrypter } +// AEADEncrypter is an interface for AEAD encryption implementations. type AEADEncrypter interface { GcmEncrypter + + // GenerateHeaderAuth generates the header authentication tag and returns the + // authentication tag, iv, and an error if any occurred. GenerateHeaderAuth(derivedDataKey, headerBytes []byte) ([]byte, []byte, error) + + // ConstructIV constructs the IV from the sequence number. ConstructIV(seqNum int) []byte } +// AEADDecrypter is an interface for AEAD decryption implementations. type AEADDecrypter interface { GcmDecrypter + + // ValidateHeaderAuth validates that the header authentication tag against the + // message header, and returns an error if any occurred. ValidateHeaderAuth(derivedDataKey, headerAuthTag, headerBytes []byte) error } From 2f13e366c5f3fa248a452582f9a95671eacdd1d9 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 22:25:10 +0200 Subject: [PATCH 22/30] docs(keys): KMS key documentation --- pkg/keys/kms/doc.go | 5 +++++ pkg/keys/kms/kms.go | 39 +++++++++++------------------------- pkg/keys/kms/kms_mrk.go | 11 ++++++++-- pkg/keys/kms/kms_mrk_test.go | 12 +++++------ pkg/keys/kms/kms_test.go | 16 +++++++-------- 5 files changed, 40 insertions(+), 43 deletions(-) create mode 100644 pkg/keys/kms/doc.go diff --git a/pkg/keys/kms/doc.go b/pkg/keys/kms/doc.go new file mode 100644 index 00000000..c942a88e --- /dev/null +++ b/pkg/keys/kms/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package kms contains KMS and KMS MRK Master Key implementations. +package kms diff --git a/pkg/keys/kms/kms.go b/pkg/keys/kms/kms.go index 284bdb51..f6f13388 100644 --- a/pkg/keys/kms/kms.go +++ b/pkg/keys/kms/kms.go @@ -21,10 +21,11 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) -var ( - ErrKmsClient = errors.New("KMSClient error") -) +// ErrKmsClient is returned when AWS KMS encounters an error. +var ErrKmsClient = errors.New("KMSClient error") +// KeyHandler is an interface specific to the Kms [MasterKey] which is used by +// the KmsMasterKeyProvider. type KeyHandler interface { model.MasterKey decryptDataKey(ctx context.Context, encryptedDataKey model.EncryptedDataKeyI, _ *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) @@ -34,8 +35,10 @@ type KeyHandler interface { validateAllowedDecrypt(edkKeyID string) error } +// KeyFactory is a factory for creating Kms [MasterKey]. type KeyFactory struct{} +// NewMasterKey factory method returns a new instance of Kms [MasterKey]. func (f *KeyFactory) NewMasterKey(args ...interface{}) (model.MasterKey, error) { if len(args) != 2 { //nolint:gomnd return nil, fmt.Errorf("invalid number of arguments") @@ -50,15 +53,16 @@ func (f *KeyFactory) NewMasterKey(args ...interface{}) (model.MasterKey, error) return nil, fmt.Errorf("invalid keyID") } - return NewKmsMasterKey(client, keyID) + return newKmsMasterKey(client, keyID) } +// MasterKey contains the Kms Master Key, KMS Client, and it implements the [model.MasterKey] interface. type MasterKey struct { keys.BaseKey kmsClient model.KMSClient } -func NewKmsMasterKey(client model.KMSClient, keyID string) (*MasterKey, error) { +func newKmsMasterKey(client model.KMSClient, keyID string) (*MasterKey, error) { if client == nil { return nil, fmt.Errorf("KMSMasterKey: client must not be nil") } @@ -75,12 +79,7 @@ func NewKmsMasterKey(client model.KMSClient, keyID string) (*MasterKey, error) { var _ model.MasterKey = (*MasterKey)(nil) var _ KeyHandler = (*MasterKey)(nil) -// GenerateDataKey returns DataKey is generated from primaryMasterKey in MasterKeyProvider -// DataKey contains: -// -// provider keyID of this (MasterKey) KmsMasterKey -// dataKey Plaintext of this generated dataKey -// encryptedDataKey CiphertextBlob of this generated dataKey +// GenerateDataKey generates a new data key and returns it. func (kmsMK *MasterKey) GenerateDataKey(ctx context.Context, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { dataKeyRequest := kmsMK.buildGenerateDataKeyRequest(alg, ec) @@ -112,14 +111,7 @@ func (kmsMK *MasterKey) buildGenerateDataKeyRequest(alg *suite.AlgorithmSuite, e } } -// EncryptDataKey returns EncryptedDataKey which is encrypted from DataKey that was generated at GenerateDataKey -// EncryptedDataKey contains: -// -// provider keyID of this (MasterKey) KmsMasterKey -// encryptedDataKey CiphertextBlob is encrypted content of dataKey (this or other) -// -// i.e. GenerateDataKey (encryption material generator), once per primaryMasterKey -> -// -> for each MasterKey (KmsMasterKey) registered in providers.MasterKeyProvider do EncryptDataKey +// EncryptDataKey encrypts the data key and returns the encrypted data key. func (kmsMK *MasterKey) EncryptDataKey(ctx context.Context, dataKey model.DataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.EncryptedDataKeyI, error) { encryptDataKeyRequest := kmsMK.buildEncryptRequest(dataKey, ec) @@ -158,14 +150,7 @@ func (kmsMK *MasterKey) validateAllowedDecrypt(edkKeyID string) error { return nil } -// DecryptDataKey returns DataKey which is decrypted from EncryptedDataKey that was encrypted by EncryptDataKey -// DataKey contains: -// -// provider keyID of this (MasterKey) KmsMasterKey MUST equals to EncryptedDataKey keyID -// dataKey Plaintext is decrypted content of EncryptedDataKey encryptedDataKey -// encryptedDataKey encrypted content of (this) EncryptedDataKey -// -// Decrypted dataKey (plaintext) MUST match DataKey (plaintext) that was originally generated at GenerateDataKey. +// DecryptDataKey decrypts the encrypted data key and returns the data key. func (kmsMK *MasterKey) DecryptDataKey(ctx context.Context, encryptedDataKey model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { if err := kmsMK.validateAllowedDecrypt(encryptedDataKey.KeyID()); err != nil { return nil, err diff --git a/pkg/keys/kms/kms_mrk.go b/pkg/keys/kms/kms_mrk.go index c796bbf1..76b28721 100644 --- a/pkg/keys/kms/kms_mrk.go +++ b/pkg/keys/kms/kms_mrk.go @@ -14,12 +14,16 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) +// MrkMasterKey is a Kms [MasterKey] that uses a KMS multi-Region key. It embeds +// the Kms [MasterKey] and implements the Kms [KeyHandler] interface. type MrkMasterKey struct { MasterKey } +// MrkKeyFactory is a factory for creating Kms [MrkMasterKey]. type MrkKeyFactory struct{} +// NewMasterKey factory method returns a new instance of Kms [MrkMasterKey]. func (f *MrkKeyFactory) NewMasterKey(args ...interface{}) (model.MasterKey, error) { if len(args) != 2 { //nolint:gomnd return nil, fmt.Errorf("invalid number of arguments") @@ -34,14 +38,14 @@ func (f *MrkKeyFactory) NewMasterKey(args ...interface{}) (model.MasterKey, erro return nil, fmt.Errorf("invalid keyID") } - return NewKmsMrkMasterKey(client, keyID) + return newKmsMrkMasterKey(client, keyID) } // checking that MrkMasterKey implements both model.MasterKey and KeyHandler interfaces. var _ model.MasterKey = (*MrkMasterKey)(nil) var _ KeyHandler = (*MrkMasterKey)(nil) -func NewKmsMrkMasterKey(client model.KMSClient, keyID string) (*MrkMasterKey, error) { +func newKmsMrkMasterKey(client model.KMSClient, keyID string) (*MrkMasterKey, error) { if client == nil { return nil, fmt.Errorf("KMSMrkMasterKey: client must not be nil") } @@ -56,6 +60,8 @@ func NewKmsMrkMasterKey(client model.KMSClient, keyID string) (*MrkMasterKey, er }, nil } +// OwnsDataKey checks if the key resource ARN matches the keyID of the master +// key. Both ARNs must be MRK ARNs. func (kmsMrkMK *MrkMasterKey) OwnsDataKey(key model.Key) bool { if kmsMrkMK.Metadata().ProviderID == key.KeyProvider().ProviderID && arn.IsMrkArnEqual(kmsMrkMK.Metadata().KeyID, key.KeyID()) { return true @@ -70,6 +76,7 @@ func (kmsMrkMK *MrkMasterKey) validateAllowedDecrypt(edkKeyID string) error { return nil } +// DecryptDataKey decrypts the encrypted data key and returns the data key. func (kmsMrkMK *MrkMasterKey) DecryptDataKey(ctx context.Context, encryptedDataKey model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { if err := kmsMrkMK.validateAllowedDecrypt(encryptedDataKey.KeyID()); err != nil { return nil, err diff --git a/pkg/keys/kms/kms_mrk_test.go b/pkg/keys/kms/kms_mrk_test.go index d23592a4..97577fda 100644 --- a/pkg/keys/kms/kms_mrk_test.go +++ b/pkg/keys/kms/kms_mrk_test.go @@ -71,11 +71,11 @@ func TestNewKmsMrkMasterKey(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewKmsMrkMasterKey(tt.args.client, tt.args.keyID) - if !tt.wantErr(t, err, fmt.Sprintf("NewKmsMrkMasterKey(%v, %v)", tt.args.client, tt.args.keyID)) { + got, err := newKmsMrkMasterKey(tt.args.client, tt.args.keyID) + if !tt.wantErr(t, err, fmt.Sprintf("newKmsMrkMasterKey(%v, %v)", tt.args.client, tt.args.keyID)) { return } - assert.Equalf(t, tt.want, got, "NewKmsMrkMasterKey(%v, %v)", tt.args.client, tt.args.keyID) + assert.Equalf(t, tt.want, got, "newKmsMrkMasterKey(%v, %v)", tt.args.client, tt.args.keyID) }) } } @@ -127,7 +127,7 @@ func TestKmsMrkMasterKey_validateAllowedDecrypt(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockKmsClient := mocks.NewMockKMSClient(t) - kmsMK, err := NewKmsMrkMasterKey(mockKmsClient, tt.keyID) + kmsMK, err := newKmsMrkMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) tt.wantErr(t, kmsMK.validateAllowedDecrypt(tt.edkKeyID), fmt.Sprintf("validateAllowedDecrypt(%v)", tt.edkKeyID)) @@ -188,7 +188,7 @@ func TestKmsMrkMasterKey_OwnsDataKey(t *testing.T) { mockKey.EXPECT().KeyID().Return(tt.mockMeta.KeyID).Once() mockKey.EXPECT().KeyProvider().Return(tt.mockMeta).Once() - kmsMrkMK, err := NewKmsMrkMasterKey(mockKmsClient, tt.keyID) + kmsMrkMK, err := newKmsMrkMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) assert.Equalf(t, tt.want, kmsMrkMK.OwnsDataKey(mockKey), "OwnsDataKey(%v)", mockKey) @@ -256,7 +256,7 @@ func TestKmsMrkMasterKey_DecryptDataKey(t *testing.T) { }, nil).Once() } - kmsMrkMK, err := NewKmsMrkMasterKey(mockKmsClient, tt.keyID) + kmsMrkMK, err := newKmsMrkMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) edk := model.NewEncryptedDataKey( diff --git a/pkg/keys/kms/kms_test.go b/pkg/keys/kms/kms_test.go index dbccbeea..bcfbd981 100644 --- a/pkg/keys/kms/kms_test.go +++ b/pkg/keys/kms/kms_test.go @@ -121,7 +121,7 @@ func TestKmsMasterKey_GenerateDataKey(t *testing.T) { }, nil).Once() } - kmsMK, err := NewKmsMasterKey(mockKmsClient, tt.keyID) + kmsMK, err := newKmsMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) got, err := kmsMK.GenerateDataKey(ctx, tt.args.alg, tt.args.ec) @@ -234,7 +234,7 @@ func TestKmsMasterKey_EncryptDataKey(t *testing.T) { }, nil).Once() } - kmsMK, err := NewKmsMasterKey(mockKmsClient, tt.keyID) + kmsMK, err := newKmsMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) dataKey := model.NewDataKey( @@ -391,7 +391,7 @@ func TestKmsMasterKey_decryptDataKey(t *testing.T) { } } - kmsMK, err := NewKmsMasterKey(mockKmsClient, tt.keyID) + kmsMK, err := newKmsMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) edk := model.NewEncryptedDataKey( @@ -447,7 +447,7 @@ func TestKmsMasterKey_validateAllowedDecrypt(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockKmsClient := mocks.NewMockKMSClient(t) - kmsMK, err := NewKmsMasterKey(mockKmsClient, tt.keyID) + kmsMK, err := newKmsMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) tt.wantErr(t, kmsMK.validateAllowedDecrypt(tt.edkKeyID), fmt.Sprintf("validateAllowedDecrypt(%v)", tt.edkKeyID)) @@ -506,7 +506,7 @@ func TestKmsMasterKey_DecryptDataKey(t *testing.T) { }, nil).Once() } - kmsMK, err := NewKmsMasterKey(mockKmsClient, tt.keyID) + kmsMK, err := newKmsMasterKey(mockKmsClient, tt.keyID) require.NoError(t, err) edk := model.NewEncryptedDataKey( @@ -576,11 +576,11 @@ func TestNewKmsMasterKey(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewKmsMasterKey(tt.args.client, tt.args.keyID) - if !tt.wantErr(t, err, fmt.Sprintf("NewKmsMasterKey(%v, %v)", tt.args.client, tt.args.keyID)) { + got, err := newKmsMasterKey(tt.args.client, tt.args.keyID) + if !tt.wantErr(t, err, fmt.Sprintf("newKmsMasterKey(%v, %v)", tt.args.client, tt.args.keyID)) { return } - assert.Equalf(t, tt.want, got, "NewKmsMasterKey(%v, %v)", tt.args.client, tt.args.keyID) + assert.Equalf(t, tt.want, got, "newKmsMasterKey(%v, %v)", tt.args.client, tt.args.keyID) }) } } From 7be11ab300a05a288c5439439def3a95f8f3ad92 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 22:25:28 +0200 Subject: [PATCH 23/30] docs(keys): Raw Master Key documentation --- pkg/keys/raw/doc.go | 5 +++++ pkg/keys/raw/raw.go | 14 ++++++++++++-- pkg/keys/raw/raw_test.go | 6 +++--- 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 pkg/keys/raw/doc.go diff --git a/pkg/keys/raw/doc.go b/pkg/keys/raw/doc.go new file mode 100644 index 00000000..4497ff0f --- /dev/null +++ b/pkg/keys/raw/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package raw contains Raw Master Key implementation. +package raw diff --git a/pkg/keys/raw/raw.go b/pkg/keys/raw/raw.go index f6cbe85b..b056d0f7 100644 --- a/pkg/keys/raw/raw.go +++ b/pkg/keys/raw/raw.go @@ -18,14 +18,18 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// KeyHandler is an interface specific to the RawMasterKey which is used by Raw +// Master Key Provider. type KeyHandler interface { model.MasterKey encryptDataKey(dataKey []byte, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) ([]byte, error) decryptDataKey(encryptedDataKey []byte, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) ([]byte, error) } +// KeyFactory is a factory for creating RawMasterKey. type KeyFactory struct{} +// NewMasterKey factory method returns a new instance of Raw [MasterKey]. func (f *KeyFactory) NewMasterKey(args ...interface{}) (model.MasterKey, error) { if len(args) != 3 { //nolint:gomnd return nil, fmt.Errorf("invalid number of arguments") @@ -43,9 +47,10 @@ func (f *KeyFactory) NewMasterKey(args ...interface{}) (model.MasterKey, error) return nil, fmt.Errorf("invalid rawKey") } - return NewRawMasterKey(providerID, keyID, rawKey) + return newRawMasterKey(providerID, keyID, rawKey) } +// MasterKey contains the Raw Master Key and implements the [model.MasterKey] interface. type MasterKey struct { keys.BaseKey keyInfoPrefix []byte @@ -54,7 +59,7 @@ type MasterKey struct { keyWrapper model.Wrapper } -func NewRawMasterKey(providerID, keyID string, rawKey []byte) (*MasterKey, error) { +func newRawMasterKey(providerID, keyID string, rawKey []byte) (*MasterKey, error) { rawKeyCpy := make([]byte, len(rawKey)) copy(rawKeyCpy, rawKey) @@ -82,6 +87,7 @@ func NewRawMasterKey(providerID, keyID string, rawKey []byte) (*MasterKey, error var _ model.MasterKey = (*MasterKey)(nil) var _ KeyHandler = (*MasterKey)(nil) +// GenerateDataKey generates a new data key and returns it. func (rawMK *MasterKey) GenerateDataKey(_ context.Context, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { dataKey, _ := rand.CryptoRandomBytes(alg.EncryptionSuite.DataKeyLen) @@ -115,6 +121,7 @@ func (rawMK *MasterKey) encryptDataKey(dataKey []byte, alg *suite.AlgorithmSuite return encryptedDataKey, nil } +// EncryptDataKey encrypts the data key and returns the encrypted data key. func (rawMK *MasterKey) EncryptDataKey(_ context.Context, dk model.DataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.EncryptedDataKeyI, error) { encryptedDataKey, err := rawMK.encryptDataKey(dk.DataKey(), alg, ec) if err != nil { @@ -127,6 +134,8 @@ func (rawMK *MasterKey) EncryptDataKey(_ context.Context, dk model.DataKeyI, alg ), nil } +// OwnsDataKey returns true if key is owned by the master key. In other words, +// the key was encrypted with the master key. func (rawMK *MasterKey) OwnsDataKey(key model.Key) bool { otherKeyInfoPrefix := rawMK.keyWrapper.SerializeKeyInfoPrefix(key.KeyID()) if rawMK.Metadata().ProviderID == key.KeyProvider().ProviderID && @@ -137,6 +146,7 @@ func (rawMK *MasterKey) OwnsDataKey(key model.Key) bool { return false } +// DecryptDataKey decrypts the encrypted data key and returns the data key. func (rawMK *MasterKey) DecryptDataKey(_ context.Context, encryptedDataKey model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { if encryptedDataKey == nil { return nil, fmt.Errorf("RawMasterKey error: invalid encryptedDataKey: %w", keys.ErrDecryptKey) diff --git a/pkg/keys/raw/raw_test.go b/pkg/keys/raw/raw_test.go index 455812e4..a30479f3 100644 --- a/pkg/keys/raw/raw_test.go +++ b/pkg/keys/raw/raw_test.go @@ -145,11 +145,11 @@ func TestNewRawMasterKey(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NewRawMasterKey(tt.args.providerID, tt.args.keyID, tt.args.rawKey) - if !tt.wantErr(t, err, fmt.Sprintf("NewRawMasterKey(%v, %v, %v)", tt.args.providerID, tt.args.keyID, tt.args.rawKey)) { + got, err := newRawMasterKey(tt.args.providerID, tt.args.keyID, tt.args.rawKey) + if !tt.wantErr(t, err, fmt.Sprintf("newRawMasterKey(%v, %v, %v)", tt.args.providerID, tt.args.keyID, tt.args.rawKey)) { return } - assert.Equalf(t, tt.want, got, "NewRawMasterKey(%v, %v, %v)", tt.args.providerID, tt.args.keyID, tt.args.rawKey) + assert.Equalf(t, tt.want, got, "newRawMasterKey(%v, %v, %v)", tt.args.providerID, tt.args.keyID, tt.args.rawKey) }) } } From 14c34b22fac99bebed3e55086effa34c37dcd942 Mon Sep 17 00:00:00 2001 From: wobondar Date: Fri, 15 Mar 2024 22:26:06 +0200 Subject: [PATCH 24/30] docs(keys): Base key and generic key errors documentation --- pkg/keys/basekey.go | 10 ++++++++++ pkg/keys/doc.go | 5 +++++ pkg/keys/errors.go | 13 ++++++++----- 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 pkg/keys/doc.go diff --git a/pkg/keys/basekey.go b/pkg/keys/basekey.go index 31682c01..bde87154 100644 --- a/pkg/keys/basekey.go +++ b/pkg/keys/basekey.go @@ -5,22 +5,32 @@ package keys import "github.com/chainifynet/aws-encryption-sdk-go/pkg/model" +// BaseKey is implementation of [model.MasterKeyBase] that methods can be reused or +// overridden by other master key implementations. type BaseKey struct { metadata model.KeyMeta } +// NewBaseKey returns a new instance of [BaseKey]. func NewBaseKey(metadata model.KeyMeta) BaseKey { return BaseKey{metadata: metadata} } +// KeyID returns the key ID of the master key. func (mk *BaseKey) KeyID() string { return mk.metadata.KeyID } +// Metadata returns the [model.KeyMeta] metadata of the master key. func (mk *BaseKey) Metadata() model.KeyMeta { return mk.metadata } +// OwnsDataKey returns true if key is owned by the master key. In other words, +// the key was encrypted with the master key. +// +// Raw Master Key and KMS MRK Master Key implementations are using a different +// logic to determine if the key is owned by the master key. func (mk *BaseKey) OwnsDataKey(key model.Key) bool { return mk.metadata.KeyID == key.KeyID() } diff --git a/pkg/keys/doc.go b/pkg/keys/doc.go new file mode 100644 index 00000000..f4a2d068 --- /dev/null +++ b/pkg/keys/doc.go @@ -0,0 +1,5 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package keys contains implementations of Master Keys and generic key errors. +package keys diff --git a/pkg/keys/errors.go b/pkg/keys/errors.go index e18b9191..8886fad2 100644 --- a/pkg/keys/errors.go +++ b/pkg/keys/errors.go @@ -5,8 +5,11 @@ package keys import "errors" -var ( - ErrDecryptKey = errors.New("unable to decrypt data key") - ErrGenerateDataKey = errors.New("unable to generate data key") - ErrEncryptKey = errors.New("unable to encrypt data key") -) +// ErrDecryptKey is returned when the data key cannot be decrypted. +var ErrDecryptKey = errors.New("unable to decrypt data key") + +// ErrGenerateDataKey is returned when the data key cannot be generated. +var ErrGenerateDataKey = errors.New("unable to generate data key") + +// ErrEncryptKey is returned when the data key cannot be encrypted. +var ErrEncryptKey = errors.New("unable to encrypt data key") From 0db7e4b6eecfa0c9a75add37c7d8e3040d00e983 Mon Sep 17 00:00:00 2001 From: wobondar Date: Sat, 16 Mar 2024 01:34:47 +0200 Subject: [PATCH 25/30] docs(kmsprovider): KMS Master Key Provider documentation --- pkg/providers/kmsprovider/config.go | 10 +- pkg/providers/kmsprovider/consts.go | 2 + pkg/providers/kmsprovider/doc.go | 74 ++++++++++++++ pkg/providers/kmsprovider/kmsprovider.go | 119 +++++++++++++++++++++- pkg/providers/kmsprovider/options.go | 13 ++- pkg/providers/kmsprovider/options_test.go | 2 +- 6 files changed, 211 insertions(+), 9 deletions(-) create mode 100644 pkg/providers/kmsprovider/doc.go diff --git a/pkg/providers/kmsprovider/config.go b/pkg/providers/kmsprovider/config.go index c6d3213c..3e55b67c 100644 --- a/pkg/providers/kmsprovider/config.go +++ b/pkg/providers/kmsprovider/config.go @@ -19,7 +19,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/keys/kms" "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" "github.com/chainifynet/aws-encryption-sdk-go/pkg/providers" - arn2 "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) func resolveProviderType(opts *Options) ProviderType { @@ -89,7 +89,7 @@ func resolveDefaultRegion(keyIDs []string, opts *Options) { var region string if len(keyIDs) > 0 { for _, keyID := range keyIDs { - keyArn, err := arn2.ParseArn(keyID) + keyArn, err := arn.ParseArn(keyID) if err != nil { // try next keyID in case of invalid ARN continue @@ -176,7 +176,7 @@ func validateConfig(t ProviderType, keyIDs []string, options *Options) error { / func validateKeyArns(keyIDs []string) error { for _, keyID := range keyIDs { - if _, err := arn2.ParseArn(keyID); err != nil { + if _, err := arn.ParseArn(keyID); err != nil { return fmt.Errorf("%q keyID is not a valid ARN: %w", keyID, err) } } @@ -213,7 +213,7 @@ func validateAccountID(accountID string) error { } func validateUniqueMrks(keyIDs []string) error { - mrkKeyIDs, err := arn2.FilterKeyIDs(arn2.IsValidMrkIdentifier, keyIDs) + mrkKeyIDs, err := arn.FilterKeyIDs(arn.IsValidMrkIdentifier, keyIDs) if err != nil { return err } @@ -223,7 +223,7 @@ func validateUniqueMrks(keyIDs []string) error { if structs.MapContains(duplicateIDs, key1) && structs.MapContains(duplicateIDs, key2) { continue } - ok, _ := arn2.KeyResourceEqual(key1, key2) + ok, _ := arn.KeyResourceEqual(key1, key2) // error ignored because ARN is already validated IsValidMrkIdentifier // or filtered out by FilterKeyIDs if ok { diff --git a/pkg/providers/kmsprovider/consts.go b/pkg/providers/kmsprovider/consts.go index 7522cc0d..0e6e856d 100644 --- a/pkg/providers/kmsprovider/consts.go +++ b/pkg/providers/kmsprovider/consts.go @@ -9,6 +9,7 @@ const ( _awsAccountIDLength = 12 // length of AWS account ID (e.g. "123456789012") ) +// ProviderType represents the type of KMS Provider. type ProviderType int const ( @@ -18,6 +19,7 @@ const ( MrkAwareDiscoveryKmsProvider // MRK-Aware Discovery-Enabled KMS Provider ) +// String returns the string representation of the KMS Provider type. func (k ProviderType) String() string { switch k { case StrictKmsProvider: diff --git a/pkg/providers/kmsprovider/doc.go b/pkg/providers/kmsprovider/doc.go new file mode 100644 index 00000000..d4940e55 --- /dev/null +++ b/pkg/providers/kmsprovider/doc.go @@ -0,0 +1,74 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package kmsprovider contains KMS Master Key Provider implementation. +// +// Example [DiscoveryKmsProvider] in discovery mode: +// +// kmsProvider, err := kmsprovider.New() +// if err != nil { +// panic(err) // handle error +// } +// +// Example [StrictKmsProvider] in strict mode: +// +// keyID := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// kmsProvider, err := kmsprovider.New(keyID) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [StrictKmsProvider] with custom AWS config: +// +// keyID := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// kmsProvider, err := kmsprovider.NewWithOpts( +// []string{keyID}, +// kmsprovider.WithAwsLoadOptions( +// // add more AWS Config options if needed +// config.WithSharedConfigProfile("your_profile_name"), +// config.WithRegion("us-west-2"), +// ), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [MrkAwareStrictKmsProvider]: +// +// keyID := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// kmsProvider, err := kmsprovider.NewWithOpts( +// []string{keyID}, // KMS CMK ARNs +// kmsprovider.WithMrkAwareness(), // enable MRK-aware +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [DiscoveryKmsProvider] with discovery filter: +// +// kmsProvider, err := kmsprovider.NewWithOpts( +// nil, +// // enable discovery, and filter by accountIDs and partition +// kmsprovider.WithDiscoveryFilter([]string{"123456789011"}, "aws"), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [MrkAwareDiscoveryKmsProvider] with discovery region and filter: +// +// kmsProvider, err := kmsprovider.NewWithOpts( +// nil, +// // enable discovery, and filter by accountIDs and partition +// kmsprovider.WithDiscoveryFilter([]string{"123456789011"}, "aws"), +// kmsprovider.WithMrkAwareness(), // enable MRK-aware +// kmsprovider.WithDiscoveryRegion("us-west-2"), // specify region for discovery +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// See [examples] for more detailed usage. +// +// [examples]: https://github.com/chainifynet/aws-encryption-sdk-go/tree/main/example +package kmsprovider diff --git a/pkg/providers/kmsprovider/kmsprovider.go b/pkg/providers/kmsprovider/kmsprovider.go index d02d9c40..e53ccbaa 100644 --- a/pkg/providers/kmsprovider/kmsprovider.go +++ b/pkg/providers/kmsprovider/kmsprovider.go @@ -20,11 +20,69 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) +// KmsProvider is an interface for KMS providers. type KmsProvider interface { model.MasterKeyProvider getClient(ctx context.Context, keyID string) (model.KMSClient, error) } +// NewWithOpts creates a new [KmsKeyProvider] with the given keyIDs. +// +// It also accepts an optional variadic set of functional [Options] for configuring the provider. +// +// See usage below and check [examples] for more detailed usage. +// +// Example [StrictKmsProvider] with custom AWS config: +// +// keyID := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// kmsProvider, err := kmsprovider.NewWithOpts( +// []string{keyID}, +// kmsprovider.WithAwsLoadOptions( +// // add more AWS Config options if needed +// config.WithSharedConfigProfile("your_profile_name"), +// config.WithRegion("us-west-2"), +// ), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [MrkAwareStrictKmsProvider]: +// +// keyID := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// kmsProvider, err := kmsprovider.NewWithOpts( +// []string{keyID}, // KMS CMK ARNs +// kmsprovider.WithMrkAwareness(), // enable MRK-aware +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [DiscoveryKmsProvider] with discovery filter: +// +// kmsProvider, err := kmsprovider.NewWithOpts( +// nil, +// // enable discovery, and filter by accountIDs and partition +// kmsprovider.WithDiscoveryFilter([]string{"123456789011"}, "aws"), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [MrkAwareDiscoveryKmsProvider] with discovery region and filter: +// +// kmsProvider, err := kmsprovider.NewWithOpts( +// nil, +// // enable discovery, and filter by accountIDs and partition +// kmsprovider.WithDiscoveryFilter([]string{"123456789011"}, "aws"), +// kmsprovider.WithMrkAwareness(), // enable MRK-aware +// kmsprovider.WithDiscoveryRegion("us-west-2"), // specify region for discovery +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// [examples]: https://github.com/chainifynet/aws-encryption-sdk-go/tree/main/example func NewWithOpts(keyIDs []string, optFns ...func(options *Options) error) (*KmsKeyProvider[model.MasterKey], error) { var options Options for _, optFn := range optFns { @@ -54,6 +112,37 @@ func NewWithOpts(keyIDs []string, optFns ...func(options *Options) error) (*KmsK return p, nil } +// New creates a new [KmsKeyProvider] with the given keyIDs. +// +// If no keyIDs are provided, [DiscoveryKmsProvider] will be created. +// +// Example [DiscoveryKmsProvider] in discovery mode: +// +// kmsProvider, err := kmsprovider.New() +// if err != nil { +// panic(err) // handle error +// } +// +// Example [StrictKmsProvider] in strict mode: +// +// keyID := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// kmsProvider, err := kmsprovider.New(keyID) +// if err != nil { +// panic(err) // handle error +// } +// +// Example [StrictKmsProvider] with multiple keyIDs: +// +// keyID1 := "arn:aws:kms:us-east-1:123456789011:key/12345678-1234-1234-1234-123456789011" +// keyID2 := "arn:aws:kms:us-east-1:123456789011:key/22345678-1234-1234-1234-123456789012" +// kmsProvider, err := kmsprovider.New(keyID1, keyID2) +// if err != nil { +// panic(err) // handle error +// } +// +// See [examples] for more detailed usage. +// +// [examples]: https://github.com/chainifynet/aws-encryption-sdk-go/tree/main/example func New(keyIDs ...string) (*KmsKeyProvider[model.MasterKey], error) { if len(keyIDs) == 0 { return NewWithOpts(keyIDs, WithDiscovery()) @@ -72,6 +161,7 @@ func newKmsProvider(options *Options, pType ProviderType) *KmsKeyProvider[model. } } +// KmsKeyProvider is a KMS key provider. type KmsKeyProvider[KT model.MasterKey] struct { keyProvider model.BaseKeyProvider primaryMasterKey *common.KeyEntry[KT] @@ -87,14 +177,17 @@ type KmsKeyProvider[KT model.MasterKey] struct { keyEntriesForDecrypt map[string]common.KeyEntry[KT] // keyEntriesForDecrypt where common.KeyEntry not a pointer } +// ProviderID returns the ID [types.KmsProviderID]. func (kmsKP *KmsKeyProvider[KT]) ProviderID() string { return kmsKP.keyProvider.ID() } +// ProviderKind returns the kind [types.AwsKms]. func (kmsKP *KmsKeyProvider[KT]) ProviderKind() types.ProviderKind { return kmsKP.keyProvider.Kind() } +// ValidateProviderID validates master key provider ID matches the given provider ID. func (kmsKP *KmsKeyProvider[KT]) ValidateProviderID(otherID string) error { if kmsKP.keyProvider.ID() != otherID { return fmt.Errorf("%q providerID doesnt match to with MasterKeyProvider ID %q", otherID, kmsKP.keyProvider.ID()) @@ -102,6 +195,7 @@ func (kmsKP *KmsKeyProvider[KT]) ValidateProviderID(otherID string) error { return nil } +// ValidateMasterKey validates the given keyID is a valid KMS key ARN. func (kmsKP *KmsKeyProvider[KT]) ValidateMasterKey(keyID string) error { if err := arn.ValidateKeyArn(keyID); err != nil { return fmt.Errorf("invalid keyID %q: %w", keyID, err) @@ -109,6 +203,8 @@ func (kmsKP *KmsKeyProvider[KT]) ValidateMasterKey(keyID string) error { return nil } +// AddMasterKey validates the given keyID, checks if it doesn't exist within the +// KMS Provider, creates Kms Master Key, and adds it to the master key provider. func (kmsKP *KmsKeyProvider[KT]) AddMasterKey(keyID string) (model.MasterKey, error) { if err := kmsKP.ValidateMasterKey(keyID); err != nil { return nil, err @@ -136,6 +232,9 @@ func (kmsKP *KmsKeyProvider[KT]) AddMasterKey(keyID string) (model.MasterKey, er return kmsKP.keyEntriesForEncrypt[keyID].GetEntry(), nil } +// NewMasterKey returns a new instance of [kms.MasterKey] created by [kms.KeyFactory]. +// +// It also checks if the keyID is allowed by the discovery filter. func (kmsKP *KmsKeyProvider[KT]) NewMasterKey(ctx context.Context, keyID string) (model.MasterKey, error) { if kmsKP.providerType == MrkAwareDiscoveryKmsProvider { keyArn, _ := arn.ParseArn(keyID) @@ -152,7 +251,7 @@ func (kmsKP *KmsKeyProvider[KT]) NewMasterKey(ctx context.Context, keyID string) } if kmsKP.options.discovery && kmsKP.options.discoveryFilter != nil { - if !kmsKP.options.discoveryFilter.IsAllowed(keyID) { + if !kmsKP.options.discoveryFilter.isAllowed(keyID) { return nil, fmt.Errorf("%q keyID is not allowed by discovery filter: %w", keyID, providers.ErrFilterKeyNotAllowed) } } @@ -196,6 +295,8 @@ func (kmsKP *KmsKeyProvider[KT]) addRegionalClient(ctx context.Context, region s return nil } +// MasterKeysForEncryption returns the primary [model.MasterKey] and a list of master +// keys registered with the KMS Provider for encryption. func (kmsKP *KmsKeyProvider[KT]) MasterKeysForEncryption(_ context.Context, _ suite.EncryptionContext) (model.MasterKey, []model.MasterKey, error) { if kmsKP.primaryMasterKey == nil { return nil, nil, fmt.Errorf("no primary key: %w", errors.Join(providers.ErrMasterKeyProvider, providers.ErrMasterKeyProviderEncrypt, providers.ErrMasterKeyProviderNoPrimaryKey)) @@ -213,6 +314,14 @@ func (kmsKP *KmsKeyProvider[KT]) MasterKeysForEncryption(_ context.Context, _ su return kmsKP.primaryMasterKey.GetEntry(), nil, nil } +// MasterKeyForDecrypt returns [kms.MasterKey] for the given metadata. +// +// First, it checks registered keys for Encrypt, then checks registered keys for Decrypt. +// +// If the key is not found, it creates a new master key and adds it to the master +// key provider to be used for decryption. +// +// This method mainly used by keyprovider.KeyProvider when vendOnDecrypt is enabled. func (kmsKP *KmsKeyProvider[KT]) MasterKeyForDecrypt(ctx context.Context, metadata model.KeyMeta) (model.MasterKey, error) { if err := kmsKP.ValidateProviderID(metadata.ProviderID); err != nil { return nil, fmt.Errorf("providerID validation: %w", errors.Join(providers.ErrMasterKeyProvider, err)) @@ -244,6 +353,10 @@ func (kmsKP *KmsKeyProvider[KT]) MasterKeyForDecrypt(ctx context.Context, metada return decryptMasterKey, nil } +// MasterKeysForDecryption returns the list of master keys registered for +// encryption and decryption with the KMS Provider. +// +// This method mainly used by keyprovider.KeyProvider. func (kmsKP *KmsKeyProvider[KT]) MasterKeysForDecryption() []model.MasterKey { var allMembers []model.MasterKey var allMemberKeys []string @@ -265,6 +378,7 @@ func (kmsKP *KmsKeyProvider[KT]) MasterKeysForDecryption() []model.MasterKey { return allMembers } +// DecryptDataKey attempts to decrypt the encrypted data key with a KeyProvider. func (kmsKP *KmsKeyProvider[KT]) DecryptDataKey(ctx context.Context, encryptedDataKey model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { dataKey, err := kmsKP.keyProvider.DecryptDataKey(ctx, kmsKP, encryptedDataKey, alg, ec) if err != nil { @@ -273,7 +387,8 @@ func (kmsKP *KmsKeyProvider[KT]) DecryptDataKey(ctx context.Context, encryptedDa return dataKey, nil } -// DecryptDataKeyFromList iterates through EDK, calls DecryptDataKey +// DecryptDataKeyFromList attempts to decrypt the encrypted data keys with a +// KeyProvider. func (kmsKP *KmsKeyProvider[KT]) DecryptDataKeyFromList(ctx context.Context, encryptedDataKeys []model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { dataKey, err := kmsKP.keyProvider.DecryptDataKeyFromList(ctx, kmsKP, encryptedDataKeys, alg, ec) if err != nil { diff --git a/pkg/providers/kmsprovider/options.go b/pkg/providers/kmsprovider/options.go index a77c55fa..be20845d 100644 --- a/pkg/providers/kmsprovider/options.go +++ b/pkg/providers/kmsprovider/options.go @@ -10,6 +10,7 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/utils/arn" ) +// Options contains the configuration options for the [KmsKeyProvider]. type Options struct { awsConfigLoaders []func(options *config.LoadOptions) error clientFactory model.KMSClientFactory @@ -22,8 +23,10 @@ type Options struct { keyProvider model.BaseKeyProvider } +// OptionsFunc is a function that applies an option to the [Options]. type OptionsFunc func(options *Options) error +// WithAwsLoadOptions sets the AWS configuration loaders for the KMS provider. func WithAwsLoadOptions(optFns ...func(options *config.LoadOptions) error) OptionsFunc { return func(o *Options) error { o.awsConfigLoaders = optFns @@ -31,6 +34,7 @@ func WithAwsLoadOptions(optFns ...func(options *config.LoadOptions) error) Optio } } +// WithClientFactory sets the KMS client factory for the KMS provider. func WithClientFactory(factory model.KMSClientFactory) OptionsFunc { return func(o *Options) error { o.clientFactory = factory @@ -38,6 +42,7 @@ func WithClientFactory(factory model.KMSClientFactory) OptionsFunc { } } +// WithDiscovery enables the discovery mode for the KMS provider. func WithDiscovery() OptionsFunc { return func(o *Options) error { o.discovery = true @@ -45,6 +50,8 @@ func WithDiscovery() OptionsFunc { } } +// WithDiscoveryFilter sets the discovery filter for the KMS provider, it also +// enables the discovery mode. func WithDiscoveryFilter(accountIDs []string, partition string) OptionsFunc { return func(o *Options) error { filter := &discoveryFilter{accountIDs: accountIDs, partition: partition} @@ -54,6 +61,7 @@ func WithDiscoveryFilter(accountIDs []string, partition string) OptionsFunc { } } +// WithMrkAwareness enables the multi-region key awareness for the KMS provider. func WithMrkAwareness() OptionsFunc { return func(o *Options) error { o.mrkAware = true @@ -61,6 +69,7 @@ func WithMrkAwareness() OptionsFunc { } } +// WithDiscoveryRegion sets the discovery region for the KMS provider. func WithDiscoveryRegion(region string) OptionsFunc { return func(o *Options) error { o.discoveryRegion = region @@ -68,6 +77,7 @@ func WithDiscoveryRegion(region string) OptionsFunc { } } +// WithKeyFactory sets the master key factory for the KMS provider. func WithKeyFactory(keyFactory model.MasterKeyFactory) OptionsFunc { return func(o *Options) error { o.keyFactory = keyFactory @@ -75,6 +85,7 @@ func WithKeyFactory(keyFactory model.MasterKeyFactory) OptionsFunc { } } +// WithKeyProvider sets the base key provider for the KMS provider. func WithKeyProvider(keyProvider model.BaseKeyProvider) OptionsFunc { return func(o *Options) error { o.keyProvider = keyProvider @@ -87,7 +98,7 @@ type discoveryFilter struct { partition string } -func (df *discoveryFilter) IsAllowed(keyID string) bool { +func (df *discoveryFilter) isAllowed(keyID string) bool { keyArn, err := arn.ParseArn(keyID) if err != nil { return false diff --git a/pkg/providers/kmsprovider/options_test.go b/pkg/providers/kmsprovider/options_test.go index 9f7e6a5f..a7222f3a 100644 --- a/pkg/providers/kmsprovider/options_test.go +++ b/pkg/providers/kmsprovider/options_test.go @@ -259,7 +259,7 @@ func Test_discoveryFilter_IsAllowed(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := tt.filter.IsAllowed(tt.keyID) + got := tt.filter.isAllowed(tt.keyID) assert.Equal(t, tt.want, got) }) } From 550b27bd089e6682df274a18a434523199ee52f5 Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 21 Mar 2024 15:15:41 +0200 Subject: [PATCH 26/30] chore(model): Custom key provider type --- pkg/model/types/provider.go | 9 ++++++--- pkg/model/types/provider_test.go | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg/model/types/provider.go b/pkg/model/types/provider.go index 11cea073..87f94638 100644 --- a/pkg/model/types/provider.go +++ b/pkg/model/types/provider.go @@ -12,9 +12,10 @@ const ( type ProviderKind int8 const ( - _noneProvider ProviderKind = iota // 0 is NONE - AwsKms // 1 is AWS_KMS key provider - Raw // 2 is RAW key provider + _noneProvider ProviderKind = iota // 0 is NONE. + AwsKms // 1 is AWS_KMS key provider. + Raw // 2 is RAW key provider. + Custom // 3 is CUSTOM is a type for custom key provider implementation. ) func (p ProviderKind) String() string { @@ -25,6 +26,8 @@ func (p ProviderKind) String() string { return "AWS_KMS" case Raw: return "RAW" + case Custom: + return "CUSTOM" default: return "NONE" } diff --git a/pkg/model/types/provider_test.go b/pkg/model/types/provider_test.go index 30e5db61..2ba7e475 100644 --- a/pkg/model/types/provider_test.go +++ b/pkg/model/types/provider_test.go @@ -31,6 +31,11 @@ func TestProviderType_String(t *testing.T) { provider: Raw, want: "RAW", }, + { + name: "Custom Provider", + provider: Custom, + want: "CUSTOM", + }, { name: "Unknown Provider", provider: ProviderKind(99), From b7f04d2cc62d9e2ec19490be29deb018dcf2ed4d Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 21 Mar 2024 15:17:20 +0200 Subject: [PATCH 27/30] feat(keyprovider): keyprovider alias package --- pkg/providers/keyprovider/doc.go | 9 +++ pkg/providers/keyprovider/keyprovider.go | 22 ++++++ pkg/providers/keyprovider/keyprovider_test.go | 68 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 pkg/providers/keyprovider/doc.go create mode 100644 pkg/providers/keyprovider/keyprovider.go create mode 100644 pkg/providers/keyprovider/keyprovider_test.go diff --git a/pkg/providers/keyprovider/doc.go b/pkg/providers/keyprovider/doc.go new file mode 100644 index 00000000..cab1e2e0 --- /dev/null +++ b/pkg/providers/keyprovider/doc.go @@ -0,0 +1,9 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package keyprovider provides a way to create KeyProvider via alias. +// +// See [Custom Key Provider] example how to use it. +// +// [Custom Key Provider]: https://github.com/chainifynet/aws-encryption-sdk-go/tree/main/example/customKeyProvider +package keyprovider diff --git a/pkg/providers/keyprovider/keyprovider.go b/pkg/providers/keyprovider/keyprovider.go new file mode 100644 index 00000000..fcbf48aa --- /dev/null +++ b/pkg/providers/keyprovider/keyprovider.go @@ -0,0 +1,22 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package keyprovider + +import ( + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/keyprovider" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" +) + +// NewKeyProvider is an alias for internal [keyprovider.NewKeyProvider]. +// +// It returns a new [keyprovider.KeyProvider] with the given providerID, +// providerKind, and vendOnDecrypt. +// +// - providerID: The provider ID. Must be unique across all providers. +// - providerKind: The provider kind. Use [types.Custom] for custom providers. +// - vendOnDecrypt: If true, the provider will vend data keys on decrypt which +// enables discovery of the provider. +func NewKeyProvider(providerID string, providerKind types.ProviderKind, vendOnDecrypt bool) *keyprovider.KeyProvider { + return keyprovider.NewKeyProvider(providerID, providerKind, vendOnDecrypt) +} diff --git a/pkg/providers/keyprovider/keyprovider_test.go b/pkg/providers/keyprovider/keyprovider_test.go new file mode 100644 index 00000000..9ccf2353 --- /dev/null +++ b/pkg/providers/keyprovider/keyprovider_test.go @@ -0,0 +1,68 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package keyprovider + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/chainifynet/aws-encryption-sdk-go/pkg/internal/providers/keyprovider" + "github.com/chainifynet/aws-encryption-sdk-go/pkg/model/types" +) + +func TestNewKeyProvider(t *testing.T) { + type args struct { + providerID string + providerKind types.ProviderKind + vendOnDecrypt bool + } + tests := []struct { + name string + args args + }{ + { + name: "Raw Key Provider", + args: args{ + providerID: "raw", + providerKind: types.Raw, + vendOnDecrypt: false, + }, + }, + { + name: "KMS Key Provider without discovery", + args: args{ + providerID: types.KmsProviderID, + providerKind: types.AwsKms, + vendOnDecrypt: false, + }, + }, + { + name: "KMS Key Provider with discovery", + args: args{ + providerID: types.KmsProviderID, + providerKind: types.AwsKms, + vendOnDecrypt: true, + }, + }, + { + name: "Custom Key Provider", + args: args{ + providerID: "myprovider", + providerKind: types.Custom, + vendOnDecrypt: false, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := NewKeyProvider(tt.args.providerID, tt.args.providerKind, tt.args.vendOnDecrypt) + assert.IsType(t, &keyprovider.KeyProvider{}, got) + + assert.Equal(t, tt.args.providerID, got.ID()) + assert.Equal(t, tt.args.providerKind, got.Kind()) + assert.Equal(t, tt.args.vendOnDecrypt, got.VendOnDecrypt()) + }) + } +} From e0b2c89495903748bd1ee8cea6b060bbd12adafd Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 21 Mar 2024 15:59:34 +0200 Subject: [PATCH 28/30] fix(kmsprovider): clean up --- pkg/providers/kmsprovider/kmsprovider.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/providers/kmsprovider/kmsprovider.go b/pkg/providers/kmsprovider/kmsprovider.go index e53ccbaa..d53a8b19 100644 --- a/pkg/providers/kmsprovider/kmsprovider.go +++ b/pkg/providers/kmsprovider/kmsprovider.go @@ -213,7 +213,6 @@ func (kmsKP *KmsKeyProvider[KT]) AddMasterKey(keyID string) (model.MasterKey, er // TODO fix context at the some point key, err := kmsKP.NewMasterKey(context.Background(), keyID) if err != nil { - // TODO introduce provider errors in order distinguish between MasterKey and MasterKeyProvider errors return nil, err } @@ -225,7 +224,6 @@ func (kmsKP *KmsKeyProvider[KT]) AddMasterKey(keyID string) (model.MasterKey, er kmsKP.primaryMasterKey = kmsKeyEntry } - //kmsKeyEntry2 := common.NewKeyEntry(castKey) kmsKP.keyEntriesForEncrypt[key.KeyID()] = common.NewKeyEntry(castKey) } From 092d82e522a2b8e50f454032bef52a615775407a Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 21 Mar 2024 16:12:40 +0200 Subject: [PATCH 29/30] docs(rawprovider): Raw Master Key Provider documentation --- pkg/providers/rawprovider/doc.go | 21 +++++++++ pkg/providers/rawprovider/options.go | 5 +++ pkg/providers/rawprovider/rawprovider.go | 54 +++++++++++++++++++++--- 3 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 pkg/providers/rawprovider/doc.go diff --git a/pkg/providers/rawprovider/doc.go b/pkg/providers/rawprovider/doc.go new file mode 100644 index 00000000..2c9aa7b1 --- /dev/null +++ b/pkg/providers/rawprovider/doc.go @@ -0,0 +1,21 @@ +// Copyright Chainify Group LTD. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// Package rawprovider contains Raw Master Key Provider implementation. +// +// See usage below or check [examples] for more detailed use. +// +// Example configuration: +// +// // static key to use for encryption and decryption +// staticKey1 := []byte("superSecureKeySecureKey32bytes32") +// rawProvider, err := rawprovider.NewWithOpts( +// "raw", +// rawprovider.WithStaticKey("static1", staticKey1), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// [examples]: https://github.com/chainifynet/aws-encryption-sdk-go/tree/main/example +package rawprovider diff --git a/pkg/providers/rawprovider/options.go b/pkg/providers/rawprovider/options.go index 13c01106..087884c9 100644 --- a/pkg/providers/rawprovider/options.go +++ b/pkg/providers/rawprovider/options.go @@ -10,6 +10,7 @@ type staticKey struct { key []byte } +// Options contains the configuration options for the [RawKeyProvider]. type Options struct { staticKeys map[string][]byte configKeys []staticKey @@ -17,8 +18,10 @@ type Options struct { keyProvider model.BaseKeyProvider } +// OptionsFunc is a function that applies an option to the [Options]. type OptionsFunc func(*Options) error +// WithStaticKey configures a static key for the Raw provider. func WithStaticKey(keyID string, key []byte) OptionsFunc { return func(o *Options) error { o.configKeys = append(o.configKeys, staticKey{keyID, key}) @@ -26,6 +29,7 @@ func WithStaticKey(keyID string, key []byte) OptionsFunc { } } +// WithKeyFactory sets the master key factory for the Raw provider. func WithKeyFactory(keyFactory model.MasterKeyFactory) OptionsFunc { return func(o *Options) error { o.keyFactory = keyFactory @@ -33,6 +37,7 @@ func WithKeyFactory(keyFactory model.MasterKeyFactory) OptionsFunc { } } +// WithKeyProvider sets the base key provider for the Raw provider. func WithKeyProvider(keyProvider model.BaseKeyProvider) OptionsFunc { return func(o *Options) error { o.keyProvider = keyProvider diff --git a/pkg/providers/rawprovider/rawprovider.go b/pkg/providers/rawprovider/rawprovider.go index c1b2972c..6893af02 100644 --- a/pkg/providers/rawprovider/rawprovider.go +++ b/pkg/providers/rawprovider/rawprovider.go @@ -17,6 +17,35 @@ import ( "github.com/chainifynet/aws-encryption-sdk-go/pkg/suite" ) +// RawProvider is an interface for Raw Key Providers. +type RawProvider interface { + model.MasterKeyProvider + getStaticKey(keyID string) ([]byte, error) +} + +// NewWithOpts creates a new [RawKeyProvider] with the given keyIDs. +// +// It also accepts an optional variadic set of functional [Options] for +// configuring the provider. +// +// At least one keyID must be configured via [WithStaticKey] for the provider to +// be valid. +// +// See usage below or check [examples] for more detailed use. +// +// Example configuration: +// +// // static key to use for encryption and decryption +// staticKey1 := []byte("superSecureKeySecureKey32bytes32") +// rawProvider, err := rawprovider.NewWithOpts( +// "raw", +// rawprovider.WithStaticKey("static1", staticKey1), +// ) +// if err != nil { +// panic(err) // handle error +// } +// +// [examples]: https://github.com/chainifynet/aws-encryption-sdk-go/tree/main/example func NewWithOpts(providerID string, optFns ...func(options *Options) error) (*RawKeyProvider[model.MasterKey], error) { options := Options{ staticKeys: make(map[string][]byte, 5), // increase if needed @@ -52,11 +81,7 @@ func newRawProvider(options *Options) *RawKeyProvider[model.MasterKey] { } } -type RawProvider interface { - model.MasterKeyProvider - getStaticKey(keyID string) ([]byte, error) -} - +// RawKeyProvider is a Raw Key Provider. type RawKeyProvider[KT model.MasterKey] struct { keyProvider model.BaseKeyProvider primaryMasterKey *common.KeyEntry[KT] @@ -66,14 +91,17 @@ type RawKeyProvider[KT model.MasterKey] struct { keyEntriesForEncrypt map[string]*common.KeyEntry[KT] } +// ProviderID returns the ID of the provider. func (rawKP *RawKeyProvider[KT]) ProviderID() string { return rawKP.keyProvider.ID() } +// ProviderKind returns the kind [types.Raw]. func (rawKP *RawKeyProvider[KT]) ProviderKind() types.ProviderKind { return rawKP.keyProvider.Kind() } +// ValidateProviderID validates master key provider ID matches the given provider ID. func (rawKP *RawKeyProvider[KT]) ValidateProviderID(otherID string) error { if rawKP.keyProvider.ID() != otherID { return fmt.Errorf("%q providerID doesnt match to with MasterKeyProvider ID %q", otherID, rawKP.keyProvider.ID()) @@ -81,6 +109,7 @@ func (rawKP *RawKeyProvider[KT]) ValidateProviderID(otherID string) error { return nil } +// ValidateMasterKey validates the given keyID are registered in the provider. func (rawKP *RawKeyProvider[KT]) ValidateMasterKey(keyID string) error { sk, err := rawKP.getStaticKey(keyID) if err != nil { @@ -89,6 +118,8 @@ func (rawKP *RawKeyProvider[KT]) ValidateMasterKey(keyID string) error { return validateStaticKey(keyID, sk) } +// AddMasterKey validates the given keyID, checks if it doesn't exist within the +// Raw Provider, creates Raw Master Key, and adds it to the master key provider. func (rawKP *RawKeyProvider[KT]) AddMasterKey(keyID string) (model.MasterKey, error) { if err := rawKP.ValidateMasterKey(keyID); err != nil { return nil, err @@ -96,7 +127,6 @@ func (rawKP *RawKeyProvider[KT]) AddMasterKey(keyID string) (model.MasterKey, er if _, exists := rawKP.keyEntriesForEncrypt[keyID]; !exists { key, err := rawKP.NewMasterKey(context.Background(), keyID) if err != nil { - // TODO introduce provider errors in order distinguish between MasterKey and MasterKeyProvider errors return nil, err } @@ -121,6 +151,7 @@ func (rawKP *RawKeyProvider[KT]) getStaticKey(keyID string) ([]byte, error) { return rawKP.options.staticKeys[keyID], nil } +// NewMasterKey returns a new instance of [raw.MasterKey] created by [raw.KeyFactory]. func (rawKP *RawKeyProvider[KT]) NewMasterKey(_ context.Context, keyID string) (model.MasterKey, error) { sk, err := rawKP.getStaticKey(keyID) if err != nil { @@ -133,6 +164,8 @@ func (rawKP *RawKeyProvider[KT]) NewMasterKey(_ context.Context, keyID string) ( return key, nil } +// MasterKeysForEncryption returns the primary [model.MasterKey] and a list of master +// keys registered with the Raw Provider for encryption. func (rawKP *RawKeyProvider[KT]) MasterKeysForEncryption(_ context.Context, _ suite.EncryptionContext) (model.MasterKey, []model.MasterKey, error) { if rawKP.primaryMasterKey == nil { return nil, nil, fmt.Errorf("no primary key: %w", errors.Join(providers.ErrMasterKeyProvider, providers.ErrMasterKeyProviderEncrypt, providers.ErrMasterKeyProviderNoPrimaryKey)) @@ -150,11 +183,14 @@ func (rawKP *RawKeyProvider[KT]) MasterKeysForEncryption(_ context.Context, _ su return rawKP.primaryMasterKey.GetEntry(), nil, nil } +// MasterKeyForDecrypt always returns an error because [RawKeyProvider] doesn't +// support vend data keys for decryption. func (rawKP *RawKeyProvider[KT]) MasterKeyForDecrypt(_ context.Context, _ model.KeyMeta) (model.MasterKey, error) { // should be never requested because VendOnDecrypt is false for RawKeyProvider return nil, fmt.Errorf("MasterKeyForDecrypt not allowed for RawKeyProvider: %w", errors.Join(providers.ErrMasterKeyProvider, providers.ErrMasterKeyProviderDecrypt)) } +// DecryptDataKey attempts to decrypt the encrypted data key with a KeyProvider. func (rawKP *RawKeyProvider[KT]) DecryptDataKey(ctx context.Context, encryptedDataKey model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { dataKey, err := rawKP.keyProvider.DecryptDataKey(ctx, rawKP, encryptedDataKey, alg, ec) if err != nil { @@ -163,6 +199,8 @@ func (rawKP *RawKeyProvider[KT]) DecryptDataKey(ctx context.Context, encryptedDa return dataKey, nil } +// DecryptDataKeyFromList attempts to decrypt data key from the encrypted data +// keys with a KeyProvider. func (rawKP *RawKeyProvider[KT]) DecryptDataKeyFromList(ctx context.Context, encryptedDataKeys []model.EncryptedDataKeyI, alg *suite.AlgorithmSuite, ec suite.EncryptionContext) (model.DataKeyI, error) { dataKey, err := rawKP.keyProvider.DecryptDataKeyFromList(ctx, rawKP, encryptedDataKeys, alg, ec) if err != nil { @@ -171,6 +209,10 @@ func (rawKP *RawKeyProvider[KT]) DecryptDataKeyFromList(ctx context.Context, enc return dataKey, nil } +// MasterKeysForDecryption returns the list of master keys registered for +// decryption with the Raw Provider. +// +// This method mainly used by keyprovider.KeyProvider. func (rawKP *RawKeyProvider[KT]) MasterKeysForDecryption() []model.MasterKey { var allMembers []model.MasterKey var allMemberKeys []string From 22d9a3467520fc0e6f8f5db74dfbf2109b2d2fc5 Mon Sep 17 00:00:00 2001 From: wobondar Date: Thu, 21 Mar 2024 16:20:19 +0200 Subject: [PATCH 30/30] docs: update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b6e0e00b..fd7b3b74 100644 --- a/README.md +++ b/README.md @@ -188,13 +188,13 @@ if err != nil { ## TODO - [ ] Add support for Caching Materials Manager. -- [x] Add support for Message Format Version 1 [#170](https://github.com/chainifynet/aws-encryption-sdk-go/pull/46). +- [x] Add support for Message Format Version 1 [#170](https://github.com/chainifynet/aws-encryption-sdk-go/pull/170). - [x] Add support for AWS KMS Multi-Region Keys [#46](https://github.com/chainifynet/aws-encryption-sdk-go/pull/46). - [ ] Add support for KMS aliases. - [x] Cover `providers` package with tests. - [x] Cover `keys` package with tests. - [x] Cover `materials` package with tests. -- [ ] GoDoc documentation. +- [x] GoDoc documentation [#294](https://github.com/chainifynet/aws-encryption-sdk-go/pull/294). - [ ] Streamlined encryption and decryption. ## Support and Contributions