Documentation
¶
Overview ¶
Package simplecipher wraps the standard library's crypto/cipher package.
It provides a simple interface to encrypt and decrypt strings or io.Reader/io.Writer streams using AES encryption.
Index ¶
- Variables
- type Cipher
- func NewCBC(key, iv Key) Cipher
- func NewCFB(key, iv Key) Cipher
- func NewCTR(key, iv Key) Cipher
- func NewGCM(key, nonce Key) Cipher
- func NewOFB(key, iv Key) Cipher
- func SimpleCBC(keyPassphrase string) Cipher
- func SimpleCFB(keyPassphrase string) Cipher
- func SimpleCTR(keyPassphrase string) Cipher
- func SimpleGCM(keyPassphrase, noncePassphrase string) Cipher
- func SimpleOFB(keyPassphrase string) Cipher
- type Key
- func Bytes(b []byte) Key
- func NewAesKey(passphrase string, options ...KeyGenOption) Key
- func NewIv(passphrase string, options ...KeyGenOption) Key
- func NewKey(passphrase string, len KeyLen, salt string) Key
- func NewNonce(passphrase string, options ...KeyGenOption) Key
- func NewRandomIv() Key
- func String(s string) Key
- type KeyGenOption
- type KeyLen
- type Stream
- type StringCodec
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrPlaintextBlockSize = errors.New("plaintext is not a multiple of the block size") ErrCipherTextTooShort = errors.New("ciphertext too short") ErrCipherTextBlockSize = errors.New("ciphertext is not a multiple of the block size") ErrPanic = errors.New("recovered from panic") ErrCopy = errors.New("copy error") ErrNewAesCipher = errors.New("aes.NewCipher error") )
Errors
var DefaultSalt = func() string {
return "3c7bef42a1524af19442b1b0a5751d29"
}
DefaultSalt returns a fixed random string to make the key derivation more secure. keyGen use this salt by default.
simplecipher.DefaultSalt = func() string { return "NaCl" }
Make sure to keep this function idempotence, that is, it should return the same result for each call. Otherwise, the decryption may fail due to the inconsistent key derivation.
The returned salt string is recommended to be >= 8 bytes long.
For any use case, it is recommended to customize this function to generate a different salt for each of your applications.
For real security, use New*() Ciphers with WithSalt() option to customize the salt for each key derivation. Or considering use trusted remote procedure calls to fetch the salt to avoid hardcoding the salt into the source code and binaries.
Functions ¶
This section is empty.
Types ¶
type Cipher ¶
type Cipher interface { // Encrypt the given plaintext and return the ciphertext as a [DefaultStringCodec] encoded string. Encrypt(plainText string) (cipherText string, err error) // Decrypt the given ciphertext ([DefaultStringCodec] encoded) and return the plaintext. Decrypt(cipherText string) (plainText string, err error) }
Cipher is an interface for encryption and decryption of strings.
Cipher implementations should recover from underlying panics and return them as errors.
Cipher encodes the ciphertext with DefaultStringCodec when Encrypting and decodes the ciphertext from a DefaultStringCodec string when Decrypting.
func NewCBC ¶
NewCBC creates a new CBC cipher with the given key and iv.
The iv will be prepended to the ciphertext during encryption, and the first block of the ciphertext will be treated as the IV during decryption.
It's caller's responsibility to ensure the following:
- The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256.
- The IV must be aes.BlockSize bytes long.
- The plaintext must be padded to a multiple of aes.BlockSize bytes.
Use SimpleCBC if you are not familiar with these.
See also: cipher.NewCBCDecrypter, cipher.NewCBCEncrypter for low-level usage.
func NewCFB ¶
NewCFB creates a new CFB cipher with the given key and iv.
The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256. The iv must be aes.BlockSize bytes long.
The iv will be prepended to the ciphertext during encryption, and the first block of the ciphertext will be treated as the IV during decryption.
Use SimpleCFB if you are not familiar with this.
See also: cipher.NewCFBDecrypter, cipher.NewCFBEncrypter for low-level usage.
func NewCTR ¶
NewCTR creates a new CTR cipher with the given key and iv.
The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256. The iv must be aes.BlockSize bytes long.
The iv will be prepended to the ciphertext during encryption, and the first block of the ciphertext will be treated as the IV during decryption.
Use SimpleCTR if you are not familiar with this.
See also: cipher.NewCTR for low-level usage.
Example ¶
ExampleNewCTR demonstrates how to use NewCTR to encrypt a plaintext and decrypt the ciphertext using the same key and iv via OpenSSL.
rawKey := "my-raw-key-with-32-bytes-length-" rawIv := "16ByteInitVector" cipher := NewCTR(String(rawKey), String(rawIv)) encrypted, _ := cipher.Encrypt("Hello, World!") fmt.Println("ciphertext by simplecipher:", encrypted) decrypted, _ := cipher.Decrypt(encrypted) fmt.Println("decrypted by simplecipher:", decrypted) // or use openssl to decrypt the ciphertext // echo "raw ciphertext" | openssl enc -d -aes-256-ctr -K "key in hex" -iv "iv in hex" rawCiphertext, _ := hex.DecodeString(encrypted[32:]) // remove the iv, openssl doesn't recognize it hexKey := hex.EncodeToString([]byte(rawKey)) hexIv := hex.EncodeToString([]byte(rawIv)) //fmt.Println("key in hex:", hexKey) //fmt.Println("iv in hex:", hexIv) opensslCmd := exec.Command("openssl", "enc", "-d", "-aes-256-ctr", "-K", hexKey, "-iv", hexIv) opensslStdin, _ := opensslCmd.StdinPipe() _, _ = opensslStdin.Write(rawCiphertext) _ = opensslStdin.Close() opensslDecrypted, _ := opensslCmd.CombinedOutput() fmt.Println("decrypted by openssl:", string(opensslDecrypted))
Output: ciphertext by simplecipher: 313642797465496e6974566563746f720c2058d6452bd8771bf706e8b0 decrypted by simplecipher: Hello, World! decrypted by openssl: Hello, World!
func NewGCM ¶
NewGCM creates a new GCM cipher with the given key and nonce. It's caller's responsibility to ensure the following:
- The key must be 16 or 32 bytes long to select AES-128 or AES-256.
- The nonce must be 12 bytes long.
Use SimpleGCM if you are not familiar with these.
See also: cipher.NewGCM for low-level usage.
func NewOFB ¶
NewOFB creates a new OFB cipher with the given key and iv.
The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256. The iv must be aes.BlockSize bytes long.
The iv will be prepended to the ciphertext during encryption, and the first block of the ciphertext will be treated as the IV during decryption.
Use SimpleOFB if you are not familiar with this.
See also: cipher.NewOFB for low-level usage.
func SimpleCBC ¶
SimpleCBC creates a new AES-256-CBC cipher with the given key.
The keyPassphrase parameter can be any arbitrary string. It will be used to derive the real key used in the CBC mode via scrypt.
Random iv will be generated for each encryption and prepended to the ciphertext.
The plaintext is automatically padded to a multiple of aes.BlockSize bytes with PKCS7 padding.
See also: NewCBC for more control.
func SimpleCFB ¶
SimpleCFB creates a new AES-256-CFB cipher with a key derived from the given keyPassphrase and a random iv prepended to the ciphertext.
See also: NewCFB for more control.
func SimpleCTR ¶
SimpleCTR creates a new AES-256-CTR cipher with a key derived from the given keyPassphrase and a random iv prepended to the ciphertext.
See also: NewCTR for more control.
Example ¶
DefaultSalt = func() string { return "NaCl" } key := "my-secret-key" plainText := "Hello, World!" cipher := SimpleCTR(key) encrypted, _ := cipher.Encrypt(plainText) // fmt.Println(encrypted) decrypted, _ := cipher.Decrypt(encrypted) fmt.Println(decrypted)
Output: Hello, World!
func SimpleGCM ¶
SimpleGCM creates a new AES-256-GCM cipher from the given key and nonce.
The keyPassphrase and noncePassphrase parameters can be any arbitrary strings. SimpleGCM will derive the real key and nonce used in the GCM mode from the these passphrases via scrypt.
Attention: SimpleGCM is not compatible with other libraries, because it uses a custom key derivation function. You can only decrypt the encrypted ciphertext with the same version of SimpleGCM and the same passphrases passed to it.
See also: NewGCM
Example ¶
DefaultSalt = func() string { return "NaCl" } key := "my-secret-key" nonce := time.Now().Format(time.DateOnly) plainText := "Hello, World!" cipher := SimpleGCM(key, nonce) encrypted, _ := cipher.Encrypt(plainText) // fmt.Println(encrypted) decrypted, _ := cipher.Decrypt(encrypted) fmt.Println(decrypted)
Output: Hello, World!
type Key ¶
type Key interface { // Bytes return a byte slice of the key. Bytes() []byte }
Key is an interface for AES cipher keys, ivs, and nonces.
To keep things simple, basically everything you need to encrypt/decrypt with AES, except the plaintext/ciphertext, are treated as keys in this package.
Notice different use cases of keys require different lengths. Use NewAesKey, NewNonce, or NewIv to create keys matching the requirements if you are not sure.
func NewAesKey ¶
func NewAesKey(passphrase string, options ...KeyGenOption) Key
NewAesKey creates a new AES key derived from the passphrase.
Aes256 and DefaultSalt are used by default. Use WithSalt and WithLen options to customize the key derivation.
func NewIv ¶
func NewIv(passphrase string, options ...KeyGenOption) Key
NewIv creates a new IV with aes.BlockSize bytes.
The output key will be derived from the passphrase via Sequential Memory-Hard Functions with DefaultSalt.
func NewKey ¶
NewKey derives a new key in the specified length from the passphrase.
The output key will be derived from the Passphrase (with Salt) via Sequential Memory-Hard Functions (see scrypt.Key for details).
Any UTF-8 string can be used as an input key (including "") and Salt.
More than 32 bytes are recommended for the Passphrase. And at least 8 bytes are recommended for Salt.
Use NewAesKey, NewNonce, or NewIv for specific key types.
Example ¶
// derive a key from a passphrase passphrase := "my-secret-key" keyLen := Aes256 // 32 salt := "NaCl" key := NewKey(passphrase, keyLen, salt) // use the key for encryption or any other purpose _ = key
func NewNonce ¶
func NewNonce(passphrase string, options ...KeyGenOption) Key
NewNonce creates a new nonce with default NonceSize.
The output key will be derived from the passphrase via Sequential Memory-Hard Functions with DefaultSalt.
func NewRandomIv ¶
func NewRandomIv() Key
NewRandomIv creates a new random IV with aes.BlockSize bytes.
type KeyGenOption ¶
type KeyGenOption func(gen *keyGen)
KeyGenOption is a functional option to customize the KeyGen struct.
func WithLen ¶
func WithLen(keyLen KeyLen) KeyGenOption
WithLen sets the key length for the AES key. Available key lengths are Aes128, Aes192, and Aes256.
If an invalid key length is provided, it will default to Aes256.
func WithPassphrase ¶
func WithPassphrase(passphrase string) KeyGenOption
WithPassphrase sets the passphrase for the key derivation. The passphrase can be any UTF-8 string. The length of the passphrase is recommended to be >= 32 bytes for security and < 72 bytes for performance.
func WithSalt ¶
func WithSalt(salt string) KeyGenOption
WithSalt sets the salt for the key derivation. The salt should be a random string >= 8 bytes long to make the key derivation more secure.
type KeyLen ¶
type KeyLen int
KeyLen is a type to indicate the length of the key in bytes.
Available KeyLen values for AES keys are 16, 24 and 32 bytes for Aes128, Aes192, and Aes256 respectively.
const (
NonceSize KeyLen = 12
)
NonceSize is the default size of the nonce for AEAD ciphers.
type Stream ¶
type Stream interface { // EncryptStream encrypts the given plaintext from the reader // and write the ciphertext to the given writer without encoding. EncryptStream(plainText io.Reader, cipherText io.Writer) error // DecryptStream decrypts the given ciphertext (not encoded) // and write the plaintext to the given writer. DecryptStream(cipherText io.Reader, plainText io.Writer) error }
Stream is an interface for encryption and decryption of io.Reader and io.Writer.
Notice that, unlike Cipher, Stream does not encode the ciphertext. The cipherText output of Encrypt and the cipherText input of Decrypt are not encoded in any way (or in NopCodec), they are just raw bytes.
func NewCFBStream ¶
NewCFBStream creates a new CFB stream cipher with the given key and iv.
The iv will be used as the initial value for the CFB mode.
It's caller's responsibility to ensure the following:
- The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256.
- The IV must be aes.BlockSize bytes long.
Use SimpleCFBStream if you are not familiar with these. See also: cipher.NewCFBDecrypter, cipher.NewCFBEncrypter for low-level usage.
func NewCTRStream ¶
NewCTRStream creates a new CTR stream cipher with the given key and iv.
The iv will be used as the initial value for the CTR mode.
It's caller's responsibility to ensure the following:
- The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256.
- The IV must be aes.BlockSize bytes long.
Use SimpleCTRStream if you are not familiar with these. See also: cipher.NewCTR for low-level usage.
func NewOFBStream ¶
NewOFBStream creates a new OFB stream cipher with the given key and iv.
The iv will be used as the initial value for the OFB mode.
It's caller's responsibility to ensure the following:
- The key must be 16, 24, or 32 bytes long to select AES-128, AES-192, or AES-256.
- The IV must be aes.BlockSize bytes long.
Use SimpleOFBStream if you are not familiar with these. See also: cipher.NewOFB for low-level usage.
func SimpleCFBStream ¶
SimpleCFBStream creates a new AES-256-CFB stream cipher from the given key and iv.
An Aes256 key for encryption/decryption will be derived from the arbitrary keyPassphrase string via scrypt.
The iv will be a random value.
See also: NewCFBStream for more control.
func SimpleCTRStream ¶
SimpleCTRStream creates a new AES-256-CTR stream cipher from the given key and iv.
An Aes256 key for encryption/decryption will be derived from the arbitrary keyPassphrase string via scrypt.
The iv will be a random value.
See also: NewCTRStream for more control.
Example ¶
DefaultSalt = func() string { return "NaCl" } key := "my-secret-key" plainText := "Hello, World!" stream := SimpleCTRStream(key) // Encrypting plaintextReader := bytes.NewReader([]byte(plainText)) encryptedBuffer := new(bytes.Buffer) _ = stream.EncryptStream(plaintextReader, encryptedBuffer) encrypted := encryptedBuffer.String() // fmt.Println(encrypted) // Decrypting encryptedReader := bytes.NewReader([]byte(encrypted)) decryptedBuffer := new(bytes.Buffer) _ = stream.DecryptStream(encryptedReader, decryptedBuffer) decrypted := decryptedBuffer.String() fmt.Println(decrypted)
Output: Hello, World!
func SimpleOFBStream ¶
SimpleOFBStream creates a new AES-256-OFB stream cipher from the given key and iv.
An Aes256 key for encryption/decryption will be derived from the arbitrary keyPassphrase string via scrypt.
The iv will be a random value.
See also: NewOFBStream for more control.
type StringCodec ¶
type StringCodec interface { EncodeToString(src []byte) string DecodeString(s string) ([]byte, error) }
StringCodec is an interface that provides encoding and decoding functions for Cipher ciphertexts.
var Base32HexCodec StringCodec = base32Codec{base32.HexEncoding}
Base32HexCodec encodes and decodes using base32 encoding with extended hex alphabet:
- alphabet is "0123456789ABCDEFGHIJKLMNOPQRSTUV"
- padding character is '='
See also: base32.HexEncoding
var Base32StdCodec StringCodec = base32Codec{base32.StdEncoding}
Base32StdCodec encodes and decodes using standard base32 encoding:
- alphabet is "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
- padding character is '='
See also: base32.StdEncoding
var Base64StdCodec StringCodec = base64Codec{base64.StdEncoding}
Base64StdCodec encodes and decodes using standard base64 encoding:
- alphabet is "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
- padding character is '='
See also: base64.StdEncoding
var Base64URLCodec StringCodec = base64Codec{base64.URLEncoding}
Base64URLCodec encodes and decodes using URL-compatible base64 encoding:
- alphabet is "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
- padding character is '='
See also: base64.URLEncoding
var DefaultStringCodec StringCodec = HexCodec
DefaultStringCodec is the default StringCodec used by Cipher implementations. It is set to HexCodec by default.
You can change it to Base64StdCodec, Base64URLCodec, Base32StdCodec, or Base32HexCodec:
simplecipher.DefaultStringCodec = simplecipher.Base64StdCodec ciphertext := simplecipher.SimpleCTR("strong-key").Encrypt("plaintext") fmt.Println(ciphertext) // "YmFzZTY0c2VjcmV0"
If encoding and decoding are not needed, or you want to handle it yourself, set it to NopCodec:
simplecipher.DefaultStringCodec = simplecipher.NopCodec ciphertext := simplecipher.SimpleCTR("strong-key").Encrypt("plaintext") rawCiphertextBytes := []byte(ciphertext) // rawCiphertextBytes is now the ciphertext bytes output by the algorithm without encoding.
See also: HexCodec, Base64StdCodec, Base64URLCodec, Base32StdCodec, Base32HexCodec, NopCodec
var HexCodec StringCodec = hexCodec{}
HexCodec encodes and decodes using hexadecimal encoding:
- alphabet is "0123456789abcdef"
See also: hex.EncodeToString, hex.DecodeString
var NopCodec StringCodec = nopCodec{}
NopCodec does not encode or decode the input. It just converts the type from []byte to string and vice versa.