wrapping

package module
v2.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2023 License: MPL-2.0 Imports: 12 Imported by: 9

README

Go-KMS-Wrapping - Go library for encrypting values through various KMS providers

Go Reference

NOTE: This is version 2 of the library. The v0 branch contains version 0, which may be needed for legacy applications or while transitioning to version 2.

Go-KMS-Wrapping is a library that can be used to encrypt things through various KMS providers -- public clouds, Vault's Transit plugin, etc. It is similar in concept to various other cryptosystems (like NaCl) but focuses on using third party KMSes. This library is the underpinning of Vault's auto-unseal functionality, and should be ready to use for many other applications.

For KMS providers that do not support encrypting arbitrarily large values, the library will generate an envelope data encryption key (DEK), encrypt the value with it using an authenticated cipher, and use the KMS to encrypt the DEK.

The key being used by a given implementation can change; the library stores information about which key was actually used to encrypt a given value as part of the returned data, and this key will be used for decryption. By extension, this means that users should be careful not to delete keys in KMS systems simply because they're not configured to be used by this library currently, as they may have been used for past encryption operations.

Features

  • Supports many KMSes:
    • AEAD using AES-GCM and a provided key
    • Alibaba Cloud KMS (uses envelopes)
    • AWS KMS (uses envelopes)
    • Azure KeyVault (uses envelopes)
    • GCP CKMS (uses envelopes)
    • Huawei Cloud KMS (uses envelopes)
    • OCI KMS (uses envelopes)
    • Tencent Cloud KMS (uses envelopes)
    • Vault Transit mount
  • Transparently supports multiple decryption targets, allowing for key rotation
  • Supports Additional Authenticated Data (AAD) for all KMSes except Vault Transit.

Extras

There are several extra(s) packages included which build upon the base go-kms-wrapping features to provide "extra" capabilities.

  • The multi package is capable of encrypting to a specified wrapper and decrypting using one of several wrappers switched on key ID. This can allow easy key rotation for KMSes that do not natively support it.

  • The structwrapping package allows for structs to have members encrypted and decrypted in a single pass via a single wrapper. This can be used for workflows such as database library callback functions to easily encrypt/decrypt data as it goes to/from storage.

  • The kms package provides key management system features for wrappers including scoped KEKs and DEKs which are wrapped with an external KMS when stored in sqlite or postgres.

  • The crypto package provides additional operations like HMAC-SHA256 and a derived reader from which keys can be read.

Installation

go get github.com/hashicorp/go-kms-wrapping/v2

Overview

The library exports a Wrapper interface that is implemented by multiple providers. For each provider, the standard flow is as follows:

  1. Create a wrapper using the New method
  2. Call SetConfig to pass either wrapper-specific options or use the wrapping.WithConfigMap option to pass a configuration map
  3. Use the wrapper as needed

It is possible, in v2 of this library, to instantiate a wrapper as a plugin. This allows avoiding pulling dependencies of the wrapper directly into another system's process space. See the example plugin-cli for a complete example on how to do build wrapper plugins and use them in an application or the test plugins for guidance in how to build a plugin; in this case, you'll definitely want to use wrapping.WithConfigMap to pass configuration to avoid pulling in package-specific options.

The best place to find the currently available set of configuration options supported by each provider is its code, but it can also be found in Vault's seal configuration documentation. All environment variables noted there also work in this library, however, non-Vault-specific variants of the environment variables are also available for each provider. See the code/comments in each given provider for the currently allowed env vars.

Usage

Following is an example usage of the AWS KMS provider.

// Context used in this library is passed to various underlying provider
// libraries; how it's used is dependent on the provider libraries
ctx := context.Background()

wrapper := awskms.NewWrapper()
_, err := wrapper.SetConfig(ctx, wrapping.WithConfigMap(map[string]string{
    "kms_key_id": "1234abcd-12ab-34cd-56ef-1234567890ab",
}))
if err != nil {
    return err
}
blobInfo, err := wrapper.Encrypt(ctx, []byte("foo"))
if err != nil {
    return err
}

//
// Do some things...
//

