Skip to content

Commit 9a21055

Browse files
authored
Allow loading EC, ED25519, ED448 public keys from cryptography (#1310)
Our code is quite capable of supporting these public key types, so allow users to do so. We also beef up the test suite to test all these key types, along with DSA keys which were not explicitly tested.
1 parent 9eaa107 commit 9a21055

File tree

2 files changed

+161
-7
lines changed

2 files changed

+161
-7
lines changed

src/OpenSSL/crypto.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,16 @@
8989

9090

9191
_Key = Union[
92-
dsa.DSAPrivateKey, dsa.DSAPublicKey, rsa.RSAPrivateKey, rsa.RSAPublicKey
92+
dsa.DSAPrivateKey,
93+
dsa.DSAPublicKey,
94+
ec.EllipticCurvePrivateKey,
95+
ec.EllipticCurvePublicKey,
96+
ed25519.Ed25519PrivateKey,
97+
ed25519.Ed25519PublicKey,
98+
ed448.Ed448PrivateKey,
99+
ed448.Ed448PublicKey,
100+
rsa.RSAPrivateKey,
101+
rsa.RSAPublicKey,
93102
]
94103
StrOrBytesPath = Union[str, bytes, PathLike]
95104
PassphraseCallableT = Union[bytes, Callable[..., bytes]]
@@ -310,13 +319,16 @@ def from_cryptography_key(cls, crypto_key: _Key) -> "PKey":
310319
if not isinstance(
311320
crypto_key,
312321
(
313-
rsa.RSAPublicKey,
314-
rsa.RSAPrivateKey,
315-
dsa.DSAPublicKey,
316322
dsa.DSAPrivateKey,
323+
dsa.DSAPublicKey,
317324
ec.EllipticCurvePrivateKey,
325+
ec.EllipticCurvePublicKey,
318326
ed25519.Ed25519PrivateKey,
327+
ed25519.Ed25519PublicKey,
319328
ed448.Ed448PrivateKey,
329+
ed448.Ed448PublicKey,
330+
rsa.RSAPrivateKey,
331+
rsa.RSAPublicKey,
320332
),
321333
):
322334
raise TypeError("Unsupported key type")
@@ -328,7 +340,16 @@ def from_cryptography_key(cls, crypto_key: _Key) -> "PKey":
328340
PublicFormat,
329341
)
330342

