smp25519


Namesmp25519 JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/979st/smp25519-python
SummarySecure Messaging Protocol 25519
upload_time2025-01-18 21:07:15
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseUnlicense
keywords python sockets udp secure x25519 blake3 chacha20 protocol messaging
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # SMP25519 | Secure Messaging Protocol 25519 | Python
![SMP25519 Flow Chart](./svg/smp25519_flow_chart.svg)
## Overview
SMP25519 is designed to facilitate secure communication using the X25519 key exchange, BLAKE3 hashing, and ChaCha20 encryption. It provides a straightforward interface for generating secure identities, creating handshake messages, deriving shared secrets, and encrypting/decrypting data.
## Installation
```
pip install smp25519
```
## Dependencies
To use SMP25519, install the required dependencies:
```
pip install cryptography blake3 pycryptodomex
```
## License
This package is distributed under the [Unlicense](https://choosealicense.com/licenses/unlicense/).
## Contact
For support or inquiries, contact truebreaker@proton.me.
# Examples
## Client
```python
import socket
import smp25519
import base64

def main() -> None:
    """
    Secure UDP client example using the smp25519 package.
    This script demonstrates how to establish a secure communication channel with a server using key exchange and encryption.
    """
    # Step 1: Generate client identity (private key, public key, and connection ID).
    private_key, public_key, connection_id = smp25519.generate_identity()

    # Step 2 (RECOMMENDED): Define the server's known public key (Base64 encoded).
    known_server_public_key = base64.b64decode("Vh4DBTYyDbwTqg1eZzTnuTxThscIoNQgLpxgsBCOFCU=".encode())

    # Step 3: Create a UDP socket.
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    dest_addr = ("localhost", 12000) # Server address and port.

    print(f"Secure UDP Client: Attempting connection to {dest_addr}")

    # Step 4: Send handshake message containing the client's public key.
    sock.sendto(smp25519.create_handshake_message(public_key), dest_addr)

    # Step 5: Receive and validate handshake response from the server.
    data, addr = sock.recvfrom(1024)
    if smp25519.is_handshake_message(data) == False:
        print("Error: Handshake failed. Invalid response received.")
        return
    
    # Extract the server's public key from the handshake message.
    server_public_key = smp25519.extract_public_key_from_handshake(data)

    # (RECOMMENDED) Verify the server's public key.
    if server_public_key != known_server_public_key:
        print("Error: Known server public key mismatch. Aborting connection.")
        return

    # Step 6: Derive the shared secret using the server's public key and a salt.
    # shared_secret = smp25519.derive_shared_secret(private_key, server_public_key, b"examplesalt")
    shared_secret = smp25519.derive_shared_secret(private_key, server_public_key)

    # Step 7: Exchange encrypted messages with the server.
    while True:
        # Input message from the user.
        message = input("Enter a message to send (or press Enter to retry): ").strip()
        if len(message) == 0:
            continue
        
        # Encrypt and send the message.
        encrypted_message = smp25519.encrypt_and_send_data(connection_id, message.encode(), shared_secret)
        sock.sendto(encrypted_message, dest_addr)

        # Receive and decrypt the server's response.
        data, addr = sock.recvfrom(1024)
        decrypted_message = smp25519.decrypt_received_data(data, shared_secret)
        print(f"Server response from {addr}: {decrypted_message.decode()}")

if __name__ == "__main__":
    main()
```
## Server
```python
import socket
import smp25519
import base64

def main() -> None:
    """
    Secure UDP server example using the smp25519 package.
    This script demonstrates how to establish a secure communication channel with a single
    client at a time using key exchange and encryption.
    """
    # Step 1: Generate the server's identity.
    # private_key, public_key, connection_id = smp25519.generate_identity()

    # Or use a pre-existing private key (Base64 encoded) and derive the public key.
    private_key = base64.b64decode("4Pe2QvF6zk41OWkMTqVR8e9nvwhbOEaDRti6oykaG18=".encode())
    public_key = smp25519.get_public_key_from_private(private_key)
    print(f"Server public key (Base64): {base64.b64encode(public_key).decode()}")

    # Step 2: Set up the UDP socket and bind to a port.
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    dest_addr = ("localhost", 12000)
    sock.bind(dest_addr)
    print(f"Secure UDP Server: Listening on {dest_addr}")

    # Variables to store client-specific connection data.
    client_connection_id: bytes = None
    client_shared_secret: bytes = None

    # Step 3: Main server loop.
    while True:
        # Receive data from a client.
        data, addr = sock.recvfrom(1024)
        print(f"Connection from {addr}")

        # Step 4: Handle handshake messages.
        if smp25519.is_handshake_message(data) == True:
            print(f"Handshake received from {addr}")

            # Extract the client's public key and generate a connection ID.
            client_public_key = smp25519.extract_public_key_from_handshake(data)
            client_connection_id = smp25519.generate_connection_id_from_public_key(client_public_key)

            # Derive a shared secret using the client's public key and a salt.
            # client_shared_secret = smp25519.derive_shared_secret(private_key, client_public_key, b"examplesalt")
            client_shared_secret = smp25519.derive_shared_secret(private_key, client_public_key)

            # Respond with the server's handshake message.
            handshake = smp25519.create_handshake_message(public_key)
            sock.sendto(handshake, addr)
            print("Handshake completed.")
            continue
        
        # Step 5: Handle encrypted messages.
        if smp25519.is_valid_data(data) == True:
            # Verify the connection ID matches the client.
            if smp25519.extract_connection_id_from_data(data) != client_connection_id:
                print(f"Error: Unknown client ID from {addr}. Ignoring message.")
                continue
            
            # Decrypt the received message.
            decrypted_message = smp25519.decrypt_received_data(data, client_shared_secret)
            print(f"Message from {addr}: {decrypted_message.decode()}")

            # Send an encrypted response back to the client.
            response_message = "Hello from Server!"
            encrypted_response = smp25519.encrypt_and_send_data(client_connection_id, response_message.encode(), client_shared_secret)
            sock.sendto(encrypted_response, addr)
            print("Response sent.")
            continue
        
        # Step 6: Handle unrecognized data.
        print(f"Error: Received unknown data from {addr}")

if __name__ == "__main__":
    main()
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/979st/smp25519-python",
    "name": "smp25519",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python, sockets, udp, secure, x25519, blake3, chacha20, protocol, messaging",
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/4d/d3/68c83bb2ef43d494bde766ab2452220ca6153474e21069360c372b633b23/smp25519-1.0.0.tar.gz",
    "platform": null,
    "description": "# SMP25519 | Secure Messaging Protocol 25519 | Python\r\n![SMP25519 Flow Chart](./svg/smp25519_flow_chart.svg)\r\n## Overview\r\nSMP25519 is designed to facilitate secure communication using the X25519 key exchange, BLAKE3 hashing, and ChaCha20 encryption. It provides a straightforward interface for generating secure identities, creating handshake messages, deriving shared secrets, and encrypting/decrypting data.\r\n## Installation\r\n```\r\npip install smp25519\r\n```\r\n## Dependencies\r\nTo use SMP25519, install the required dependencies:\r\n```\r\npip install cryptography blake3 pycryptodomex\r\n```\r\n## License\r\nThis package is distributed under the [Unlicense](https://choosealicense.com/licenses/unlicense/).\r\n## Contact\r\nFor support or inquiries, contact truebreaker@proton.me.\r\n# Examples\r\n## Client\r\n```python\r\nimport socket\r\nimport smp25519\r\nimport base64\r\n\r\ndef main() -> None:\r\n    \"\"\"\r\n    Secure UDP client example using the smp25519 package.\r\n    This script demonstrates how to establish a secure communication channel with a server using key exchange and encryption.\r\n    \"\"\"\r\n    # Step 1: Generate client identity (private key, public key, and connection ID).\r\n    private_key, public_key, connection_id = smp25519.generate_identity()\r\n\r\n    # Step 2 (RECOMMENDED): Define the server's known public key (Base64 encoded).\r\n    known_server_public_key = base64.b64decode(\"Vh4DBTYyDbwTqg1eZzTnuTxThscIoNQgLpxgsBCOFCU=\".encode())\r\n\r\n    # Step 3: Create a UDP socket.\r\n    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\r\n    dest_addr = (\"localhost\", 12000) # Server address and port.\r\n\r\n    print(f\"Secure UDP Client: Attempting connection to {dest_addr}\")\r\n\r\n    # Step 4: Send handshake message containing the client's public key.\r\n    sock.sendto(smp25519.create_handshake_message(public_key), dest_addr)\r\n\r\n    # Step 5: Receive and validate handshake response from the server.\r\n    data, addr = sock.recvfrom(1024)\r\n    if smp25519.is_handshake_message(data) == False:\r\n        print(\"Error: Handshake failed. Invalid response received.\")\r\n        return\r\n    \r\n    # Extract the server's public key from the handshake message.\r\n    server_public_key = smp25519.extract_public_key_from_handshake(data)\r\n\r\n    # (RECOMMENDED) Verify the server's public key.\r\n    if server_public_key != known_server_public_key:\r\n        print(\"Error: Known server public key mismatch. Aborting connection.\")\r\n        return\r\n\r\n    # Step 6: Derive the shared secret using the server's public key and a salt.\r\n    # shared_secret = smp25519.derive_shared_secret(private_key, server_public_key, b\"examplesalt\")\r\n    shared_secret = smp25519.derive_shared_secret(private_key, server_public_key)\r\n\r\n    # Step 7: Exchange encrypted messages with the server.\r\n    while True:\r\n        # Input message from the user.\r\n        message = input(\"Enter a message to send (or press Enter to retry): \").strip()\r\n        if len(message) == 0:\r\n            continue\r\n        \r\n        # Encrypt and send the message.\r\n        encrypted_message = smp25519.encrypt_and_send_data(connection_id, message.encode(), shared_secret)\r\n        sock.sendto(encrypted_message, dest_addr)\r\n\r\n        # Receive and decrypt the server's response.\r\n        data, addr = sock.recvfrom(1024)\r\n        decrypted_message = smp25519.decrypt_received_data(data, shared_secret)\r\n        print(f\"Server response from {addr}: {decrypted_message.decode()}\")\r\n\r\nif __name__ == \"__main__\":\r\n    main()\r\n```\r\n## Server\r\n```python\r\nimport socket\r\nimport smp25519\r\nimport base64\r\n\r\ndef main() -> None:\r\n    \"\"\"\r\n    Secure UDP server example using the smp25519 package.\r\n    This script demonstrates how to establish a secure communication channel with a single\r\n    client at a time using key exchange and encryption.\r\n    \"\"\"\r\n    # Step 1: Generate the server's identity.\r\n    # private_key, public_key, connection_id = smp25519.generate_identity()\r\n\r\n    # Or use a pre-existing private key (Base64 encoded) and derive the public key.\r\n    private_key = base64.b64decode(\"4Pe2QvF6zk41OWkMTqVR8e9nvwhbOEaDRti6oykaG18=\".encode())\r\n    public_key = smp25519.get_public_key_from_private(private_key)\r\n    print(f\"Server public key (Base64): {base64.b64encode(public_key).decode()}\")\r\n\r\n    # Step 2: Set up the UDP socket and bind to a port.\r\n    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\r\n    dest_addr = (\"localhost\", 12000)\r\n    sock.bind(dest_addr)\r\n    print(f\"Secure UDP Server: Listening on {dest_addr}\")\r\n\r\n    # Variables to store client-specific connection data.\r\n    client_connection_id: bytes = None\r\n    client_shared_secret: bytes = None\r\n\r\n    # Step 3: Main server loop.\r\n    while True:\r\n        # Receive data from a client.\r\n        data, addr = sock.recvfrom(1024)\r\n        print(f\"Connection from {addr}\")\r\n\r\n        # Step 4: Handle handshake messages.\r\n        if smp25519.is_handshake_message(data) == True:\r\n            print(f\"Handshake received from {addr}\")\r\n\r\n            # Extract the client's public key and generate a connection ID.\r\n            client_public_key = smp25519.extract_public_key_from_handshake(data)\r\n            client_connection_id = smp25519.generate_connection_id_from_public_key(client_public_key)\r\n\r\n            # Derive a shared secret using the client's public key and a salt.\r\n            # client_shared_secret = smp25519.derive_shared_secret(private_key, client_public_key, b\"examplesalt\")\r\n            client_shared_secret = smp25519.derive_shared_secret(private_key, client_public_key)\r\n\r\n            # Respond with the server's handshake message.\r\n            handshake = smp25519.create_handshake_message(public_key)\r\n            sock.sendto(handshake, addr)\r\n            print(\"Handshake completed.\")\r\n            continue\r\n        \r\n        # Step 5: Handle encrypted messages.\r\n        if smp25519.is_valid_data(data) == True:\r\n            # Verify the connection ID matches the client.\r\n            if smp25519.extract_connection_id_from_data(data) != client_connection_id:\r\n                print(f\"Error: Unknown client ID from {addr}. Ignoring message.\")\r\n                continue\r\n            \r\n            # Decrypt the received message.\r\n            decrypted_message = smp25519.decrypt_received_data(data, client_shared_secret)\r\n            print(f\"Message from {addr}: {decrypted_message.decode()}\")\r\n\r\n            # Send an encrypted response back to the client.\r\n            response_message = \"Hello from Server!\"\r\n            encrypted_response = smp25519.encrypt_and_send_data(client_connection_id, response_message.encode(), client_shared_secret)\r\n            sock.sendto(encrypted_response, addr)\r\n            print(\"Response sent.\")\r\n            continue\r\n        \r\n        # Step 6: Handle unrecognized data.\r\n        print(f\"Error: Received unknown data from {addr}\")\r\n\r\nif __name__ == \"__main__\":\r\n    main()\r\n```\r\n",
    "bugtrack_url": null,
    "license": "Unlicense",
    "summary": "Secure Messaging Protocol 25519",
    "version": "1.0.0",
    "project_urls": {
        "Homepage": "https://github.com/979st/smp25519-python"
    },
    "split_keywords": [
        "python",
        " sockets",
        " udp",
        " secure",
        " x25519",
        " blake3",
        " chacha20",
        " protocol",
        " messaging"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "eec1198a516d7c97832d00bc3ccf1e61926be329f24537c13dfa16b5e47b73e5",
                "md5": "576bd7713f49c352eb28f37d208f5ebb",
                "sha256": "de5a520b36605026034c6213a1915aff407350837f999751b22ce620a2f31596"
            },
            "downloads": -1,
            "filename": "smp25519-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "576bd7713f49c352eb28f37d208f5ebb",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 6525,
            "upload_time": "2025-01-18T21:07:14",
            "upload_time_iso_8601": "2025-01-18T21:07:14.195501Z",
            "url": "https://files.pythonhosted.org/packages/ee/c1/198a516d7c97832d00bc3ccf1e61926be329f24537c13dfa16b5e47b73e5/smp25519-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4dd368c83bb2ef43d494bde766ab2452220ca6153474e21069360c372b633b23",
                "md5": "2e360c644776b75a65776add4ef61e50",
                "sha256": "6e455d1b93bd7b4ff25ca72f728943a025ed3768cc88016c88a30a782b8b156b"
            },
            "downloads": -1,
            "filename": "smp25519-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "2e360c644776b75a65776add4ef61e50",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 6400,
            "upload_time": "2025-01-18T21:07:15",
            "upload_time_iso_8601": "2025-01-18T21:07:15.959947Z",
            "url": "https://files.pythonhosted.org/packages/4d/d3/68c83bb2ef43d494bde766ab2452220ca6153474e21069360c372b633b23/smp25519-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-01-18 21:07:15",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "979st",
    "github_project": "smp25519-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "smp25519"
}
        
Elapsed time: 0.41900s