Documentation
¶
Overview ¶
Package libcipher provides a collection of cryptographic utilities for encryption, decryption, integrity verification, and secure key generation. It includes implementations for AES-GCM (authenticated encryption) and AES-CBC combined with HMAC (for encryption with integrity verification), as well as functions for sealed HMAC hash creation and constant-time comparison.
The package offers the following functionalities:
- AES-GCM based encryption/decryption, which provides both confidentiality and authenticity.
- AES-CBC with HMAC for scenarios where nonce collisions are a concern, especially in high-volume or distributed environments. This mode encrypts data using AES-CBC (with PKCS#7 padding) and ensures integrity via an HMAC over the encrypted payload and additional data.
- Sealed HMAC hash creation and comparison, where a unique salt is automatically added and the resulting JSON-encoded object encapsulates both the computed HMAC digest and the salt.
- Cryptographically secure key generation.
Security Considerations:
- The encryption key and integrity key must be kept secret and must be distinct. Reusing keys for different purposes can compromise security.
- When using AES-CBC with HMAC, ensure that the entire ciphertext fits in memory as the HMAC is computed over the complete message. For high-volume systems, AES-GCM may be preferred.
Index ¶
- func CheckHash(signingKey string, salt string, shouldBe string, hash []byte) (bool, error)
- func Equal(sealedHash1, sealedHash2 []byte) bool
- func GenerateKey(keyLength int) (string, error)
- func NewHash(args GenerateHashArgs, hashfn func() hash.Hash) ([]byte, error)
- type CipherTextError
- type Decryptor
- type EncryptionKeyError
- type Encryptor
- type GenerateHashArgs
- type HashError
- type IntegrityKeyError
- type InvalidUsageError
- type KeyGenerationError
- type MessageError
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CheckHash ¶
CheckHash verifies the shouldBe string against the hash. params: - signingKey (string) - the signing key for the hash - salt (string) - the salt used for the hash - password (string) - the password to verify - hash ([]byte) - the stored hash to compare against returns: (bool, error) - whether the password matches the hash and an error if any
Note: Think twice, maybe bycrypt is what you need.
func Equal ¶
Equal compares two JSON-encoded sealed hashes in constant time. It unmarshals each sealed hash into a SealedHash struct and then compares both the Hash and Salt fields using hmac.Equal.
Usage:
ok := Equal(sealedHash1, sealedHash2)
if !ok {
// the sealed hashes do not match
}
Returns true if both the hash and salt components are equal; otherwise, false. If either sealed hash cannot be unmarshalled, the function returns false.
func GenerateKey ¶
GenerateKey generates a cryptographically random key with the specified length.
func NewHash ¶
func NewHash(args GenerateHashArgs, hashfn func() hash.Hash) ([]byte, error)
NewHash generates a sealed hash from the provided arguments and hash function. It computes an HMAC digest over the concatenation of the input data and a unique salt, and packages the result along with the salt in a JSON-encoded SealedHash object.
Usage:
sealed, err := NewHash(GenerateHashArgs{
Hash: data,
SigningKey: key,
}, sha256.New)
if err != nil {
// handle error
}
When to use: Use NewHash when you need to securely generate a hash that verifies the integrity and authenticity of data. A unique salt is automatically added so that identical inputs produce distinct outputs, and the signing key is applied during the HMAC computation. The signing key is not required during verification since it is already embedded in the computed HMAC digest.
Types ¶
type CipherTextError ¶
type CipherTextError string
func (CipherTextError) Error ¶
func (e CipherTextError) Error() string
type Decryptor ¶
type Decryptor interface {
// Encrypts/Decrypts a message, misuse may lead to a panic.
Crypt(cipherpackage []byte) ([]byte, []byte, error)
}
provides a method to crypt a cipher package. Misuse of this method may lead to a panic.
func NewCBCHMACDecryptor ¶
func NewCBCHMACDecryptor(encryptionKey []byte, integrityKey []byte, calculateMAC func() hash.Hash) (Decryptor, error)
Configure & init the AES-CBC+HMAC cryptor in decryption mode.
func NewGCMDecryptor ¶
NewGCMDecryptor creates a new Decryptor using AES-GCM with the given key.
type EncryptionKeyError ¶
type EncryptionKeyError string
func (EncryptionKeyError) Error ¶
func (e EncryptionKeyError) Error() string
type Encryptor ¶
type Encryptor interface {
// Encrypts/Decrypts a message, misuse may lead to a panic.
Crypt(message []byte, additionalData []byte) ([]byte, error)
}
provides a method to crypt a message with additional data. Misuse of this method may lead to a panic.
func NewCBCHMACEncryptor ¶
func NewCBCHMACEncryptor(encryptionKey []byte, integrityKey []byte, calculateMAC func() hash.Hash, rand io.Reader) (Encryptor, error)
Configure & init the AES-CBC+HMAC cryptor in encryption mode. AES-CBC with PKCS7 padding HMAC for integrity.
The final encrypted string format: [ MAC | AD-Length | AD | Initialization Vector | Block 1 | Block 2 | ... ] uses rand from the arguments for introducing randomness.
Don't use this for big messages, the whole cypher has to be in mem for computing the Hmac.
The encryption key and integrity key must be distinct. Both keys have to be kept secret. Rotating must be done to both keys simultaneously.
Compromised Encryption Key:
An attacker, possessing the encryption key, could decrypt sensitive data. If you rotate only the integrity key, they still have access to the previously encrypted data.
Compromised Integrity Key:
An attacker with the integrity key could potentially modify encrypted data, forge HMACs, and tamper with the system without detection. Even if you rotate the encryption key, the integrity of past data is compromised.
the MAC is calculated from ( AD-Length | AD | Initialization Vector | Block 1 | Block 2 | ... )
GCM Comparison:
Use CBC with HMAC over GCM (or any stream cipher) when avoiding nonce collisions can be challenging is a problem.
This is the case if you deal with:
- high-volume systems (the probability of nonce collisions increases, especially if the nonce space is limited).
- distributed environments (coordinating nonce generation across nodes and ensuring uniqueness becomes even more complex).
- or scenarios where encrypted data needs to be stored persistently. For example, if encrypted data is stored in a database.
and later retrieved and re-encrypted, ensuring that a new, unique nonce is used each time can be challenging.
Since this is a one-person project, ensure you review the code before using it to validate its security and correctness.
type GenerateHashArgs ¶
GenerateHashArgs contains the input parameters for generating a sealed hash. The Payload field is the data to be hashed, and SigningKey is the key used to compute the HMAC digest. The SigningKey should be kept secret.
type IntegrityKeyError ¶
type IntegrityKeyError string
func (IntegrityKeyError) Error ¶
func (e IntegrityKeyError) Error() string
type InvalidUsageError ¶
type InvalidUsageError string
func (InvalidUsageError) Error ¶
func (e InvalidUsageError) Error() string
type KeyGenerationError ¶
type KeyGenerationError string
func (KeyGenerationError) Error ¶
func (e KeyGenerationError) Error() string
type MessageError ¶
type MessageError string
func (MessageError) Error ¶
func (e MessageError) Error() string