1
0
Fork 0
mirror of https://github.com/Luzifer/go-openssl.git synced 2024-12-20 19:01:18 +00:00

Add salt validation and improve comments

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2017-09-18 15:49:33 +02:00
parent 317731a683
commit 54263e5c8a
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
2 changed files with 38 additions and 5 deletions

View file

@ -7,10 +7,13 @@ import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"io"
)
var ErrInvalidSalt = errors.New("Salt needs to have exactly 8 byte")
// OpenSSL is a helper to generate OpenSSL compatible encryption
// with autmatic IV derivation and storage. As long as the key is known all
// data can also get decrypted using OpenSSL CLI.
@ -70,8 +73,9 @@ func (o *OpenSSL) decrypt(key, iv, data []byte) ([]byte, error) {
}
// EncryptString encrypts a string in a manner compatible to OpenSSL encryption
// functions using AES-256-CBC as encryption algorithm. Generating salt.
func (o *OpenSSL) EncryptString(passphrase string, plaintextString string) ([]byte, error) {
// functions using AES-256-CBC as encryption algorithm. This function generates
// a random salt on every execution.
func (o *OpenSSL) EncryptString(passphrase, plaintextString string) ([]byte, error) {
salt := make([]byte, 8) // Generate an 8 byte salt
_, err := io.ReadFull(rand.Reader, salt)
if err != nil {
@ -81,10 +85,20 @@ func (o *OpenSSL) EncryptString(passphrase string, plaintextString string) ([]by
return o.EncryptStringWithSalt(passphrase, salt, plaintextString)
}
// EncryptString encrypts a string in a manner compatible to OpenSSL encryption
// functions using AES-256-CBC as encryption algorithm. Ability to pass custom
// salt.
// EncryptStringWithSalt encrypts a string in a manner compatible to OpenSSL
// encryption functions using AES-256-CBC as encryption algorithm. The salt
// needs to be passed in here which ensures the same result on every execution
// on cost of a much weaker encryption as with EncryptString.
//
// The salt passed into this function needs to have exactly 8 byte.
//
// If you don't have a good reason to use this, please don't! For more information
// see this: https://en.wikipedia.org/wiki/Salt_(cryptography)#Common_mistakes
func (o *OpenSSL) EncryptStringWithSalt(passphrase string, salt []byte, plaintextString string) ([]byte, error) {
if len(salt) != 8 {
return nil, ErrInvalidSalt
}
data := make([]byte, len(plaintextString)+aes.BlockSize)
copy(data[0:], o.openSSLSaltHeader)
copy(data[8:], salt)

View file

@ -119,3 +119,22 @@ func TestEncryptToOpenSSL(t *testing.T) {
t.Errorf("OpenSSL output did not match input.\nOutput was: %s", out.String())
}
}
func TestSaltValidation(t *testing.T) {
plaintext := "hallowelt"
passphrase := "z4yH36a6zerhfE5427ZV"
o := New()
if _, err := o.EncryptStringWithSalt(passphrase, []byte("12345"), plaintext); err != ErrInvalidSalt {
t.Errorf("5-character salt was accepted, needs to have 8 character")
}
if _, err := o.EncryptStringWithSalt(passphrase, []byte("1234567890"), plaintext); err != ErrInvalidSalt {
t.Errorf("10-character salt was accepted, needs to have 8 character")
}
if _, err := o.EncryptStringWithSalt(passphrase, []byte{0xcb, 0xd5, 0x1a, 0x3, 0x84, 0xba, 0xa8, 0xc8}, plaintext); err == ErrInvalidSalt {
t.Errorf("Salt with 8 byte unprintable characters was not accepted")
}
}