Address more review comments.
Tests are now also type checked as this helps verifying the correctness of the type annotations.pull/125/head
parent
1fb34e5cd8
commit
747243cc50
|
|
@ -27,6 +27,7 @@ wolfCrypt-py Release 5.9.2 (Jul 1, 2026)
|
|||
* Fix issue in AES-GCM tag verification
|
||||
* Address many small issues found by Fenrir
|
||||
* Add reseed support to random number generator
|
||||
* The RsaPublic key parameter is now mandatory as it is always needed by an internal function call.
|
||||
|
||||
|
||||
wolfCrypt-py Release 5.8.4 (Jan 7, 2026)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ classifiers = [
|
|||
dynamic = ["version"]
|
||||
dependencies = [
|
||||
"cffi>=1.17",
|
||||
"typing-extensions",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
@ -143,7 +144,7 @@ python-version = "3.10"
|
|||
root = ["."]
|
||||
|
||||
[tool.ty.src]
|
||||
exclude = ["./lib", "./tests"]
|
||||
exclude = ["./lib"]
|
||||
|
||||
[tool.ty.rules]
|
||||
all = "warn"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
from contextlib import nullcontext
|
||||
|
||||
|
|
@ -38,6 +39,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
gcm = AesGcmStream(key, iv)
|
||||
buf = gcm.encrypt("hello world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19b6197d2e', 'utf-8')
|
||||
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
|
||||
gcmdec = AesGcmStream(key, iv)
|
||||
|
|
@ -53,6 +55,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
gcm = AesGcmStream(key, iv, 12)
|
||||
buf = gcm.encrypt("hello world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19', 'utf-8')
|
||||
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
|
||||
gcmdec = AesGcmStream(key, iv, 12)
|
||||
|
|
@ -67,6 +70,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
buf = gcm.encrypt("hello")
|
||||
buf += gcm.encrypt(" world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
assert b2h(authTag) == bytes('ac8fcee96dc6ef8e5236da19b6197d2e', 'utf-8')
|
||||
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
|
||||
gcmdec = AesGcmStream(key, iv)
|
||||
|
|
@ -83,6 +87,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
gcm.set_aad(aad)
|
||||
buf = gcm.encrypt("hello world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
print(b2h(authTag))
|
||||
assert b2h(authTag) == bytes('8f85338aa0b13f48f8b17482dbb8acca', 'utf-8')
|
||||
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
|
||||
|
|
@ -101,6 +106,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
buf = gcm.encrypt("hello")
|
||||
buf += gcm.encrypt(" world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
assert b2h(authTag) == bytes('8f85338aa0b13f48f8b17482dbb8acca', 'utf-8')
|
||||
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
|
||||
gcmdec = AesGcmStream(key, iv)
|
||||
|
|
@ -119,6 +125,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
gcm.set_aad(aad)
|
||||
buf = gcm.encrypt("hello world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
print(b2h(authTag))
|
||||
assert b2h(authTag) == bytes('8f85338aa0b13f48f8b17482dbb8acca', 'utf-8')
|
||||
assert b2h(buf) == bytes('5ba7d42e1bf01d7998e932', "utf-8")
|
||||
|
|
@ -152,6 +159,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
gcm = AesGcmStream(key, iv, tag_bytes=good)
|
||||
gcm.encrypt("hello world")
|
||||
tag = gcm.final()
|
||||
assert tag is not None
|
||||
assert len(tag) == good
|
||||
|
||||
def test_decrypt_rejects_wrong_tag_length():
|
||||
|
|
@ -160,6 +168,7 @@ if _lib.AESGCM_STREAM_ENABLED:
|
|||
gcm = AesGcmStream(key, iv, tag_bytes=16)
|
||||
buf = gcm.encrypt("hello world")
|
||||
authTag = gcm.final()
|
||||
assert authTag is not None
|
||||
assert len(authTag) == 16
|
||||
|
||||
# Truncated tag: would silently lower the verification window to
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
from collections import namedtuple
|
||||
import pytest
|
||||
|
|
@ -90,8 +91,8 @@ def signature_vectors():
|
|||
"51a4edaf9f1199f93e448482f27c43a53e0bc65b04e9848128e3"
|
||||
"60314e864190e6bb9812bfbf4b40994f2c1d4ca7aad9"),
|
||||
hash_cls=Sha256,
|
||||
pub_key=RsaPublic.from_pem(pub_key_pem),
|
||||
priv_key=RsaPrivate.from_pem(priv_key_pem)
|
||||
pub_key=RsaPublic.from_pem(pub_key_pem), # ty: ignore[possibly-missing-attribute]
|
||||
priv_key=RsaPrivate.from_pem(priv_key_pem) # ty: ignore[possibly-missing-attribute]
|
||||
))
|
||||
|
||||
return vectors
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ if _lib.CHACHA20_POLY1305_ENABLED:
|
|||
from wolfcrypt.utils import t2b
|
||||
from wolfcrypt.exceptions import WolfCryptError
|
||||
from binascii import unhexlify as h2b
|
||||
from wolfcrypt.ciphers import ChaCha20Poly1305
|
||||
from wolfcrypt.ciphers import ChaCha20Poly1305 # ty: ignore[possibly-missing-import]
|
||||
|
||||
def test_encrypt_decrypt():
|
||||
key = h2b("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f")
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
import os
|
||||
import random
|
||||
|
|
@ -60,10 +61,8 @@ if _lib.ED448_ENABLED:
|
|||
|
||||
@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)
|
||||
fields = ("key", "iv", "plaintext", "ciphertext", "ciphertext_ctr", "raw_key", "pkcs8_key", "pem")
|
||||
TestVector = namedtuple("TestVector", fields, defaults=(None,) * len(fields))
|
||||
|
||||
# test vector dictionary
|
||||
vectorArray = {}
|
||||
|
|
@ -75,19 +74,19 @@ def vectors():
|
|||
plaintext=t2b("now is the time "),
|
||||
ciphertext=h2b("959492575f4281532ccc9d4677a233cb"),
|
||||
ciphertext_ctr = h2b('287528ddf484b1055debbe751eb52b8a')
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
if _lib.CHACHA_ENABLED:
|
||||
vectorArray[ChaCha]=TestVector(
|
||||
key="0123456789abcdef01234567890abcdef",
|
||||
iv="1234567890abcdef",
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
if _lib.DES3_ENABLED:
|
||||
vectorArray[Des3]=TestVector(
|
||||
key=h2b("0123456789abcdeffedeba987654321089abcdef01234567"),
|
||||
iv=h2b("1234567890abcdef"),
|
||||
plaintext=t2b("Now is the time for all "),
|
||||
ciphertext=h2b("43a0297ed184f80e8964843212d508981894157487127db0")
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
if _lib.RSA_ENABLED:
|
||||
vectorArray[RsaPublic]=TestVector(
|
||||
key=h2b(
|
||||
|
|
@ -98,7 +97,7 @@ def vectors():
|
|||
"0E22E96BA426BA4CE8C1FD4A6F2B1FEF8AAEF69062E5641EEB2B3C67C8DC"
|
||||
"2700F6916865A90203010001"),
|
||||
pem=os.path.join(certs_dir, "server-keyPub.pem")
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
vectorArray[RsaPrivate]=TestVector(
|
||||
key=h2b(
|
||||
"3082025C02010002818100BC730EA849F374A2A9EF18A5DA559921F9C8EC"
|
||||
|
|
@ -164,7 +163,7 @@ def vectors():
|
|||
"1666d37c742b15b4a2febf086b1a5d3f"
|
||||
"9012b105863129dbd9e2"),
|
||||
pem=os.path.join(certs_dir, "server-key.pem")
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
|
||||
if _lib.ECC_ENABLED:
|
||||
vectorArray[EccPublic]=TestVector(
|
||||
|
|
@ -178,7 +177,7 @@ def vectors():
|
|||
"55bff40f44509a3dce9bb7f0c54df5707bd4ec248e1980ec5a4ca22403622c9b"
|
||||
"daefa2351243847616c6569506cc01a9bdf6751a42f7bda9b236225fc75d7fb4"
|
||||
)
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
vectorArray[EccPrivate]=TestVector(
|
||||
key=h2b(
|
||||
"30770201010420F8CF926BBD1E28F1A8ABA1234F3274188850AD7EC7EC92"
|
||||
|
|
@ -192,7 +191,7 @@ def vectors():
|
|||
"daefa2351243847616c6569506cc01a9bdf6751a42f7bda9b236225fc75d7fb4"
|
||||
"f8cf926bbd1e28f1a8aba1234f3274188850ad7ec7ec92f88f974daf568965c7"
|
||||
)
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
|
||||
if _lib.ED25519_ENABLED:
|
||||
vectorArray[Ed25519Private]=TestVector(
|
||||
|
|
@ -200,33 +199,33 @@ def vectors():
|
|||
"47CD22B276161AA18BA1E0D13DBE84FE4840E4395D784F555A92E8CF739B"
|
||||
"F86B"
|
||||
)
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
vectorArray[Ed25519Public]=TestVector(
|
||||
key=h2b(
|
||||
"8498C65F4841145F9C51E8BFF4504B5527E0D5753964B7CB3C707A2B9747"
|
||||
"FC96"
|
||||
)
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
if _lib.ED448_ENABLED:
|
||||
vectorArray[Ed448Private]=TestVector(
|
||||
key=h2b("c2b29804e9a893c9e275cac1f8a3033f3d4b78b79eb427ed359fdeb8"
|
||||
"82d657c129c7930936b181971b795167ad18cabeeb52b59b94f115ad"
|
||||
"59"
|
||||
)
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
vectorArray[Ed448Public]=TestVector(
|
||||
key=h2b("89fb2b5a5ab67dd317794cc5f1700cace295b043f3ad73a66299e10a"
|
||||
"d3fc0a28289ddd1c641598a354113867a42e82ad844b4d858d92e4e7"
|
||||
"80"
|
||||
)
|
||||
)
|
||||
) # ty: ignore[missing-argument]
|
||||
return vectorArray
|
||||
|
||||
algo_params = []
|
||||
if _lib.AES_ENABLED:
|
||||
algo_params.append(Aes)
|
||||
algo_params.append(Aes) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.DES3_ENABLED:
|
||||
algo_params.append(Des3)
|
||||
algo_params.append(Des3) # ty: ignore[possibly-unresolved-reference]
|
||||
|
||||
@pytest.fixture(params=algo_params)
|
||||
def cipher_cls(request):
|
||||
|
|
@ -320,7 +319,7 @@ if _lib.CHACHA_ENABLED:
|
|||
return r
|
||||
|
||||
@pytest.fixture
|
||||
def test_chacha_enc_dec(chacha_obj):
|
||||
def test_chacha_enc_dec(chacha_obj, vectors):
|
||||
plaintext = t2b("Everyone gets Friday off.")
|
||||
cyt = chacha_obj.encrypt(plaintext)
|
||||
chacha_obj.set_iv(vectors[ChaCha].iv)
|
||||
|
|
@ -372,25 +371,25 @@ if _lib.RSA_ENABLED:
|
|||
def rsa_private_pem(vectors):
|
||||
with open(vectors[RsaPrivate].pem, "rb") as f:
|
||||
pem = f.read()
|
||||
return RsaPrivate.from_pem(pem)
|
||||
return RsaPrivate.from_pem(pem) # ty: ignore[possibly-missing-attribute]
|
||||
|
||||
@pytest.fixture
|
||||
def rsa_public_pem(vectors):
|
||||
with open(vectors[RsaPublic].pem, "rb") as f:
|
||||
pem = f.read()
|
||||
return RsaPublic.from_pem(pem)
|
||||
return RsaPublic.from_pem(pem) # ty: ignore[possibly-missing-attribute]
|
||||
|
||||
@pytest.fixture
|
||||
def rsa_private_pem_rng(vectors, rng):
|
||||
with open(vectors[RsaPrivate].pem, "rb") as f:
|
||||
pem = f.read()
|
||||
return RsaPrivate.from_pem(pem, rng=rng)
|
||||
return RsaPrivate.from_pem(pem, rng=rng) # ty: ignore[possibly-missing-attribute]
|
||||
|
||||
@pytest.fixture
|
||||
def rsa_public_pem_rng(vectors, rng):
|
||||
with open(vectors[RsaPublic].pem, "rb") as f:
|
||||
pem = f.read()
|
||||
return RsaPublic.from_pem(pem, rng=rng)
|
||||
return RsaPublic.from_pem(pem, rng=rng) # ty: ignore[possibly-missing-attribute]
|
||||
|
||||
def test_new_rsa_raises(vectors):
|
||||
with pytest.raises(WolfCryptError):
|
||||
|
|
@ -401,7 +400,7 @@ if _lib.RSA_ENABLED:
|
|||
|
||||
if _lib.KEYGEN_ENABLED:
|
||||
with pytest.raises(WolfCryptError): # invalid key size
|
||||
RsaPrivate.make_key(16384)
|
||||
RsaPrivate.make_key(16384) # ty: ignore[possibly-missing-attribute]
|
||||
|
||||
|
||||
def test_rsa_encrypt_decrypt(rsa_private, rsa_public):
|
||||
|
|
|
|||
|
|
@ -55,39 +55,39 @@ def _static_attrs():
|
|||
yield Random, "_delete"
|
||||
|
||||
if _lib.SHA_ENABLED:
|
||||
from wolfcrypt.hashes import Sha
|
||||
from wolfcrypt.hashes import Sha # ty: ignore[possibly-missing-import]
|
||||
yield Sha, "_delete"
|
||||
yield Sha, "_copy"
|
||||
if _lib.SHA256_ENABLED:
|
||||
from wolfcrypt.hashes import Sha256
|
||||
from wolfcrypt.hashes import Sha256 # ty: ignore[possibly-missing-import]
|
||||
yield Sha256, "_delete"
|
||||
yield Sha256, "_copy"
|
||||
if _lib.SHA384_ENABLED:
|
||||
from wolfcrypt.hashes import Sha384
|
||||
from wolfcrypt.hashes import Sha384 # ty: ignore[possibly-missing-import]
|
||||
yield Sha384, "_delete"
|
||||
yield Sha384, "_copy"
|
||||
if _lib.SHA512_ENABLED:
|
||||
from wolfcrypt.hashes import Sha512
|
||||
from wolfcrypt.hashes import Sha512 # ty: ignore[possibly-missing-import]
|
||||
yield Sha512, "_delete"
|
||||
yield Sha512, "_copy"
|
||||
if _lib.HMAC_ENABLED:
|
||||
from wolfcrypt.hashes import _Hmac
|
||||
from wolfcrypt.hashes import _Hmac # ty: ignore[possibly-missing-import]
|
||||
yield _Hmac, "_delete"
|
||||
|
||||
if _lib.AESGCM_STREAM_ENABLED:
|
||||
from wolfcrypt.ciphers import AesGcmStream
|
||||
from wolfcrypt.ciphers import AesGcmStream # ty: ignore[possibly-missing-import]
|
||||
yield AesGcmStream, "_delete"
|
||||
if _lib.RSA_ENABLED:
|
||||
from wolfcrypt.ciphers import _Rsa
|
||||
from wolfcrypt.ciphers import _Rsa # ty: ignore[possibly-missing-import]
|
||||
yield _Rsa, "_delete"
|
||||
if _lib.ECC_ENABLED:
|
||||
from wolfcrypt.ciphers import _Ecc
|
||||
from wolfcrypt.ciphers import _Ecc # ty: ignore[possibly-missing-import]
|
||||
yield _Ecc, "_delete"
|
||||
if _lib.ED25519_ENABLED:
|
||||
from wolfcrypt.ciphers import _Ed25519
|
||||
from wolfcrypt.ciphers import _Ed25519 # ty: ignore[possibly-missing-import]
|
||||
yield _Ed25519, "_delete"
|
||||
if _lib.ED448_ENABLED:
|
||||
from wolfcrypt.ciphers import _Ed448
|
||||
from wolfcrypt.ciphers import _Ed448 # ty: ignore[possibly-missing-import]
|
||||
yield _Ed448, "_delete"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
from collections import namedtuple
|
||||
import pytest
|
||||
|
|
@ -116,26 +117,26 @@ def vectors():
|
|||
|
||||
hash_params = []
|
||||
if _lib.SHA_ENABLED:
|
||||
hash_params.append(Sha)
|
||||
hash_params.append(Sha) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA256_ENABLED:
|
||||
hash_params.append(Sha256)
|
||||
hash_params.append(Sha256) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA384_ENABLED:
|
||||
hash_params.append(Sha384)
|
||||
hash_params.append(Sha384) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA512_ENABLED:
|
||||
hash_params.append(Sha512)
|
||||
hash_params.append(Sha512) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA3_ENABLED:
|
||||
hash_params.append(Sha3)
|
||||
hash_params.append(Sha3) # ty: ignore[possibly-unresolved-reference]
|
||||
|
||||
hmac_params = []
|
||||
if _lib.HMAC_ENABLED:
|
||||
if _lib.SHA_ENABLED:
|
||||
hmac_params.append(HmacSha)
|
||||
hmac_params.append(HmacSha) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA256_ENABLED:
|
||||
hmac_params.append(HmacSha256)
|
||||
hmac_params.append(HmacSha256) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA384_ENABLED:
|
||||
hmac_params.append(HmacSha384)
|
||||
hmac_params.append(HmacSha384) # ty: ignore[possibly-unresolved-reference]
|
||||
if _lib.SHA512_ENABLED:
|
||||
hmac_params.append(HmacSha512)
|
||||
hmac_params.append(HmacSha512) # ty: ignore[possibly-unresolved-reference]
|
||||
|
||||
@pytest.fixture(params=(hash_params + hmac_params))
|
||||
def hash_cls(request):
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
from wolfcrypt._ffi import lib as _lib
|
||||
|
||||
|
|
@ -202,7 +203,7 @@ if _lib.ML_DSA_ENABLED:
|
|||
|
||||
# test that the seed type is checked (should be bytes-like, not string)
|
||||
with pytest.raises(TypeError):
|
||||
_ = mldsa_priv.sign_with_seed(message, " " * ML_DSA_SIGNATURE_SEED_LENGTH)
|
||||
_ = mldsa_priv.sign_with_seed(message, "") # ty: ignore[invalid-argument-type]
|
||||
|
||||
def test_sign_with_seed_and_context(mldsa_type, rng):
|
||||
signature_seed = rng.bytes(ML_DSA_SIGNATURE_SEED_LENGTH)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
from wolfcrypt._ffi import lib as _lib
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
# ty: ignore[possibly-missing-import]
|
||||
|
||||
from collections import namedtuple
|
||||
import pytest
|
||||
from wolfcrypt._ffi import lib as _lib
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
# __init__.pyi
|
||||
#
|
||||
# Copyright (C) 2026 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
|
||||
|
||||
import _cffi_backend
|
||||
import wolfcrypt._ffi.lib as lib
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
# lib.pyi
|
||||
#
|
||||
# Copyright (C) 2026 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
|
||||
|
||||
from _cffi_backend import FFI
|
||||
from typing import TypeAlias
|
||||
|
|
@ -34,6 +53,224 @@ SHA384_ENABLED: int
|
|||
SHA512_ENABLED: int
|
||||
WC_RNG_SEED_CB_ENABLED: int
|
||||
|
||||
# Error codes
|
||||
WC_FAILURE: int
|
||||
MAX_CODE_E: int
|
||||
WC_FIRST_E: int
|
||||
WC_SPAN1_FIRST_E: int
|
||||
MP_MEM: int
|
||||
MP_VAL: int
|
||||
MP_WOULDBLOCK: int
|
||||
MP_NOT_INF: int
|
||||
OPEN_RAN_E: int
|
||||
READ_RAN_E: int
|
||||
WINCRYPT_E: int
|
||||
CRYPTGEN_E: int
|
||||
RAN_BLOCK_E: int
|
||||
BAD_MUTEX_E: int
|
||||
WC_TIMEOUT_E: int
|
||||
WC_PENDING_E: int
|
||||
WC_NO_PENDING_E: int
|
||||
MP_INIT_E: int
|
||||
MP_READ_E: int
|
||||
MP_EXPTMOD_E: int
|
||||
MP_TO_E: int
|
||||
MP_SUB_E: int
|
||||
MP_ADD_E: int
|
||||
MP_MUL_E: int
|
||||
MP_MULMOD_E: int
|
||||
MP_MOD_E: int
|
||||
MP_INVMOD_E: int
|
||||
MP_CMP_E: int
|
||||
MP_ZERO_E: int
|
||||
AES_EAX_AUTH_E: int
|
||||
KEY_EXHAUSTED_E: int
|
||||
MEMORY_E: int
|
||||
VAR_STATE_CHANGE_E: int
|
||||
FIPS_DEGRADED_E: int
|
||||
FIPS_CODE_SZ_E: int
|
||||
FIPS_DATA_SZ_E: int
|
||||
RSA_WRONG_TYPE_E: int
|
||||
RSA_BUFFER_E: int
|
||||
BUFFER_E: int
|
||||
ALGO_ID_E: int
|
||||
PUBLIC_KEY_E: int
|
||||
DATE_E: int
|
||||
SUBJECT_E: int
|
||||
ISSUER_E: int
|
||||
CA_TRUE_E: int
|
||||
EXTENSIONS_E: int
|
||||
ASN_PARSE_E: int
|
||||
ASN_VERSION_E: int
|
||||
ASN_GETINT_E: int
|
||||
ASN_RSA_KEY_E: int
|
||||
ASN_OBJECT_ID_E: int
|
||||
ASN_TAG_NULL_E: int
|
||||
ASN_EXPECT_0_E: int
|
||||
ASN_BITSTR_E: int
|
||||
ASN_UNKNOWN_OID_E: int
|
||||
ASN_DATE_SZ_E: int
|
||||
ASN_BEFORE_DATE_E: int
|
||||
ASN_AFTER_DATE_E: int
|
||||
ASN_SIG_OID_E: int
|
||||
ASN_TIME_E: int
|
||||
ASN_INPUT_E: int
|
||||
ASN_SIG_CONFIRM_E: int
|
||||
ASN_SIG_HASH_E: int
|
||||
ASN_SIG_KEY_E: int
|
||||
ASN_DH_KEY_E: int
|
||||
KDF_SRTP_KAT_FIPS_E: int
|
||||
ASN_CRIT_EXT_E: int
|
||||
ASN_ALT_NAME_E: int
|
||||
ASN_NO_PEM_HEADER: int
|
||||
ED25519_KAT_FIPS_E: int
|
||||
ED448_KAT_FIPS_E: int
|
||||
PBKDF2_KAT_FIPS_E: int
|
||||
WC_KEY_MISMATCH_E: int
|
||||
ECC_BAD_ARG_E: int
|
||||
ASN_ECC_KEY_E: int
|
||||
ECC_CURVE_OID_E: int
|
||||
BAD_FUNC_ARG: int
|
||||
NOT_COMPILED_IN: int
|
||||
UNICODE_SIZE_E: int
|
||||
NO_PASSWORD: int
|
||||
ALT_NAME_E: int
|
||||
BAD_OCSP_RESPONDER: int
|
||||
CRL_CERT_DATE_ERR: int
|
||||
AES_GCM_AUTH_E: int
|
||||
AES_CCM_AUTH_E: int
|
||||
ASYNC_INIT_E: int
|
||||
COMPRESS_INIT_E: int
|
||||
COMPRESS_E: int
|
||||
DECOMPRESS_INIT_E: int
|
||||
DECOMPRESS_E: int
|
||||
BAD_ALIGN_E: int
|
||||
ASN_NO_SIGNER_E: int
|
||||
ASN_CRL_CONFIRM_E: int
|
||||
ASN_CRL_NO_SIGNER_E: int
|
||||
ASN_OCSP_CONFIRM_E: int
|
||||
BAD_STATE_E: int
|
||||
BAD_PADDING_E: int
|
||||
REQ_ATTRIBUTE_E: int
|
||||
PKCS7_OID_E: int
|
||||
PKCS7_RECIP_E: int
|
||||
FIPS_NOT_ALLOWED_E: int
|
||||
ASN_NAME_INVALID_E: int
|
||||
RNG_FAILURE_E: int
|
||||
HMAC_MIN_KEYLEN_E: int
|
||||
RSA_PAD_E: int
|
||||
LENGTH_ONLY_E: int
|
||||
IN_CORE_FIPS_E: int
|
||||
AES_KAT_FIPS_E: int
|
||||
DES3_KAT_FIPS_E: int
|
||||
HMAC_KAT_FIPS_E: int
|
||||
RSA_KAT_FIPS_E: int
|
||||
DRBG_KAT_FIPS_E: int
|
||||
DRBG_CONT_FIPS_E: int
|
||||
AESGCM_KAT_FIPS_E: int
|
||||
THREAD_STORE_KEY_E: int
|
||||
THREAD_STORE_SET_E: int
|
||||
MAC_CMP_FAILED_E: int
|
||||
IS_POINT_E: int
|
||||
ECC_INF_E: int
|
||||
ECC_PRIV_KEY_E: int
|
||||
ECC_OUT_OF_RANGE_E: int
|
||||
SRP_CALL_ORDER_E: int
|
||||
SRP_VERIFY_E: int
|
||||
SRP_BAD_KEY_E: int
|
||||
ASN_NO_SKID: int
|
||||
ASN_NO_AKID: int
|
||||
ASN_NO_KEYUSAGE: int
|
||||
SKID_E: int
|
||||
AKID_E: int
|
||||
KEYUSAGE_E: int
|
||||
CERTPOLICIES_E: int
|
||||
WC_INIT_E: int
|
||||
SIG_VERIFY_E: int
|
||||
BAD_COND_E: int
|
||||
SIG_TYPE_E: int
|
||||
HASH_TYPE_E: int
|
||||
FIPS_INVALID_VER_E: int
|
||||
WC_KEY_SIZE_E: int
|
||||
ASN_COUNTRY_SIZE_E: int
|
||||
MISSING_RNG_E: int
|
||||
ASN_PATHLEN_SIZE_E: int
|
||||
ASN_PATHLEN_INV_E: int
|
||||
BAD_KEYWRAP_ALG_E: int
|
||||
BAD_KEYWRAP_IV_E: int
|
||||
WC_CLEANUP_E: int
|
||||
ECC_CDH_KAT_FIPS_E: int
|
||||
DH_CHECK_PUB_E: int
|
||||
BAD_PATH_ERROR: int
|
||||
ASYNC_OP_E: int
|
||||
ECC_PRIVATEONLY_E: int
|
||||
EXTKEYUSAGE_E: int
|
||||
WC_HW_E: int
|
||||
WC_HW_WAIT_E: int
|
||||
PSS_SALTLEN_E: int
|
||||
PRIME_GEN_E: int
|
||||
BER_INDEF_E: int
|
||||
RSA_OUT_OF_RANGE_E: int
|
||||
RSAPSS_PAT_FIPS_E: int
|
||||
ECDSA_PAT_FIPS_E: int
|
||||
DH_KAT_FIPS_E: int
|
||||
AESCCM_KAT_FIPS_E: int
|
||||
SHA3_KAT_FIPS_E: int
|
||||
ECDHE_KAT_FIPS_E: int
|
||||
AES_GCM_OVERFLOW_E: int
|
||||
AES_CCM_OVERFLOW_E: int
|
||||
RSA_KEY_PAIR_E: int
|
||||
DH_CHECK_PRIV_E: int
|
||||
WC_AFALG_SOCK_E: int
|
||||
WC_DEVCRYPTO_E: int
|
||||
ZLIB_INIT_ERROR: int
|
||||
ZLIB_COMPRESS_ERROR: int
|
||||
ZLIB_DECOMPRESS_ERROR: int
|
||||
PKCS7_NO_SIGNER_E: int
|
||||
WC_PKCS7_WANT_READ_E: int
|
||||
CRYPTOCB_UNAVAILABLE: int
|
||||
PKCS7_SIGNEEDS_CHECK: int
|
||||
PSS_SALTLEN_RECOVER_E: int
|
||||
CHACHA_POLY_OVERFLOW: int
|
||||
ASN_SELF_SIGNED_E: int
|
||||
SAKKE_VERIFY_FAIL_E: int
|
||||
MISSING_IV: int
|
||||
MISSING_KEY: int
|
||||
BAD_LENGTH_E: int
|
||||
ECDSA_KAT_FIPS_E: int
|
||||
RSA_PAT_FIPS_E: int
|
||||
KDF_TLS12_KAT_FIPS_E: int
|
||||
KDF_TLS13_KAT_FIPS_E: int
|
||||
KDF_SSH_KAT_FIPS_E: int
|
||||
DHE_PCT_E: int
|
||||
ECC_PCT_E: int
|
||||
FIPS_PRIVATE_KEY_LOCKED_E: int
|
||||
PROTOCOLCB_UNAVAILABLE: int
|
||||
AES_SIV_AUTH_E: int
|
||||
NO_VALID_DEVID: int
|
||||
IO_FAILED_E: int
|
||||
SYSLIB_FAILED_E: int
|
||||
USE_HW_PSK: int
|
||||
ENTROPY_RT_E: int
|
||||
ENTROPY_APT_E: int
|
||||
ASN_DEPTH_E: int
|
||||
ASN_LEN_E: int
|
||||
SM4_GCM_AUTH_E: int
|
||||
SM4_CCM_AUTH_E: int
|
||||
WC_SPAN1_LAST_E: int
|
||||
WC_SPAN1_MIN_CODE_E: int
|
||||
WC_SPAN2_FIRST_E: int
|
||||
DEADLOCK_AVERTED_E: int
|
||||
ASCON_AUTH_E: int
|
||||
WC_ACCEL_INHIBIT_E: int
|
||||
BAD_INDEX_E: int
|
||||
INTERRUPTED_E: int
|
||||
WC_SPAN2_LAST_E: int
|
||||
WC_LAST_E: int
|
||||
WC_SPAN2_MIN_CODE_E: int
|
||||
MIN_CODE_E: int
|
||||
# end of the error codes
|
||||
|
||||
FIPS_VERSION: int
|
||||
|
||||
WC_MGF1NONE: int
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ from wolfcrypt._ffi import ffi as _ffi
|
|||
from wolfcrypt._ffi import lib as _lib
|
||||
from wolfcrypt.exceptions import WolfCryptError, WolfCryptApiError
|
||||
from wolfcrypt.hashes import _Hash
|
||||
from .types import SupportsRsaSign, SupportsRsaVerify
|
||||
|
||||
if _lib.SHA_ENABLED:
|
||||
from wolfcrypt.hashes import Sha # ty: ignore[possibly-missing-import]
|
||||
|
|
@ -78,7 +79,7 @@ if _lib.ASN_ENABLED:
|
|||
else:
|
||||
raise WolfCryptError(f"Unknown hash class {hash_cls.__name__}")
|
||||
|
||||
def make_signature(data: bytes, hash_cls: type[_Hash], key = None) -> bytes:
|
||||
def make_signature(data: bytes, hash_cls: type[_Hash], key: SupportsRsaSign | None = None) -> bytes:
|
||||
hash_obj = hash_cls()
|
||||
hash_obj.update(data)
|
||||
digest = hash_obj.digest()
|
||||
|
|
@ -96,7 +97,7 @@ if _lib.ASN_ENABLED:
|
|||
else:
|
||||
return plaintext_sig
|
||||
|
||||
def check_signature(signature: bytes, data: bytes, hash_cls: type[_Hash], pub_key) -> bool:
|
||||
def check_signature(signature: bytes, data: bytes, hash_cls: type[_Hash], pub_key: SupportsRsaVerify) -> bool:
|
||||
computed_signature = make_signature(data, hash_cls)
|
||||
decrypted_signature = pub_key.verify(signature)
|
||||
return _hmac.compare_digest(computed_signature, decrypted_signature)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from collections.abc import Sequence
|
||||
from enum import IntEnum
|
||||
|
||||
from typing_extensions import override
|
||||
|
|
@ -32,6 +33,7 @@ from wolfcrypt.exceptions import WolfCryptError, WolfCryptApiError
|
|||
from wolfcrypt.hashes import hash_type_to_cls
|
||||
from wolfcrypt.random import Random
|
||||
from wolfcrypt.utils import BytesOrStr, t2b
|
||||
from .types import SupportsRsaSign, SupportsRsaVerify
|
||||
|
||||
if _lib.ASN_ENABLED:
|
||||
from wolfcrypt.asn import pem_to_der # ty: ignore[possibly-missing-import]
|
||||
|
|
@ -185,7 +187,7 @@ class _Cipher(ABC):
|
|||
def _decrypt(self, destination: _ffi.CData, source: bytes) -> int: ...
|
||||
|
||||
@classmethod
|
||||
def new(cls, key: BytesOrStr, mode: int, IV: BytesOrStr | None = None) -> _Cipher: # pylint: disable=W0613
|
||||
def new(cls, key: BytesOrStr, mode: int, IV: BytesOrStr | None = None, **kwargs: int) -> _Cipher: # pylint: disable=W0613
|
||||
"""
|
||||
Returns a ciphering object, using the secret key contained in
|
||||
the string **key**, and using the feedback mode **mode**, which
|
||||
|
|
@ -326,7 +328,7 @@ if _lib.AES_SIV_ENABLED:
|
|||
if len(self._key) not in AesSiv._key_sizes:
|
||||
raise ValueError(f"key must be {AesSiv._key_sizes} in length, not {len(self._key)}")
|
||||
|
||||
def encrypt(self, associated_data: BytesOrStr | list[BytesOrStr], nonce: BytesOrStr, plaintext: BytesOrStr) -> tuple[bytes, bytes]:
|
||||
def encrypt(self, associated_data: BytesOrStr | Sequence[bytes] | Sequence[bytearray] | Sequence[str] | Sequence[memoryview], nonce: BytesOrStr, plaintext: BytesOrStr) -> tuple[bytes, bytes]:
|
||||
"""
|
||||
Encrypt plaintext data using the nonce provided. The associated
|
||||
data is not encrypted but is included in the authentication tag.
|
||||
|
|
@ -353,7 +355,7 @@ if _lib.AES_SIV_ENABLED:
|
|||
raise WolfCryptApiError("AES-SIV encryption error", ret)
|
||||
return _ffi.buffer(siv)[:], _ffi.buffer(ciphertext)[:]
|
||||
|
||||
def decrypt(self, associated_data: BytesOrStr | list[BytesOrStr], nonce: BytesOrStr, siv: BytesOrStr, ciphertext: BytesOrStr) -> bytes:
|
||||
def decrypt(self, associated_data: BytesOrStr | Sequence[bytes] | Sequence[bytearray] | Sequence[str] | Sequence[memoryview], nonce: BytesOrStr, siv: BytesOrStr, ciphertext: BytesOrStr) -> bytes:
|
||||
"""
|
||||
Decrypt the ciphertext using the nonce and SIV provided.
|
||||
The integrity of the associated data is checked.
|
||||
|
|
@ -383,7 +385,7 @@ if _lib.AES_SIV_ENABLED:
|
|||
return _ffi.buffer(plaintext)[:]
|
||||
|
||||
@staticmethod
|
||||
def _prepare_associated_data(associated_data: BytesOrStr | list[BytesOrStr]) -> tuple[_ffi.CData, bytes | list[bytes]]:
|
||||
def _prepare_associated_data(associated_data: BytesOrStr | Sequence[bytes] | Sequence[bytearray] | Sequence[str] | Sequence[memoryview]) -> tuple[_ffi.CData, bytes | list[bytes]]:
|
||||
"""
|
||||
Prepare associated data for sending to C library.
|
||||
|
||||
|
|
@ -801,7 +803,7 @@ if _lib.RSA_ENABLED:
|
|||
|
||||
|
||||
|
||||
class RsaPublic(_Rsa):
|
||||
class RsaPublic(_Rsa, SupportsRsaVerify):
|
||||
def __init__(self, key: BytesOrStr, hash_type: int | None = None, rng: Random | None = None) -> None:
|
||||
super().__init__(rng)
|
||||
|
||||
|
|
@ -870,6 +872,7 @@ if _lib.RSA_ENABLED:
|
|||
|
||||
return _ffi.buffer(ciphertext)[:]
|
||||
|
||||
@override
|
||||
def verify(self, signature: BytesOrStr) -> bytes:
|
||||
"""
|
||||
Verifies **signature**, using the public key data in the
|
||||
|
|
@ -933,7 +936,7 @@ if _lib.RSA_ENABLED:
|
|||
return ret == 0
|
||||
|
||||
|
||||
class RsaPrivate(RsaPublic):
|
||||
class RsaPrivate(RsaPublic, SupportsRsaSign):
|
||||
if _lib.KEYGEN_ENABLED:
|
||||
@classmethod
|
||||
def make_key(cls, size: int, rng: Random | None = None, hash_type: int | None = None) -> RsaPrivate:
|
||||
|
|
@ -1067,6 +1070,7 @@ if _lib.RSA_ENABLED:
|
|||
|
||||
return _ffi.buffer(plaintext, ret)[:]
|
||||
|
||||
@override
|
||||
def sign(self, plaintext: BytesOrStr) -> bytes:
|
||||
"""
|
||||
Signs **plaintext**, using the private key data in the object.
|
||||
|
|
@ -1424,7 +1428,7 @@ if _lib.ECC_ENABLED:
|
|||
return _ffi.buffer(Qx, qx_size[0])[:], _ffi.buffer(Qy,
|
||||
qy_size[0])[:], _ffi.buffer(d, d_size[0])[:]
|
||||
|
||||
def shared_secret(self, peer: EccPrivate) -> bytes:
|
||||
def shared_secret(self, peer: EccPublic) -> bytes:
|
||||
"""
|
||||
Generates a new secret key using the private key data in the object
|
||||
and the peer's public key.
|
||||
|
|
@ -2562,6 +2566,9 @@ if _lib.ML_DSA_ENABLED:
|
|||
out_size = _ffi.new("word32 *")
|
||||
out_size[0] = in_size
|
||||
|
||||
if not isinstance(seed, (list, tuple, bytes)):
|
||||
raise TypeError("seed must be bytes or list/tuple")
|
||||
|
||||
if len(seed) != ML_DSA_SIGNATURE_SEED_LENGTH:
|
||||
raise ValueError(
|
||||
f"Seed for generating a signature must be {ML_DSA_SIGNATURE_SEED_LENGTH} bytes."
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ from wolfcrypt.utils import t2b
|
|||
if _lib.HKDF_ENABLED:
|
||||
from wolfcrypt.hashes import _Hmac # ty: ignore[possibly-missing-import]
|
||||
|
||||
def HKDF(hash_cls: _Hmac, in_key: bytes | str, salt: bytes | str | None = None, info: bytes | str | None = None, out_len: int | None = None) -> bytes:
|
||||
def HKDF(hash_cls: type[_Hmac], in_key: bytes | str, salt: bytes | str | None = None, info: bytes | str | None = None, out_len: int | None = None) -> bytes:
|
||||
"""
|
||||
Perform HKDF Extract-and-Expand in one call (wraps wc_HKDF).
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ if _lib.HKDF_ENABLED:
|
|||
|
||||
return _ffi.buffer(out, out_len)[:]
|
||||
|
||||
def HKDF_Extract(hash_cls: _Hmac, salt: bytes | str | None, in_key: bytes | str) -> bytes:
|
||||
def HKDF_Extract(hash_cls: type[_Hmac], salt: bytes | str | None, in_key: bytes | str) -> bytes:
|
||||
"""
|
||||
HKDF-Extract: PRK = HMAC-Hash(salt, IKM)
|
||||
Wraps wc_HKDF_Extract.
|
||||
|
|
@ -102,7 +102,7 @@ if _lib.HKDF_ENABLED:
|
|||
|
||||
return _ffi.buffer(out, out_len)[:]
|
||||
|
||||
def HKDF_Expand(hash_cls: _Hmac, prk: bytes | str, info: bytes | str | None, out_len: int) -> bytes:
|
||||
def HKDF_Expand(hash_cls: type[_Hmac], prk: bytes | str, info: bytes | str | None, out_len: int) -> bytes:
|
||||
"""
|
||||
HKDF-Expand: OKM = HKDF-Expand(PRK, info, L)
|
||||
Wraps wc_HKDF_Expand.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# types.py
|
||||
#
|
||||
# Copyright (C) 2026 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
|
||||
|
||||
from abc import abstractmethod
|
||||
from typing import Protocol
|
||||
|
||||
from .utils import BytesOrStr
|
||||
|
||||
|
||||
class SupportsRsaSign(Protocol):
|
||||
@abstractmethod
|
||||
def sign(self, plaintext: BytesOrStr) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
||||
class SupportsRsaVerify(Protocol):
|
||||
@abstractmethod
|
||||
def verify(self, signature: BytesOrStr) -> bytes:
|
||||
raise NotImplementedError
|
||||
Loading…
Reference in New Issue