Skip to content

Commit 3667130

Browse files
committed
experimental image pixels encryption; test cases for argon2 hash generation, password generation, 2fa, file and image encryption;
1 parent 117284a commit 3667130

18 files changed

+485
-19
lines changed

files/turtle.jpg

-384 KB
Binary file not shown.

files/turtle_x1024.bmp

4.5 MB
Binary file not shown.

files/turtle_x1920.bmp

15.8 MB
Binary file not shown.

files/turtle_x256.bmp

288 KB
Binary file not shown.

files/turtle_x512.bmp

1.13 MB
Binary file not shown.

test_2fa.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import argparse
2+
import time
3+
from turtlpass.turtlpass_rp2040 import TurtlPassRP2040
4+
from turtlpass.otp_management import add_otp_shared_secret, get_encrypted_otp_secrets, generate_otp_code, delete_all_secrets_from_eeprom
5+
6+
def test_add_otp_shared_secret(turtlpass, secure_hash: str, otp_shared_secret: str) -> None:
7+
if add_otp_shared_secret(turtlpass, secure_hash, otp_shared_secret):
8+
time.sleep(.5)
9+
get_encrypted_otp_secrets(turtlpass)
10+
11+
time.sleep(1)
12+
13+
def test_otp_code(turtlpass, secure_hash, expected_otp, timestamp):
14+
if not generate_otp_code(turtlpass, secure_hash, timestamp):
15+
return False
16+
17+
otp_code = input("Type OTP code here: ")
18+
19+
if otp_code == expected_otp:
20+
print("✅ OTP codes match.")
21+
else:
22+
print("❌ OTP codes do not match.")
23+
print(f"Expected OTP code: {expected_otp}")
24+
return True
25+
26+
def main(device_path: str) -> None:
27+
with TurtlPassRP2040(device_path=device_path) as turtlpass:
28+
test_cases = [
29+
{
30+
"secure_hash": "cfb82615cbd35b67ff2efd2bd4b70aff071d02feaa21549a587c268b3f11ef2d0bbf0673f70f4cd84072051d2bb3c64e2b5eba1a2733983534a95651ae436c5b",
31+
"otp_shared_secret": "PDLTYQWSNZAUPCMY",
32+
"timestamp": 1676821524,
33+
"expected_otp": "007359"
34+
}
35+
]
36+
print("Deleting all secrets from EEPROM...")
37+
if not delete_all_secrets_from_eeprom(turtlpass):
38+
return
39+
40+
for test_case in test_cases:
41+
test_add_otp_shared_secret(turtlpass, test_case["secure_hash"], test_case["otp_shared_secret"])
42+
test_otp_code(turtlpass, test_case["secure_hash"], test_case["expected_otp"], test_case["timestamp"])
43+
44+
if __name__ == "__main__":
45+
parser = argparse.ArgumentParser(description="Test 2FA Manager - Add shared secret & Get OTP Code")
46+
parser.add_argument("device_path", type=str, help="Path to the TurtlPass RP2040 device ($ ls /dev/cu.* | grep usbmodem)")
47+
args = parser.parse_args()
48+
main(args.device_path)
49+
50+
# python3 test_2fa.py /dev/cu.usbmodem14101

test_2fa_add_random.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import argparse
2+
import random
3+
import string
4+
from turtlpass.argon2_hash_generator import generate_secure_hash
5+
from turtlpass.turtlpass_rp2040 import TurtlPassRP2040
6+
from turtlpass.otp_management import add_otp_shared_secret, get_encrypted_otp_secrets, generate_otp_code, delete_all_secrets_from_eeprom
7+
8+
def test_add_random_secret(turtlpass):
9+
pin = random.randint(100000, 999999)
10+
secure_hash = generate_secure_hash(pin, "domain", "account")
11+
otp_shared_secret = generate_random_string(32);
12+
if add_otp_shared_secret(turtlpass, secure_hash, otp_shared_secret):
13+
return True
14+
else:
15+
print("<ERROR>")
16+
return False
17+
18+
def generate_random_string(length):
19+
characters = string.ascii_uppercase + string.digits
20+
return ''.join(random.choice(characters) for _ in range(length))
21+
22+
def main(device_path: str) -> None:
23+
with TurtlPassRP2040(device_path=device_path) as turtlpass:
24+
25+
print("Deleting all secrets from EEPROM...")
26+
if not delete_all_secrets_from_eeprom(turtlpass):
27+
return
28+
29+
for index in range(105):
30+
if not test_add_random_secret(turtlpass):
31+
break
32+
print("Current:", index)
33+
34+
get_encrypted_otp_secrets(turtlpass)
35+
36+
37+
if __name__ == "__main__":
38+
parser = argparse.ArgumentParser(description="Test 2FA Manager - Add random secrets")
39+
parser.add_argument("device_path", type=str, help="Path to the TurtlPass RP2040 device ($ ls /dev/cu.* | grep usbmodem)")
40+
args = parser.parse_args()
41+
main(args.device_path)
42+
43+
# python3 test_2fa_add_random.py /dev/cu.usbmodem14101

