diff --git a/doc/jose/jwk/jwksupport/jwk.go b/doc/jose/jwk/jwksupport/jwk.go index 9c2f253..f9e85c4 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" @@ -62,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 @@ -99,6 +100,13 @@ 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 +173,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 +255,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..fce93e0 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,30 @@ 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) + + 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"`