You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/libs/crypto/hmac_sha256_test.go

182 lines
5.0 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package crypto
import (
"context"
"crypto/ed25519"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"io"
"testing"
wrapping "github.com/hashicorp/go-kms-wrapping/v2"
"github.com/mr-tron/base58"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/blake2b"
)
func Test_HmacSha256(t *testing.T) {
testCtx := context.Background()
testWrapper := TestWrapper(t)
tests := []struct {
name string
data []byte
wrapper wrapping.Wrapper
salt []byte
info []byte
opts []Option
wantHmac string
wantErr bool
wantErrIs error
}{
{
name: "missing data",
wrapper: testWrapper,
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "missing wrapper",
data: []byte("test"),
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "prk-and-ed25519",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrk([]byte("prk")), WithEd25519()},
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "prk-and-wrapper",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrk([]byte("prk")), WithEd25519()},
wantErr: true,
wantErrIs: ErrInvalidParameter,
},
{
name: "blake2b-with-prefix",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrefix("prefix:")},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:")),
},
{
name: "blake2b-with-prefix-with-base64",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrefix("prefix:"), WithBase64Encoding()},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:"), WithBase64Encoding()),
},
{
name: "blake2b-with-prefix-with-base58",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithPrefix("prefix:"), WithBase58Encoding()},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrefix("prefix:"), WithBase58Encoding()),
},
{
name: "with-prk",
data: []byte("test"),
opts: []Option{WithPrk([]byte("prk-0123456789012345678901234567890"))},
wantHmac: testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrk([]byte("prk-0123456789012345678901234567890"))),
},
{
name: "withEd25519",
data: []byte("test"),
wrapper: testWrapper,
opts: []Option{WithEd25519()},
wantHmac: testWithEd25519(t, []byte("test"), testWrapper, nil, nil),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
hm, err := HmacSha256(testCtx, tt.data, tt.wrapper, tt.salt, tt.info, tt.opts...)
if tt.wantErr {
require.Error(err)
if tt.wantErrIs != nil {
assert.ErrorIs(err, tt.wantErrIs)
}
return
}
require.NoError(err)
assert.Equal(tt.wantHmac, hm)
})
}
t.Run("HmacSha256WithPrk", func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
hm, err := HmacSha256WithPrk(testCtx, []byte("test"), []byte("prk-0123456789012345678901234567890"))
require.NoError(err)
want := testWithBlake2b(t, []byte("test"), testWrapper, nil, nil, WithPrk([]byte("prk-0123456789012345678901234567890")))
assert.Equal(want, hm)
})
}
func testWithEd25519(t *testing.T, data []byte, w wrapping.Wrapper, salt, info []byte, opt ...Option) string {
t.Helper()
require := require.New(t)
reader, err := NewDerivedReader(context.Background(), w, 32, salt, info)
require.NoError(err)
edKey, _, err := ed25519.GenerateKey(reader)
require.NoError(err)
var key [32]byte
n := copy(key[:], edKey)
require.Equal(n, 32)
return testHmac(t, key[:], data, opt...)
}
func testWithBlake2b(t *testing.T, data []byte, w wrapping.Wrapper, salt, info []byte, opt ...Option) string {
t.Helper()
require := require.New(t)
require.NotNil(data)
require.NotNil(w)
opts, err := getOpts(opt...)
require.NoError(err)
var key [32]byte
switch {
case opts.withPrk != nil:
key = blake2b.Sum256(opts.withPrk)
default:
reader, err := NewDerivedReader(context.Background(), w, 32, salt, info)
require.NoError(err)
readerKey := make([]byte, 32)
n, err := io.ReadFull(reader, readerKey)
require.NoError(err)
require.Equal(n, 32)
key = blake2b.Sum256(readerKey)
}
return testHmac(t, key[:], data, opt...)
}
func testHmac(t *testing.T, key, data []byte, opt ...Option) string {
t.Helper()
require := require.New(t)
mac := hmac.New(sha256.New, key)
_, _ = mac.Write(data)
hmac := mac.Sum(nil)
var hmacString string
opts, err := getOpts(opt...)
require.NoError(err)
switch {
case opts.withBase64Encoding:
hmacString = base64.RawURLEncoding.EncodeToString(hmac)
case opts.withBase58Encoding:
hmacString = base58.Encode(hmac)
default:
hmacString = string(hmac)
}
if opts.withPrefix != "" {
return opts.withPrefix + hmacString
}
return hmacString
}