Skip to content

Commit b7bf278

Browse files
authored
Merge pull request #27 from tekktrik/doc/add-documentation
Improve documentation
2 parents 859dd35 + d1cdbf2 commit b7bf278

File tree

15 files changed

+425
-245
lines changed

15 files changed

+425
-245
lines changed

adafruit_rsa/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
#
44
# SPDX-License-Identifier: Apache-2.0
55

6-
"""RSA module
6+
"""
7+
RSA module
8+
====================================================
79
810
Module for calculating large primes, and RSA encryption, decryption, signing
911
and verification. Includes generating public and private keys.
1012
11-
WARNING: this implementation does not use compression of the cleartext input to
13+
**WARNING:** This implementation does not use compression of the cleartext input to
1214
prevent repetitions, or other common security improvements. Use with care.
1315
1416
"""

adafruit_rsa/_compat.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@
33
#
44
# SPDX-License-Identifier: Apache-2.0
55

6-
"""Python compatibility wrappers."""
6+
"""
7+
`adafruit_rsa._compat`
8+
====================================================
9+
10+
Python compatibility wrappers.
11+
"""
712

813
import sys
914
from struct import pack
1015

16+
try:
17+
from typing import Any, Literal, Tuple
18+
except ImportError:
19+
pass
20+
1121
__version__ = "0.0.0-auto.0"
1222
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RSA.git"
1323

@@ -31,87 +41,86 @@
3141
INTEGER_TYPES = (int,)
3242

3343

34-
def write_to_stdout(data):
44+
def write_to_stdout(data: bytes) -> None:
3545
"""Writes bytes to stdout
3646
37-
:type data: bytes
47+
:param bytes data: Data to write
3848
"""
3949
# On Py3 we must use the buffer interface to write bytes.
4050
sys.stdout.buffer.write(data)
4151

4252

43-
def is_bytes(obj):
53+
def is_bytes(obj: Any) -> bool:
4454
"""
4555
Determines whether the given value is a byte string.
4656
4757
:param obj:
4858
The value to test.
49-
:returns:
50-
``True`` if ``value`` is a byte string; ``False`` otherwise.
59+
:return:
60+
``True`` if ``obj`` is a byte string; ``False`` otherwise.
5161
"""
5262
return isinstance(obj, bytes)
5363

5464

55-
def is_integer(obj):
65+
def is_integer(obj: Any) -> bool:
5666
"""
5767
Determines whether the given value is an integer.
5868
5969
:param obj:
6070
The value to test.
61-
:returns:
62-
``True`` if ``value`` is an integer; ``False`` otherwise.
71+
:return:
72+
``True`` if ``obj`` is an integer; ``False`` otherwise.
6373
"""
6474
return isinstance(obj, INTEGER_TYPES)
6575

6676

67-
def byte(num):
77+
def byte(num: int) -> bytes:
6878
"""
6979
Converts a number between 0 and 255 (both inclusive) to a base-256 (byte)
7080
representation.
7181
7282
Use it as a replacement for ``chr`` where you are expecting a byte
7383
because this will work on all current versions of Python::
7484
75-
:param num:
76-
An unsigned integer between 0 and 255 (both inclusive).
77-
:returns:
78-
A single byte.
85+
:param int num: An unsigned integer between 0 and 255 (both inclusive).
86+
:return: A single byte.
7987
"""
8088
return pack("B", num)
8189

8290

83-
def xor_bytes(bytes_1, bytes_2):
91+
def xor_bytes(bytes_1: bytes, bytes_2: bytes) -> bytes:
8492
"""
8593
Returns the bitwise XOR result between two bytes objects, bytes_1 ^ bytes_2.
8694
8795
Bitwise XOR operation is commutative, so order of parameters doesn't
8896
generate different results. If parameters have different length, extra
8997
length of the largest one is ignored.
9098
91-
:param bytes_1:
92-
First bytes object.
93-
:param bytes_2:
94-
Second bytes object.
95-
:returns:
96-
Bytes object, result of XOR operation.
99+
:param bytes bytes_1: First bytes object.
100+
:param bytes_2: Second bytes object.
101+
:return: Bytes object, result of XOR operation.
97102
"""
98103
return bytes(x ^ y for x, y in zip(bytes_1, bytes_2))
99104

100105

101-
def get_word_alignment(num, force_arch=64, _machine_word_size=MACHINE_WORD_SIZE):
106+
def get_word_alignment(
107+
num: int,
108+
force_arch: int = 64,
109+
_machine_word_size: Literal[64, 32] = MACHINE_WORD_SIZE,
110+
) -> Tuple[int, int, int, str]:
102111
"""
103112
Returns alignment details for the given number based on the platform
104113
Python is running on.
105114
106-
:param num:
107-
Unsigned integral number.
108-
:param force_arch:
115+
:param int num:
116+
Unsigned integer number.
117+
:param int force_arch:
109118
If you don't want to use 64-bit unsigned chunks, set this to
110119
anything other than 64. 32-bit chunks will be preferred then.
111120
Default 64 will be used when on a 64-bit machine.
112-
:param _machine_word_size:
121+
:param int _machine_word_size:
113122
(Internal) The machine word size used for alignment.
114-
:returns:
123+
:return:
115124
4-tuple::
116125
117126
(word_bits, word_bytes,

adafruit_rsa/asn1.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
#
44
# SPDX-License-Identifier: Apache-2.0
55

6-
"""ASN.1 definitions.
6+
"""
7+
`adafruit_rsa.asn1`
8+
====================================================
9+
10+
ASN.1 definitions.
711
812
Not all ASN.1-handling code use these definitions, but when it does, they should be here.
913
"""

adafruit_rsa/common.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,31 @@
33
#
44
# SPDX-License-Identifier: Apache-2.0
55

6-
"""Common functionality shared by several modules."""
6+
"""
7+
`adafruit_rsa.common`
8+
====================================================
9+
10+
Common functionality shared by several modules.
11+
"""
712

813
# pylint: disable=invalid-name
914

15+
try:
16+
from typing import Optional, Tuple, Sequence
17+
except ImportError:
18+
pass
19+
1020
__version__ = "0.0.0-auto.0"
1121
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RSA.git"
1222

1323

14-
def bit_length(int_type):
24+
def bit_length(int_type: int) -> int:
1525
"""Return the number of bits necessary to represent an integer in binary,
16-
excluding the sign and leading zeros"""
26+
excluding the sign and leading zeros
27+
28+
:param int int_type: The integer to check
29+
"""
30+
1731
length = 0
1832
while int_type:
1933
int_type >>= 1
@@ -24,7 +38,7 @@ def bit_length(int_type):
2438
class NotRelativePrimeError(ValueError):
2539
"""Raises if provided a and b not relatively prime."""
2640

27-
def __init__(self, a, b, d, msg=None):
41+
def __init__(self, a: int, b: int, d: int, msg: Optional[str] = None):
2842
super().__init__(
2943
msg or "%d and %d are not relatively prime, divider=%i" % (a, b, d)
3044
)
@@ -33,7 +47,7 @@ def __init__(self, a, b, d, msg=None):
3347
self.d = d
3448

3549

36-
def bit_size(num):
50+
def bit_size(num: int) -> int:
3751
"""
3852
Number of bits needed to represent a integer excluding any prefix
3953
0 bits.
@@ -47,11 +61,11 @@ def bit_size(num):
4761
>>> bit_size(1025)
4862
11
4963
50-
:param num:
64+
:param int num:
5165
Integer value. If num is 0, returns 0. Only the absolute value of the
5266
number is considered. Therefore, signed integers will be abs(num)
5367
before the number's bit length is determined.
54-
:returns:
68+
:return:
5569
Returns the number of bits in the integer.
5670
"""
5771

@@ -63,7 +77,7 @@ def bit_size(num):
6377
) from err
6478

