From c9511367b5c006268c26ead17c400145428c5875 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Thu, 15 Feb 2024 14:38:55 +0100 Subject: [PATCH 1/2] feat: add rsa support for jwk --- doc/jose/jwk/jwksupport/jwk.go | 13 ++++++++++- doc/jose/jwk/jwksupport/jwk_test.go | 34 +++++++++++++++++++++++++++++ spi/crypto/crypto.go | 2 ++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/doc/jose/jwk/jwksupport/jwk.go b/doc/jose/jwk/jwksupport/jwk.go index 9c2f253..e1417d3 100644 --- a/doc/jose/jwk/jwksupport/jwk.go +++ b/doc/jose/jwk/jwksupport/jwk.go @@ -10,6 +10,7 @@ import ( "crypto/ecdsa" "crypto/ed25519" "crypto/elliptic" + "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" @@ -99,6 +100,12 @@ func PubKeyBytesToKey(bytes []byte, keyType kms.KeyType) (interface{}, error) { } return ecKey, nil + case kms.RSARS256, kms.RSAPS256: + pubKeyRsa, err := x509.ParsePKIXPublicKey(bytes) + if err != nil { + return nil, errors.New("rsa: invalid public key") + } + return pubKeyRsa, nil case kms.ECDSASecp256k1TypeDER: return parseSecp256k1DER(bytes) case kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType: @@ -165,7 +172,8 @@ func PubKeyBytesToJWK(bytes []byte, keyType kms.KeyType) (*jwk.JWK, error) { kms.ECDSASecp256k1TypeIEEEP1363, kms.ECDSASecp256k1TypeDER, kms.ECDSAP256TypeIEEEP1363, kms.ECDSAP384TypeIEEEP1363, kms.ECDSAP521TypeIEEEP1363, kms.ECDSAP256TypeDER, kms.ECDSAP384TypeDER, kms.ECDSAP521TypeDER, - kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType: + kms.NISTP256ECDHKWType, kms.NISTP384ECDHKWType, kms.NISTP521ECDHKWType, + kms.RSARS256, kms.RSAPS256: key, err := PubKeyBytesToKey(bytes, keyType) if err != nil { return nil, err @@ -246,6 +254,9 @@ func PublicKeyFromJWK(jwkKey *jwk.JWK) (*cryptoapi.PublicKey, error) { pubKey.X = bbsKey case ed25519.PublicKey: pubKey.X = key + case *rsa.PublicKey: + pubKey.N = key.N.Bytes() + pubKey.E = big.NewInt(int64(key.E)).Bytes() case ed25519.PrivateKey: var ok bool diff --git a/doc/jose/jwk/jwksupport/jwk_test.go b/doc/jose/jwk/jwksupport/jwk_test.go index 5d9b153..a9a3eae 100644 --- a/doc/jose/jwk/jwksupport/jwk_test.go +++ b/doc/jose/jwk/jwksupport/jwk_test.go @@ -11,6 +11,7 @@ import ( "crypto/ed25519" "crypto/elliptic" "crypto/rand" + "crypto/rsa" "crypto/sha256" "crypto/x509" "crypto/x509/pkix" @@ -433,6 +434,21 @@ func TestPubKeyBytesToKey(t *testing.T) { }, expectType: &ecdsa.PublicKey{}, }, + { + keyTypes: []kms.KeyType{ + kms.RSARS256, + kms.RSAPS256, + }, + getKey: func(keyType kms.KeyType) ([]byte, error) { + key, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, err + } + + return x509.MarshalPKIXPublicKey(&key.PublicKey) + }, + expectType: &rsa.PublicKey{}, + }, { keyTypes: []kms.KeyType{ kms.ECDSASecp256k1TypeDER, @@ -844,6 +860,24 @@ func TestPublicKeyFromJWK(t *testing.T) { }) } +func TestRSAKey(t *testing.T) { + key, err := rsa.GenerateKey(rand.Reader, 2048) + require.NoError(t, err) + + pubBytes, err := x509.MarshalPKIXPublicKey(&key.PublicKey) + require.NoError(t, err) + + resultJWK, err := PubKeyBytesToJWK(pubBytes, kms.RSARS256) + require.NoError(t, err) + + pb, err := PublicKeyFromJWK(resultJWK) + require.NoError(t, err) + require.NotNil(t, pb) + require.NotNil(t, pb.N) + require.NotNil(t, pb.E) + require.Equal(t, "RSA", pb.Type) +} + type PublicKeyInfo struct { Raw asn1.RawContent Algorithm pkix.AlgorithmIdentifier diff --git a/spi/crypto/crypto.go b/spi/crypto/crypto.go index 5e616ca..ccb2cbc 100644 --- a/spi/crypto/crypto.go +++ b/spi/crypto/crypto.go @@ -100,6 +100,8 @@ type RecipientWrappedKey struct { type PublicKey struct { KID string `json:"kid,omitempty"` X []byte `json:"x,omitempty"` + N []byte `json:"n,omitempty"` + E []byte `json:"e,omitempty"` Y []byte `json:"y,omitempty"` Curve string `json:"curve,omitempty"` Type string `json:"type,omitempty"` From 19ff5e2ba7bc8d97465267d85a85d8d79773b783 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Thu, 15 Feb 2024 14:43:47 +0100 Subject: [PATCH 2/2] fix: lint --- doc/jose/jwk/jwksupport/jwk.go | 3 ++- doc/jose/jwk/jwksupport/jwk_test.go | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/jose/jwk/jwksupport/jwk.go b/doc/jose/jwk/jwksupport/jwk.go index e1417d3..f9e85c4 100644 --- a/doc/jose/jwk/jwksupport/jwk.go +++ b/doc/jose/jwk/jwksupport/jwk.go @@ -63,7 +63,7 @@ func JWKFromKey(opaqueKey interface{}) (*jwk.JWK, error) { // PubKeyBytesToKey creates an opaque key struct from the given public key bytes. // It's e.g. *ecdsa.PublicKey, *ecdsa.PrivateKey, ed25519.VerificationMethod, *bbs12381g2pub.PrivateKey or // *bbs12381g2pub.PublicKey. -func PubKeyBytesToKey(bytes []byte, keyType kms.KeyType) (interface{}, error) { // nolint:gocyclo +func PubKeyBytesToKey(bytes []byte, keyType kms.KeyType) (interface{}, error) { // nolint:gocyclo,funlen switch keyType { case kms.ED25519Type: return ed25519.PublicKey(bytes), nil @@ -105,6 +105,7 @@ func PubKeyBytesToKey(bytes []byte, keyType kms.KeyType) (interface{}, error) { if err != nil { return nil, errors.New("rsa: invalid public key") } + return pubKeyRsa, nil case kms.ECDSASecp256k1TypeDER: return parseSecp256k1DER(bytes) diff --git a/doc/jose/jwk/jwksupport/jwk_test.go b/doc/jose/jwk/jwksupport/jwk_test.go index a9a3eae..fce93e0 100644 --- a/doc/jose/jwk/jwksupport/jwk_test.go +++ b/doc/jose/jwk/jwksupport/jwk_test.go @@ -860,6 +860,12 @@ func TestPublicKeyFromJWK(t *testing.T) { }) } +func TestRSAKeyFailParse(t *testing.T) { + resultJWK, err := PubKeyBytesToJWK([]byte{0x1}, kms.RSARS256) + require.ErrorContains(t, err, "rsa: invalid public key") + require.Nil(t, resultJWK) +} + func TestRSAKey(t *testing.T) { key, err := rsa.GenerateKey(rand.Reader, 2048) require.NoError(t, err)