plaintext, err := wrapper.Decrypt(ctx, blobInfo)
if err != nil {
    return err
}
if string(plaintext) != "foo" {
    return errors.New("mismatch between input and output")
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrFunctionNotImplemented = errors.New("the wrapping plugin does not implement this function")

ErrFunctionNotImplemented represents a function that hasn't been implemented

View Source
var ErrInvalidParameter = errors.New("invalid parameter")

ErrInvalidParameter represents an invalid parameter error

View Source
var File_github_com_hashicorp_go_kms_wrapping_v2_types_proto protoreflect.FileDescriptor

Functions

func EnvelopeDecrypt

func EnvelopeDecrypt(data *EnvelopeInfo, opt ...Option) ([]byte, error)

EnvelopeDecrypt takes in EnvelopeInfo and potentially additional options and decrypts. Also note: if you provided a plaintext of []byte("") to EnvelopeEncrypt, then this function will return []byte(nil).

Supported options:

* wrapping.WithAad: Additional authenticated data that should be sourced from a separate location, and must match what was provided during envelope encryption.

Types

type AeadType

type AeadType uint32
const (
	AeadTypeUnknown AeadType = iota
	AeadTypeAesGcm
)

These values define supported types of AEADs

func AeadTypeMap

func AeadTypeMap(t string) AeadType

func (AeadType) String

func (t AeadType) String() string

type BlobInfo

type BlobInfo struct {

	// Ciphertext is the encrypted bytes
	Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"`
	// IV is the initialization value used during encryption
	Iv []byte `protobuf:"bytes,2,opt,name=iv,proto3" json:"iv,omitempty"`
	// HMAC is the bytes of the HMAC, if any
	Hmac []byte `protobuf:"bytes,3,opt,name=hmac,proto3" json:"hmac,omitempty"`
	// Wrapped can be used by the client to indicate whether Ciphertext actually
	// contains wrapped data or not. This can be useful if you want to reuse the
	// same struct to pass data along before and after wrapping. Deprecated in
	// favor of plaintext.
	//
	// Deprecated: Do not use.
	Wrapped bool `protobuf:"varint,4,opt,name=wrapped,proto3" json:"wrapped,omitempty"`
	// Plaintext can be used to allow the same struct to be used to pass data
	// along before and after (un)wrapping.
	Plaintext []byte `protobuf:"bytes,7,opt,name=plaintext,proto3" json:"plaintext,omitempty"`
	// KeyInfo contains information about the key that was used to create this value
	KeyInfo *KeyInfo `protobuf:"bytes,5,opt,name=key_info,json=keyInfo,proto3" json:"key_info,omitempty"`
	// ValuePath can be used by the client to store information about where the
	// value came from. Deprecated in favor of client_data.
	//
	// Deprecated: Do not use.
	ValuePath string `protobuf:"bytes,6,opt,name=value_path,json=valuePath,proto3" json:"value_path,omitempty"`
	// ClientData can be used by the client to store extra information, for
	// instance, the location/provenance of where an encrypted value came from
	// (useful for associating AAD to the encrypted value).
	ClientData *_struct.Struct `protobuf:"bytes,8,opt,name=client_data,json=clientData,proto3" json:"client_data,omitempty"`
	// contains filtered or unexported fields
}

BlobInfo contains information about the encrypted value along with information about the key used to encrypt it

func (*BlobInfo) Descriptor deprecated

func (*BlobInfo) Descriptor() ([]byte, []int)

Deprecated: Use BlobInfo.ProtoReflect.Descriptor instead.

func (*BlobInfo) GetCiphertext

func (x *BlobInfo) GetCiphertext() []byte

func (*BlobInfo) GetClientData

func (x *BlobInfo) GetClientData() *_struct.Struct

func (*BlobInfo) GetHmac

func (x *BlobInfo) GetHmac() []byte

func (*BlobInfo) GetIv

func (x *BlobInfo) GetIv() []byte

func (*BlobInfo) GetKeyInfo

func (x *BlobInfo) GetKeyInfo() *KeyInfo

func (*BlobInfo) GetPlaintext

func (x *BlobInfo) GetPlaintext() []byte

func (*BlobInfo) GetValuePath deprecated

func (x *BlobInfo) GetValuePath() string

Deprecated: Do not use.

func (*BlobInfo) GetWrapped deprecated

func (x *BlobInfo) GetWrapped() bool

Deprecated: Do not use.

func (*BlobInfo) ProtoMessage

func (*BlobInfo) ProtoMessage()

func (*BlobInfo) ProtoReflect

func (x *BlobInfo) ProtoReflect() protoreflect.Message

func (*BlobInfo) Reset

func (x *BlobInfo) Reset()

func (*BlobInfo) String

func (x *BlobInfo) String() string

type EnvelopeInfo

type EnvelopeInfo struct {

	// Ciphertext is the ciphertext from the envelope
	Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"`
	// Key is the key used in the envelope
	Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
	// IV is the initialization value used during encryption in the envelope
	Iv []byte `protobuf:"bytes,3,opt,name=iv,proto3" json:"iv,omitempty"`
	// contains filtered or unexported fields
}

EnvelopeInfo contains the information necessary to perfom encryption or decryption in an envelope fashion

func EnvelopeEncrypt

func EnvelopeEncrypt(plaintext []byte, opt ...Option) (*EnvelopeInfo, error)

EnvelopeEncrypt takes in plaintext and envelope encrypts it, generating an EnvelopeInfo value. An empty plaintext is a valid parameter and will not cause an error. Also note: if you provide a plaintext of []byte(""), EnvelopeDecrypt will return []byte(nil).

Supported options:

* wrapping.WithAad: Additional authenticated data that should be sourced from a separate location, and must also be provided during envelope decryption

func (*EnvelopeInfo) Descriptor deprecated

func (*EnvelopeInfo) Descriptor() ([]byte, []int)

Deprecated: Use EnvelopeInfo.ProtoReflect.Descriptor instead.

func (*EnvelopeInfo) GetCiphertext

func (x *EnvelopeInfo) GetCiphertext() []byte

func (*EnvelopeInfo) GetIv

func (x *EnvelopeInfo) GetIv() []byte

func (*EnvelopeInfo) GetKey

func (x *EnvelopeInfo) GetKey() []byte

func (*EnvelopeInfo) ProtoMessage

func (*EnvelopeInfo) ProtoMessage()

func (*EnvelopeInfo) ProtoReflect

func (x *EnvelopeInfo) ProtoReflect() protoreflect.Message

func (*EnvelopeInfo) Reset

func (x *EnvelopeInfo) Reset()

func (*EnvelopeInfo) String

func (x *EnvelopeInfo) String() string

type HashType

type HashType uint32
const (
	HashTypeUnknown HashType = iota
	HashTypeSha256
)

These values define supported types of hashes

func HashTypeMap

func HashTypeMap(t string) HashType

func (HashType) String

func (t HashType) String() string

type HmacComputer

type HmacComputer interface {
	// HmacKeyID is the ID of the key currently used for HMACing (if any)
	HmacKeyId(context.Context) (string, error)
}

type InitFinalizer

type InitFinalizer interface {
	// Init allows performing any necessary setup calls before using a
	// Wrapper.
	Init(ctx context.Context, options ...Option) error

	// Finalize can be called when all usage of a Wrapper is done if any cleanup
	// or finalization is required.
	Finalize(ctx context.Context, options ...Option) error
}

type KeyExporter

type KeyExporter interface {
	// KeyBytes returns the "current" key bytes
	KeyBytes(context.Context) ([]byte, error)
}

KeyExporter defines an optional interface for wrappers to implement that returns the "current" key bytes. This will be implementation-specific.

type KeyInfo

type KeyInfo struct {

	// Mechanism is the method used by the wrapper to encrypt and sign the
	// data as defined by the wrapper.
	Mechanism     uint64 `protobuf:"varint,1,opt,name=mechanism,proto3" json:"mechanism,omitempty"`
	HmacMechanism uint64 `protobuf:"varint,2,opt,name=hmac_mechanism,json=hmacMechanism,proto3" json:"hmac_mechanism,omitempty"`
	// This is an opaque ID used by the wrapper to identify the specific key to
	// use as defined by the wrapper. This could be a version, key label, or
	// something else.
	KeyId     string `protobuf:"bytes,3,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty"`
	HmacKeyId string `protobuf:"bytes,4,opt,name=hmac_key_id,json=hmacKeyId,proto3" json:"hmac_key_id,omitempty"`
	// These value are used when generating our own data encryption keys
	// and encrypting them using the wrapper
	WrappedKey []byte `protobuf:"bytes,5,opt,name=wrapped_key,json=wrappedKey,proto3" json:"wrapped_key,omitempty"`
	// Mechanism specific flags
	Flags uint64 `protobuf:"varint,6,opt,name=flags,proto3" json:"flags,omitempty"`
	// contains filtered or unexported fields
}

KeyInfo contains information regarding which Wrapper key was used to encrypt the entry

func (*KeyInfo) Descriptor deprecated

func (*KeyInfo) Descriptor() ([]byte, []int)

Deprecated: Use KeyInfo.ProtoReflect.Descriptor instead.

func (*KeyInfo) GetFlags

func (x *KeyInfo) GetFlags() uint64

func (*KeyInfo) GetHmacKeyId

func (x *KeyInfo) GetHmacKeyId() string

func (*KeyInfo) GetHmacMechanism

func (x *KeyInfo) GetHmacMechanism() uint64

func (*KeyInfo) GetKeyId

func (x *KeyInfo) GetKeyId() string

func (*KeyInfo) GetMechanism

func (x *KeyInfo) GetMechanism() uint64

func (*KeyInfo) GetWrappedKey

func (x *KeyInfo) GetWrappedKey() []byte

func (*KeyInfo) ProtoMessage

func (*KeyInfo) ProtoMessage()

func (*KeyInfo) ProtoReflect

func (x *KeyInfo) ProtoReflect() protoreflect.Message

func (*KeyInfo) Reset

func (x *KeyInfo) Reset()

func (*KeyInfo) String

func (x *KeyInfo) String() string

type Option

type Option func() interface{}

Option - a type that wraps an interface for compile-time safety but can contain an option for this package or for wrappers implementing this interface.

func WithAad

func WithAad(with []byte) Option

WithAad provides optional additional authenticated data

func WithConfigMap

func WithConfigMap(with map[string]string) Option

WithConfigMap is an option accepted by wrappers at configuration time and/or in other function calls to control wrapper-specific behavior.

func WithIV

func WithIV(with []byte) Option

WithIV provides

func WithKeyId

func WithKeyId(with string) Option

WithKeyId provides a common way to pass in a key identifier

type OptionFunc

type OptionFunc func(*Options) error

OptionFunc - a type for funcs that operate on the shared Options struct. The options below explicitly wrap this so that we can switch on it when parsing opts for various wrappers.

type Options

type Options struct {

	// The key ID being specified
	WithKeyId string `protobuf:"bytes,10,opt,name=with_key_id,json=withKeyId,proto3" json:"with_key_id,omitempty"`
	// The AAD bytes, if any
	WithAad []byte `protobuf:"bytes,20,opt,name=with_aad,json=withAad,proto3" json:"with_aad,omitempty"`
	WithIv  []byte `protobuf:"bytes,12,opt,name=with_iv,json=withIv,proto3" json:"with_iv,omitempty"`
	// Wrapper-specific configuration to pass along
	WithConfigMap map[string]string `` /* 191-byte string literal not displayed */
	// contains filtered or unexported fields
}

Options holds options common to all wrappers

func GetOpts

func GetOpts(opt ...Option) (*Options, error)

GetOpts iterates the inbound Options and returns a struct

func (*Options) Descriptor deprecated

func (*Options) Descriptor() ([]byte, []int)

Deprecated: Use Options.ProtoReflect.Descriptor instead.

func (*Options) GetWithAad

func (x *Options) GetWithAad() []byte

func (*Options) GetWithConfigMap

func (x *Options) GetWithConfigMap() map[string]string

func (*Options) GetWithIv

func (x *Options) GetWithIv() []byte

func (*Options) GetWithKeyId

func (x *Options) GetWithKeyId() string

func (*Options) ProtoMessage

func (*Options) ProtoMessage()

func (*Options) ProtoReflect

func (x *Options) ProtoReflect() protoreflect.Message

func (*Options) Reset

func (x *Options) Reset()

func (*Options) String

func (x *Options) String() string

type TestInitFinalizer

type TestInitFinalizer struct {
	*TestWrapper
}

func NewTestInitFinalizer

func NewTestInitFinalizer(secret []byte) *TestInitFinalizer

NewTestInitFinalizer constructs a test wrapper

func (*TestInitFinalizer) Finalize

func (t *TestInitFinalizer) Finalize(_ context.Context, _ ...Option) error

Finalize finalizes the test wrapper

func (*TestInitFinalizer) Init

func (t *TestInitFinalizer) Init(_ context.Context, _ ...Option) error

Init initializes the test wrapper

type TestInitFinalizerHmacComputer

type TestInitFinalizerHmacComputer struct {
	*TestInitFinalizer
}

func NewTestInitFinalizerHmacComputer

func NewTestInitFinalizerHmacComputer(secret []byte) *TestInitFinalizerHmacComputer

NewTestInitFinalizerHmacComputer constructs a test wrapper

func (*TestInitFinalizerHmacComputer) HmacKeyId

HmacKeyId returns the HMAC key id

type TestWrapper

type TestWrapper struct {
	// contains filtered or unexported fields
}

TestWrapper is a wrapper that can be used for tests

func NewTestEnvelopeWrapper

func NewTestEnvelopeWrapper(secret []byte) *TestWrapper

NewTestWrapper constructs a test wrapper

func NewTestWrapper

func NewTestWrapper(secret []byte) *TestWrapper

NewTestWrapper constructs a test wrapper

func (*TestWrapper) Decrypt

func (t *TestWrapper) Decrypt(_ context.Context, dwi *BlobInfo, opts ...Option) ([]byte, error)

Decrypt allows decrypting via the test wrapper

func (*TestWrapper) Encrypt

func (t *TestWrapper) Encrypt(ctx context.Context, plaintext []byte, opts ...Option) (*BlobInfo, error)

Encrypt allows encrypting via the test wrapper

func (*TestWrapper) HmacKeyId

func (t *TestWrapper) HmacKeyId(_ context.Context) string

HmacKeyId returns the configured HMAC key ID

func (*TestWrapper) KeyBytes

func (t *TestWrapper) KeyBytes(context.Context) ([]byte, error)

KeyBytes returns the current key bytes

func (*TestWrapper) KeyId

func (t *TestWrapper) KeyId(_ context.Context) (string, error)

KeyId returns the configured key ID

func (*TestWrapper) SetConfig

func (t *TestWrapper) SetConfig(_ context.Context, opt ...Option) (*WrapperConfig, error)

SetConfig sets config, and currently it only supports the WithKeyId option for test wrappers

func (*TestWrapper) SetKeyId

func (t *TestWrapper) SetKeyId(k string)

SetKeyID allows setting the test wrapper's key ID

func (*TestWrapper) Type

Type returns the type of the test wrapper

type Wrapper

type Wrapper interface {
	// Type is the type of Wrapper
	Type(context.Context) (WrapperType, error)

	// KeyId is the ID of the key currently used for encryption
	KeyId(context.Context) (string, error)

	// SetConfig applies the given options to a wrapper and returns
	// configuration information. WithConfigMap will almost certainly be
	// required to be passed in to give wrapper-specific configuration
	// information to the wrapper. WithKeyId is also supported.
	SetConfig(ctx context.Context, options ...Option) (*WrapperConfig, error)

	// Encrypt encrypts the given byte slice and stores the resulting
	// information in the returned blob info. Which options are used depends on
	// the underlying wrapper. Supported options: WithAad.
	Encrypt(ctx context.Context, plaintext []byte, options ...Option) (*BlobInfo, error)
	// Decrypt decrypts the given byte slice and stores the resulting
	// information in the returned byte slice. Which options are used depends on
	// the underlying wrapper. Supported options: WithAad.
	Decrypt(ctx context.Context, ciphertext *BlobInfo, options ...Option) ([]byte, error)
}

Wrapper is an an interface where supporting implementations allow for encrypting and decrypting data.

type WrapperConfig

type WrapperConfig struct {
	Metadata map[string]string `` /* 158-byte string literal not displayed */
	// contains filtered or unexported fields
}

WrapperConfig is the result of a call to SetConfig on a wrapper, returning relevant information about the wrapper and its updated configuration

func (*WrapperConfig) Descriptor deprecated

func (*WrapperConfig) Descriptor() ([]byte, []int)

Deprecated: Use WrapperConfig.ProtoReflect.Descriptor instead.

func (*WrapperConfig) GetMetadata

func (x *WrapperConfig) GetMetadata() map[string]string

func (*WrapperConfig) ProtoMessage

func (*WrapperConfig) ProtoMessage()

func (*WrapperConfig) ProtoReflect

func (x *WrapperConfig) ProtoReflect() protoreflect.Message

func (*WrapperConfig) Reset

func (x *WrapperConfig) Reset()

func (*WrapperConfig) String

func (x *WrapperConfig) String() string

type WrapperType

type WrapperType string
const (
	WrapperTypeUnknown         WrapperType = "unknown"
	WrapperTypeAead            WrapperType = "aead"
	WrapperTypeAliCloudKms     WrapperType = "alicloudkms"
	WrapperTypeAwsKms          WrapperType = "awskms"
	WrapperTypeAzureKeyVault   WrapperType = "azurekeyvault"
	WrapperTypeGcpCkms         WrapperType = "gcpckms"
	WrapperTypeHsmAuto         WrapperType = "hsm-auto"
	WrapperTypeHuaweiCloudKms  WrapperType = "huaweicloudkms"
	WrapperTypeOciKms          WrapperType = "ocikms"
	WrapperTypePkcs11          WrapperType = "pkcs11"
	WrapperTypePooled          WrapperType = "pooled"
	WrapperTypeShamir          WrapperType = "shamir"
	WrapperTypeTencentCloudKms WrapperType = "tencentcloudkms"
	WrapperTypeTransit         WrapperType = "transit"
	WrapperTypeTest            WrapperType = "test-auto"
)

These values define known types of Wrappers

func (WrapperType) String

func (t WrapperType) String() string

Directories

Path Synopsis
extras
internal
xor
wrappers

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL