Documentation ¶
Overview ¶
Easy to use crypto package for a variety of usages.
Catgi Security packages ¶
It provides a secure and fast HMAC function using Blake2b ¶
It provides a secure and deterministic key derivation mechanism using keypaths and Blake2b.
It provides a secure and easy symmetric encryption using Polycha20 and the key derivatino mechanism. Each encryption gets it's own key thusly preventing nonce reuse for multiple calls to the encryption method.
Index ¶
- Constants
- Variables
- func DecryptBlockData(key SecretKey, data io.Reader) (io.Reader, <-chan error, error)
- func DecryptBytes(key SecretKey, data []byte) ([]byte, error)
- func DecryptStreamData(key SecretKey, data io.Reader) (io.Reader, <-chan error, error)
- func EncryptBlockData(key SecretKey, data io.Reader) (io.Reader, <-chan error, error)
- func EncryptBytes(key SecretKey, data []byte) ([]byte, error)
- func EncryptStreamData(key SecretKey, data io.Reader) (io.Reader, <-chan error, error)
- func GetKey(key SecretKey, cipher Cipher, mode CryptMode) ([]byte, []byte, error)
- func GetKeyFromPrekey(key SecretKey, salt []byte) ([]byte, error)
- func HMAC(key []byte, data io.Reader) ([]byte, error)
- func VerifyHMAC(hmac, key []byte, data io.Reader) (err error)
- type Cipher
- type CryptMode
- type DecryptWorker
- type EncryptWorker
- type EncryptedBlock
- type SecretKey
Constants ¶
const ( CipherDefault = CipherPolyCha20 // Encrypt and Decrypt using Chacha20 with Poly1305 CipherPolyCha20 = iota )
const ( CryptModeWhole = "fullkey" CryptModeStream = "streamkey" CryptModeBlock = "blockkey" )
const ( BlockSize = 4 * 1024 BlockHeaderSize = 8 )
Variables ¶
var ErrEmptyBlock = errors.New("Empty Block")
This is a non-critical error. It indicates that some block had the size 0, containing only a header.
var HMACVerificationFail = errors.New("HMAC Verification failed")
HMACVerificationFail is returned by VerifyHMAC when the hmac given did not match the given datastream.
Functions ¶
func DecryptBlockData ¶
func DecryptStreamData ¶
func EncryptBlockData ¶
func EncryptStreamData ¶
EncryptStreamData will accept a secret key and a incoming io.Reader to read from. It will encrypt all incoming data using 4KiB blocks. If an error occurs during initialization, it will return a nil error channel and nil io.Reader. If the initialization is correct, it will start the cipher worker in a go routine. The Worker will return an error over the given error channel and close the io.Reader on it's side. The worker will block waiting for either input or output, it's output is not buffered. The Encryption will derive all secrets from the given SecretKey in such a way that the function DecryptStreamData can decrypt it given it has the same key.
func GetKey ¶
GetKey is a wrapper for GetKeyFromSalt that generates a random salt to be used for the key using a random nonce. Internally it combines a PreKey with a randomly generated nonce.
func GetKeyFromPrekey ¶
GetKeyFromPreKey applies the given salt to a PreKey. You should not use this to derive from anything but the data you get from GetPreKey.
Types ¶
type Cipher ¶
type Cipher uint16
Cipher represents a encryption mode used by this package The default cipher is CipherPolyCha20
type DecryptWorker ¶
func (*DecryptWorker) DecipherAll ¶
func (c *DecryptWorker) DecipherAll() error
func (*DecryptWorker) DecipherStreamOrBlock ¶
func (c *DecryptWorker) DecipherStreamOrBlock() error
type EncryptWorker ¶
type EncryptWorker struct { AEAD cipher.AEAD // AEAD cipher used Salt []byte // Salt used for key derivation Input io.Reader // Data Input Reader Output io.Writer // Cipher Output Writer }
EncryptWorker is used to cipher a stream of data. It'll read atleast blockSize of bytes and encrypt them
func (*EncryptWorker) CipherAll ¶
func (c *EncryptWorker) CipherAll() error
Cipher all reads the entire plaintext and ciphers it at once and encrypts them in a single block When all data is encrypted or an error occurs, the output is closed and the error returned.
func (*EncryptWorker) CipherBlock ¶
func (c *EncryptWorker) CipherBlock() error
CipherBlock works like CipherStream but the output blocks have a fixed size, making it more suitable for disk/file operations.
func (*EncryptWorker) CipherStream ¶
func (c *EncryptWorker) CipherStream() error
CipherStream will read from input and output a ciphered stream of data.
type EncryptedBlock ¶
type EncryptedBlock struct { Cipher uint16 `msgpack:"cipher"` // Cipher is a constant determining the cipher algorithm Padding uint16 `msgpack:"padding"` // Padding is the number of bytes added to the data. Whe not used set to 0x0000 Nonce []byte `msgpack:"nonce"` // Nonce is the encryption nonce used Salt []byte `msgpack:"salt"` // Salt is used to derive the key used for decryption Data []byte `msgpack:"data"` // Data is the actual ciphertext }
EncryptedBlock contains an encrypted block of data with necessary information to decrypt it again. When used in Block-Mode, the maximum size that should be used is 2^16-1 In Stream- or Whole-Mode the maximum safe size is a bit under 2^32, depending on nonce, salt and encoding overhead.
type SecretKey ¶
type SecretKey [64]byte
SecretKey is a special 64 byte long secret that can be used to derive an arbitrary amount of subkeys. All subkeys are deterministically based on their path and their parent, allowing an application or library to reuse a secret for many operations in different locations. As a bonus, if a subkey is compromised, it's parents are not, so you can expose as many keys as you like to less trustworthy clients without fearing that someone could forge more keys.
Keep in mind that keys are deterministic, so if a key is compromised the specific path used will remain forever compromised for the same parent key. You need to change the path or the master secret to regain security.
Since this key uses HMACs, you can also utilize it to generate encryption keys. If a key and it's path are compromised, an attacker cannot forge other keys unless they have knowledge of the parent.
To protect the master, it is recommended to use a path depth of atleast 2. Ex.: /myapp/example/org/ would be an acceptable derivative secret of a master key.
func GetPreKey ¶
GetPreKey derives a so called prekey. This prekey is used when decrypting data streams that use the same cipher and cryptmode, allowing the AEAD mode to operate at least-depth while still being able to decrypt as much data as possible.
func NewSecretKey ¶
NewSecretKey will take the given master secret and generate a SecretKey from it. If the master is shorter than 64 bytes, it will first be hashed using Blake2b. If the master is longer than 64 bytes, the excessive data is discarded.
func (SecretKey) DeriveKey ¶
DeriveKey will compute a new secret based on the given path and the defined secret key.
Applications should derive to a depth of 3 path segments before externalizing a key, ie transmitting it over network.
The path is computed recursively on the result of the previous path such that the path computation can be split at any point. If no path is specified, then the given master is returned.
Illustration:
DeriveKey(path1, path2) == DeriveKey(DeriveKey(path1), path2)
SecretKey.DeriveKey() == SecretKey
func (SecretKey) GetNSecretBytes ¶
GetNSecretBytes reads N bytes from a HKDF with an optional salt. (Set salt to nil if no salt is used) Keep in mind that HKDF has an upper limit on entropy, you should not read excessive amounts of random data from here. I recommend not using more than 4096 bytes of data, this has worked for my tests so far with good reliability and should be sufficient for 99% of applications.
func (SecretKey) MustDeriveKey ¶
MustDeriveKey works like DeriveKey but panics on an error.