Skip to content

Commit ef01e3b

Browse files
authored
Merge pull request #256 from tlsfuzzer/eddsa
EdDSA support
2 parents 6c20190 + 82da89c commit ef01e3b

File tree

4 files changed

+141
-1
lines changed

4 files changed

+141
-1
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ jobs:
1818
os: ubuntu-latest
1919
container: centos:6
2020
python-version: 2.6
21+
- name: py3.10 with ossl3.0
22+
os: ubuntu-latest
23+
container: ubuntu:22.04
24+
python-version: "3.10"
25+
tox-env: py310
2126
- name: py2.7
2227
os: ubuntu-18.04
2328
python-version: 2.7
@@ -115,7 +120,7 @@ jobs:
115120
with:
116121
fetch-depth: 50
117122
- name: Ensure dependencies on CentOS
118-
if: ${{ matrix.container }}
123+
if: ${{ matrix.container == 'centos:6' }}
119124
run: |
120125
ls /etc/yum.repos.d/
121126
cat /etc/yum.repos.d/CentOS-Base.repo
@@ -144,6 +149,11 @@ jobs:
144149
yum clean all
145150
yum repolist all
146151
yum install -y git make python curl gcc libffi-devel python-devel glibc-devel openssl-devel wget
152+
- name: Ensure dependencies on Ubuntu 22.04
153+
if: ${{ matrix.container == 'ubuntu:22.04' }}
154+
run: |
155+
apt-get update
156+
apt-get install -y git make python-is-python3 python3 curl wget python3-distutils python3-pip
147157
- name: Verify git status
148158
run: |
149159
git status

src/ecdsa/test_keys.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ def test_load_ed25519_from_pem(self):
336336

337337
vk = VerifyingKey.from_pem(vk_pem)
338338

339+
self.assertIsInstance(vk.curve, Curve)
340+
self.assertIs(vk.curve, Ed25519)
341+
339342
vk_str = (
340343
b"\x23\x00\x50\xd0\xd6\x64\x22\x28\x8e\xe3\x55\x89\x7e\x6e\x41\x57"
341344
b"\x8d\xae\xde\x44\x26\xee\x56\x27\xbc\x85\xe6\x0b\x2f\x2a\xcb\x65"
@@ -400,6 +403,9 @@ def test_ed448_from_pem(self):
400403

401404
vk = VerifyingKey.from_pem(pem_str)
402405

406+
self.assertIsInstance(vk.curve, Curve)
407+
self.assertIs(vk.curve, Ed448)
408+
403409
vk_str = (
404410
b"\x79\x0b\x5e\xb5\x2b\xbb\x08\xc1\x33\x13\xe5\xd6\x07\x5d\x01\x83"
405411
b"\x8e\xcb\x08\x0d\x20\x88\xd8\xa4\x3b\x11\xf3\x76\x9f\xad\x67\xf7"

src/ecdsa/test_malformed_sigs.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
"sha384",
1414
"sha512",
1515
]
16+
# skip algorithms broken by change to OpenSSL 3.0 and early versions
17+
# of hashlib that list algorithms that require the legacy provider to work
18+
# https://bugs.python.org/issue38820
19+
algorithms_available = [
20+
i
21+
for i in algorithms_available
22+
if i not in ("mdc2", "md2", "md4", "whirlpool", "ripemd160")
23+
]
1624
from functools import partial
1725
import pytest
1826
import sys

src/ecdsa/test_pyecdsa.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
BRAINPOOLP320r1,
4444
BRAINPOOLP384r1,
4545
BRAINPOOLP512r1,
46+
Ed25519,
47+
Ed448,
4648
curves,
4749
)
4850
from .ecdsa import (
@@ -1354,6 +1356,120 @@ def do_test_to_openssl(self, curve, hash_name="SHA1"):
13541356
% mdarg
13551357
)
13561358

