secret

package
v0.7.1 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2020 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const MaxSize = 1 << 20 // 1 MiB

MaxSize is the max. size of a (encrypted) secret.

Neither a secret nor an encrypted secret should be larger than 1 MiB.

Implementions of Remote should use this to limit the amount of data they read from the key-value store.

Variables

This section is empty.

Functions

This section is empty.

Types

type KMS added in v0.7.0

type KMS interface {
	// Encrypt encrypts the given plaintext with the
	// cryptographic key referenced by the given key name.
	// It returns the encrypted plaintext as ciphertext.
	// If the encryption fails Encrypt returns a non-nil
	// error.
	Encrypt(key string, plaintext []byte) (ciphertext []byte, err error)

	// Decrypt tries to decrypt the given ciphertext
	// and returns the secret plaintext on success.
	// If the decryption fails Decrypt returns a non-nil
	// error.
	Decrypt(key string, ciphertext []byte) (plaintext []byte, err error)
}

KMS is a key management system that holds a set of cryptographic secret keys. The KMS interface specifies what operations can be performed with these secret keys.

In particularly, a KMS can encrypt a value, i.e. a secret, with one of its cryptographic keys and returns the encrypted value as ciphertext. The ciphertext can then be passed to the KMS again - together with the same key name - which then tries to decrypt it and returns the plaintext on success.

type Remote added in v0.7.0

type Remote interface {
	// Create adds the given key-value pair to
	// the remote store if and only if no entry
	// for the given key exists already.
	//
	// If key already exists at the remote store
	// it does not replace the secret and returns
	// kes.ErrKeyExists.
	//
	// Create returns the first error it encounters
	// while trying to add the given key-value pair
	// to the store, if any.
	Create(key string, value string) error

	// Delete deletes the given key and the associated
	// value from the remote store. It does not return
	// an non-nil error if the key does not exist.
	//
	// Delete returns the first error it encounters
	// while trying to delete the given key from the
	// store, if any.
	Delete(key string) error

	// Get returns the value associated with the given
	// key. If no value is associated with key then Get
	// returns kes.ErrKeyNotFound.
	//
	// Get returns the first error it encounters while
	// trying to add the given key-value pair to the
	// store, if any.
	Get(key string) (value string, err error)
}

Remote is a key-value store for plain or encrypted secrets. Therefore, it stores keys and values as strings.

Remote is the interface that must be implemented by secret store backends, like Vault or AWS SecretsManager.

type Secret

type Secret [32]byte

Secret is a 256 bit secret key. It can wrap and unwrap session or data keys.

func (Secret) MarshalJSON added in v0.7.0

func (s Secret) MarshalJSON() ([]byte, error)

func (*Secret) ParseString

func (s *Secret) ParseString(v string) error

ParseString parses v and sets the secret key to the parsed value, on success.

ParseString will always be able to successfully parse a string produced by Secret.String().

func (Secret) String

func (s Secret) String() string

String returns the string representation of the secret key.

It is guaranteed that the returned string is valid JSON.

func (*Secret) UnmarshalJSON added in v0.7.0

func (s *Secret) UnmarshalJSON(b []byte) error

func (Secret) Unwrap

func (s Secret) Unwrap(ciphertext []byte, associatedData []byte) ([]byte, error)

Unwrap decrypts and verifies the ciphertext, verifies the associated data and, if successful, returns the resuting plaintext. It returns an error if ciphertext is malformed or not authentic.

func (Secret) Wrap

func (s Secret) Wrap(plaintext, associatedData []byte) ([]byte, error)

Wrap encrypts and authenticates the plaintext, authenticates the associatedData and returns the resulting ciphertext.

It should be used to encrypt a session or data key provided as plaintext.

If the executing CPU provides AES hardware support, Wrap derives keys using AES and encrypts plaintexts using AES-GCM. Otherwise, Wrap derives keys using HChaCha20 and encrypts plaintexts using ChaCha20-Poly1305.

type Store

type Store struct {
	// Key is the name of the cryptographic key
	// at the KMS used to encrypt newly created
	// secrets before sending them to the remote
	// key-value store.
	//
	// If KMS is nil it will be ignored.
	// It must not be modified once the Store
	// has been used to fetch or store secrets.
	Key string

	// KMS is the KMS implementation used to
	// encrypt secrets before sending them to
	// the remove key-value store.
	//
	// It uses the Store.Key as the default
	// cryptographic key for encrypting new
	// secrets
	//
	// If the KMS is nil then all newly created
	// secrets will be stored as plaintext.
	//
	// If KMS is present and the remote key-value
	// store returns a plaintext value then the
	// Store still tries to decrypt the plaintext
	// value - which should fail.
	// Similarly, if no KMS is present and the
	// remote key-value store returns an encrypted
	// value then the Store does not try to decrypt
	// the value.
	// Basically, the remote store must return only
	// plaintext values or ciphertext values - but
	// not both.
	//
	// It must not be modified once the Store has been
	// used to fetch or store secrets.
	KMS KMS

	// Remote is the remote key-value store. Secrets
	// will be fetched from or written to this store.
	//
	// It must not be modified once the Store has been
	// used to fetch or store secrets.
	Remote Remote
	// contains filtered or unexported fields
}

Store is the local secret store connected to a remote key-value store.

It is responsible for en/decrypting secrets if a KMS is present and for caching secrets fetched from the remote key value store.

func (*Store) Create

func (s *Store) Create(name string, secret Secret) (err error)

Create adds the given secret with the given name to the secret store. If there is already a secret with this name then it does not replacce the secret and returns kes.ErrKeyExists.

func (*Store) Delete

func (s *Store) Delete(name string) error

Delete deletes the secret associated with the given name, if one exists.

func (*Store) Get

func (s *Store) Get(name string) (Secret, error)

Get returns the secret associated with the given name, if any. If no such secret exists it returns kes.ErrKeyNotFound.

func (*Store) StartGC added in v0.7.0

func (s *Store) StartGC(ctx context.Context, expiry, unusedExpiry time.Duration)

StartGC starts the cache garbage collection background process. The GC will discard all cached secrets after expiry. Further, it will discard all entries that havn't been used for unusedExpiry.

If expiry is 0 the GC will not discard any secrets. Similarly, if the unusedExpiry is 0 then the GC will not discard unused secrets.

There is only one garbage collection background process. Calling StartGC more than once has no effect.

Notes

Bugs

  • The KDF implemented by insecureAESDeriveKey is not a PRF. The following example shows that there exists a relation between 4 generated keys:

    iv0 = 0¹⁶
    iv1 = 1 || 0¹⁵
    iv2 = 0¹⁵ || 1
    iv3 = 1 || 0¹⁴ || 1
    

    Generating 4 derived keys with these 4 iv values using the same key `K` gives:

    k0 = insecureAESDeriveKey(K, iv0)
    k1 = insecureAESDeriveKey(K, iv1)
    k2 = insecureAESDeriveKey(K, iv2)
    k3 = insecureAESDeriveKey(K, iv3)
    

    Now, the following statement holds (^ is XOR):

    k0 ^ k1 ^ k2 == k3
    

    This shows that insecureAESDeriveKey is not a PRF.

Jump to

Keyboard shortcuts

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