6579

66-
def byte_size(number):
80+
def byte_size(number: int) -> int:
6781
"""
6882
Returns the number of bytes required to hold a specific long number.
6983
@@ -78,21 +92,19 @@ def byte_size(number):
7892
>>> byte_size(1 << 1024)
7993
129
8094
81-
:param number:
82-
An unsigned integer
83-
:returns:
84-
The number of bytes required to hold a specific long number.
95+
:param int number: An unsigned integer
96+
:return: The number of bytes required to hold a specific long number.
8597
"""
8698
if number == 0:
8799
return 1
88100
return ceil_div(bit_size(number), 8)
89101

90102

91-
def ceil_div(num, div):
103+
def ceil_div(num: int, div: int) -> int:
92104
"""
93-
Returns the ceiling function of a division between `num` and `div`.
105+
Returns the ceiling function of a division between ``num`` and ``div``.
94106
95-
Usage::
107+
Usage:
96108
97109
>>> ceil_div(100, 7)
98110
15
@@ -101,9 +113,8 @@ def ceil_div(num, div):
101113
>>> ceil_div(1, 4)
102114
1
103115
104-
:param num: Division's numerator, a number
105-
:param div: Division's divisor, a number
106-
116+
:param int num: Division's numerator, a number
117+
:param int div: Division's divisor, a number
107118
:return: Rounded up result of the division between the parameters.
108119
"""
109120
quanta, mod = divmod(num, div)
@@ -112,7 +123,7 @@ def ceil_div(num, div):
112123
return quanta
113124