1359+
OPENSSL_SUPPORTED_TYPES = set()
1360+
try:
1361+
if "-rawin" in run_openssl("pkeyutl -help"):
1362+
OPENSSL_SUPPORTED_TYPES = set(
1363+
c.lower()
1364+
for c in ("ED25519", "ED448")
1365+
if c in run_openssl("list -public-key-methods")
1366+
)
1367+
except SubprocessError:
1368+
pass
1369+
1370+
def do_eddsa_test_to_openssl(self, curve):
1371+
curvename = curve.name.upper()
1372+
1373+
if os.path.isdir("t"):
1374+
shutil.rmtree("t")
1375+
os.mkdir("t")
1376+
1377+
sk = SigningKey.generate(curve=curve)
1378+
vk = sk.get_verifying_key()
1379+
1380+
data = b"data"
1381+
with open("t/pubkey.der", "wb") as e:
1382+
e.write(vk.to_der())
1383+
with open("t/pubkey.pem", "wb") as e:
1384+
e.write(vk.to_pem())
1385+
1386+
sig = sk.sign(data)
1387+
1388+
with open("t/data.sig", "wb") as e:
1389+
e.write(sig)
1390+
with open("t/data.txt", "wb") as e:
1391+
e.write(data)
1392+
with open("t/baddata.txt", "wb") as e:
1393+
e.write(data + b"corrupt")
1394+
1395+
with self.assertRaises(SubprocessError):
1396+
run_openssl(
1397+
"pkeyutl -verify -pubin -inkey t/pubkey.pem -rawin "
1398+
"-in t/baddata.txt -sigfile t/data.sig"
1399+
)
1400+
run_openssl(
1401+
"pkeyutl -verify -pubin -inkey t/pubkey.pem -rawin "
1402+
"-in t/data.txt -sigfile t/data.sig"
1403+
)
1404+
1405+
shutil.rmtree("t")
1406+
1407+
# in practice at least OpenSSL 3.0.0 is needed to make EdDSA signatures
1408+
# earlier versions support EdDSA only in X.509 certificates
1409+
@pytest.mark.skipif(
1410+
"ed25519" not in OPENSSL_SUPPORTED_TYPES,
1411+
reason="system openssl does not support signing with Ed25519",
1412+
)
1413+
def test_to_openssl_ed25519(self):
1414+
return self.do_eddsa_test_to_openssl(Ed25519)
1415+
1416+
@pytest.mark.skipif(
1417+
"ed448" not in OPENSSL_SUPPORTED_TYPES,
1418+
reason="system openssl does not support signing with Ed448",
1419+
)
1420+
def test_to_openssl_ed448(self):
1421+
return self.do_eddsa_test_to_openssl(Ed448)
1422+
1423+
def do_eddsa_test_from_openssl(self, curve):
1424+
curvename = curve.name
1425+
1426+
if os.path.isdir("t"):
1427+
shutil.rmtree("t")
1428+
os.mkdir("t")
1429+
1430+
data = b"data"
1431+
1432+
run_openssl(
1433+
"genpkey -algorithm {0} -outform PEM -out t/privkey.pem".format(
1434+
curvename
1435+
)
1436+
)
1437+
run_openssl(
1438+
"pkey -outform PEM -pubout -in t/privkey.pem -out t/pubkey.pem"
1439+
)
1440+
1441+
with open("t/data.txt", "wb") as e:
1442+
e.write(data)
1443+
run_openssl(
1444+
"pkeyutl -sign -inkey t/privkey.pem "
1445+
"-rawin -in t/data.txt -out t/data.sig"
1446+
)
1447+
1448+
with open("t/data.sig", "rb") as e:
1449+
sig = e.read()
1450+
with open("t/pubkey.pem", "rb") as e:
1451+
vk = VerifyingKey.from_pem(e.read())
1452+
1453+
self.assertIs(vk.curve, curve)
1454+
1455+
vk.verify(sig, data)
1456+
1457+
shutil.rmtree("t")
1458+
1459+
@pytest.mark.skipif(
1460+
"ed25519" not in OPENSSL_SUPPORTED_TYPES,
1461+
reason="system openssl does not support signing with Ed25519",
1462+
)
1463+
def test_from_openssl_ed25519(self):
1464+
return self.do_eddsa_test_from_openssl(Ed25519)
1465+
1466+
@pytest.mark.skipif(
1467+
"ed448" not in OPENSSL_SUPPORTED_TYPES,
1468+
reason="system openssl does not support signing with Ed448",
1469+
)
1470+
def test_from_openssl_ed448(self):
1471+
return self.do_eddsa_test_from_openssl(Ed448)
1472+
13571473

13581474
class TooSmallCurve(unittest.TestCase):
13591475
OPENSSL_SUPPORTED_CURVES = set(

0 commit comments

Comments
 (0)