wolfcrypt-py/tests/test_ciphers.py

718 lines
26 KiB
Python

# test_ciphers.py
#
# Copyright (C) 2006-2022 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 collections import namedtuple
import pytest
from wolfcrypt._ffi import ffi as _ffi
from wolfcrypt._ffi import lib as _lib
from wolfcrypt.utils import t2b, h2b
import os
certs_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "certs")
if _lib.DES3_ENABLED:
from wolfcrypt.ciphers import Des3
if _lib.AES_ENABLED:
from wolfcrypt.ciphers import Aes
if _lib.CHACHA_ENABLED:
from wolfcrypt.ciphers import ChaCha
if _lib.RSA_ENABLED:
from wolfcrypt.ciphers import (RsaPrivate, RsaPublic, HASH_TYPE_SHA256, MGF1SHA256, HASH_TYPE_SHA, MGF1SHA1)
if _lib.ECC_ENABLED:
from wolfcrypt.ciphers import (EccPrivate, EccPublic)
if _lib.ED25519_ENABLED:
from wolfcrypt.ciphers import (Ed25519Private, Ed25519Public)
if _lib.ED448_ENABLED:
from wolfcrypt.ciphers import (Ed448Private, Ed448Public)
from wolfcrypt.ciphers import (
MODE_CTR, MODE_ECB, MODE_CBC, WolfCryptError
)
@pytest.fixture
def vectors():
TestVector = namedtuple("TestVector", """key iv plaintext ciphertext
ciphertext_ctr raw_key
pkcs8_key pem""")
TestVector.__new__.__defaults__ = (None,) * len(TestVector._fields)
# test vector dictionary
vectorArray = {}
if _lib.AES_ENABLED:
vectorArray[Aes]=TestVector(
key="0123456789abcdef",
iv="1234567890abcdef",
plaintext=t2b("now is the time "),
ciphertext=h2b("959492575f4281532ccc9d4677a233cb"),
ciphertext_ctr = h2b('287528ddf484b1055debbe751eb52b8a')
)
if _lib.CHACHA_ENABLED:
vectorArray[ChaCha]=TestVector(
key="0123456789abcdef01234567890abcdef",
iv="1234567890abcdef",
)
if _lib.DES3_ENABLED:
vectorArray[Des3]=TestVector(
key=h2b("0123456789abcdeffedeba987654321089abcdef01234567"),
iv=h2b("1234567890abcdef"),
plaintext=t2b("Now is the time for all "),
ciphertext=h2b("43a0297ed184f80e8964843212d508981894157487127db0")
)
if _lib.RSA_ENABLED:
vectorArray[RsaPublic]=TestVector(
key=h2b(
"30819F300D06092A864886F70D010101050003818D0030818902818100BC"
"730EA849F374A2A9EF18A5DA559921F9C8ECB36D48E53535757737ECD161"
"905F3ED9E4D5DF94CAC1A9D719DA86C9E84DC4613682FEABAD7E7725BB8D"
"11A5BC623AA838CC39A20466B4F7F7F3AADA4D020EBB5E8D6948DC77C928"
"0E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B3C67C8DC"
"2700F6916865A90203010001"),
pem=os.path.join(certs_dir, "server-keyPub.pem")
)
vectorArray[RsaPrivate]=TestVector(
key=h2b(
"3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8EC"
"B36D48E53535757737ECD161905F3ED9E4D5DF94CAC1A9D719DA86C9E84D"
"C4613682FEABAD7E7725BB8D11A5BC623AA838CC39A20466B4F7F7F3AADA"
"4D020EBB5E8D6948DC77C9280E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAE"
"F69062E5641EEB2B3C67C8DC2700F6916865A902030100010281801397EA"
"E8387825A25C04CE0D407C31E5C470CD9B823B5809863B665FDC3190F14F"
"D5DB15DDDED73B95933118310E5EA3D6A21A716E81481C4BCFDB8E7A8661"
"32DCFB55C1166D279224458BF1B848B14B1DACDEDADD8E2FC291FBA5A96E"
"F83A6AF1FD5018EF9FE7C3CA78EA56D3D3725B96DD4E064E3AC3D9BE72B6"
"6507074C01024100FA47D47A7C923C55EF81F041302DA3CF8F1CE6872705"
"700DDF9835D6F18B382F24B5D084B6794F7129945AF0646AACE772C6ED4D"
"59983E673AF3742CF9611769024100C0C1820D0CEBC62FDC92F99D821A31"
"E9E9F74BF282871CEE166AD11D188270F3C0B62FF6F3F71DF18623C84EEB"
"8F568E8FF5BFF1F72BB5CC3DC657390C1B54410241009D7E05DEEDF4B7B2"
"FBFC304B551DE32F0147966905CD0E2E2CBD8363B6AB7CB76DCA5B64A7CE"
"BE86DF3B53DE61D21EEBA5F637EDACAB78D94CE755FBD71199C102401898"
"1829E61E2739702168AC0A2FA172C121869538C65890A0579CBAE3A7B115"
"C8DEF61BC2612376EFB09D1C44BE1343396717C89DCAFBF545648B38822C"
"F28102403989E59C195530BAB7488C48140EF49F7E779743E1B419353123"
"759C3B44AD691256EE0061641666D37C742B15B4A2FEBF086B1A5D3F9012"
"B105863129DBD9E2"),
pkcs8_key=h2b(
"30820276020100300d06092a864886f7"
"0d0101010500048202603082025c0201"
"0002818100bc730ea849f374a2a9ef18"
"a5da559921f9c8ecb36d48e535357577"
"37ecd161905f3ed9e4d5df94cac1a9d7"
"19da86c9e84dc4613682feabad7e7725"
"bb8d11a5bc623aa838cc39a20466b4f7"
"f7f3aada4d020ebb5e8d6948dc77c928"
"0e22e96ba426ba4ce8c1fd4a6f2b1fef"
"8aaef69062e5641eeb2b3c67c8dc2700"
"f6916865a902030100010281801397ea"
"e8387825a25c04ce0d407c31e5c470cd"
"9b823b5809863b665fdc3190f14fd5db"
"15ddded73b95933118310e5ea3d6a21a"
"716e81481c4bcfdb8e7a866132dcfb55"
"c1166d279224458bf1b848b14b1dacde"
"dadd8e2fc291fba5a96ef83a6af1fd50"
"18ef9fe7c3ca78ea56d3d3725b96dd4e"
"064e3ac3d9be72b66507074c01024100"
"fa47d47a7c923c55ef81f041302da3cf"
"8f1ce6872705700ddf9835d6f18b382f"
"24b5d084b6794f7129945af0646aace7"
"72c6ed4d59983e673af3742cf9611769"
"024100c0c1820d0cebc62fdc92f99d82"
"1a31e9e9f74bf282871cee166ad11d18"
"8270f3c0b62ff6f3f71df18623c84eeb"
"8f568e8ff5bff1f72bb5cc3dc657390c"
"1b54410241009d7e05deedf4b7b2fbfc"
"304b551de32f0147966905cd0e2e2cbd"
"8363b6ab7cb76dca5b64a7cebe86df3b"
"53de61d21eeba5f637edacab78d94ce7"
"55fbd71199c1024018981829e61e2739"
"702168ac0a2fa172c121869538c65890"
"a0579cbae3a7b115c8def61bc2612376"
"efb09d1c44be1343396717c89dcafbf5"
"45648b38822cf28102403989e59c1955"
"30bab7488c48140ef49f7e779743e1b4"
"19353123759c3b44ad691256ee006164"
"1666d37c742b15b4a2febf086b1a5d3f"
"9012b105863129dbd9e2"),
pem=os.path.join(certs_dir, "server-key.pem")
)
if _lib.ECC_ENABLED:
vectorArray[EccPublic]=TestVector(
key=h2b(
"3059301306072A8648CE3D020106082A8648CE3D0301070342000455BFF4"
"0F44509A3DCE9BB7F0C54DF5707BD4EC248E1980EC5A4CA22403622C9BDA"
"EFA2351243847616C6569506CC01A9BDF6751A42F7BDA9B236225FC75D7F"
"B4"
),
raw_key=h2b(
"55bff40f44509a3dce9bb7f0c54df5707bd4ec248e1980ec5a4ca22403622c9b"
"daefa2351243847616c6569506cc01a9bdf6751a42f7bda9b236225fc75d7fb4"
)
)
vectorArray[EccPrivate]=TestVector(
key=h2b(
"30770201010420F8CF926BBD1E28F1A8ABA1234F3274188850AD7EC7EC92"
"F88F974DAF568965C7A00A06082A8648CE3D030107A1440342000455BFF4"
"0F44509A3DCE9BB7F0C54DF5707BD4EC248E1980EC5A4CA22403622C9BDA"
"EFA2351243847616C6569506CC01A9BDF6751A42F7BDA9B236225FC75D7F"
"B4"
),
raw_key=h2b(
"55bff40f44509a3dce9bb7f0c54df5707bd4ec248e1980ec5a4ca22403622c9b"
"daefa2351243847616c6569506cc01a9bdf6751a42f7bda9b236225fc75d7fb4"
"f8cf926bbd1e28f1a8aba1234f3274188850ad7ec7ec92f88f974daf568965c7"
)
)
if _lib.ED25519_ENABLED:
vectorArray[Ed25519Private]=TestVector(
key = h2b(
"47CD22B276161AA18BA1E0D13DBE84FE4840E4395D784F555A92E8CF739B"
"F86B"
)
)
vectorArray[Ed25519Public]=TestVector(
key=h2b(
"8498C65F4841145F9C51E8BFF4504B5527E0D5753964B7CB3C707A2B9747"
"FC96"
)
)
if _lib.ED448_ENABLED:
vectorArray[Ed448Private]=TestVector(
key=h2b("c2b29804e9a893c9e275cac1f8a3033f3d4b78b79eb427ed359fdeb8"
"82d657c129c7930936b181971b795167ad18cabeeb52b59b94f115ad"
"59"
)
)
vectorArray[Ed448Public]=TestVector(
key=h2b("89fb2b5a5ab67dd317794cc5f1700cace295b043f3ad73a66299e10a"
"d3fc0a28289ddd1c641598a354113867a42e82ad844b4d858d92e4e7"
"80"
)
)
return vectorArray
algo_params = []
if _lib.AES_ENABLED:
algo_params.append(Aes)
if _lib.DES3_ENABLED:
algo_params.append(Des3)
@pytest.fixture(params=algo_params)
def cipher_cls(request):
return request.param
def cipher_new(cipher_cls, vectors):
return cipher_cls.new(
vectors[cipher_cls].key,
MODE_CBC,
vectors[cipher_cls].iv)
def test_block_cipher(cipher_cls, vectors):
key = vectors[cipher_cls].key
iv = vectors[cipher_cls].iv
plaintext = vectors[cipher_cls].plaintext
ciphertext = vectors[cipher_cls].ciphertext
ciphertext_ctr = vectors[cipher_cls].ciphertext_ctr
with pytest.raises(ValueError):
cipher_cls.new(key[:-1], MODE_CBC, iv) # invalid key length
with pytest.raises(ValueError):
cipher_cls.new(key, -1, iv) # invalid mode
with pytest.raises(ValueError):
cipher_cls.new(key, MODE_ECB, iv) # unsuported mode
with pytest.raises(ValueError):
cipher_cls.new(key, MODE_CBC, None) # invalid iv
with pytest.raises(ValueError):
cipher_cls.new(key, MODE_CBC, iv[:-1]) # invalid iv length
# Test AES in counter mode
if ciphertext_ctr is not None:
cipher_obj = cipher_cls.new(key, MODE_CTR, iv)
res = cipher_obj.encrypt(plaintext)
assert res == ciphertext_ctr
cipher_obj = cipher_cls.new(key, MODE_CTR, iv)
assert plaintext == cipher_obj.decrypt(res)
# single encryption
cipher_obj = cipher_new(cipher_cls, vectors)
assert cipher_obj.encrypt(plaintext) == ciphertext
# many encryptions
cipher_obj = cipher_new(cipher_cls, vectors)
result = t2b("")
segments = tuple(plaintext[i:i + cipher_obj.block_size]
for i in range(0, len(plaintext), cipher_obj.block_size))
for segment in segments:
result += cipher_obj.encrypt(segment)
assert result == ciphertext
# single decryption
cipher_obj = cipher_new(cipher_cls, vectors)
assert cipher_obj.decrypt(ciphertext) == plaintext
# many decryptions
cipher_obj = cipher_new(cipher_cls, vectors)
result = t2b("")
segments = tuple(ciphertext[i:i + cipher_obj.block_size]
for i in range(0, len(ciphertext), cipher_obj.block_size))
for segment in segments:
result += cipher_obj.decrypt(segment)
assert result == plaintext
# invalid data sizes
with pytest.raises(ValueError):
cipher_obj.encrypt(plaintext[:-1])
with pytest.raises(ValueError):
cipher_obj.decrypt(ciphertext[:-1])
if _lib.CHACHA_ENABLED:
@pytest.fixture
def chacha_obj(vectors):
r = ChaCha(vectors[ChaCha].key, 32)
r.set_iv(vectors[ChaCha].iv)
return r
@pytest.fixture
def test_chacha_enc_dec(chacha_obj):
plaintext = t2b("Everyone gets Friday off.")
cyt = chacha_obj.encrypt(plaintext)
chacha_obj.set_iv(vectors[ChaCha].iv)
dec = chacha_obj.decrypt(cyt)
assert plaintext == dec
if _lib.RSA_ENABLED:
@pytest.fixture
def rsa_private(vectors):
return RsaPrivate(vectors[RsaPrivate].key)
@pytest.fixture
def rsa_private_pkcs8(vectors):
return RsaPrivate(vectors[RsaPrivate].pkcs8_key)
@pytest.fixture
def rsa_public(vectors):
return RsaPublic(vectors[RsaPublic].key)
@pytest.fixture
def rsa_private_pem(vectors):
with open(vectors[RsaPrivate].pem, "rb") as f:
pem = f.read()
return RsaPrivate.from_pem(pem)
@pytest.fixture
def rsa_public_pem(vectors):
with open(vectors[RsaPublic].pem, "rb") as f:
pem = f.read()
return RsaPublic.from_pem(pem)
def test_new_rsa_raises(vectors):
with pytest.raises(WolfCryptError):
RsaPrivate(vectors[RsaPrivate].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError):
RsaPublic(vectors[RsaPublic].key[:-1]) # invalid key length
if _lib.KEYGEN_ENABLED:
with pytest.raises(WolfCryptError): # invalid key size
RsaPrivate.make_key(16384)
def test_rsa_encrypt_decrypt(rsa_private, rsa_public):
plaintext = t2b("Everyone gets Friday off.")
# normal usage, encrypt with public, decrypt with private
ciphertext = rsa_public.encrypt(plaintext)
assert 1024 / 8 == len(ciphertext) == rsa_public.output_size
assert plaintext == rsa_private.decrypt(ciphertext)
# private object holds both private and public info, so it can also encrypt
# using the known public key.
ciphertext = rsa_private.encrypt(plaintext)
assert 1024 / 8 == len(ciphertext) == rsa_private.output_size
assert plaintext == rsa_private.decrypt(ciphertext)
def test_rsa_encrypt_decrypt_pad_oaep(rsa_private, rsa_public):
plaintext = t2b("Everyone gets Friday off.")
# normal usage, encrypt with public, decrypt with private
ciphertext = rsa_public.encrypt_oaep(plaintext, HASH_TYPE_SHA, MGF1SHA1, "")
assert 1024 / 8 == len(ciphertext) == rsa_public.output_size
assert plaintext == rsa_private.decrypt_oaep(ciphertext, HASH_TYPE_SHA, MGF1SHA1, "")
# private object holds both private and public info, so it can also encrypt
# using the known public key.
ciphertext = rsa_private.encrypt_oaep(plaintext, HASH_TYPE_SHA, MGF1SHA1, "")
assert 1024 / 8 == len(ciphertext) == rsa_private.output_size
assert plaintext == rsa_private.decrypt_oaep(ciphertext, HASH_TYPE_SHA, MGF1SHA1, "")
def test_rsa_pkcs8_encrypt_decrypt(rsa_private_pkcs8, rsa_public):
plaintext = t2b("Everyone gets Friday off.")
# normal usage, encrypt with public, decrypt with private
ciphertext = rsa_public.encrypt(plaintext)
assert 1024 / 8 == len(ciphertext) == rsa_public.output_size
assert plaintext == rsa_private_pkcs8.decrypt(ciphertext)
# private object holds both private and public info, so it can also encrypt
# using the known public key.
ciphertext = rsa_private_pkcs8.encrypt(plaintext)
assert 1024 / 8 == len(ciphertext) == rsa_private_pkcs8.output_size
assert plaintext == rsa_private_pkcs8.decrypt(ciphertext)
def test_rsa_sign_verify(rsa_private, rsa_public):
plaintext = t2b("Everyone gets Friday off.")
# normal usage, sign with private, verify with public
signature = rsa_private.sign(plaintext)
assert 1024 / 8 == len(signature) == rsa_private.output_size
assert plaintext == rsa_public.verify(signature)
# private object holds both private and public info, so it can also verify
# using the known public key.
signature = rsa_private.sign(plaintext)
assert 1024 / 8 == len(signature) == rsa_private.output_size
assert plaintext == rsa_private.verify(signature)
if _lib.RSA_PSS_ENABLED:
def test_rsa_pss_sign_verify(rsa_private, rsa_public):
plaintext = t2b("Everyone gets Friday off yippee.")
# normal usage, sign with private, verify with public
signature = rsa_private.sign_pss(plaintext, HASH_TYPE_SHA256, MGF1SHA256)
assert 1024 / 8 == len(signature) == rsa_private.output_size
assert 0 == rsa_public.verify_pss(plaintext, signature, HASH_TYPE_SHA256, MGF1SHA256)
# private object holds both private and public info, so it can also verify
# using the known public key.
signature = rsa_private.sign_pss(plaintext, HASH_TYPE_SHA256, MGF1SHA256)
assert 1024 / 8 == len(signature) == rsa_private.output_size
assert 0 == rsa_private.verify_pss(plaintext, signature, HASH_TYPE_SHA256, MGF1SHA256)
def test_rsa_sign_verify_pem(rsa_private_pem, rsa_public_pem):
plaintext = t2b("Everyone gets Friday off.")
# normal usage, sign with private, verify with public
signature = rsa_private_pem.sign(plaintext)
assert 256 == len(signature) == rsa_private_pem.output_size
assert plaintext == rsa_public_pem.verify(signature)
# private object holds both private and public info, so it can also verify
# using the known public key.
signature = rsa_private_pem.sign(plaintext)
assert 256 == len(signature) == rsa_private_pem.output_size
assert plaintext == rsa_private_pem.verify(signature)
def test_rsa_pkcs8_sign_verify(rsa_private_pkcs8, rsa_public):
plaintext = t2b("Everyone gets Friday off.")
# normal usage, sign with private, verify with public
signature = rsa_private_pkcs8.sign(plaintext)
assert 1024 / 8 == len(signature) == rsa_private_pkcs8.output_size
assert plaintext == rsa_public.verify(signature)
# private object holds both private and public info, so it can also verify
# using the known public key.
signature = rsa_private_pkcs8.sign(plaintext)
assert 1024 / 8 == len(signature) == rsa_private_pkcs8.output_size
assert plaintext == rsa_private_pkcs8.verify(signature)
if _lib.ECC_ENABLED:
@pytest.fixture
def ecc_private(vectors):
return EccPrivate(vectors[EccPrivate].key)
@pytest.fixture
def ecc_public(vectors):
return EccPublic(vectors[EccPublic].key)
def test_new_ecc_raises(vectors):
with pytest.raises(WolfCryptError):
EccPrivate(vectors[EccPrivate].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError):
EccPublic(vectors[EccPublic].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError):
EccPrivate(vectors[EccPublic].key) # invalid key type
with pytest.raises(WolfCryptError): # invalid key size
EccPrivate.make_key(1024)
def test_key_encoding(vectors):
priv = EccPrivate()
pub = EccPublic()
raw_priv = EccPrivate()
raw_pub = EccPublic()
# Test default encode/decode key
priv.decode_key(vectors[EccPrivate].key)
pub.decode_key(vectors[EccPublic].key)
assert priv.encode_key() == vectors[EccPrivate].key
assert pub.encode_key() == vectors[EccPublic].key
# Test EccPrivate.encode_key_raw/decode_key_raw
key = vectors[EccPrivate].raw_key
raw_priv.decode_key_raw(key[0:32], key[32:64], key[64:96])
qx, qy, d = raw_priv.encode_key_raw()
assert qx[0:32] == vectors[EccPrivate].raw_key[0:32]
assert qy[0:32] == vectors[EccPrivate].raw_key[32:64]
assert d[0:32] == vectors[EccPrivate].raw_key[64:96]
# Verify ECC key is the same as the raw key
qx, qy, d = priv.encode_key_raw()
assert qx[0:32] == vectors[EccPrivate].raw_key[0:32]
assert qy[0:32] == vectors[EccPrivate].raw_key[32:64]
assert d[0:32] == vectors[EccPrivate].raw_key[64:96]
# Test EccPublic.encode_key_raw/decode_key_raw
key = vectors[EccPublic].raw_key
raw_pub.decode_key_raw(key[0:32], key[32:64])
qx, qy = raw_pub.encode_key_raw()
assert qx[0:32] == vectors[EccPublic].raw_key[0:32]
assert qy[0:32] == vectors[EccPublic].raw_key[32:64]
# Verify ECC public key is the same as the raw key
qx, qy = pub.encode_key_raw()
assert qx[0:32] == vectors[EccPublic].raw_key[0:32]
assert qy[0:32] == vectors[EccPublic].raw_key[32:64]
def test_x963(ecc_private, ecc_public):
assert ecc_private.export_x963() == ecc_public.export_x963()
def test_ecc_sign_verify(ecc_private, ecc_public):
plaintext = "Everyone gets Friday off."
# normal usage, sign with private, verify with public
signature = ecc_private.sign(plaintext)
assert len(signature) <= ecc_private.max_signature_size
assert ecc_public.verify(signature, plaintext)
# invalid signature
with pytest.raises(WolfCryptError):
ecc_public.verify(signature[:-1], plaintext)
# private object holds both private and public info, so it can also verify
# using the known public key.
assert ecc_private.verify(signature, plaintext)
ecc_x963 = EccPublic()
ecc_x963.import_x963(ecc_public.export_x963())
assert ecc_x963.verify(signature, plaintext)
ecc_x963 = EccPublic()
ecc_x963.import_x963(ecc_private.export_x963())
assert ecc_x963.verify(signature, plaintext)
ecc_x963 = EccPublic()
with pytest.raises(WolfCryptError):
ecc_x963.import_x963(ecc_public.export_x963()[:-1])
if _lib.MPAPI_ENABLED:
def test_ecc_sign_verify_raw(ecc_private, ecc_public):
plaintext = "Everyone gets Friday off."
# normal usage, sign with private, verify with public
r,s = ecc_private.sign_raw(plaintext)
assert len(r) + len(s) <= 2 * ecc_private.size
assert ecc_public.verify_raw(r, s, plaintext)
# invalid signature
ret = ecc_public.verify_raw(r, s[:-1], plaintext)
assert ret == False
# private object holds both private and public info, so it can also verify
# using the known public key.
assert ecc_private.verify_raw(r, s, plaintext)
def test_ecc_make_shared_secret():
a = EccPrivate.make_key(32)
a_pub = EccPublic()
a_pub.import_x963(a.export_x963())
b = EccPrivate.make_key(32)
b_pub = EccPublic()
b_pub.import_x963(b.export_x963())
assert a.shared_secret(b) \
== b.shared_secret(a) \
== a.shared_secret(b_pub) \
== b.shared_secret(a_pub)
if _lib.ED25519_ENABLED:
@pytest.fixture
def ed25519_private(vectors):
return Ed25519Private(vectors[Ed25519Private].key, vectors[Ed25519Public].key)
@pytest.fixture
def ed25519_public(vectors):
return Ed25519Public(vectors[Ed25519Public].key)
def test_new_ed25519_raises(vectors):
with pytest.raises(WolfCryptError):
Ed25519Private(vectors[Ed25519Private].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError):
Ed25519Public(vectors[Ed25519Public].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError): # invalid key size
Ed25519Private.make_key(1024)
def test_ed25519_key_encoding(vectors):
priv = Ed25519Private()
pub = Ed25519Public()
priv.decode_key(vectors[Ed25519Private].key)
pub.decode_key(vectors[Ed25519Public].key)
assert priv.encode_key()[0] == vectors[Ed25519Private].key
assert priv.encode_key()[1] == vectors[Ed25519Public].key # Automatically re-generated from private-only
assert pub.encode_key() == vectors[Ed25519Public].key
def test_ed25519_sign_verify(ed25519_private, ed25519_public):
plaintext = "Everyone gets Friday off."
# normal usage, sign with private, verify with public
signature = ed25519_private.sign(plaintext)
assert len(signature) <= ed25519_private.max_signature_size
assert ed25519_public.verify(signature, plaintext)
# invalid signature
with pytest.raises(WolfCryptError):
ed25519_public.verify(signature[:-1], plaintext)
# private object holds both private and public info, so it can also verify
# using the known public key.
assert ed25519_private.verify(signature, plaintext)
if _lib.ED448_ENABLED:
@pytest.fixture
def ed448_private(vectors):
return Ed448Private(vectors[Ed448Private].key, vectors[Ed448Public].key)
@pytest.fixture
def ed448_public(vectors):
return Ed448Public(vectors[Ed448Public].key)
def test_new_ed448_raises(vectors):
with pytest.raises(WolfCryptError):
Ed448Private(vectors[Ed448Private].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError):
Ed448Public(vectors[Ed448Public].key[:-1]) # invalid key length
with pytest.raises(WolfCryptError): # invalid key size
Ed448Private.make_key(1024)
def test_ed448_key_encoding(vectors):
priv = Ed448Private()
pub = Ed448Public()
priv.decode_key(vectors[Ed448Private].key)
pub.decode_key(vectors[Ed448Public].key)
assert priv.encode_key()[0] == vectors[Ed448Private].key
assert priv.encode_key()[1] == vectors[Ed448Public].key # Automatically re-generated from private-only
assert pub.encode_key() == vectors[Ed448Public].key
def test_ed448_sign_verify(ed448_private, ed448_public):
plaintext = "Everyone gets Friday off."
# normal usage, sign with private, verify with public
signature = ed448_private.sign(plaintext)
assert len(signature) <= ed448_private.max_signature_size
assert ed448_public.verify(signature, plaintext)
# invalid signature
with pytest.raises(WolfCryptError):
ed448_public.verify(signature[:-1], plaintext)
# private object holds both private and public info, so it can also verify
# using the known public key.
assert ed448_private.verify(signature, plaintext)