test_2fa_add_secrets.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import argparse
2+
import time
3+
import random
4+
import string
5+
from turtlpass.argon2_hash_generator import generate_secure_hash
6+
from turtlpass.turtlpass_rp2040 import TurtlPassRP2040
7+
from turtlpass.otp_management import add_otp_shared_secret, get_encrypted_otp_secrets, generate_otp_code, delete_all_secrets_from_eeprom
8+
9+
def test_add_otp_shared_secret(turtlpass, domain_name: str, account_id: str, pin: int, otp_shared_secret: str):
10+
secure_hash = generate_secure_hash(pin, domain_name, account_id)
11+
if add_otp_shared_secret(turtlpass, secure_hash, otp_shared_secret):
12+
return True
13+
else:
14+
print("<ERROR>")
15+
return False
16+
17+
def main(device_path: str) -> None:
18+
with TurtlPassRP2040(device_path=device_path) as turtlpass:
19+
test_cases = [
20+
{"domain_name": "amazon", "account_id": "amazon@mail.com", "pin": 704713, "otp_shared_secret": "PDLTYQWSNZAUPCMY"},
21+
{"domain_name": "google", "account_id": "google@mail.com", "pin": 631571, "otp_shared_secret": "TKTDRDZJEUSPXABC"},
22+
{"domain_name": "facebook", "account_id": "facebook@mail.com", "pin": 363873, "otp_shared_secret": "UQLERGZKEOTWYMHF"},
23+
{"domain_name": "twitter", "account_id": "twitter@mail.com", "pin": 180366, "otp_shared_secret": "NMFDKRDBUVHXNCDYYEFXPSAMKABPTFEX"},
24+
{"domain_name": "linkedin", "account_id": "linkedin@mail.com", "pin": 442071, "otp_shared_secret": "NQKUOBAIWNZGJSDKFAVYXOBRUCYAYILY"},
25+
{"domain_name": "apple", "account_id": "apple@mail.com", "pin": 246810, "otp_shared_secret": "IYSGBTFWHPLUTDTFFHAGNOLXRQNPDUFL"},
26+
{"domain_name": "instagram", "account_id": "instagram@mail.com", "pin": 331667, "otp_shared_secret": "WMHAEJUDXBRSBYSBKAYSUNNHEPFGJRXYSKSYDIYYIZTGSBHHWTVHVUHZTRJJHXTE"},
27+
{"domain_name": "netflix", "account_id": "netflix@mail.com", "pin": 950688, "otp_shared_secret": "FHTULQWCHLNHASHWSJSJFSYYYHJZBFAMUEIZRXGLOYGOYJUVATSXHFEELSMSDFZO"},
28+
{"domain_name": "spotify", "account_id": "spotify@mail.com", "pin": 217226, "otp_shared_secret": "JQCHBJCZJNVEUBWWAAYTWXTETUGWGPROYXIENLVMVCPAGALKSVVLIBMIBSEACSOG" }
29+
]
30+
31+
print("Deleting all secrets from EEPROM...")
32+
if not delete_all_secrets_from_eeprom(turtlpass):
33+
return
34+
35+
for test_case in test_cases:
36+
if not test_add_otp_shared_secret(turtlpass, test_case["domain_name"], test_case["account_id"], test_case["pin"], test_case["otp_shared_secret"]):
37+
break
38+
39+
get_encrypted_otp_secrets(turtlpass)
40+
41+
42+
if __name__ == "__main__":
43+
parser = argparse.ArgumentParser(description="Test 2FA Manager - Add shared secrets")
44+
parser.add_argument("device_path", type=str, help="Path to the TurtlPass RP2040 device ($ ls /dev/cu.* | grep usbmodem)")
45+
args = parser.parse_args()
46+
main(args.device_path)
47+
48+
# python3 test_2fa_add_secrets.py /dev/cu.usbmodem14101

test_file_encryption.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import argparse
2+
import time
3+
from turtlpass.turtlpass_rp2040 import TurtlPassRP2040
4+
from turtlpass.encryption import process_encryption
5+
6+
def test_file_encryption(turtlpass, file_name: str) -> None:
7+
secure_hash = "0"
8+
src_file = "files/" + file_name
9+
dst_file = "out/" + file_name + ".enc"
10+
process_encryption(turtlpass, "encrypt", secure_hash, src_file, dst_file)
11+
print("-" * 50)
12+
time.sleep(1)
13+
14+
def test_file_decryption(turtlpass, file_name: str) -> None:
15+
secure_hash = "0"
16+
src_file = "out/" + file_name + ".enc"
17+
dst_file = "out/" + file_name
18+
process_encryption(turtlpass, "decrypt", secure_hash, src_file, dst_file)
19+
print("-" * 50)
20+
time.sleep(1)
21+
22+
def main(device_path: str) -> None:
23+
with TurtlPassRP2040(device_path=device_path) as turtlpass:
24+
test_cases = [
25+
{"file_name": "customers-100.csv"},
26+
{"file_name": "customers-1000.csv"},
27+
{"file_name": "customers-10000.csv"},
28+
{"file_name": "customers-100000.csv"}
29+
]
30+
for test_case in test_cases:
31+
test_file_encryption(turtlpass, test_case["file_name"])
32+
33+
for test_case in test_cases:
34+
test_file_decryption(turtlpass, test_case["file_name"])
35+
36+
37+
if __name__ == "__main__":
38+
parser = argparse.ArgumentParser(description="Test File Encryption")
39+
parser.add_argument("device_path", type=str, help="Path to the TurtlPass RP2040 device ($ ls /dev/cu.* | grep usbmodem)")
40+
args = parser.parse_args()
41+
main(args.device_path)
42+
43+
# python3 test_file_encryption.py /dev/cu.usbmodem14101

