Files
zitadel/apps/api/internal/crypto/web_key_test.go
2025-08-05 15:20:32 -07:00

270 lines
5.5 KiB
Go

package crypto
import (
"crypto/elliptic"
"testing"
"github.com/go-jose/go-jose/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zitadel/zitadel/internal/zerrors"
)
func TestUnmarshalWebKeyConfig(t *testing.T) {
type args struct {
data []byte
configType WebKeyConfigType
}
tests := []struct {
name string
args args
wantConfig WebKeyConfig
wantErr error
}{
{
name: "unspecified",
args: args{
[]byte(`{}`),
WebKeyConfigTypeUnspecified,
},
wantErr: zerrors.ThrowInternal(nil, "CRYPT-Ii3AiH", "Errors.Internal"),
},
{
name: "rsa",
args: args{
[]byte(`{"bits":"2048", "hasher":"sha256"}`),
WebKeyConfigTypeRSA,
},
wantConfig: &WebKeyRSAConfig{
Bits: RSABits2048,
Hasher: RSAHasherSHA256,
},
},
{
name: "ecdsa",
args: args{
[]byte(`{"curve":"p256"}`),
WebKeyConfigTypeECDSA,
},
wantConfig: &WebKeyECDSAConfig{
Curve: EllipticCurveP256,
},
},
{
name: "ed25519",
args: args{
[]byte(`{}`),
WebKeyConfigTypeED25519,
},
wantConfig: &WebKeyED25519Config{},
},
{
name: "unknown type error",
args: args{
[]byte(`{"curve":0}`),
99,
},
wantErr: zerrors.ThrowInternal(nil, "CRYPT-Eig8ho", "Errors.Internal"),
},
{
name: "unmarshal error",
args: args{
[]byte(`~~`),
WebKeyConfigTypeED25519,
},
wantErr: zerrors.ThrowInternal(nil, "CRYPT-waeR0N", "Errors.Internal"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotConfig, err := UnmarshalWebKeyConfig(tt.args.data, tt.args.configType)
require.ErrorIs(t, err, tt.wantErr)
assert.Equal(t, gotConfig, tt.wantConfig)
})
}
}
func TestWebKeyECDSAConfig_Alg(t *testing.T) {
type fields struct {
Curve EllipticCurve
}
tests := []struct {
name string
fields fields
want jose.SignatureAlgorithm
}{
{
name: "unspecified",
fields: fields{
Curve: EllipticCurveUnspecified,
},
want: "",
},
{
name: "P256",
fields: fields{
Curve: EllipticCurveP256,
},
want: jose.ES256,
},
{
name: "P384",
fields: fields{
Curve: EllipticCurveP384,
},
want: jose.ES384,
},
{
name: "P512",
fields: fields{
Curve: EllipticCurveP512,
},
want: jose.ES512,
},
{
name: "default",
fields: fields{
Curve: 99,
},
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := WebKeyECDSAConfig{
Curve: tt.fields.Curve,
}
got := c.Alg()
assert.Equal(t, tt.want, got)
})
}
}
func TestWebKeyECDSAConfig_GetCurve(t *testing.T) {
type fields struct {
Curve EllipticCurve
}
tests := []struct {
name string
fields fields
want elliptic.Curve
}{
{
name: "unspecified",
fields: fields{EllipticCurveUnspecified},
want: nil,
},
{
name: "P256",
fields: fields{EllipticCurveP256},
want: elliptic.P256(),
},
{
name: "P384",
fields: fields{EllipticCurveP384},
want: elliptic.P384(),
},
{
name: "P512",
fields: fields{EllipticCurveP512},
want: elliptic.P521(),
},
{
name: "default",
fields: fields{99},
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := WebKeyECDSAConfig{
Curve: tt.fields.Curve,
}
got := c.GetCurve()
assert.Equal(t, tt.want, got)
})
}
}
func Test_generateEncryptedWebKey(t *testing.T) {
type args struct {
keyID string
genConfig WebKeyConfig
}
tests := []struct {
name string
args args
assertPrivate func(t *testing.T, got *jose.JSONWebKey)
assertPublic func(t *testing.T, got *jose.JSONWebKey)
wantErr error
}{
{
name: "invalid",
args: args{
keyID: "keyID",
genConfig: &WebKeyRSAConfig{
Bits: RSABitsUnspecified,
Hasher: RSAHasherSHA256,
},
},
wantErr: zerrors.ThrowInvalidArgument(nil, "CRYPTO-eaz3T", "Errors.WebKey.Config"),
},
{
name: "RSA",
args: args{
keyID: "keyID",
genConfig: &WebKeyRSAConfig{
Bits: RSABits2048,
Hasher: RSAHasherSHA256,
},
},
assertPrivate: assertJSONWebKey("keyID", "RS256", "sig", false),
assertPublic: assertJSONWebKey("keyID", "RS256", "sig", true),
},
{
name: "ECDSA",
args: args{
keyID: "keyID",
genConfig: &WebKeyECDSAConfig{
Curve: EllipticCurveP256,
},
},
assertPrivate: assertJSONWebKey("keyID", "ES256", "sig", false),
assertPublic: assertJSONWebKey("keyID", "ES256", "sig", true),
},
{
name: "ED25519",
args: args{
keyID: "keyID",
genConfig: &WebKeyED25519Config{},
},
assertPrivate: assertJSONWebKey("keyID", "EdDSA", "sig", false),
assertPublic: assertJSONWebKey("keyID", "EdDSA", "sig", true),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotPrivate, gotPublic, err := generateWebKey(tt.args.keyID, tt.args.genConfig)
require.ErrorIs(t, err, tt.wantErr)
if tt.assertPrivate != nil {
tt.assertPrivate(t, gotPrivate)
}
if tt.assertPublic != nil {
tt.assertPublic(t, gotPublic)
}
})
}
}
func assertJSONWebKey(keyID, algorithm, use string, isPublic bool) func(t *testing.T, got *jose.JSONWebKey) {
return func(t *testing.T, got *jose.JSONWebKey) {
assert.NotNil(t, got)
assert.NotNil(t, got.Key, "key")
assert.Equal(t, keyID, got.KeyID, "keyID")
assert.Equal(t, algorithm, got.Algorithm, "algorithm")
assert.Equal(t, use, got.Use, "user")
assert.Equal(t, isPublic, got.IsPublic(), "isPublic")
}
}