diff --git a/static-data/official-plugins/wot/wot/crypto/__init__.py b/static-data/official-plugins/wot/wot/crypto/__init__.py new file mode 100644 index 00000000..3fcb26f7 --- /dev/null +++ b/static-data/official-plugins/wot/wot/crypto/__init__.py @@ -0,0 +1 @@ +from wot.crypto import encryption \ No newline at end of file diff --git a/static-data/official-plugins/wot/wot/crypto/encryption.py b/static-data/official-plugins/wot/wot/crypto/encryption.py new file mode 100644 index 00000000..c9cd046b --- /dev/null +++ b/static-data/official-plugins/wot/wot/crypto/encryption.py @@ -0,0 +1,55 @@ +from typing import TYPE_CHECKING, Union + +from ..identity import Identity + +import nacl.public +import nacl.utils + + +def encrypt_to_identity_anonymously( + identity: 'Identity', + message: Union[bytes, str]) -> nacl.utils.EncryptedMessage: + their_public_key = identity.key.to_curve25519_public_key() + box = nacl.public.SealedBox(their_public_key) + + try: + message = message.encode('utf-8') + except AttributeError: + pass + + return box.encrypt(message) + + +def decrypt_from_identity_anonymously( + our_identity: 'Identity', message: bytes) -> bytes: + our_private_key = our_identity.private_key.to_curve25519_private_key() + box = nacl.public.SealedBox(our_private_key) + + return box.decrypt(message) + + +def encrypt_to_identity( + our_identity: 'Identity', + identity: 'Identity', + message: Union[bytes, str]) -> nacl.utils.EncryptedMessage: + our_private_key = our_identity.private_key.to_curve25519_private_key() + their_public_key = identity.key.to_curve25519_public_key() + box = nacl.public.Box(our_private_key, their_public_key) + + try: + message = message.encode('utf-8') + except AttributeError: + pass + + return box.encrypt(message) + + +def decrypt_from_identity( + our_identity: 'Identity', + identity: 'Identity', + message: bytes) -> bytes: + our_private_key = our_identity.private_key.to_curve25519_private_key() + their_public_key = identity.key.to_curve25519_public_key() + box = nacl.public.Box(our_private_key, their_public_key) + + return box.decrypt(message) diff --git a/static-data/official-plugins/wot/wot/crypto/signatures.py b/static-data/official-plugins/wot/wot/crypto/signatures.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/default-plugin-tests/wot/test_encrypt_to_identity.py b/tests/default-plugin-tests/wot/test_encrypt_to_identity.py new file mode 100644 index 00000000..74678651 --- /dev/null +++ b/tests/default-plugin-tests/wot/test_encrypt_to_identity.py @@ -0,0 +1,84 @@ +import dbm +import os, uuid + +import time + +TEST_DIR = 'testdata/%s-%s' % (str(uuid.uuid4())[:6], os.path.basename(__file__)) + '/' +print("Test directory:", TEST_DIR) +os.environ["ONIONR_HOME"] = TEST_DIR +os.makedirs(TEST_DIR) + +from nacl import signing + +import unittest +import sys +sys.path.append('static-data/official-plugins/wot/') +sys.path.append("src/") +import onionrblocks +from blockdb import block_db_path +import nacl.public +import nacl.exceptions +import nacl.signing + +import wot +from wot.identity import Identity + +from wot import crypto + +import blockdb + + +class TestEncryptToIdentity(unittest.TestCase): + + def test_encrypt_to_identity_bytes(self): + iden_priv_key = signing.SigningKey.generate() + iden_public = iden_priv_key.verify_key + identity = Identity(iden_priv_key, "us") + + their_priv_key = signing.SigningKey.generate() + their_public = their_priv_key.verify_key + their_identity = Identity(their_priv_key, "them") + + test_message = b"test message" + + encrypted = crypto.encryption.encrypt_to_identity(identity, their_identity, test_message) + decrypted = nacl.public.Box(their_priv_key.to_curve25519_private_key(), iden_public.to_curve25519_public_key()).decrypt(encrypted) + self.assertEqual(decrypted, test_message) + + def test_encrypt_to_identity_str(self): + iden_priv_key = signing.SigningKey.generate() + iden_public = iden_priv_key.verify_key + identity = Identity(iden_priv_key, "us") + + their_priv_key = signing.SigningKey.generate() + their_public = their_priv_key.verify_key + their_identity = Identity(their_priv_key, "them") + + test_message = "test message" + + encrypted = crypto.encryption.encrypt_to_identity(identity, their_identity, test_message) + decrypted = nacl.public.Box(their_priv_key.to_curve25519_private_key(), iden_public.to_curve25519_public_key()).decrypt(encrypted) + self.assertEqual(decrypted, test_message.encode('utf-8')) + + def test_encrypt_to_identity_bytes_invalid(self): + iden_priv_key = signing.SigningKey.generate() + iden_public = iden_priv_key.verify_key + identity = Identity(iden_priv_key, "us") + + their_priv_key = signing.SigningKey.generate() + their_public = their_priv_key.verify_key + their_identity = Identity(their_priv_key, "them") + + test_message = b"test message" + + encrypted = crypto.encryption.encrypt_to_identity(identity, their_identity, test_message) + encrypted = encrypted[:-1] + b'\x00' + try: + decrypted = nacl.public.Box(their_priv_key.to_curve25519_private_key(), iden_public.to_curve25519_public_key()).decrypt(encrypted) + except nacl.exceptions.CryptoError: + pass + else: + self.fail("Decrypted invalid message") + + +unittest.main()