Documentation ¶
Overview ¶
Package passlock provides functions for encrypting data using a key derived from a user-provided passphrase. This uses AES-256 encryption to encrypt the provided data.
Definition of terms: ¶
- plaintext: Data that has not been encrypted.
- passphrase: A user-defined phrase used in place of an encryption key. Longer is better.
- key: A key is a byte array of a size specific to the encryption algorithm used. An AES-128 key may not be used for AES-256 encryption operations.
- salt: A salt is a generated byte array that is the same size as the key. This is generated using a secure random source, and is the entropy used for key generation and recovery.
- key derivation: The process of securely creating a key from secure inputs. This process should be practically infeasible to reproduce without knowing the original inputs.
- scrypt: A CPU and memory hard algorithm used for key derivation in this library. This was designed as an improvement to bcrypt to combat GPU brute force attacks.
- AES: Stands for Advanced Encryption Standard. This is an encryption algorithm that - at the time of this writing - has not been shown to be directly broken in any way. Side-channel attacks are possible, but are a weakness of implementation and hardware.
- base key: The key used to encrypt/decrypt the payload in a MultiLocker.
- surrogate key: A key used to encrypt the base key in a MultiLocker. This allows different passphrases to be used with the same encrypted payload.
How it works: ¶
A key and salt is generated from the given passphrase. The salt is appended to the encrypted payload so the same key can be derived later given the same passphrase. Scrypt is memory and CPU hard, so it's impractical to brute force the salt to get the original passphrase, provided that sufficient tuning values are provided to the KeyGenerator. A normal user is really only expected to define an iteration count for key generation.
The key, salt, and plaintext are passed to the Lock function to encrypt the payload and append the salt to it. The key is recovered from the encrypted payload by passing the original passphrase and the payload to KeyGenerator.Derive. The key and encrypted payload are passed to the Unlock function to decrypt the payload and return the original plain text.
The MultiLocker type extends the functionality above by providing the ability to use multiple surrogate keys to interact with the encrypted payload. A MultiLocker is created using a KeyGenerator, and the encrypted payload is set by calling MultiLocker.Lock with the base passphrase and plaintext. Once created, surrogate keys may be added to the MultiLocker that allow reading the encrypted payload. A MultiLocker with surrogate keys and encrypted payload may be persisted to disk in binary form, and read back - including key generation settings.
A freshly read MultiLocker may not be changed in any way. Editing is enabled by calling EnableUpdate with the base passphrase. After this call completes successfully, surrogate keys may be added or removed. A new encrypted payload may only be set in a MultiLocker with the base passphrase. A WriteMultiLocker allows surrogate passphrases to be used to lock a new payload, instead of just the base passphrase.
General guidelines: ¶
- It's possible to customize the CPU cost, iteration count, and relative block size parameters directly for key generation. If you're not an expert, then don't use SetIterations, SetCPUCost, or SetRelativeBlockSize.
- Both short and long delay iteration GeneratorOpt functions are provided, choose the correct iterations for your use-case using either SetLongDelayIterations or SetShortDelayIterations.
- If encrypted data is intended to be stored indefinitely, choose the SetLongDelayIterations option for key generation.
- This method of encryption (AES-GCM) supports encrypting and authenticating at most about 64GB at a time. You could get around this by splitting a very large file into multiple chunks that include some metadata to prevent reordering or truncating.
- AES-256 is a good default for a lot of cases, with excellent security and good throughput speeds.
- This library supports AES-256 since that is the best supported by the Go standard lib, but AES-128 may also be used for situations where more throughput is desired.
- The main limit to operation speed comes from key generation (as intended), the AES key size makes a much smaller impact to performance unless a very large payload is encrypted.
- When deriving the key from an encrypted payload, make sure that the same KeyGenerator settings are used. Not doing so will result in an incorrect key.
- Technically, a surrogate key could be used to update a MultiLocker encrypted payload without invalidating other surrogate keys, since there are no cryptographic blockers to that. The base MultiLocker doesn't provide that function as a logical constraint only.
- The MultiLocker base key may not be updated without invalidating all surrogate keys.
Index ¶
- Constants
- Variables
- type Encrypted
- type GeneratorOpt
- func SetAES128KeySize() GeneratorOpt
- func SetAES256KeySize() GeneratorOpt
- func SetCPUCost(cost uint8) GeneratorOpt
- func SetIterations(iterations uint64) GeneratorOpt
- func SetLongDelayIterations() GeneratorOpt
- func SetRelativeBlockSize(size uint8) GeneratorOpt
- func SetShortDelayIterations() GeneratorOpt
- type Key
- type KeyGenerator
- func (g *KeyGenerator) DeriveKey(pass Passphrase, data Encrypted) (key Key, err error)
- func (g *KeyGenerator) DeriveKeySalt(pass Passphrase, data Encrypted) (key Key, salt Salt, err error)
- func (g *KeyGenerator) DeriveSalt(data Encrypted) (salt Salt, err error)
- func (g *KeyGenerator) GenerateKey(pass Passphrase) (key Key, salt Salt, err error)
- type MultiLocker
- func (l *MultiLocker) AddSurrogatePass(id string, pass Passphrase) error
- func (l *MultiLocker) DisableUpdate()
- func (l *MultiLocker) EnableUpdate(pass []byte) error
- func (l *MultiLocker) ListKeyIDs() []string
- func (l *MultiLocker) Lock(pass []byte, unencrypted Plaintext) error
- func (l *MultiLocker) Read(r io.Reader) error
- func (l *MultiLocker) RemoveSurrogatePass(id string) error
- func (l *MultiLocker) Unlock(id string, pass []byte) ([]byte, error)
- func (l *MultiLocker) UpdateSurrogatePass(id string, newPass Passphrase) error
- func (l *MultiLocker) Write(w io.Writer) error
- type Passphrase
- type Plaintext
- type Salt
- type WriteMultiLocker
Constants ¶
Variables ¶
var ( ErrEmptyPassPhrase = errors.New("cannot use an empty passphrase") ErrInvalidData = errors.New("unable to use input data") )
var ( ErrInvalidHeader = errors.New("invalid MultiLocker header") ErrInvalidPassword = errors.New("invalid password") )
Functions ¶
This section is empty.
Types ¶
type Encrypted ¶
type Encrypted []byte
Encrypted is an encrypted payload.
func Lock ¶
Lock will encrypt the payload with the given Key, and append the given Salt to the payload. Exposure of the Salt doesn't weaken the Key, since the passphrase is also required to arrive at the same Key. Salt exposure is required to be able to derive the same Key from the same passphrase. However, tampering with the Salt or the payload would prevent Unlock from recovering the Plaintext payload.
type GeneratorOpt ¶
type GeneratorOpt = func(*KeyGenerator) error
GeneratorOpt is a function option to be used with NewKeyGenerator.
func SetAES128KeySize ¶
func SetAES128KeySize() GeneratorOpt
SetAES128KeySize uses 128 bits (16 bytes) as the key size to be generated.
func SetAES256KeySize ¶
func SetAES256KeySize() GeneratorOpt
SetAES256KeySize uses 256 bits (32 bytes) as the key size to be generated.
func SetCPUCost ¶
func SetCPUCost(cost uint8) GeneratorOpt
SetCPUCost sets the parallelism factor for key generation from the default of 1. Only use this option if you know what you're doing.
func SetIterations ¶
func SetIterations(iterations uint64) GeneratorOpt
SetIterations allows the caller to customize the iteration count. Only use this option if you know what you're doing.
func SetLongDelayIterations ¶
func SetLongDelayIterations() GeneratorOpt
SetLongDelayIterations sets a higher iteration count. This is sufficient for infrequent key derivation, or cases where the key will be cached for long periods of time. This option is much more resistant to password cracking, and is the default.
func SetRelativeBlockSize ¶
func SetRelativeBlockSize(size uint8) GeneratorOpt
SetRelativeBlockSize sets the relative block size. Only use this option if you know what you're doing.
func SetShortDelayIterations ¶
func SetShortDelayIterations() GeneratorOpt
SetShortDelayIterations sets a lower iteration count. This is appropriate for situations where a shorter delay is desired because of frequent key derivations. This option balances speed with password cracking resistance. It's recommended to use longer passwords with this approach.
type Key ¶
type Key []byte
Key is an AES key that can be used to encrypt or decrypt an encrypted payload.
type KeyGenerator ¶
type KeyGenerator struct {
// contains filtered or unexported fields
}
func NewKeyGenerator ¶
func NewKeyGenerator(opts ...GeneratorOpt) (*KeyGenerator, error)
NewKeyGenerator creates a new KeyGenerator using the options provided as zero or more GeneratorOpt. By default, the generator generates a key for AES256KeySize using DefaultLargeIterations.
func (*KeyGenerator) DeriveKey ¶
func (g *KeyGenerator) DeriveKey(pass Passphrase, data Encrypted) (key Key, err error)
DeriveKey will recover a key with the salt in the payload and the given passphrase. This doesn't ensure that the given passphrase is the *correct* passphrase used to encrypt the payload.
func (*KeyGenerator) DeriveKeySalt ¶
func (g *KeyGenerator) DeriveKeySalt(pass Passphrase, data Encrypted) (key Key, salt Salt, err error)
DeriveKeySalt will recover a key and the original salt in the payload with the given passphrase. This doesn't ensure that the given passphrase is the *correct* passphrase used to encrypt the payload.
func (*KeyGenerator) DeriveSalt ¶
func (g *KeyGenerator) DeriveSalt(data Encrypted) (salt Salt, err error)
DeriveSalt gets the salt value from the encrypted payload.
func (*KeyGenerator) GenerateKey ¶
func (g *KeyGenerator) GenerateKey(pass Passphrase) (key Key, salt Salt, err error)
GenerateKey will generate an AES key and salt using the configuration of the KeyGenerator.
type MultiLocker ¶
type MultiLocker struct {
// contains filtered or unexported fields
}
MultiLocker allows using surrogate keys - in addition to a base key - for reading an encrypted payload. If surrogate key writes are desired, then use the WriteMultiLocker instead.
func NewMultiLocker ¶
func NewMultiLocker(gen *KeyGenerator) *MultiLocker
func (*MultiLocker) AddSurrogatePass ¶
func (l *MultiLocker) AddSurrogatePass(id string, pass Passphrase) error
AddSurrogatePass will add a new surrogate key to this MultiLocker. Update must be enabled in this MultiLocker before this can be done.
func (*MultiLocker) DisableUpdate ¶
func (l *MultiLocker) DisableUpdate()
DisableUpdate will disable updates to this MultiLocker.
func (*MultiLocker) EnableUpdate ¶
func (l *MultiLocker) EnableUpdate(pass []byte) error
EnableUpdate validates the MultiLocker and ensures that it's in a suitable state for updating by setting the base key. The original base passphrase must be used, not a surrogate passphrase, to validate that the correct key is populated.
func (*MultiLocker) ListKeyIDs ¶
func (l *MultiLocker) ListKeyIDs() []string
ListKeyIDs lists all surrogate key IDs in this MultiLocker.
func (*MultiLocker) Lock ¶
func (l *MultiLocker) Lock(pass []byte, unencrypted Plaintext) error
Lock will lock a new payload with the base key. If surrogate keys are present, then the same salt will be used to ensure that surrogate keys are not invalidated.
func (*MultiLocker) Read ¶
func (l *MultiLocker) Read(r io.Reader) error
Read will read the MultiLocker as a binary payload from the io.Reader.
func (*MultiLocker) RemoveSurrogatePass ¶
func (l *MultiLocker) RemoveSurrogatePass(id string) error
RemoveSurrogatePass will remove a surrogate key. Update must be enabled in this MultiLocker before this can be done.
func (*MultiLocker) Unlock ¶
func (l *MultiLocker) Unlock(id string, pass []byte) ([]byte, error)
Unlock will unlock the payload with a surrogate key.
func (*MultiLocker) UpdateSurrogatePass ¶
func (l *MultiLocker) UpdateSurrogatePass(id string, newPass Passphrase) error
UpdateSurrogatePass will update the passphrase of an existing surrogate key by ID. Update must be enabled in this MultiLocker before this can be done.
type Passphrase ¶
type Passphrase []byte
Passphrase is a human-readable string used to generate a Key.
type Salt ¶
type Salt []byte
Salt is a slice of secure random bytes that is used with scrypt to generate a Key from a Passphrase.
type WriteMultiLocker ¶
type WriteMultiLocker struct {
*MultiLocker
}
WriteMultiLocker is the same as MultiLocker, except that the logical constraint that surrogate keys cannot write a new payload is lifted.
func NewWriteMultiLocker ¶
func NewWriteMultiLocker(gen *KeyGenerator) *WriteMultiLocker
func (*WriteMultiLocker) SurrogateLock ¶
func (l *WriteMultiLocker) SurrogateLock(id string, pass Passphrase, unencrypted Plaintext) error
SurrogateLock will Lock a new payload in the MultiLocker using a surrogate key.