From 99db3f4ff1b5595661f830cdf9d654e5244aad8f Mon Sep 17 00:00:00 2001 From: Chris Pappalardo Date: Tue, 25 Apr 2023 14:28:27 -0700 Subject: [PATCH] added missing type annotations --- adafruit_hashlib/__init__.py | 11 +++++++++-- adafruit_hashlib/_md5.py | 34 ++++++++++++++++++++-------------- adafruit_hashlib/_sha1.py | 19 ++++++++++++++----- adafruit_hashlib/_sha256.py | 31 +++++++++++++++++++++---------- adafruit_hashlib/_sha512.py | 32 ++++++++++++++++++++++---------- 5 files changed, 86 insertions(+), 41 deletions(-) diff --git a/adafruit_hashlib/__init__.py b/adafruit_hashlib/__init__.py index 5b49e0c..74ea4c6 100644 --- a/adafruit_hashlib/__init__.py +++ b/adafruit_hashlib/__init__.py @@ -22,6 +22,13 @@ * Adafruit CircuitPython firmware for the supported boards: https://github.com/adafruit/circuitpython/releases """ + +try: + from typing import List, Optional, Union +except ImportError: + pass + + try: from hashlib import md5, sha1, sha224, sha256, sha512 from hashlib import sha3_384 as sha384 @@ -38,7 +45,7 @@ ALGOS_AVAIL = ["sha1", "md5", "sha224", "sha256", "sha384", "sha512"] -def new(algo, data=b""): +def new(algo, data: Optional[bytes] = b"") -> Union[md5, sha1, sha224, sha256, sha512]: """Creates a new hashlib object. :param str algo: Name of the desired algorithm. @@ -52,7 +59,7 @@ def new(algo, data=b""): @property -def algorithms_available(): +def algorithms_available() -> List[str]: """Returns a list containing the names of the hash algorithms that are available in this module. """ diff --git a/adafruit_hashlib/_md5.py b/adafruit_hashlib/_md5.py index b7ec68b..b0d9fa2 100644 --- a/adafruit_hashlib/_md5.py +++ b/adafruit_hashlib/_md5.py @@ -43,6 +43,12 @@ """ # pylint: disable=invalid-name,missing-function-docstring,too-many-arguments +try: + from typing import Optional, Tuple +except ImportError: + # suppress because typing does not exist on circuitpython + pass + import binascii import struct from micropython import const @@ -73,26 +79,26 @@ # F, G, H and I are basic MD5 functions. -def F(x, y, z): +def F(x: int, y: int, z: int) -> int: return (x & y) | ((~x) & z) -def G(x, y, z): +def G(x: int, y: int, z: int) -> int: return (x & z) | (y & (~z)) -def H(x, y, z): +def H(x: int, y: int, z: int) -> int: return x ^ y ^ z -def I(x, y, z): +def I(x: int, y: int, z: int) -> int: return y ^ (x | (~z)) # ROTATE_LEFT rotates x left n bits. -def ROTATE_LEFT(x, n): +def ROTATE_LEFT(x: int, n: int) -> int: x = x & 0xFFFFFFFF return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF @@ -101,35 +107,35 @@ def ROTATE_LEFT(x, n): # Rotation is separate from addition to prevent recomputation. -def FF(a, b, c, d, x, s, ac): +def FF(a: int, b: int, c: int, d: int, x: int, s: int, ac: int) -> int: a = a + F(b, c, d) + x + ac a = ROTATE_LEFT(a, s) a = a + b return a -def GG(a, b, c, d, x, s, ac): +def GG(a: int, b: int, c: int, d: int, x: int, s: int, ac: int) -> int: a = a + G(b, c, d) + x + ac a = ROTATE_LEFT(a, s) a = a + b return a -def HH(a, b, c, d, x, s, ac): +def HH(a: int, b: int, c: int, d: int, x: int, s: int, ac: int) -> int: a = a + H(b, c, d) + x + ac a = ROTATE_LEFT(a, s) a = a + b return a -def II(a, b, c, d, x, s, ac): +def II(a: int, b: int, c: int, d: int, x: int, s: int, ac: int) -> int: a = a + I(b, c, d) + x + ac a = ROTATE_LEFT(a, s) a = a + b return a -def encode(data, length): +def encode(data: Tuple[int], length: int) -> bytes: """Encodes input (UINT4) into output (unsigned char). Assumes length is a multiple of 4. """ @@ -137,7 +143,7 @@ def encode(data, length): return struct.pack(*("%iI" % k,) + tuple(data[:k])) -def decode(data, length): +def decode(data: bytes, length: int) -> Tuple[int]: """Decodes input (unsigned char) into output (UINT4). Assumes length is a multiple of 4. """ @@ -152,7 +158,7 @@ class md5: block_size = 64 name = "md5" - def __init__(self, string=b""): + def __init__(self, string: Optional[bytes] = b""): """Constructs an MD5 hash object.""" self.count = 0 self.buffer = b"" @@ -163,7 +169,7 @@ def __init__(self, string=b""): if string: self.update(string) - def update(self, data): + def update(self, data: bytes): """Update the hash object with the bytes-like object.""" data_len = len(data) @@ -231,7 +237,7 @@ def copy(self): new.state = self.state return new - def _transform(self, block): + def _transform(self, block: bytes): """MD5 basic transformation. Transforms state based on block.""" # pylint: disable=invalid-name,too-many-statements a, b, c, d = self.state diff --git a/adafruit_hashlib/_sha1.py b/adafruit_hashlib/_sha1.py index 8b3e8b5..ac1b14e 100755 --- a/adafruit_hashlib/_sha1.py +++ b/adafruit_hashlib/_sha1.py @@ -19,6 +19,13 @@ from io import BytesIO from micropython import const +try: + from typing import Optional, Tuple, Union +except ImportError: + # suppress because typing does not exist on circuitpython + pass + + # SHA Block size and message digest sizes, in bytes. SHA_BLOCKSIZE = 64 SHA_DIGESTSIZE = 20 @@ -30,7 +37,7 @@ K3 = const(0xCA62C1D6) -def _getbuf(data): +def _getbuf(data: Union[str, bytes]) -> bytes: """Converts data into ascii, returns bytes of data. :param str bytes bytearray data: Data to convert. @@ -41,7 +48,7 @@ def _getbuf(data): return bytes(data) -def _left_rotate(n, b): +def _left_rotate(n: int, b: int) -> int: """Left rotate a 32-bit integer, n, by b bits. :param int n: 32-bit integer :param int b: Desired rotation amount, in bits. @@ -51,7 +58,9 @@ def _left_rotate(n, b): # pylint: disable=invalid-name, too-many-arguments -def _hash_computation(chunk, h0, h1, h2, h3, h4): +def _hash_computation( + chunk: bytes, h0: int, h1: int, h2: int, h3: int, h4: int +) -> Tuple[int, int, int, int, int]: """Processes 64-bit chunk of data and returns new digest variables. Per FIPS [6.1.2] :param bytes bytearray chunk: 64-bit bytearray @@ -118,7 +127,7 @@ class sha1: block_size = SHA_BLOCKSIZE name = "sha1" - def __init__(self, data=None): + def __init__(self, data: Optional[Union[str, bytes]] = None): """Construct a SHA-1 hash object. :param bytes data: Optional data to process @@ -159,7 +168,7 @@ def _create_digest(self): return h return _hash_computation(message[64:], *h) - def update(self, data): + def update(self, data: Optional[Union[str, bytes]]): """Updates the hash object with bytes-like object, data. :param bytes data: bytearray or bytes object diff --git a/adafruit_hashlib/_sha256.py b/adafruit_hashlib/_sha256.py index 5004adb..6df455c 100644 --- a/adafruit_hashlib/_sha256.py +++ b/adafruit_hashlib/_sha256.py @@ -11,6 +11,13 @@ """ # pylint: disable=invalid-name, unnecessary-lambda, unnecessary-lambda-assignment, missing-docstring +try: + from typing import Dict, List, Optional, Tuple, Union +except ImportError: + # suppress because typing does not exist on circuitpython + pass + + # SHA Block size and message digest sizes, in bytes. SHA_BLOCKSIZE = 64 SHA_DIGESTSIZE = 32 @@ -42,7 +49,7 @@ def new_shaobject(): Gamma1 = lambda x: (S(x, 17) ^ S(x, 19) ^ R(x, 10)) # pylint: disable=too-many-statements -def sha_transform(sha_info): +def sha_transform(sha_info: Dict[str, Union[List[int], int]]) -> None: W = [] d = sha_info["data"] @@ -59,7 +66,9 @@ def sha_transform(sha_info): ss = sha_info["digest"][:] # pylint: disable=too-many-arguments, line-too-long - def RND(a, b, c, d, e, f, g, h, i, ki): + def RND( + a: int, b: int, c: int, d: int, e: int, f: int, g: int, h: int, i: int, ki: int + ) -> Tuple[int, int]: """Compress""" t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i] t1 = Sigma0(a) + Maj(a, b, c) @@ -267,7 +276,7 @@ def RND(a, b, c, d, e, f, g, h, i, ki): sha_info["digest"] = dig -def sha_init(): +def sha_init() -> Dict[str, Union[List[int], int]]: """Initialize the SHA digest.""" sha_info = new_shaobject() sha_info["digest"] = [ @@ -287,7 +296,7 @@ def sha_init(): return sha_info -def sha224_init(): +def sha224_init() -> Dict[str, Union[List[int], int]]: """Initialize a SHA224 digest.""" sha_info = new_shaobject() sha_info["digest"] = [ @@ -307,13 +316,15 @@ def sha224_init(): return sha_info -def getbuf(string): +def getbuf(string: Union[str, bytes]) -> bytes: if isinstance(string, str): return string.encode("ascii") return bytes(string) -def sha_update(sha_info, buffer): +def sha_update( + sha_info: Dict[str, Union[List[int], int]], buffer: Union[str, bytes] +) -> None: """Update the SHA digest. :param dict sha_info: SHA Digest. :param str buffer: SHA buffer size. @@ -360,7 +371,7 @@ def sha_update(sha_info, buffer): sha_info["local"] = size -def sha_final(sha_info): +def sha_final(sha_info: Dict[str, Union[List[int], int]]) -> bytes: """Finish computing the SHA Digest.""" lo_bit_count = sha_info["count_lo"] hi_bit_count = sha_info["count_hi"] @@ -401,13 +412,13 @@ class sha256: block_size = SHA_BLOCKSIZE name = "sha256" - def __init__(self, s=None): + def __init__(self, s: Optional[Union[str, bytes]] = None): """Constructs a SHA256 hash object.""" self._sha = sha_init() if s: sha_update(self._sha, getbuf(s)) - def update(self, s): + def update(self, s: Union[str, bytes]): """Updates the hash object with a bytes-like object, s.""" sha_update(self._sha, getbuf(s)) @@ -434,7 +445,7 @@ class sha224(sha256): digest_size = digestsize = 28 name = "sha224" - def __init__(self, s=None): + def __init__(self, s: Optional[Union[str, bytes]] = None): """Constructs a SHA224 hash object.""" self._sha = sha224_init() if s: diff --git a/adafruit_hashlib/_sha512.py b/adafruit_hashlib/_sha512.py index 22e354d..2373f66 100644 --- a/adafruit_hashlib/_sha512.py +++ b/adafruit_hashlib/_sha512.py @@ -12,6 +12,13 @@ """ # pylint: disable=invalid-name, unnecessary-lambda, unnecessary-lambda-assignment, missing-docstring, line-too-long +try: + from typing import Dict, List, Optional, Tuple, Union +except ImportError: + # suppress because typing does not exist on circuitpython + pass + + # SHA Block size and message digest sizes, in bytes. SHA_BLOCKSIZE = 128 SHA_DIGESTSIZE = 64 @@ -43,8 +50,9 @@ def new_shaobject(): Gamma0 = lambda x: (S(x, 1) ^ S(x, 8) ^ R(x, 7)) Gamma1 = lambda x: (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + # pylint: disable=protected-access, too-many-statements -def sha_transform(sha_info): +def sha_transform(sha_info: Dict[str, Union[List[int], int]]) -> None: W = [] d = sha_info["data"] @@ -69,7 +77,9 @@ def sha_transform(sha_info): ss = sha_info["digest"][:] # pylint: disable=line-too-long, too-many-arguments - def RND(a, b, c, d, e, f, g, h, i, ki): + def RND( + a: int, b: int, c: int, d: int, e: int, f: int, g: int, h: int, i: int, ki: int + ) -> Tuple[int, int]: t0 = (h + Sigma1(e) + Ch(e, f, g) + ki + W[i]) & 0xFFFFFFFFFFFFFFFF t1 = (Sigma0(a) + Maj(a, b, c)) & 0xFFFFFFFFFFFFFFFF d = (d + t0) & 0xFFFFFFFFFFFFFFFF @@ -324,7 +334,7 @@ def RND(a, b, c, d, e, f, g, h, i, ki): sha_info["digest"] = dig -def sha_init(): +def sha_init() -> Dict[str, Union[List[int], int]]: """Initialize the SHA digest.""" sha_info = new_shaobject() sha_info["digest"] = [ @@ -344,7 +354,7 @@ def sha_init(): return sha_info -def sha384_init(): +def sha384_init() -> Dict[str, Union[List[int], int]]: """Initialize a SHA384 digest.""" sha_info = new_shaobject() sha_info["digest"] = [ @@ -364,13 +374,15 @@ def sha384_init(): return sha_info -def getbuf(s): +def getbuf(s: Union[str, bytes]) -> bytes: if isinstance(s, str): return s.encode("ascii") return bytes(s) -def sha_update(sha_info, buffer): +def sha_update( + sha_info: Dict[str, Union[List[int], int]], buffer: Union[str, bytes] +) -> None: """Update the SHA digest. :param dict sha_info: SHA Digest. :param str buffer: SHA buffer size. @@ -417,7 +429,7 @@ def sha_update(sha_info, buffer): sha_info["local"] = count -def sha_final(sha_info): +def sha_final(sha_info: Dict[str, Union[List[int], int]]) -> bytes: """Finish computing the SHA Digest.""" lo_bit_count = sha_info["count_lo"] hi_bit_count = sha_info["count_hi"] @@ -476,13 +488,13 @@ class sha512: block_size = SHA_BLOCKSIZE name = "sha512" - def __init__(self, s=None): + def __init__(self, s: Optional[Union[str, bytes]] = None): """Constructs a SHA512 hash object.""" self._sha = sha_init() if s: sha_update(self._sha, getbuf(s)) - def update(self, s): + def update(self, s: Union[str, bytes]): """Updates the hash object with a bytes-like object, s.""" sha_update(self._sha, getbuf(s)) @@ -509,7 +521,7 @@ class sha384(sha512): digest_size = digestsize = 48 name = "sha384" - def __init__(self, s=None): + def __init__(self, s: Optional[Union[str, bytes]] = None): """Constructs a SHA224 hash object.""" self._sha = sha384_init() if s: