1
0
Fork 0
telegraf/plugins/secretstores/http/aes_test.go

320 lines
8.5 KiB
Go
Raw Permalink Normal View History

package http
import (
"encoding/hex"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/config"
)
func TestAES(t *testing.T) {
keySource := hex.EncodeToString([]byte("0123456789abcdefghijklmnopqrstuvwxyz"))
expected := "my $ecret-Passw0rd"
iv := hex.EncodeToString([]byte("0123456789abcdef"))
tests := []struct {
cipher string
encrypted string
key string
}{
{
cipher: "AES128/CBC/PKCS#5",
encrypted: "9E36B490B0B1D6CE28550DF9DE65FC0013FF9F0939E24DA4A24324BDB5EABA04",
key: keySource[:32],
},
{
cipher: "AES192/CBC/PKCS#5",
encrypted: "D3A5A0004B6783351F89B00C1D4154EDF2321EDAD3111B5551C18836B9FCFD62",
key: keySource[:48],
},
{
cipher: "AES256/CBC/PKCS#5",
encrypted: "9751D7FB4B1497DEBC8A95C5D88097ECB1B8E63979E2D41E7ECD304D6B39B808",
key: keySource[:64],
},
}
for _, tt := range tests {
t.Run(tt.cipher, func(t *testing.T) {
decrypter := AesEncryptor{
Variant: strings.Split(tt.cipher, "/"),
Key: config.NewSecret([]byte(tt.key)),
Vec: config.NewSecret([]byte(iv)),
}
require.NoError(t, decrypter.Init())
enc, err := hex.DecodeString(tt.encrypted)
require.NoError(t, err)
dec, err := decrypter.Decrypt(enc)
require.NoError(t, err)
require.Equal(t, expected, string(dec))
})
}
}
func TestAESNoPadding(t *testing.T) {
keySource := hex.EncodeToString([]byte("0123456789abcdefghijklmnopqrstuvwxyz"))
expected := "my $ecret-Passw0rd"
iv := hex.EncodeToString([]byte("0123456789abcdef"))
tests := []struct {
cipher string
encrypted string
key string
}{
{
cipher: "AES128/CBC",
encrypted: "9E36B490B0B1D6CE28550DF9DE65FC0013FF9F0939E24DA4A24324BDB5EABA04",
key: keySource[:32],
},
{
cipher: "AES192/CBC",
encrypted: "D3A5A0004B6783351F89B00C1D4154EDF2321EDAD3111B5551C18836B9FCFD62",
key: keySource[:48],
},
{
cipher: "AES256/CBC",
encrypted: "9751D7FB4B1497DEBC8A95C5D88097ECB1B8E63979E2D41E7ECD304D6B39B808",
key: keySource[:64],
},
}
for _, tt := range tests {
t.Run(tt.cipher, func(t *testing.T) {
decrypter := AesEncryptor{
Variant: strings.Split(tt.cipher, "/"),
Key: config.NewSecret([]byte(tt.key)),
Vec: config.NewSecret([]byte(iv)),
}
require.NoError(t, decrypter.Init())
enc, err := hex.DecodeString(tt.encrypted)
require.NoError(t, err)
dec, err := decrypter.Decrypt(enc)
require.NoError(t, err)
require.Len(t, string(dec), 32)
require.Contains(t, string(dec), expected)
})
}
}
func TestAESKDF(t *testing.T) {
expected := "my $ecret-Passw0rd"
iv := hex.EncodeToString([]byte("asupersecretiv42"))
tests := []struct {
cipher string
password string
salt string
iterations int
encrypted string
}{
{
cipher: "AES256/CBC/PKCS#5",
password: "a secret password",
salt: "somerandombytes",
iterations: 2000,
encrypted: "224b169206ce918f167ae0da18f4de45bede0d2c853d45e55f1422d1446037bf",
},
}
for _, tt := range tests {
t.Run(tt.cipher, func(t *testing.T) {
decrypter := AesEncryptor{
Variant: strings.Split(tt.cipher, "/"),
KDFConfig: KDFConfig{
Algorithm: "PBKDF2-HMAC-SHA256",
Passwd: config.NewSecret([]byte(tt.password)),
Salt: config.NewSecret([]byte(tt.salt)),
Iterations: tt.iterations,
},
Vec: config.NewSecret([]byte(iv)),
}
require.NoError(t, decrypter.Init())
enc, err := hex.DecodeString(tt.encrypted)
require.NoError(t, err)
dec, err := decrypter.Decrypt(enc)
require.NoError(t, err)
require.Equal(t, expected, string(dec))
})
}
}
func TestAESInitErrors(t *testing.T) {
tests := []struct {
name string
variant []string
key string
iv string
kdfcfg *KDFConfig
expected string
}{
{
name: "no mode",
variant: []string{"AES128"},
expected: "please specify cipher mode",
},
{
name: "too many elements",
variant: []string{"AES128", "CBC", "PKCS#5", "superfluous"},
expected: "too many variant elements",
},
{
name: "no AES",
variant: []string{"rsa", "cbc"},
expected: `requested AES but specified "rsa"`,
},
{
name: "no cipher",
expected: "please specify cipher",
},
{
name: "unsupported cipher",
variant: []string{"aes64", "cbc"},
expected: "unsupported AES cipher",
},
{
name: "unsupported mode",
variant: []string{"aes128", "foo"},
expected: "unsupported cipher mode",
},
{
name: "unsupported padding",
variant: []string{"aes128", "cbc", "bar"},
expected: "unsupported padding",
},
{
name: "missing key",
variant: []string{"aes128", "cbc", "none"},
expected: "either key or password has to be specified",
},
{
name: "wrong key length",
variant: []string{"aes256", "cbc"},
key: "63238c069e3c5d6aaa20048c43ce4ed0",
expected: "key length (128 bit) does not match cipher (256 bit)",
},
{
name: "invalid key",
variant: []string{"aes256", "cbc"},
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
expected: "decoding key failed: encoding/hex: invalid byte: U+0078 'x'",
},
{
name: "missing IV",
variant: []string{"aes128", "cbc"},
key: "63238c069e3c5d6aaa20048c43ce4ed0",
expected: "'init_vector' has to be specified or derived from password",
},
{
name: "invalid IV",
variant: []string{"aes128", "cbc"},
key: "63238c069e3c5d6aaa20048c43ce4ed0",
iv: "abcd",
expected: "init vector size must match block size",
},
{
name: "missing salt and iterations",
variant: []string{"aes128", "cbc", "none"},
kdfcfg: &KDFConfig{
Passwd: config.NewSecret([]byte("secret")),
},
expected: "salt and iterations required for password-based-keys",
},
{
name: "wrong keygen algorithm",
variant: []string{"aes128", "cbc", "none"},
kdfcfg: &KDFConfig{
Algorithm: "foo",
Passwd: config.NewSecret([]byte("secret")),
Salt: config.NewSecret([]byte("salt")),
Iterations: 2000,
},
expected: "unknown key-derivation function",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.NotEmpty(t, tt.expected)
decrypter := AesEncryptor{
Variant: tt.variant,
}
if tt.key != "" {
decrypter.Key = config.NewSecret([]byte(tt.key))
}
if tt.iv != "" {
decrypter.Vec = config.NewSecret([]byte(tt.iv))
}
if tt.kdfcfg != nil {
decrypter.KDFConfig = *tt.kdfcfg
}
require.ErrorContains(t, decrypter.Init(), tt.expected)
})
}
}
func TestAESDecryptError(t *testing.T) {
tests := []struct {
name string
encrypted string
messMode string
messKey string
messIV string
expected string
}{
{
name: "wrong data length",
encrypted: "abcd",
expected: "invalid data size",
},
{
name: "mode tampered",
encrypted: "9E36B490B0B1D6CE28550DF9DE65FC0013FF9F0939E24DA4A24324BDB5EABA04",
messMode: "tampered",
expected: `unsupported cipher mode "tampered"`,
},
{
name: "invalid key",
encrypted: "9E36B490B0B1D6CE28550DF9DE65FC0013FF9F0939E24DA4A24324BDB5EABA04",
messKey: "tampered",
expected: "decoding key failed: encoding/hex: invalid byte: U+0074 't'",
},
{
name: "wrong key length",
encrypted: "9E36B490B0B1D6CE28550DF9DE65FC0013FF9F0939E24DA4A24324BDB5EABA04",
messKey: "01234567",
expected: "creating AES cipher failed: crypto/aes: invalid key size",
},
{
name: "invalid key",
encrypted: "9E36B490B0B1D6CE28550DF9DE65FC0013FF9F0939E24DA4A24324BDB5EABA04",
messIV: "tampered",
expected: "decoding init vector failed: encoding/hex: invalid byte: U+0074 't'",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require.NotEmpty(t, tt.expected)
decrypter := AesEncryptor{
Variant: []string{"AES128", "CBC", "PKCS#5"},
Key: config.NewSecret([]byte(hex.EncodeToString([]byte("0123456789abcdef")))),
Vec: config.NewSecret([]byte(hex.EncodeToString([]byte("0123456789abcdef")))),
}
require.NoError(t, decrypter.Init())
enc, err := hex.DecodeString(tt.encrypted)
require.NoError(t, err)
// Mess with the internal values for testing
if tt.messMode != "" {
decrypter.mode = tt.messMode
}
if tt.messKey != "" {
decrypter.Key = config.NewSecret([]byte(tt.messKey))
}
if tt.messIV != "" {
decrypter.Vec = config.NewSecret([]byte(tt.messIV))
}
_, err = decrypter.Decrypt(enc)
require.ErrorContains(t, err, tt.expected)
})
}
}