Skip to content

Commit 024d32c

Browse files
committed
Add tests for transip.utils.*
Signed-off-by: Roald Nefs <info@roaldnefs.com>
1 parent 567d569 commit 024d32c

2 files changed

Lines changed: 121 additions & 2 deletions

File tree

tests/test_utils.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Copyright (C) 2021 Roald Nefs <info@roaldnefs.com>
4+
#
5+
# This file is part of python-transip.
6+
#
7+
# python-transip is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Lesser General Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# python-transip is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Lesser General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser General Public License
18+
# along with python-transip. If not, see <https://www.gnu.org/licenses/>.
19+
20+
import unittest
21+
import string
22+
23+
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
24+
25+
from transip.utils import (
26+
load_rsa_private_key, generate_message_signature, generate_nonce
27+
)
28+
29+
30+
class UtilsTest(unittest.TestCase):
31+
"""Test the transip.utils functions."""
32+
33+
privkey: str
34+
35+
@classmethod
36+
def setUpClass(cls) -> None:
37+
cls.privkey: str = ( # type: ignore
38+
"-----BEGIN RSA PRIVATE KEY-----\n"
39+
"MIIEpAIBAAKCAQEAsUSEHsMuB380OUZQWDyyND4q8lEuJAgNnMkO8s5NGwzP8XSi\n"
40+
"2DdFglLGLe9kjpADs3XqZFsk8ZFFn7x0idFydGyh9tbJ2WkR9E+kNUJV5iQDzPOB\n"
41+
"wvyygEREqnl/o1h3c1q8tD2HZKBcjChn9JbMzdWwAaIs3ppcGWrEI0jZFFfSAyIZ\n"
42+
"GkC3k3umOykWIKflQcT/soAfdqW+2P9/KD/wb3AZCer2i6B2hiITiDbHh5q84Hgk\n"
43+
"D/Zg1M4yrYDyxDeGkAJHkGKNaE0tgUPoz3XTGP7uFYIx00qJyhmnzQcyV/Xcw3ZQ\n"
44+
"7DFUj1HQ5wG/kEF9a4F1+AAiO5C5QbGTFYSwBwIDAQABAoIBABbtIZlI7P8TOJHf\n"
45+
"wixnTTTshWlpjmoikIAikMheXiKNeadkylrkaxz7z53JRFwbzB69tV7dWt3TSAns\n"
46+
"ubXJXOAp3JisFtcDe8r5MeeheLKXHda396RcQknMioTxycw6eNh2d8ln28br5oxJ\n"
47+
"/YfoqPxGEsljTCJOHHM9F7johwrWSQ6f+gmiOkABvIHKgTBLa++v0D+vNrUjM6rx\n"
48+
"IE+dBrx8yIgkF4qSg4Dqnr7D0KqCZUGLZ/3K8ShQUtiQYzyHIWKUId3NUecIQcrT\n"
49+
"2Ri2TITKuER0fa7Mr+3LMSh/3+HtP2AoM34ouxr9H98LFz/UXxuFIRFTx7UVRt4N\n"
50+
"3zqhsEECgYEA+TnXanBJmFz3sNYtlQixtKrh496GB0NheuK4xeNEj9/3gJ6J/rtL\n"
51+
"ZHI7VH8r6aqoqw7sO/WJdxkwZTBOz2fe1QJ5BN0HBI5S6jIBQv9Nfqar0TDvNLB+\n"
52+
"pH6eYJZ/IEFIMObv9YmsPohXpGeXynecrpl8SazEIWLb8IzgLY0HpokCgYEAthX5\n"
53+
"1th4Re0P9rzXp21bbEwcvOKcg5dcpSaTtA1eQEILl6qqT3FP7w8/Ed7NRRY9Gcs+\n"
54+
"inAc96YRNAgIGgfT3R1BmxOMWfdFBT1zlCheS6egKKLzVPzKPiMoMP4zu4hy6uH5\n"
55+
"YVqpDLu0YQu1J2L0VYdZ9xAC0//Rx8KRcs6m/g8CgYEA41VDja+HMhf7R67WPU+E\n"
56+
"6YvGKRjdoNpxnKoaaUd5TtO46/WxYk5t4t3gCJ9H6wjkecRO8BJ0pdKwNlzuRno0\n"
57+
"5JAw26LRt/Iq571dMUO36IMXzuWYDLPBkUJ+LRSaOU3TD+hXkd1W5GNxrmFgMCsT\n"
58+
"HKCcooeZD+shPDcEdghipiECgYARBTDbYlSrxKMPX0uRPOmkz+CHz27t5gIk9dws\n"
59+
"omtC+ml2/d75mg/surIci4UIhjGj7Zmk+yHaDE3jXTTUqhKlwoxVYJhn+HMdMEdT\n"
60+
"fAqEa+DOq5yvPwnwkPy6x6gySWjkh8b10LGonQsZXyzJx7grHoHMVFTPWERVtdw+\n"
61+
"rQ5zBQKBgQC0Iwx4eeQYx60OCZpioNEQ3QPaFgqoWYEexmcMlpgQ9ycdnHx3SkE8\n"
62+
"SlMokcPIEJDhdF3632kIAHOOJeA4Tmshf+ol/O2U2PDgbJZL6W6FJlT28sZVUU8j\n"
63+
"IjFmiAiW6IIEqkJxuR1diAjppEiMmSkjPavo7oQs0TZMMUkli1N9dw==\n"
64+
"-----END RSA PRIVATE KEY-----"
65+
)
66+
67+
def test_load_rsa_private_key(self) -> None:
68+
"""
69+
Test the content of a RSA private key can be converted to a
70+
RSAPrivateKey instance.
71+
"""
72+
self.assertTrue(isinstance(load_rsa_private_key(self.privkey), RSAPrivateKey))
73+
74+
def test_generate_message_signature(self) -> None:
75+
"""
76+
Test message signature generation using the defined RSA private key.
77+
78+
Example message encoded using:
79+
https://8gwifi.org/rsasignverifyfunctions.jsp
80+
"""
81+
message: str = "A message for signing"
82+
encoded: str = ("NFi2v07lhYmyTarOtIfpw50W25ukKWjtqsVzti/Y2RiGKPEzJQtFZ"
83+
"QaYJCFfIn8HfYjdbzOTK5DIFxwL8NCJK3Mb+wxZOkO4NDJC7mVgdO"
84+
"I6VuET4F3Er4ZjO4pkMLSaV6B0Mcm/yj8Wom1lfeRZxItDXPAbkMj"
85+
"47Ywsx7enAEXfrZrYwHy+rWLPN6WWCrCDWAJGu7lz5+YIy7rpLyRx"
86+
"Ff57QkMMJal0VCWyQUx+JBMdoW7rGVN1u+AxRY0yFj+QxWRB1z0JC"
87+
"E0Xmur+gQ+4+rgIEDE6VU2VY0A8+SY7hyRb2JN8yoLAeI+21ODwo5"
88+
"h/x1zw3Bstyzuvzo0QmHp7Mw==")
89+
90+
self.assertTrue(
91+
generate_message_signature(message, self.privkey) == encoded
92+
)
93+
94+
def test_generate_nonce_length(self) -> None:
95+
"""
96+
Test the length of the generated nonce and whether or not an
97+
exception is thrown for invalid lengths.
98+
"""
99+
# Test valid lengths
100+
for length in [1, 2, 32]:
101+
self.assertTrue(len(generate_nonce(length)) == length)
102+
103+
# Test invalid lengths
104+
for length in [0, -1]:
105+
self.assertRaises(ValueError, generate_nonce, length)
106+
107+
def test_generate_nonce_alphabet(self) -> None:
108+
"""
109+
Test if the generated nonce only contains characters from the alphabet.
110+
"""
111+
alphabet: str = 'a'
112+
self.assertTrue(generate_nonce(3, alphabet) == 'aaa')

transip/utils.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,22 @@ def generate_message_signature(
7575
return b64_bytes.decode('ascii')
7676

7777

78-
def generate_nonce(length: int) -> str:
78+
def generate_nonce(length: int, alphabet: str = None) -> str:
7979
"""
8080
Generate a nonce.
8181
8282
Args:
8383
length (int): The number of characters to return.
84+
alphabet (str): The alphabet to choose characters from, defaults to
85+
ascii leters and digits.
8486
8587
Returns:
8688
str: The nonce of specified characters.
8789
"""
88-
alphabet: str = string.ascii_letters + string.digits
90+
if not length >= 1:
91+
raise ValueError(
92+
"The specified nonce length must greater or equal to 1"
93+
)
94+
95+
alphabet = alphabet or (string.ascii_letters + string.digits)
8996
return ''.join(secrets.choice(alphabet) for i in range(length))

0 commit comments

Comments
 (0)