114125

115-
def extended_gcd(a, b):
126+
def extended_gcd(a: int, b: int) -> Tuple[int, int, int]:
116127
"""Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb"""
117128
# r = gcd(a,b) i = multiplicitive inverse of a mod b
118129
# or j = multiplicitive inverse of b mod a
@@ -136,7 +147,7 @@ def extended_gcd(a, b):
136147
return a, lx, ly # Return only positive values
137148

138149

139-
def inverse(x, n):
150+
def inverse(x: int, n: int) -> int:
140151
"""Returns the inverse of x % n under multiplication, a.k.a x^-1 (mod n)
141152
142153
>>> inverse(7, 4)
@@ -153,14 +164,14 @@ def inverse(x, n):
153164
return inv
154165

155166

156-
def crt(a_values, modulo_values):
167+
def crt(a_values: Sequence[int], modulo_values: Sequence[int]) -> int:
157168
"""Chinese Remainder Theorem.
158169
159170
Calculates x such that x = a[i] (mod m[i]) for each i.
160171
161-
:param a_values: the a-values of the above equation
162-
:param modulo_values: the m-values of the above equation
163-
:returns: x such that x = a[i] (mod m[i]) for each i
172+
:param Sequence[int] a_values: the a-values of the above equation
173+
:param Sequence[int] modulo_values: the m-values of the above equation
174+
:return: x such that x = a[i] (mod m[i]) for each i
164175
165176
166177
>>> crt([2, 3], [3, 5])

adafruit_rsa/core.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
#
44
# SPDX-License-Identifier: Apache-2.0
55

6-
"""Core mathematical operations.
6+
"""
7+
`adafruit_rsa.core`
8+
====================================================
9+
10+
Core mathematical operations.
711
812
This is the actual core RSA implementation, which is only defined
913
mathematically on integers.
@@ -12,12 +16,18 @@
1216
# pylint: disable=invalid-name
1317
from adafruit_rsa._compat import is_integer
1418

19+
try:
20+
from typing import Any
21+
except ImportError:
22+
pass
23+
1524
__version__ = "0.0.0-auto.0"
1625
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RSA.git"
1726

1827

19-
def fast_pow(x, e, m):
28+
def fast_pow(x: int, e: int, m: int) -> int:
2029
"""Performs fast modular exponentiation, saves RAM on small CPUs/micros.
30+
2131
:param int x: Base
2232
:param int y: Exponent
2333
:param int e: Second exponent
@@ -35,15 +45,15 @@ def fast_pow(x, e, m):
3545
return Y
3646

3747

38-
def assert_int(var, name):
48+
def assert_int(var: Any, name: str) -> None:
3949
"""Asserts provided variable is an integer."""
4050
if is_integer(var):
4151
return
4252

4353
raise TypeError("%s should be an integer, not %s" % (name, var.__class__))
4454

4555

46-
def encrypt_int(message, ekey, n):
56+
def encrypt_int(message: int, ekey: int, n: int) -> int:
4757
"""Encrypts a message using encryption key 'ekey', working modulo n"""
4858

4959
assert_int(message, "message")
@@ -61,7 +71,7 @@ def encrypt_int(message, ekey, n):
6171
return fast_pow(message, ekey, n)
6272

6373

64-
def decrypt_int(cyphertext, dkey, n):
74+
def decrypt_int(cyphertext: int, dkey: int, n: int) -> int:
6575
"""Decrypts a cypher text using the decryption key 'dkey', working modulo n"""
6676

6777
assert_int(cyphertext, "cyphertext")

0 commit comments

Comments
 (0)