-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathtest_mldsa.py
More file actions
158 lines (128 loc) · 5.61 KB
/
test_mldsa.py
File metadata and controls
158 lines (128 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# test_mldsa.py
#
# Copyright (C) 2025 wolfSSL Inc.
#
# This file is part of wolfSSL. (formerly known as CyaSSL)
#
# wolfSSL is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# wolfSSL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
# pylint: disable=redefined-outer-name
from wolfcrypt._ffi import lib as _lib
if _lib.ML_DSA_ENABLED:
import pytest
from wolfcrypt.ciphers import MlDsaPrivate, MlDsaPublic, MlDsaType
from wolfcrypt.random import Random
@pytest.fixture
def rng():
return Random()
@pytest.fixture(
params=[MlDsaType.ML_DSA_44, MlDsaType.ML_DSA_65, MlDsaType.ML_DSA_87]
)
def mldsa_type(request):
return request.param
def test_init_base(mldsa_type):
mldsa_priv = MlDsaPrivate(mldsa_type)
assert isinstance(mldsa_priv, MlDsaPrivate)
mldsa_pub = MlDsaPublic(mldsa_type)
assert isinstance(mldsa_pub, MlDsaPublic)
def test_size_properties(mldsa_type):
refvals = {
MlDsaType.ML_DSA_44: {
"sig_size": 2420,
"pub_key_size": 1312,
"priv_key_size": 2560,
},
MlDsaType.ML_DSA_65: {
"sig_size": 3309,
"pub_key_size": 1952,
"priv_key_size": 4032,
},
MlDsaType.ML_DSA_87: {
"sig_size": 4627,
"pub_key_size": 2592,
"priv_key_size": 4896,
},
}
mldsa_pub = MlDsaPublic(mldsa_type)
assert mldsa_pub.sig_size == refvals[mldsa_type]["sig_size"]
assert mldsa_pub.key_size == refvals[mldsa_type]["pub_key_size"]
mldsa_priv = MlDsaPrivate(mldsa_type)
assert mldsa_priv.sig_size == refvals[mldsa_type]["sig_size"]
assert mldsa_priv.pub_key_size == refvals[mldsa_type]["pub_key_size"]
assert mldsa_priv.priv_key_size == refvals[mldsa_type]["priv_key_size"]
def test_initializations(mldsa_type, rng):
mldsa_priv = MlDsaPrivate.make_key(mldsa_type, rng)
assert type(mldsa_priv) is MlDsaPrivate
mldsa_priv2 = MlDsaPrivate(mldsa_type)
assert type(mldsa_priv2) is MlDsaPrivate
mldsa_pub = MlDsaPublic(mldsa_type)
assert type(mldsa_pub) is MlDsaPublic
def test_key_import_export(mldsa_type, rng):
# Generate key pair and export keys
mldsa_priv = MlDsaPrivate.make_key(mldsa_type, rng)
priv_key = mldsa_priv.encode_priv_key()
pub_key = mldsa_priv.encode_pub_key()
assert len(priv_key) == mldsa_priv.priv_key_size
assert len(pub_key) == mldsa_priv.pub_key_size
# Export key pair from imported one
mldsa_priv2 = MlDsaPrivate(mldsa_type)
mldsa_priv2.decode_key(priv_key, pub_key)
priv_key2 = mldsa_priv2.encode_priv_key()
pub_key2 = mldsa_priv2.encode_pub_key()
assert priv_key == priv_key2
assert pub_key == pub_key2
# Export private key from imported one
mldsa_priv3 = MlDsaPrivate(mldsa_type)
mldsa_priv3.decode_key(priv_key)
priv_key3 = mldsa_priv3.encode_priv_key()
assert priv_key == priv_key3
# Export public key from imported one
mldsa_pub = MlDsaPublic(mldsa_type)
mldsa_pub.decode_key(pub_key)
pub_key3 = mldsa_pub.encode_key()
assert pub_key == pub_key3
def test_sign_verify(mldsa_type, rng):
# Generate a key pair and export public key
mldsa_priv = MlDsaPrivate.make_key(mldsa_type, rng)
pub_key = mldsa_priv.encode_pub_key()
# Import public key
mldsa_pub = MlDsaPublic(mldsa_type)
mldsa_pub.decode_key(pub_key)
# Sign a message
message = b"This is a test message for ML-DSA signature"
signature = mldsa_priv.sign(message, rng)
assert len(signature) == mldsa_priv.sig_size
# Verify the signature by MlDsaPrivate
assert mldsa_priv.verify(signature, message)
# Verify the signature by MlDsaPublic
assert mldsa_pub.verify(signature, message)
# Verify with wrong message
wrong_message = b"This is a wrong message for ML-DSA signature"
assert not mldsa_pub.verify(signature, wrong_message)
# Verify a signature generated without a context but where a context
# is provided during verify
ctx = b"This is a test context for ML-DSA signature"
wrong_ctx = b"This is a wrong context for ML-DSA signature"
assert not mldsa_pub.verify(signature, message, ctx=wrong_ctx)
# Sign a message with context
signature = mldsa_priv.sign(message, rng, ctx=ctx)
assert len(signature) == mldsa_priv.sig_size
# Verify the signature by MlDsaPrivate
assert mldsa_priv.verify(signature, message, ctx=ctx)
# Verify the signature by MlDsaPublic
assert mldsa_pub.verify(signature, message, ctx=ctx)
# Verify but do not provide a context
assert not mldsa_pub.verify(signature, message, ctx=None)
# Verify with wrong context
assert not mldsa_pub.verify(signature, message, ctx=wrong_ctx)