331-
if isinstance(crypto_key, (rsa.RSAPublicKey, dsa.DSAPublicKey)):
343+
if isinstance(
344+
crypto_key,
345+
(
346+
dsa.DSAPublicKey,
347+
ec.EllipticCurvePublicKey,
348+
ed25519.Ed25519PublicKey,
349+
ed448.Ed448PublicKey,
350+
rsa.RSAPublicKey,
351+
),
352+
):
332353
return load_publickey(
333354
FILETYPE_ASN1,
334355
crypto_key.public_bytes(

tests/test_crypto.py

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414
import pytest
1515
from cryptography import x509
1616
from cryptography.hazmat.primitives import hashes, serialization
17-
from cryptography.hazmat.primitives.asymmetric import ec, ed448, ed25519, rsa
17+
from cryptography.hazmat.primitives.asymmetric import (
18+
dsa,
19+
ec,
20+
ed448,
21+
ed25519,
22+
rsa,
23+
)
1824

1925
from OpenSSL._util import ffi as _ffi
2026
from OpenSSL._util import lib as _lib
@@ -714,6 +720,11 @@ def utcnow():
714720
zo0MUVPQgwJ3aJtNM1QMOQUayCrRwfklg+D/rFSUwEUqtZh7fJDiFqz3
715721
-----END PRIVATE KEY-----
716722
"""
723+
ec_public_key_pem = b"""-----BEGIN PUBLIC KEY-----
724+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJLzzbuz2tRnLFlOL+6bTX6giVavA
725+
sc6NDFFT0IMCd2ibTTNUDDkFGsgq0cH5JYPg/6xUlMBFKrWYe3yQ4has9w==
726+
-----END PUBLIC KEY-----
727+
"""
717728

718729
ec_root_key_pem = b"""-----BEGIN EC PRIVATE KEY-----
719730
MIGlAgEBBDEAz/HOBFPYLB0jLWeTpJn4Yc4m/C4mdWymVHBjOmnwiPHKT326iYN/
@@ -744,15 +755,101 @@ def utcnow():
744755
-----END RSA PRIVATE KEY-----
745756
"""
746757

758+
dsa_private_key_pem = b"""-----BEGIN PRIVATE KEY-----
759+
MIICZAIBADCCAjkGByqGSM44BAEwggIsAoIBAQD7UzdlshSCIIuntch43VmfCX1+
760+
WQDTvGw83sRZcN+B7nwFn4dm2PU8cby17oCjX7buBvalVqofnUokrSIDA6Rozm/f
761+
2wpGR9oVpd0xh9cI50pw1G3RZ4lcNWTP8C8O20eIzJoCH1KElcWLCHLAa3XoGOMv
762+
p4XnbVgMdc9/ydt4qttzIVPV4cZoVObzixoKCgwHyVPDxe0JaCe2cIwxyQY0IwAI
763+
PfaUWEAo+bf7pOosdnatJYm9MkKe8bEgKGQcUl9S8FXLhRejMo+oobcRjuBHTAmY
764+
fuV1iGlLrkFNrc2O6M1CRZhOoddoy53IeHcSjfzKET1biE3tCOUdHjUnABqfAiEA
765+
1llvauVKMLvFCDatVKRY+zNGJaa5dwff4qDtodz6sa8CggEAd+btod0di21mqFaf
766+
vc1ddmLK74PddMseT8DmoN/YduJaGLAOOVJ61rdG+KPXIar+8X5yqXfzP0MiYGkE
767+
A+xpNIImC3rzHElYNa8imA7ud8f+oC5jQijp0GhzVIS4UW83rZwakX7LITNE9Oj9
768+
FkETH1ZskHpp5BNlNoaSIW2+T7n/a+lq+tN60gP3f6FPBv5obB0pjqh+OAzEil/4
769+
Ys0dtCB0022cCUCqThMhWewlE2W2JioDLV5QkD91NMQNQwljDONNcs94AaWeVONK
770+
RaBQXlFsJPHzS8uKpsFeusFTrHIeEJW/8GQp/tfXP1ajEdg5EGxOhXFkem4ZMIus
771+
YFTbWwQiAiBFtgi8aNV0Jz2o8T+cxjVqVEgGdYNQqmpzqqBsM5AEOw==
772+
-----END PRIVATE KEY-----
773+
"""
774+
dsa_public_key_pem = b"""-----BEGIN PUBLIC KEY-----
775+
MIIDRjCCAjkGByqGSM44BAEwggIsAoIBAQD7UzdlshSCIIuntch43VmfCX1+WQDT
776+
vGw83sRZcN+B7nwFn4dm2PU8cby17oCjX7buBvalVqofnUokrSIDA6Rozm/f2wpG
777+
R9oVpd0xh9cI50pw1G3RZ4lcNWTP8C8O20eIzJoCH1KElcWLCHLAa3XoGOMvp4Xn
778+
bVgMdc9/ydt4qttzIVPV4cZoVObzixoKCgwHyVPDxe0JaCe2cIwxyQY0IwAIPfaU
779+
WEAo+bf7pOosdnatJYm9MkKe8bEgKGQcUl9S8FXLhRejMo+oobcRjuBHTAmYfuV1
780+
iGlLrkFNrc2O6M1CRZhOoddoy53IeHcSjfzKET1biE3tCOUdHjUnABqfAiEA1llv
781+
auVKMLvFCDatVKRY+zNGJaa5dwff4qDtodz6sa8CggEAd+btod0di21mqFafvc1d
782+
dmLK74PddMseT8DmoN/YduJaGLAOOVJ61rdG+KPXIar+8X5yqXfzP0MiYGkEA+xp
783+
NIImC3rzHElYNa8imA7ud8f+oC5jQijp0GhzVIS4UW83rZwakX7LITNE9Oj9FkET
784+
H1ZskHpp5BNlNoaSIW2+T7n/a+lq+tN60gP3f6FPBv5obB0pjqh+OAzEil/4Ys0d
785+
tCB0022cCUCqThMhWewlE2W2JioDLV5QkD91NMQNQwljDONNcs94AaWeVONKRaBQ
786+
XlFsJPHzS8uKpsFeusFTrHIeEJW/8GQp/tfXP1ajEdg5EGxOhXFkem4ZMIusYFTb
787+
WwOCAQUAAoIBAEe6z5ud1k4EDD9mLP7UYALWrgc1NXUlDynoYkjr+T/NVf1eaMdq
788+
0vFbGcEmz05UPUNXOhDH0szUDxQam3IE9C27ZO4SOquc0/rIhPY6i75SJW13P+cg
789+
gdXhDMTW5JOlyV6CPUoCWKOtn1ds3pTDuuWlZ89UzOWQUbC1si6vvz43zDyhfu6U
790+
owgIusPxowErm2sH66+MPa8fYxVX7ZJL0mEfubejrloAbo5unYI/bUYIhx4mtpP/
791+
h/isFRifEAwG3yX6F9X/ZOYL53Z93EFPLJGRGMmQbkmXRA6lyvHdsC+OC/OCvPjW
792+
WfTXW9NHtUqpEks+OXBkyV971Hk5NvdLLr8=
793+
-----END PUBLIC KEY-----
794+
"""
795+
747796
ed25519_private_key_pem = b"""-----BEGIN PRIVATE KEY-----
748797
MC4CAQAwBQYDK2VwBCIEIKlxBbhVsSURoLTmsu9uTqYH6oF7zpxmp1ZQCAPhDmI2
749798
-----END PRIVATE KEY-----
750799
"""
800+
ed25519_public_key_pem = b"""-----BEGIN PUBLIC KEY-----
801+
MCowBQYDK2VwAyEAq+FrpdwI1oTPytx8kGzuLVc+78zJE7hjYG4E9hwXoKI=
802+
-----END PUBLIC KEY-----
803+
"""
751804

752805
ed448_private_key_pem = b"""-----BEGIN PRIVATE KEY-----
753806
MEcCAQAwBQYDK2VxBDsEOcqZ7a3k6JwrJbYO8CNTPT/d7dlWCo5vCf0EYDj79ZvA\nhD8u9EPHlYJw5Y8ZQdH4WmVEfpKA23xkdQ==
754807
-----END PRIVATE KEY-----
755808
"""
809+
ed448_public_key_pem = b"""-----BEGIN PUBLIC KEY-----
810+
MEMwBQYDK2VxAzoAKFfWGCuqIaxgR9GmEXLRciYDyEjTnF56kr0sOVfwHEj+bHSU\neMJTZJR8qFSg8hNsHY1iZh9PIXcA
811+
-----END PUBLIC KEY-----
812+
"""
813+
814+
rsa_private_key_pem = b"""-----BEGIN PRIVATE KEY-----
815+
MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDZ5FaSaXKn/RTF
816+
xyNr+GRvYnMvLz5XxSDD4JzVRKXxKGFzKKXMJAeXJkvPlho7Ta/HgMNXhMPAe8TT
817+
wcIRnHJqAfmSOnka1ks3Kl6EGQBTevKzyJy8MaUhzZsL4FUUgWUETFQQT8Dwcghf
818+
JobV0k+bWT4mrKHzIquw5y+NTsaZl4jSB1labhImsU16Vj66fHp7w9+c501tOxQO
819+
M4CQNWioGm8tgPT/43QUs9e+L2HFBI+cDQbEC68l+7VM8YY8NZ/fGypoML2QMVnU
820+
Y6zneoOLJTMUulOubrL+J6DkuuhxBsIOcyxMnqwgKm4pUGlPxfPSS7+Mo3JC969k
821+
wgUHerXZAgMBAAECgf9qAzz/VMCQwnV1UxkhxH/8zgYgYL+fERFuPC/ZWv7wOicv
822+
xAjm9KC8zVb44fLE586CCc7IN+zNK9y0gB9eAGr/04RhEvWgbmoqF6wdtdNyynuE
823+
Ut4oQKn7AUc1uPAeCfM4slw0Pie98YSS/9ZhwH/eh3C10iwWA1aiLWeDrnryPuJN
824+
mNB0d/ZsaL+arhR/nU2sJixx5LDI6AG0GJrw3DBHEKb4vZPIUM3wZNs7qnuG5W17
825+
JbZDQYnkApByZu2UMWI2YUkpJC246mFPWSWMa6sAl7sTWTkUIR21lJiqyTGG3ljY
826+
C2QjHoHrrzs+pwtlLBa1a4FgbaJmnL+VzWD/FQECgYEA8r3Y2oGcY5cQPb00TE0t
827+
ekXAXiHz9sX76nzE6BMZ8cwP/cVoWtIABpdaimKUoFML8CdjOi9Ti9OoNVGWm4Pk
828+
fT/GOUdysXWIw2Z/VOLM47nDwJb3fWwxsxph+x3gWJG/Vct/1NxmCCEendM63dy7
829+
/uR8RgX+0nxvn6Y6auQfpnkCgYEA5csHboa14Favx8aHTlITWOm46ugzdbARdfWz
830+
13Ewb7m4mm/3gKtA/m+yGdQFwmtBVkmwtdCeDj0aKH3Sfvg9WCQK1x/dUkPMr//r
831+
oGUGeJU9r3ZKVJTeSJ0lKX4h3u3+1TdpnAgtuWGI4AK9fEdulfHKArxyIdbsdwRr
832+
ljaBMmECgYATpEcCz1APQu7+f+vWbLxMU46QT2EFS9npjHUGbl1AEooMt8eM6cc0
833+
wVSDNBzgqDekFBvUXnX9L4BB6DsulEqN0/Y/NkfSkjch0I5nGP8JQkPTtqOKE5Il
834+
8vGQt0crA4ge8huC5t6es8ddb/UodK8FnglsRRnsgEMsAPBjK9hfyQKBgDHD23Mr
835+
R14zR9Q7AXiLu9bonvx4lxRosg9ay7zfrX60uO7xSqeZ7vRrWiXPzgOB2N+IC/YE
836+
HQa2YuDcBucqeZaKD7LxGqxDNKP1B6Fv34vjvj0uoABbURxms/Kdd1ZhMmwYmQ2K
837+
k+Ru5AancUPl8GQWvgoDp6/+bK2Fzor0eNxhAoGBANcJ6mGvgw3px/H2MPBjRBsf
838+
tUbZ39UH3c4siLa2Rry/Pm0Fgly8CUmu1IcFQDITKbyhaGPuHGtXglBOZqXid0VL
839+
01ReWISyKwWyuRjUuscdq2m684hXHYZCq2eJroqon1nMq4C0aqr696ra0cgCfbK3
840+
5yscAByxKd+64JZziDkZ
841+
-----END PRIVATE KEY-----
842+
"""
843+
rsa_public_key_pem = b"""-----BEGIN PUBLIC KEY-----
844+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2eRWkmlyp/0Uxccja/hk
845+
b2JzLy8+V8Ugw+Cc1USl8ShhcyilzCQHlyZLz5YaO02vx4DDV4TDwHvE08HCEZxy
846+
agH5kjp5GtZLNypehBkAU3rys8icvDGlIc2bC+BVFIFlBExUEE/A8HIIXyaG1dJP
847+
m1k+Jqyh8yKrsOcvjU7GmZeI0gdZWm4SJrFNelY+unx6e8PfnOdNbTsUDjOAkDVo
848+
qBpvLYD0/+N0FLPXvi9hxQSPnA0GxAuvJfu1TPGGPDWf3xsqaDC9kDFZ1GOs53qD
849+
iyUzFLpTrm6y/ieg5LrocQbCDnMsTJ6sICpuKVBpT8Xz0ku/jKNyQvevZMIFB3q1
850+
2QIDAQAB
851+
-----END PUBLIC KEY-----
852+
"""
756853

757854
x25519_private_key_pem = b"""-----BEGIN PRIVATE KEY-----
758855
MC4CAQAwBQYDK2VuBCIEIPAjVfPNTm25VxtBRg+JjjFx9tA3M8aaBdVhjb92iBts
@@ -992,10 +1089,11 @@ class TestPKey:
9921089
@pytest.mark.parametrize(
9931090
("key_string", "key_type"),
9941091
[
995-
(intermediate_key_pem, rsa.RSAPrivateKey),
1092+
(dsa_private_key_pem, dsa.DSAPrivateKey),
9961093
(ec_private_key_pem, ec.EllipticCurvePrivateKey),
9971094
(ed25519_private_key_pem, ed25519.Ed25519PrivateKey),
9981095
(ed448_private_key_pem, ed448.Ed448PrivateKey),
1096+
(rsa_private_key_pem, rsa.RSAPrivateKey),
9991097
],
10001098
)
10011099
def test_convert_roundtrip_cryptography_private_key(
@@ -1006,6 +1104,7 @@ def test_convert_roundtrip_cryptography_private_key(
10061104
PKey.to_cryptography_key creates a proper cryptography private key.
10071105
"""
10081106
key = serialization.load_pem_private_key(key_string, None)
1107+
assert isinstance(key, key_type)
10091108
pkey = PKey.from_cryptography_key(key)
10101109

10111110
assert isinstance(pkey, PKey)
@@ -1021,6 +1120,40 @@ def test_convert_roundtrip_cryptography_private_key(
10211120
assert pkey._only_public is False
10221121
assert pkey._initialized is True
10231122

1123+
@pytest.mark.parametrize(
1124+
("key_string", "key_type"),
1125+
[
1126+
(dsa_public_key_pem, dsa.DSAPublicKey),
1127+
(ec_public_key_pem, ec.EllipticCurvePublicKey),
1128+
(ed25519_public_key_pem, ed25519.Ed25519PublicKey),
1129+
(ed448_public_key_pem, ed448.Ed448PublicKey),
1130+
(rsa_public_key_pem, rsa.RSAPublicKey),
1131+
],
1132+
)
1133+
def test_convert_roundtrip_cryptography_public_key(
1134+
self, key_string, key_type
1135+
):
1136+
"""
1137+
PKey.from_cryptography_key creates a proper public PKey.
1138+
PKey.to_cryptography_key creates a proper cryptography public key.
1139+
"""
1140+
key = serialization.load_pem_public_key(key_string, None)
1141+
assert isinstance(key, key_type)
1142+
pkey = PKey.from_cryptography_key(key)
1143+
1144+
assert isinstance(pkey, PKey)
1145+
parsed_key = pkey.to_cryptography_key()
1146+
assert isinstance(parsed_key, key_type)
1147+
assert parsed_key.public_bytes(
1148+
serialization.Encoding.PEM,
1149+
serialization.PublicFormat.SubjectPublicKeyInfo,
1150+
) == key.public_bytes(
1151+
serialization.Encoding.PEM,
1152+
serialization.PublicFormat.SubjectPublicKeyInfo,
1153+
)
1154+
assert pkey._only_public is True
1155+
assert pkey._initialized is True
1156+
10241157
def test_convert_from_cryptography_public_key(self):
10251158
"""
10261159
PKey.from_cryptography_key creates a proper public PKey.

0 commit comments

Comments
 (0)