1
0
Fork 0
mirror of https://github.com/Luzifer/go-openssl.git synced 2024-10-29 18:59:43 +00:00
go-openssl/openssl_test.go
Knut Ahlers 77069a53d0
Fix linter errors, simplify tests
Signed-off-by: Knut Ahlers <knut@ahlers.me>
2023-08-22 14:13:51 +02:00

349 lines
8.7 KiB
Go

package openssl
import (
"bytes"
"fmt"
"os/exec"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
testPassphrase = "z4yH36a6zerhfE5427ZV" //#nosec G101 -- Is hardcoded passphrase but only for testing purposes
testPlaintext = "hallowelt"
)
var testTable = []struct {
tName string
tMdParam string
tMdFunc CredsGenerator
tPBKDF bool
}{
{"MD5", "md5", BytesToKeyMD5, false},
{"SHA1", "sha1", BytesToKeySHA1, false},
{"SHA256", "sha256", BytesToKeySHA256, false},
{"SHA384", "sha384", BytesToKeySHA384, false},
{"SHA512", "sha512", BytesToKeySHA512, false},
{"PBKDF2_MD5", "md5", PBKDF2MD5, true},
{"PBKDF2_SHA1", "sha1", PBKDF2SHA1, true},
{"PBKDF2_SHA256", "sha256", PBKDF2SHA256, true},
{"PBKDF2_SHA384", "sha384", PBKDF2SHA384, true},
{"PBKDF2_SHA512", "sha512", PBKDF2SHA512, true},
}
func TestBinaryEncryptToDecryptWithCustomSalt(t *testing.T) {
salt := []byte("saltsalt")
o := New()
enc, err := o.EncryptBinaryBytesWithSaltAndDigestFunc(testPassphrase, salt, []byte(testPlaintext), BytesToKeySHA256)
require.NoError(t, err)
dec, err := o.DecryptBinaryBytes(testPassphrase, enc, BytesToKeySHA256)
require.NoError(t, err)
assert.Equal(t, testPlaintext, string(dec))
}
func TestBinaryEncryptToDecrypt(t *testing.T) {
o := New()
enc, err := o.EncryptBinaryBytes(testPassphrase, []byte(testPlaintext), BytesToKeySHA256)
require.NoError(t, err)
dec, err := o.DecryptBinaryBytes(testPassphrase, enc, BytesToKeySHA256)
require.NoError(t, err)
assert.Equal(t, testPlaintext, string(dec))
}
func TestBinaryEncryptToOpenSSL(t *testing.T) {
o := New()
for _, tc := range testTable {
t.Run(tc.tName, func(t *testing.T) {
salt, err := o.GenerateSalt()
require.NoError(t, err)
enc, err := o.EncryptBinaryBytesWithSaltAndDigestFunc(testPassphrase, salt, []byte(testPlaintext), tc.tMdFunc)
require.NoError(t, err)
// Need to specify /dev/stdin as file so that we can pass in binary
// data to openssl without creating a file
cmdArgs := []string{
"openssl", "aes-256-cbc",
"-d",
"-pass", fmt.Sprintf("pass:%s", testPassphrase),
"-md", tc.tMdParam,
"-in", "/dev/stdin",
}
if tc.tPBKDF {
cmdArgs = append(cmdArgs, "-pbkdf2")
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) //#nosec:G204 -- Hardcoded tests, this is fine
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stdin = bytes.NewBuffer(enc)
err = cmd.Run()
require.NoError(t, err)
assert.Equal(t, testPlaintext, out.String())
})
}
}
func TestBinaryEncryptWithSaltShouldHaveSameOutput(t *testing.T) {
plaintext := "outputshouldbesame"
passphrase := "passphrasesupersecure"
salt := []byte("saltsalt")
o := New()
enc1, err := o.EncryptBinaryBytesWithSaltAndDigestFunc(passphrase, salt, []byte(plaintext), BytesToKeySHA256)
require.NoError(t, err)
enc2, err := o.EncryptBinaryBytesWithSaltAndDigestFunc(passphrase, salt, []byte(plaintext), BytesToKeySHA256)
require.NoError(t, err)
assert.Equal(t, enc1, enc2)
}
func TestDecryptBinaryFromString(t *testing.T) {
o := New()
for _, tc := range testTable {
t.Run(tc.tName, func(t *testing.T) {
var out bytes.Buffer
cmdArgs := []string{
"openssl", "aes-256-cbc",
"-pass", fmt.Sprintf("pass:%s", testPassphrase),
"-md", tc.tMdParam,
"-in", "/dev/stdin",
}
if tc.tPBKDF {
cmdArgs = append(cmdArgs, "-pbkdf2")
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) //#nosec:G204 -- Hardcoded tests, this is fine
cmd.Stdout = &out
cmd.Stdin = strings.NewReader(testPlaintext)
require.NoError(t, cmd.Run())
data, err := o.DecryptBinaryBytes(testPassphrase, out.Bytes(), tc.tMdFunc)
require.NoError(t, err)
if !assert.Equal(t, testPlaintext, string(data)) {
t.Logf("Data: %s\nPlaintext: %s", string(data), testPlaintext)
}
})
}
}
func TestDecryptFromString(t *testing.T) {
o := New()
for _, tc := range testTable {
t.Run(tc.tName, func(t *testing.T) {
var out bytes.Buffer
cmdArgs := []string{
"openssl", "aes-256-cbc",
"-base64",
"-pass", fmt.Sprintf("pass:%s", testPassphrase),
"-md", tc.tMdParam,
}
if tc.tPBKDF {
cmdArgs = append(cmdArgs, "-pbkdf2")
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) //#nosec:G204 -- Hardcoded tests, this is fine
cmd.Stdout = &out
cmd.Stdin = strings.NewReader(testPlaintext)
require.NoError(t, cmd.Run())
data, err := o.DecryptBytes(testPassphrase, out.Bytes(), tc.tMdFunc)
require.NoError(t, err)
if !assert.Equal(t, testPlaintext, string(data)) {
t.Logf("Data: %s\nPlaintext: %s", string(data), testPlaintext)
}
})
}
}
func TestEncryptToDecrypt(t *testing.T) {
o := New()
enc, err := o.EncryptBytes(testPassphrase, []byte(testPlaintext), BytesToKeySHA256)
require.NoError(t, err)
dec, err := o.DecryptBytes(testPassphrase, enc, BytesToKeySHA256)
require.NoError(t, err)
assert.Equal(t, testPlaintext, string(dec))
}
func TestEncryptToDecryptWithCustomSalt(t *testing.T) {
salt := []byte("saltsalt")
o := New()
enc, err := o.EncryptBytesWithSaltAndDigestFunc(testPassphrase, salt, []byte(testPlaintext), BytesToKeySHA256)
require.NoError(t, err)
dec, err := o.DecryptBytes(testPassphrase, enc, BytesToKeySHA256)
require.NoError(t, err)
assert.Equal(t, testPlaintext, string(dec))
}
func TestEncryptToOpenSSL(t *testing.T) {
for _, tc := range testTable {
t.Run(tc.tName, func(t *testing.T) {
o := New()
salt, err := o.GenerateSalt()
require.NoError(t, err)
enc, err := o.EncryptBytesWithSaltAndDigestFunc(testPassphrase, salt, []byte(testPlaintext), tc.tMdFunc)
require.NoError(t, err)
enc = append(enc, '\n')
var out bytes.Buffer
cmdArgs := []string{
"openssl", "aes-256-cbc",
"-base64", "-d",
"-pass", fmt.Sprintf("pass:%s", testPassphrase),
"-md", tc.tMdParam,
"-in", "/dev/stdin",
}
if tc.tPBKDF {
cmdArgs = append(cmdArgs, "-pbkdf2")
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) //#nosec:G204 -- Hardcoded tests, this is fine
cmd.Stdout = &out
cmd.Stdin = bytes.NewReader(enc)
require.NoError(t, cmd.Run())
assert.Equal(t, testPlaintext, out.String())
})
}
}
func TestEncryptWithSaltShouldHaveSameOutput(t *testing.T) {
plaintext := "outputshouldbesame"
passphrase := "passphrasesupersecure"
salt := []byte("saltsalt")
o := New()
enc1, err := o.EncryptBytesWithSaltAndDigestFunc(passphrase, salt, []byte(plaintext), BytesToKeySHA256)
require.NoError(t, err)
enc2, err := o.EncryptBytesWithSaltAndDigestFunc(passphrase, salt, []byte(plaintext), BytesToKeySHA256)
require.NoError(t, err)
assert.Equal(t, enc1, enc2)
}
func TestGenerateSalt(t *testing.T) {
knownSalts := [][]byte{}
o := New()
for i := 0; i < 1000; i++ {
salt, err := o.GenerateSalt()
require.NoError(t, err)
for _, ks := range knownSalts {
assert.NotEqual(t, ks, salt)
knownSalts = append(knownSalts, salt)
}
}
}
func TestSaltValidation(t *testing.T) {
var err error
o := New()
_, err = o.EncryptBytesWithSaltAndDigestFunc(testPassphrase, []byte("12345"), []byte(testPlaintext), BytesToKeySHA256)
assert.ErrorIs(t, err, ErrInvalidSalt)
_, err = o.EncryptBytesWithSaltAndDigestFunc(testPassphrase, []byte("1234567890"), []byte(testPlaintext), BytesToKeySHA256)
assert.ErrorIs(t, err, ErrInvalidSalt)
_, err = o.EncryptBytesWithSaltAndDigestFunc(testPassphrase, []byte{0xcb, 0xd5, 0x1a, 0x3, 0x84, 0xba, 0xa8, 0xc8}, []byte(testPlaintext), BytesToKeySHA256)
assert.NoError(t, err)
}
//
// Benchmarks
//
func benchmarkDecrypt(ciphertext []byte, cg CredsGenerator, b *testing.B) {
o := New()
for n := 0; n < b.N; n++ {
_, err := o.DecryptBytes(testPassphrase, ciphertext, cg)
require.NoError(b, err)
}
}
func BenchmarkDecryptMD5(b *testing.B) {
benchmarkDecrypt([]byte("U2FsdGVkX19ZM5qQJGe/d5A/4pccgH+arBGTp+QnWPU="), BytesToKeyMD5, b)
}
func BenchmarkDecryptSHA1(b *testing.B) {
benchmarkDecrypt([]byte("U2FsdGVkX1/Yy9kegseq2Ewd4UvjFYCpIEA1cltTA1Q="), BytesToKeySHA1, b)
}
func BenchmarkDecryptSHA256(b *testing.B) {
benchmarkDecrypt([]byte("U2FsdGVkX1+O68d7BO9ibP8nB5+xtb/27IHlyjJWpl8="), BytesToKeySHA256, b)
}
func benchmarkEncrypt(plaintext string, cg CredsGenerator, b *testing.B) {
o := New()
salt, _ := o.GenerateSalt()
for n := 0; n < b.N; n++ {
_, err := o.EncryptBytesWithSaltAndDigestFunc(testPassphrase, salt, []byte(plaintext), cg)
require.NoError(b, err)
}
}
func BenchmarkEncryptMD5(b *testing.B) {
benchmarkEncrypt(testPlaintext, BytesToKeyMD5, b)
}
func BenchmarkEncryptSHA1(b *testing.B) {
benchmarkEncrypt(testPlaintext, BytesToKeySHA1, b)
}
func BenchmarkEncryptSHA256(b *testing.B) {
benchmarkEncrypt(testPlaintext, BytesToKeySHA256, b)
}
func BenchmarkGenerateSalt(b *testing.B) {
o := New()
for n := 0; n < b.N; n++ {
_, err := o.GenerateSalt()
require.NoError(b, err)
}
}