test_hash_generation.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import argparse
2+
from turtlpass.argon2_hash_generator import generate_secure_hash
3+
4+
def test_hash_generation(domain_name: str, account_id: str, pin: int, expected_hash: str) -> None:
5+
secure_hash = generate_secure_hash(pin, domain_name, account_id)
6+
7+
if secure_hash == expected_hash:
8+
print(f"✅ Hashes match for domain '{domain_name}', account '{account_id}', and PIN '{pin}'.")
9+
else:
10+
print(f"❌ Hashes do not match for domain '{domain_name}', account '{account_id}', and PIN '{pin}'.")
11+
print(f"Expected hash: {expected_hash}")
12+
print(f"Actual hash : {secure_hash}")
13+
14+
def main() -> None:
15+
test_cases = [
16+
{"domain_name": "amazon", "account_id": "amazon@mail.com", "pin": 704713, "expected_hash": "cfb82615cbd35b67ff2efd2bd4b70aff071d02feaa21549a587c268b3f11ef2d0bbf0673f70f4cd84072051d2bb3c64e2b5eba1a2733983534a95651ae436c5b"},
17+
{"domain_name": "google", "account_id": "google@mail.com", "pin": 631571, "expected_hash": "560303a41e2e97b205d3101d00a62e4e74383d0dc58032570512df0c70a92bd9bb7fbf1aa491eefcf3618b2e5a101657de69aafae9b1d3b8e7abce8369d551ad"},
18+
{"domain_name": "facebook", "account_id": "facebook@mail.com", "pin": 363873, "expected_hash": "a6e5c9ff8cf0670fe58d3a4949adcb610fa7b26cee9a98d6617f5a53185e73a02d2e0a855655b704d55d54bfd84d07ae12cb2f4cdeee0f03e146cd206ccf368f"},
19+
{"domain_name": "twitter", "account_id": "twitter@mail.com", "pin": 180366, "expected_hash": "bcc8da7302b09ce81e8f2cca813913c2ccaf39ad7664fbf9d865952c4bae5dc3fdca57617abfd27ba8032cc3f44513f92c97bef7a48e4d89bbb05fbf9b7a6bd5"},
20+
{"domain_name": "linkedin", "account_id": "linkedin@mail.com", "pin": 442071, "expected_hash": "e45270ad5b032e73127ef73dd25ce42e4ac28e77aa0d0183d4ab37049f05a9f9b7dacd9590399a482b5eccce743425eb96a66117949511757b1fae45809afd7a"},
21+
{"domain_name": "apple", "account_id": "apple@mail.com", "pin": 246810, "expected_hash": "d1b301bf0d57357e8188dee2559fd5a5502102a4dc9b351ea4edc7f4528cfa3f08e8c1b05d39271fc081ff272955c0f02d6ba846b0939a4bf5c67c88b5f1b25b"},
22+
{"domain_name": "instagram", "account_id": "instagram@mail.com", "pin": 331667, "expected_hash": "bcb666368f9214e8ecd827a60e5688f145b65524befd181cf66f01b109a5134f645f5acfef53c46543cea0045c6fb9076969020ad069e09eda60b62f40e7bdbc"},
23+
{"domain_name": "netflix", "account_id": "netflix@mail.com", "pin": 950688, "expected_hash": "80ff877241bc18df62be0779f7cbd5c4fd88c3492e9e8d288decea7ec0be04eeaae930071dc667541f910dde74288446d6553c0d78e317e437558b1a4c1ebee0"},
24+
{"domain_name": "spotify", "account_id": "spotify@mail.com", "pin": 217226, "expected_hash": "5b601b1632455d3c16717d04bb49fa8197dc9da1308355309f56bd1783726ca745ae9b684ed88518859671d943f70ae60aa8065e327674d02ba5cc0dd7f3128b"}
25+
]
26+
for test_case in test_cases:
27+
test_hash_generation(test_case["domain_name"], test_case["account_id"], test_case["pin"], test_case["expected_hash"])
28+
29+
if __name__ == "__main__":
30+
main()

0 commit comments

Comments
 (0)