Address review comments and annotate overrides.
parent
2081edd6d7
commit
1fb34e5cd8
|
|
@ -173,7 +173,6 @@ def test_random_delete_receives_only_native_object():
|
|||
r = Random()
|
||||
native = r.native_object
|
||||
r.__del__()
|
||||
r.native_object = None # prevent real cleanup on the way out
|
||||
assert received, "recorder was never called"
|
||||
args, kwargs = received[-1]
|
||||
assert kwargs == {}
|
||||
|
|
|
|||
|
|
@ -318,13 +318,13 @@ def wc_dilithium_export_public(key: DilithiumKey, public: BytePtr, public_len: I
|
|||
def wc_dilithium_verify_ctx_msg(sig: bytes, sig_len: int, ctx: bytes, ctx_len: int, msg: bytes, msg_len: int, res: IntPtr, key: DilithiumKey) -> int: ...
|
||||
def wc_dilithium_verify_msg(sig: bytes, sig_len: int, msg: bytes, msg_len: int, res: IntPtr, key: DilithiumKey) -> int: ...
|
||||
def wc_dilithium_make_key(key: DilithiumKey, rng: RNG) -> int: ...
|
||||
def wc_dilithium_make_key_from_seed(key: DilithiumKey, seed: bytes) -> int: ...
|
||||
def wc_dilithium_make_key_from_seed(key: DilithiumKey, seed: bytes | list[int] | tuple[int]) -> int: ...
|
||||
def wc_dilithium_export_private(key: DilithiumKey, out: BytePtr, out_len: IntPtr) -> int: ...
|
||||
def wc_dilithium_import_private(priv: bytes, priv_size: int, key: DilithiumKey) -> int: ...
|
||||
def wc_dilithium_sign_ctx_msg(ctx: bytes, ctx_len: int, msg: bytes, msg_len: int, sig: BytePtr, sig_len: IntPtr, key: DilithiumKey, rng: RNG) -> int: ...
|
||||
def wc_dilithium_sign_msg(msg: bytes, msg_len: int, sig: BytePtr, sig_len: IntPtr, key: DilithiumKey, rng: RNG) -> int: ...
|
||||
def wc_dilithium_sign_ctx_msg_with_seed(ctx: bytes, ctx_len: int, msg: bytes, msg_len: int, sig: BytePtr, sig_len: IntPtr, key: DilithiumKey, seed: bytes) -> int: ...
|
||||
def wc_dilithium_sign_msg_with_seed(msg: bytes, msg_len: int, sig: BytePtr, sig_len: IntPtr, key: DilithiumKey, seed: bytes) -> int: ...
|
||||
def wc_dilithium_sign_ctx_msg_with_seed(ctx: bytes, ctx_len: int, msg: bytes, msg_len: int, sig: BytePtr, sig_len: IntPtr, key: DilithiumKey, seed: bytes | list[int] | tuple[int]) -> int: ...
|
||||
def wc_dilithium_sign_msg_with_seed(msg: bytes, msg_len: int, sig: BytePtr, sig_len: IntPtr, key: DilithiumKey, seed: bytes | list[int] | tuple[int]) -> int: ...
|
||||
def wc_MlDsaKey_GetPrivLen(key: DilithiumKey, len: IntPtr) -> int: ...
|
||||
def wc_MlDsaKey_GetPubLen(key: DilithiumKey, len: IntPtr) -> int: ...
|
||||
def wc_MlDsaKey_GetSigLen(key: DilithiumKey, len: IntPtr) -> int: ...
|
||||
|
|
|
|||
|
|
@ -25,14 +25,17 @@ from __future__ import annotations
|
|||
from abc import ABC, abstractmethod
|
||||
from enum import IntEnum
|
||||
|
||||
from typing_extensions import override
|
||||
from wolfcrypt._ffi import ffi as _ffi
|
||||
from wolfcrypt._ffi import lib as _lib
|
||||
from wolfcrypt.utils import BytesOrStr, t2b
|
||||
from wolfcrypt.random import Random
|
||||
from wolfcrypt.asn import pem_to_der
|
||||
from wolfcrypt.hashes import hash_type_to_cls
|
||||
|
||||
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
|
||||
|
||||
if _lib.ASN_ENABLED:
|
||||
from wolfcrypt.asn import pem_to_der # ty: ignore[possibly-missing-import]
|
||||
|
||||
|
||||
# key direction flags
|
||||
_ENCRYPTION = 0
|
||||
|
|
@ -115,7 +118,6 @@ if _lib.RSA_ENABLED:
|
|||
HASH_TYPE_BLAKE2S = _lib.WC_HASH_TYPE_BLAKE2S
|
||||
|
||||
|
||||
|
||||
class _Cipher(ABC):
|
||||
"""
|
||||
A **PEP 272: Block Encryption Algorithms** compliant
|
||||
|
|
@ -273,6 +275,7 @@ if _lib.AES_ENABLED:
|
|||
_key_sizes = [16, 24, 32]
|
||||
_native_type = "Aes *"
|
||||
|
||||
@override
|
||||
def _set_key(self, direction: int) -> int:
|
||||
if direction == _ENCRYPTION:
|
||||
assert self._enc is not None
|
||||
|
|
@ -285,6 +288,7 @@ if _lib.AES_ENABLED:
|
|||
return _lib.wc_AesSetKey(
|
||||
self._dec, self._key, len(self._key), self._IV, _DECRYPTION)
|
||||
|
||||
@override
|
||||
def _encrypt(self, destination: _ffi.CData, source: bytes) -> int:
|
||||
assert self._enc is not None
|
||||
if self.mode == MODE_CBC:
|
||||
|
|
@ -296,6 +300,7 @@ if _lib.AES_ENABLED:
|
|||
else:
|
||||
raise ValueError("Invalid mode associated to cipher")
|
||||
|
||||
@override
|
||||
def _decrypt(self, destination: _ffi.CData, source: bytes) -> int:
|
||||
assert self._dec is not None
|
||||
if self.mode == MODE_CBC:
|
||||
|
|
@ -398,7 +403,7 @@ if _lib.AES_SIV_ENABLED:
|
|||
associated_data_bytes = t2b(associated_data)
|
||||
result = _ffi.new("AesSivAssoc[1]")
|
||||
result[0].assoc = _ffi.from_buffer(associated_data_bytes)
|
||||
result[0].assocSz = len(associated_data)
|
||||
result[0].assocSz = len(associated_data_bytes)
|
||||
else:
|
||||
# It is assumed that a list is provided.
|
||||
num_blocks = len(associated_data)
|
||||
|
|
@ -547,7 +552,7 @@ if _lib.CHACHA_ENABLED:
|
|||
_IV_nonce = b""
|
||||
_IV_counter = 0
|
||||
|
||||
def __init__(self, key: BytesOrStr="", _size: int= 32) -> None: # pylint: disable=unused-argument
|
||||
def __init__(self, key: BytesOrStr = "", size: int = 32) -> None: # pylint: disable=unused-argument
|
||||
# size is kept for backwards compatibility; key length is now
|
||||
# derived from the actual key and validated against _key_sizes.
|
||||
self._native_object = _ffi.new(self._native_type)
|
||||
|
|
@ -582,6 +587,7 @@ if _lib.CHACHA_ENABLED:
|
|||
# collide with _ENCRYPTION (0) or _DECRYPTION (1).
|
||||
_REKEY_BOTH = -1
|
||||
|
||||
@override
|
||||
def _set_key(self, direction: int) -> int:
|
||||
if self._key is None:
|
||||
return -1
|
||||
|
|
@ -608,11 +614,12 @@ if _lib.CHACHA_ENABLED:
|
|||
return ret
|
||||
return 0
|
||||
|
||||
@override
|
||||
def _encrypt(self, destination: _ffi.CData, source: bytes) -> int:
|
||||
assert self._enc is not None
|
||||
return _lib.wc_Chacha_Process(self._enc, destination,
|
||||
source, len(source))
|
||||
|
||||
@override
|
||||
def _decrypt(self, destination: _ffi.CData, source: bytes) -> int:
|
||||
assert self._dec is not None
|
||||
return _lib.wc_Chacha_Process(self._dec,
|
||||
|
|
@ -726,6 +733,7 @@ if _lib.DES3_ENABLED:
|
|||
raise ValueError("Des3 only supports MODE_CBC")
|
||||
super().__init__(key, mode, IV)
|
||||
|
||||
@override
|
||||
def _set_key(self, direction: int) -> int:
|
||||
if direction == _ENCRYPTION:
|
||||
assert self._enc is not None
|
||||
|
|
@ -734,10 +742,12 @@ if _lib.DES3_ENABLED:
|
|||
assert self._dec is not None
|
||||
return _lib.wc_Des3_SetKey(self._dec, self._key, self._IV, _DECRYPTION)
|
||||
|
||||
@override
|
||||
def _encrypt(self, destination: _ffi.CData, source: bytes) -> int:
|
||||
assert self._enc is not None
|
||||
return _lib.wc_Des3_CbcEncrypt(self._enc, destination, source, len(source))
|
||||
|
||||
@override
|
||||
def _decrypt(self, destination: _ffi.CData, source: bytes) -> int:
|
||||
assert self._dec is not None
|
||||
return _lib.wc_Des3_CbcDecrypt(self._dec, destination, source, len(source))
|
||||
|
|
@ -795,15 +805,13 @@ if _lib.RSA_ENABLED:
|
|||
def __init__(self, key: BytesOrStr, hash_type: int | None = None, rng: Random | None = None) -> None:
|
||||
super().__init__(rng)
|
||||
|
||||
if key is not None:
|
||||
key = t2b(key)
|
||||
key = t2b(key)
|
||||
self._hash_type = hash_type
|
||||
|
||||
idx = _ffi.new("word32*")
|
||||
idx[0] = 0
|
||||
|
||||
ret = _lib.wc_RsaPublicKeyDecode(key, idx,
|
||||
self.native_object, len(key))
|
||||
ret = _lib.wc_RsaPublicKeyDecode(key, idx, self.native_object, len(key))
|
||||
if ret < 0:
|
||||
raise WolfCryptApiError("Invalid key error", ret)
|
||||
|
||||
|
|
@ -981,6 +989,7 @@ if _lib.RSA_ENABLED:
|
|||
raise WolfCryptApiError("Invalid key size error", self.output_size)
|
||||
|
||||
if _lib.ASN_ENABLED:
|
||||
@override
|
||||
@classmethod
|
||||
def from_pem(cls, file: bytes, hash_type: int | None = None, rng: Random | None = None) -> RsaPrivate:
|
||||
der = pem_to_der(file, _lib.PRIVATEKEY_TYPE)
|
||||
|
|
@ -1334,6 +1343,7 @@ if _lib.ECC_ENABLED:
|
|||
|
||||
return ecc
|
||||
|
||||
@override
|
||||
def decode_key(self, key: BytesOrStr) -> None:
|
||||
"""
|
||||
Decodes an ECC private key from an ASN sequence.
|
||||
|
|
@ -1352,6 +1362,7 @@ if _lib.ECC_ENABLED:
|
|||
if self.max_signature_size <= 0: # pragma: no cover
|
||||
raise WolfCryptError(f"Key decode error ({self.max_signature_size})")
|
||||
|
||||
@override
|
||||
def decode_key_raw(self, qx: BytesOrStr, qy: BytesOrStr, d: BytesOrStr, curve_id: int = ECC_SECP256R1) -> None:
|
||||
"""
|
||||
Decodes an ECC private key from its raw elements: public (Qx,Qy)
|
||||
|
|
@ -1373,6 +1384,7 @@ if _lib.ECC_ENABLED:
|
|||
if ret != 0:
|
||||
raise WolfCryptApiError("Key decode error", ret)
|
||||
|
||||
@override
|
||||
def encode_key(self) -> bytes:
|
||||
"""
|
||||
Encodes the ECC private key in an ASN sequence.
|
||||
|
|
@ -1387,6 +1399,7 @@ if _lib.ECC_ENABLED:
|
|||
|
||||
return _ffi.buffer(key, ret)[:]
|
||||
|
||||
@override
|
||||
def encode_key_raw(self) -> tuple[bytes, bytes, bytes]:
|
||||
"""
|
||||
Encodes the ECC private key in its three raw elements
|
||||
|
|
@ -1620,6 +1633,7 @@ if _lib.ED25519_ENABLED:
|
|||
|
||||
return ed25519
|
||||
|
||||
@override
|
||||
def decode_key(self, key: BytesOrStr, pub: bytes | None = None) -> None:
|
||||
"""
|
||||
Decodes an ED25519 private + pub key
|
||||
|
|
@ -1656,6 +1670,7 @@ if _lib.ED25519_ENABLED:
|
|||
if self.max_signature_size <= 0: # pragma: no cover
|
||||
raise WolfCryptError(f"Key decode error ({self.max_signature_size})")
|
||||
|
||||
@override
|
||||
def encode_key(self) -> tuple[bytes, bytes]:
|
||||
"""
|
||||
Encodes the ED25519 private key.
|
||||
|
|
@ -1827,6 +1842,7 @@ if _lib.ED448_ENABLED:
|
|||
|
||||
return ed448
|
||||
|
||||
@override
|
||||
def decode_key(self, key: BytesOrStr, pub: bytes | None = None) -> None:
|
||||
"""
|
||||
Decodes an ED448 private + pub key
|
||||
|
|
@ -1863,6 +1879,7 @@ if _lib.ED448_ENABLED:
|
|||
if self.max_signature_size <= 0: # pragma: no cover
|
||||
raise WolfCryptError(f"Key decode error ({self.max_signature_size})")
|
||||
|
||||
@override
|
||||
def encode_key(self) -> tuple[bytes, bytes]:
|
||||
"""
|
||||
Encodes the ED448 private key.
|
||||
|
|
@ -2030,7 +2047,7 @@ if _lib.ML_KEM_ENABLED:
|
|||
pub_key_bytestype = t2b(pub_key)
|
||||
ret = _lib.wc_KyberKey_DecodePublicKey(
|
||||
self.native_object,
|
||||
_ffi.from_buffer(pub_key_bytestype),
|
||||
pub_key_bytestype,
|
||||
len(pub_key_bytestype),
|
||||
)
|
||||
|
||||
|
|
@ -2376,23 +2393,22 @@ if _lib.ML_DSA_ENABLED:
|
|||
return mldsa_priv
|
||||
|
||||
@classmethod
|
||||
def make_key_from_seed(cls, mldsa_type: MlDsaType, seed: bytes) -> MlDsaPrivate:
|
||||
def make_key_from_seed(cls, mldsa_type: MlDsaType, seed: bytes | list[int] | tuple[int]) -> MlDsaPrivate:
|
||||
"""
|
||||
Deterministically generate the key from a seed.
|
||||
|
||||
:param mldsa_type: ML-DSA type
|
||||
:type mldsa_type: MlDsaType
|
||||
:param seed: the (32 byte) seed from which to deterministically create the key
|
||||
:type seed: bytes
|
||||
:type seed: bytes or list/tuple of int
|
||||
"""
|
||||
mldsa_priv = cls(mldsa_type)
|
||||
seed_bytes = t2b(seed)
|
||||
if len(seed_bytes) != cls.ML_DSA_KEYGEN_SEED_LENGTH:
|
||||
if len(seed) != cls.ML_DSA_KEYGEN_SEED_LENGTH:
|
||||
raise ValueError(
|
||||
f"Seed for generating ML-DSA key must be {cls.ML_DSA_KEYGEN_SEED_LENGTH} bytes"
|
||||
)
|
||||
|
||||
ret = _lib.wc_dilithium_make_key_from_seed(mldsa_priv.native_object, seed_bytes)
|
||||
ret = _lib.wc_dilithium_make_key_from_seed(mldsa_priv.native_object, seed)
|
||||
|
||||
if ret < 0: # pragma: no cover
|
||||
raise WolfCryptApiError("wc_dilithium_make_key_from_seed() error", ret)
|
||||
|
|
@ -2525,12 +2541,12 @@ if _lib.ML_DSA_ENABLED:
|
|||
|
||||
return _ffi.buffer(signature, out_size[0])[:]
|
||||
|
||||
def sign_with_seed(self, message: BytesOrStr, seed: bytes, ctx: BytesOrStr | None = None) -> bytes:
|
||||
def sign_with_seed(self, message: BytesOrStr, seed: bytes | list[int] | tuple[int], ctx: BytesOrStr | None = None) -> bytes:
|
||||
"""
|
||||
:param message: message to be signed
|
||||
:type message: bytes or str
|
||||
:param seed: 32-byte seed for deterministic signature generation.
|
||||
:type seed: bytes
|
||||
:type seed: bytes or list/tuple of int (value in the range 0-255)
|
||||
:param ctx: context, maximum 255 bytes (optional by default but that requires support for no-context
|
||||
signing/verification compiled in; pass empty string "" for FIPS-204 empty-context signing).
|
||||
:type ctx: bytes or str. None for no-context signing.
|
||||
|
|
@ -2548,8 +2564,7 @@ if _lib.ML_DSA_ENABLED:
|
|||
|
||||
if len(seed) != ML_DSA_SIGNATURE_SEED_LENGTH:
|
||||
raise ValueError(
|
||||
f"Seed for generating a signature must be {ML_DSA_SIGNATURE_SEED_LENGTH}"
|
||||
"bytes."
|
||||
f"Seed for generating a signature must be {ML_DSA_SIGNATURE_SEED_LENGTH} bytes."
|
||||
)
|
||||
|
||||
if ctx is not None:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ from __future__ import annotations
|
|||
from abc import ABC, abstractmethod
|
||||
|
||||
from _cffi_backend import FFI
|
||||
from typing_extensions import override
|
||||
from wolfcrypt._ffi import ffi as _ffi
|
||||
from wolfcrypt._ffi import lib as _lib
|
||||
from wolfcrypt.exceptions import WolfCryptApiError
|
||||
|
|
@ -69,8 +70,7 @@ class _Hash(ABC):
|
|||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def new(cls, string: BytesOrStr | None) -> _Hash: ...
|
||||
|
||||
def new(cls, string: BytesOrStr | None) -> _Hash: ...
|
||||
|
||||
def copy(self) -> _Hash:
|
||||
"""
|
||||
|
|
@ -168,6 +168,7 @@ class _Hash(ABC):
|
|||
|
||||
|
||||
class _Sha(_Hash):
|
||||
@override
|
||||
@classmethod
|
||||
def new(cls, string: BytesOrStr | None = None) -> _Hash:
|
||||
"""
|
||||
|
|
@ -196,12 +197,15 @@ if _lib.SHA_ENABLED:
|
|||
if hasattr(self, '_native_object') and not getattr(self, '_shallow_copy', False):
|
||||
self._delete(self._native_object)
|
||||
|
||||
@override
|
||||
def _init(self) -> int:
|
||||
return _lib.wc_InitSha(self._native_object)
|
||||
|
||||
@override
|
||||
def _update(self, data: bytes) -> int:
|
||||
return _lib.wc_ShaUpdate(self._native_object, data, len(data))
|
||||
|
||||
@override
|
||||
def _final(self, obj: FFI.CData, ret: FFI.CData) -> int:
|
||||
return _lib.wc_ShaFinal(obj, ret)
|
||||
|
||||
|
|
@ -224,12 +228,15 @@ if _lib.SHA256_ENABLED:
|
|||
if hasattr(self, '_native_object') and not getattr(self, '_shallow_copy', False):
|
||||
self._delete(self._native_object)
|
||||
|
||||
@override
|
||||
def _init(self) -> int:
|
||||
return _lib.wc_InitSha256(self._native_object)
|
||||
|
||||
@override
|
||||
def _update(self, data: bytes) -> int:
|
||||
return _lib.wc_Sha256Update(self._native_object, data, len(data))
|
||||
|
||||
@override
|
||||
def _final(self, obj: FFI.CData, ret: FFI.CData) -> int:
|
||||
return _lib.wc_Sha256Final(obj, ret)
|
||||
|
||||
|
|
@ -252,12 +259,15 @@ if _lib.SHA384_ENABLED:
|
|||
if hasattr(self, '_native_object') and not getattr(self, '_shallow_copy', False):
|
||||
self._delete(self._native_object)
|
||||
|
||||
@override
|
||||
def _init(self) -> int:
|
||||
return _lib.wc_InitSha384(self._native_object)
|
||||
|
||||
@override
|
||||
def _update(self, data: bytes) -> int:
|
||||
return _lib.wc_Sha384Update(self._native_object, data, len(data))
|
||||
|
||||
@override
|
||||
def _final(self, obj: FFI.CData, ret: FFI.CData) -> int:
|
||||
return _lib.wc_Sha384Final(obj, ret)
|
||||
|
||||
|
|
@ -280,12 +290,15 @@ if _lib.SHA512_ENABLED:
|
|||
if hasattr(self, '_native_object') and not getattr(self, '_shallow_copy', False):
|
||||
self._delete(self._native_object)
|
||||
|
||||
@override
|
||||
def _init(self) -> int:
|
||||
return _lib.wc_InitSha512(self._native_object)
|
||||
|
||||
@override
|
||||
def _update(self, data: bytes) -> int:
|
||||
return _lib.wc_Sha512Update(self._native_object, data, len(data))
|
||||
|
||||
@override
|
||||
def _final(self, obj: FFI.CData, ret: FFI.CData) -> int:
|
||||
return _lib.wc_Sha512Final(obj, ret)
|
||||
|
||||
|
|
@ -345,10 +358,12 @@ if _lib.SHA3_ENABLED:
|
|||
if string:
|
||||
self.update(string)
|
||||
|
||||
@override
|
||||
@classmethod
|
||||
def new(cls, string: BytesOrStr | None = None, size: int = SHA3_384_DIGEST_SIZE) -> Sha3:
|
||||
return cls(string, size)
|
||||
|
||||
@override
|
||||
def copy(self) -> Sha3:
|
||||
# Bypass __init__ to avoid calling _init() on a state that _copy
|
||||
# immediately overwrites (which would leak internal resources in
|
||||
|
|
@ -373,6 +388,7 @@ if _lib.SHA3_ENABLED:
|
|||
# Keep _shallow_copy = True: memmove shares state with self.
|
||||
return c
|
||||
|
||||
@override
|
||||
def _init(self) -> int:
|
||||
if self.digest_size == Sha3.SHA3_224_DIGEST_SIZE:
|
||||
return _lib.wc_InitSha3_224(self._native_object, _ffi.NULL, 0)
|
||||
|
|
@ -384,6 +400,7 @@ if _lib.SHA3_ENABLED:
|
|||
return _lib.wc_InitSha3_512(self._native_object, _ffi.NULL, 0)
|
||||
return -1
|
||||
|
||||
@override
|
||||
def _update(self, data: bytes) -> int:
|
||||
if self.digest_size == Sha3.SHA3_224_DIGEST_SIZE:
|
||||
return _lib.wc_Sha3_224_Update(self._native_object, data, len(data))
|
||||
|
|
@ -395,6 +412,7 @@ if _lib.SHA3_ENABLED:
|
|||
return _lib.wc_Sha3_512_Update(self._native_object, data, len(data))
|
||||
return -1
|
||||
|
||||
@override
|
||||
def _final(self, obj: FFI.CData, ret: FFI.CData) -> int:
|
||||
if self.digest_size == Sha3.SHA3_224_DIGEST_SIZE:
|
||||
return _lib.wc_Sha3_224_Final(obj, ret)
|
||||
|
|
@ -460,9 +478,11 @@ if _lib.HMAC_ENABLED:
|
|||
if string:
|
||||
self.update(string)
|
||||
|
||||
@override
|
||||
def _init(self) -> int:
|
||||
return -1
|
||||
|
||||
@override
|
||||
@classmethod
|
||||
def new(cls, key: BytesOrStr, string: BytesOrStr | None = None) -> _Hash: # pylint: disable=W0221 # ty: ignore[invalid-method-override]
|
||||
"""
|
||||
|
|
@ -493,9 +513,11 @@ if _lib.HMAC_ENABLED:
|
|||
raise WolfCryptApiError("wc_HmacSetKey error", ret)
|
||||
return ret
|
||||
|
||||
@override
|
||||
def _update(self, data: bytes) -> int:
|
||||
return _lib.wc_HmacUpdate(self._native_object, data, len(data))
|
||||
|
||||
@override
|
||||
def _final(self, obj: FFI.CData, ret: FFI.CData) -> int:
|
||||
return _lib.wc_HmacFinal(obj, ret)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from __future__ import annotations
|
|||
from wolfcrypt._ffi import ffi as _ffi
|
||||
from wolfcrypt._ffi import lib as _lib
|
||||
|
||||
from wolfcrypt.exceptions import WolfCryptApiError
|
||||
from wolfcrypt.exceptions import WolfCryptApiError, WolfCryptError
|
||||
|
||||
|
||||
class Random:
|
||||
|
|
@ -34,23 +34,31 @@ class Random:
|
|||
"""
|
||||
|
||||
def __init__(self, nonce: __builtins__.bytes = b"", device_id: int = -2) -> None:
|
||||
self.native_object: _lib.RNG = _ffi.new("WC_RNG *")
|
||||
self._native_object: _lib.RNG | None = None
|
||||
self._native_object = _ffi.new("WC_RNG *")
|
||||
|
||||
ret = _lib.wc_InitRngNonce_ex(self.native_object, nonce, len(nonce), _ffi.NULL, device_id)
|
||||
ret = _lib.wc_InitRngNonce_ex(self._native_object, nonce, len(nonce), _ffi.NULL, device_id)
|
||||
if ret < 0: # pragma: no cover
|
||||
self._native_object = None
|
||||
raise WolfCryptApiError("RNG init error", ret)
|
||||
|
||||
# making sure _lib.wc_FreeRng outlives WC_RNG instances
|
||||
_delete = staticmethod(_lib.wc_FreeRng)
|
||||
|
||||
def __del__(self) -> None:
|
||||
if self.native_object:
|
||||
if self._native_object is not None:
|
||||
try:
|
||||
self._delete(self.native_object)
|
||||
self._delete(self._native_object)
|
||||
except AttributeError:
|
||||
# Can occur during interpreter shutdown
|
||||
pass
|
||||
|
||||
@property
|
||||
def native_object(self) -> _lib.RNG:
|
||||
if self._native_object is None:
|
||||
raise WolfCryptError("RNG not initialized")
|
||||
return self._native_object
|
||||
|
||||
def byte(self) -> __builtins__.bytes:
|
||||
"""
|
||||
Generate and return a random byte.
|
||||
|
|
|
|||
Loading…
Reference in New Issue