### Setup Development Environment Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Commands to clone the repository, create a virtual environment, and install development dependencies. ```bash git clone https://github.com/juliuspleunes4/noiseframework.git cd noiseframework python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -e ".[dev]" ``` -------------------------------- ### Complete logging example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Full setup for debugging NoiseFramework operations. ```python import logging from noiseframework import NoiseHandshake logging.basicConfig( level=logging.DEBUG, format="%(asctime)s [%(levelname)-8s] %(name)s: %(message)s" ) ``` -------------------------------- ### Synchronous Client/Server Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Demonstrates a basic synchronous client and server setup using NoiseConnection for secure communication. Ensure NoiseConnection is imported. ```python from noise.connection import NoiseConnection # Server side server = NoiseConnection.from_config( { "noise_pattern": "XX", "client_prologue": b"\x01\x02\x03", "server_prologue": b"\x01\x02\x03", "static_private": server_private_key, "static_public": server_public_key, "remote_public": client_public_key, "psks": {1: b"my_psk"}, "options": {"full_connection_id": True}, } ) server.set_as_server() server.start_handshake() # Client side client = NoiseConnection.from_config( { "noise_pattern": "XX", "client_prologue": b"\x01\x02\x03", "server_prologue": b"\x01\x02\x03", "static_private": client_private_key, "static_public": client_public_key, "remote_public": server_public_key, "psks": {1: b"my_psk"}, "options": {"full_connection_id": True}, } ) client.set_as_client() client.start_handshake() # After handshake is complete, send and receive messages # client.send(b"hello") # server.receive(client.read()) # server.send(b"world") # client.receive(server.read()) ``` -------------------------------- ### Logging Configuration Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Basic example of configuring logging for the Noise Framework. Assumes standard Python logging setup. ```python import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Example usage within Noise Framework components (if logging is enabled) # logger.info("Noise component initialized") ``` -------------------------------- ### Complete NoiseConnection Example (Server and Client) Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md A full example demonstrating a NoiseConnection server and client setup, including handshake, message exchange, and connection management. ```python import socket import threading from noiseframework import NoiseConnection def server(): server_sock = socket.socket() server_sock.bind(("localhost", 9999)) server_sock.listen(1) client_sock, _ = server_sock.accept() with NoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "responder") as conn: conn.accept(client_sock) # Exchange messages data = conn.receive() print(f"Server received: {data}") conn.send(b"Echo: " + data) server_sock.close() # Start server threading.Thread(target=server, daemon=True).start() # Client with NoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "initiator") as conn: conn.connect(("localhost", 9999)) conn.send(b"Hello!") response = conn.receive() print(f"Client received: {response}") ``` -------------------------------- ### Install NoiseFramework from Source Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Install the NoiseFramework package by cloning the repository and installing it locally. This is useful for development or if you need the latest unreleased changes. ```bash git clone https://github.com/juliuspleunes4/noiseframework.git cd noiseframework pip install -e . ``` -------------------------------- ### Test Installation Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/PYPI_RELEASE.md Verifies the package installation in a clean virtual environment. ```powershell # Create fresh virtual environment python -m venv test_env test_env\Scripts\Activate.ps1 # Install from PyPI pip install noiseframework # Verify installation python -c "import noiseframework; print(noiseframework.__version__)" noiseframework --version # Cleanup deactivate Remove-Item -Recurse -Force test_env ``` -------------------------------- ### Async TCP Server/Client Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Demonstrates setting up an asynchronous TCP server and client using Noise XX handshake with asyncio. This example utilizes async stream readers and writers. ```python import asyncio from noise.async_support.connection import AsyncNoiseConnection async def run_server(): server = await asyncio.start_server( handle_client, '127.0.0.1', 8888) async with server: await server.serve_forever() async def handle_client(reader, writer): addr = writer.get_extra_info('peername') print(f"Connection from {addr}") # Configure and start handshake for the client connection noise_connection = AsyncNoiseConnection.from_config({ "noise_pattern": "XX", "local_private": server_private_key, "local_public": server_public_key, "remote_public": client_public_key, # This would be obtained during handshake "psks": {1: b"my_psk"}, "options": {"full_connection_id": True}, }) noise_connection.set_as_server() await noise_connection.start_handshake(reader, writer) # ... handle encrypted communication ... writer.close() await writer.wait_closed() async def run_client(): reader, writer = await asyncio.open_connection('127.0.0.1', 8888) # Configure and start handshake for the client connection noise_connection = AsyncNoiseConnection.from_config({ "noise_pattern": "XX", "local_private": client_private_key, "local_public": client_public_key, "remote_public": server_public_key, "psks": {1: b"my_psk"}, "options": {"full_connection_id": True}, }) client.set_as_client() await noise_connection.start_handshake(reader, writer) # ... handle encrypted communication ... writer.close() await writer.wait_closed() # To run: # asyncio.run(asyncio.gather(run_server(), run_client())) ``` -------------------------------- ### Run NoiseFramework examples via CLI Source: https://github.com/juliuspleunes4/noiseframework/blob/main/examples/README.md Execute example scripts directly using the Python interpreter. ```bash python examples/basic_client_server.py python examples/file_encryption.py python examples/simple_chat.py ``` ```bash python -m examples.basic_client_server python -m examples.file_encryption python -m examples.simple_chat ``` -------------------------------- ### Set up the development environment Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CONTRIBUTING.md Commands to initialize a virtual environment and install development dependencies. ```bash python -m venv .venv .venv\Scripts\activate # Windows # or source .venv/bin/activate # Linux/Mac pip install -e ".[dev]" ``` -------------------------------- ### Basic Client-Server Example (Python) Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md This example demonstrates a basic client-server interaction using the Noise Protocol Framework. It covers setting up roles, performing handshakes, and exchanging encrypted messages. ```python import os import logging from noiseframework import NoiseHandshake, NoiseConnection, NoiseHandshakeState, NoiseTransportState, NoiseProtocolName logging.basicConfig(level=logging.INFO) def run_handshake(initiator: bool): # Use Curve25519 for DH and ChaCha20-Poly1305 for AEAD protocol_name = NoiseProtocolName.Noise_XX_25519_ChaCha20_Poly1305 handshake_pattern = "XX" # Generate ephemeral keys for the handshake my_keypair = NoiseConnection.generate_keypair() peer_keypair = NoiseConnection.generate_keypair() # In a real scenario, this would be the peer's static key # Initialize handshake state handshake_state = NoiseHandshakeState( protocol_name=protocol_name, handshake_pattern=handshake_pattern, my_static_keypair=my_keypair, peer_static_key=peer_keypair[0], # Public key of the peer is_initiator=initiator, ) # Simulate handshake messages messages = [] try: # Initiator starts if initiator: messages.append(handshake_state.write_message()) # Responder processes message and sends its own if not initiator: handshake_state.read_message(messages.pop(0)) messages.append(handshake_state.write_message()) # Initiator processes responder's message if initiator: handshake_state.read_message(messages.pop(0)) messages.append(handshake_state.write_message()) # Responder processes initiator's message if not initiator: handshake_state.read_message(messages.pop(0)) # Convert to transport state for encrypted communication transport_state = handshake_state.to_transport() logging.info(f"Handshake successful. Transport state initialized.") # Simulate sending and receiving encrypted messages message_to_send = b"Hello, secure world!" encrypted_message = transport_state.send(message_to_send) logging.info(f"Sent encrypted message: {encrypted_message}") # Simulate receiving and decrypting received_message = transport_state.receive(encrypted_message) logging.info(f"Received and decrypted message: {received_message}") assert received_message == message_to_send except Exception as e: logging.error(f"Handshake or transport failed: {e}") if __name__ == "__main__": # Run as initiator run_handshake(initiator=True) # Run as responder (in a separate process/thread) # run_handshake(initiator=False) ``` -------------------------------- ### Install NoiseFramework using pip Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Install the NoiseFramework package from PyPI. This is the recommended installation method. ```bash pip install noiseframework ``` -------------------------------- ### Log INFO output example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Example output showing major operational events like role setting and handshake completion. ```text INFO: Role set as INITIATOR INFO: Generated static keypair INFO: Handshake initialized INFO: Sent handshake message 1 (ciphertext=32 bytes) INFO: Handshake complete - ready for transport mode INFO: Created transport ciphers (initiator: send=c1, receive=c2) INFO: Sent encrypted message (ciphertext=29 bytes) ``` -------------------------------- ### Log WARNING output example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Example output showing potential issues such as nonce limits. ```text WARNING: Send cipher nonce high: 9223372036854775808 (approaching 2^64 limit - consider rekeying) ``` -------------------------------- ### Implement a Complete Async Client-Server Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md A full implementation showing both server-side stream acceptance and client-side connection initiation. ```python import asyncio from noiseframework import AsyncNoiseConnection async def handle_client(reader, writer): async with AsyncNoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "responder") as conn: await conn.accept_streams(reader, writer) data = await conn.receive() print(f"Server received: {data}") await conn.send(b"Echo: " + data) async def main(): # Start server server = await asyncio.start_server(handle_client, "localhost", 9999) # Client async with AsyncNoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "initiator") as conn: await conn.connect(("localhost", 9999)) await conn.send(b"Hello, async!") response = await conn.receive() print(f"Client received: {response}") server.close() await server.wait_closed() asyncio.run(main()) ``` -------------------------------- ### Custom Keys and Identity Verification Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md An advanced example showcasing the use of custom keys and identity verification within the NoiseConnection. This requires pre-generated keys and potentially a trust store. ```python from noise.connection import NoiseConnection # Assume keys and identity verification logic are set up # Example configuration with custom keys: config = { "noise_pattern": "IK", "local_private": local_private_key, "local_public": local_public_key, "remote_public": remote_public_key, "identity": local_identity, # Optional: for identity verification "remote_identity": remote_identity, # Optional: for identity verification "options": {"full_connection_id": True}, } connection = NoiseConnection.from_config(config) connection.set_as_initiator() # or set_as_responder() connection.start_handshake() # ... rest of the communication logic ... ``` -------------------------------- ### Install Build Tools Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/PYPI_RELEASE.md Updates pip and installs the necessary tools for building and uploading the package. ```powershell # Install/upgrade build tools python -m pip install --upgrade pip python -m pip install --upgrade build twine ``` -------------------------------- ### Configure basic logging setup Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Global configuration for NoiseFramework logging using standard Python logging. ```python import logging from noiseframework import NoiseHandshake # Configure logging globally logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)-8s] %(name)s: %(message)s" ) # Use NoiseFramework - logging happens automatically handshake = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") handshake.set_as_initiator() # Logs: "Role set as INITIATOR" ``` -------------------------------- ### Configure NoiseHandshake Instances Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Examples of initializing the handshake with default or custom loggers. ```python # Basic usage with default logger handshake = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") # With custom logger import logging custom_logger = logging.getLogger("myapp.noise") handshake = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256", logger=custom_logger) ``` -------------------------------- ### Log ERROR output example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Example output showing error conditions that precede exceptions. ```text ERROR: Attempted to write message without setting role ERROR: Attempted to set role when already set ERROR: Attempted to create transport ciphers before handshake completion ERROR: Decryption failed: Authentication tag verification failed ``` -------------------------------- ### Basic Client-Server Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Demonstrates a basic client-server interaction using NoiseTransport for secure communication. Requires `from noiseframework import NoiseTransport`. ```python from noiseframework import NoiseTransport # Server side server_transport = NoiseTransport(is_initiator=False) server_transport.set_keypair(private_key=server_private_key, public_key=server_public_key) # Client side client_transport = NoiseTransport(is_initiator=True) client_transport.set_keypair(private_key=client_private_key, public_key=client_public_key) client_transport.set_remote_public_key(server_public_key) # ... handshake and message exchange ... ``` -------------------------------- ### Asynchronous Client/Server Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Illustrates an asynchronous client and server using AsyncNoiseConnection with asyncio. Requires importing AsyncNoiseConnection and asyncio. ```python import asyncio from noise.async_support.connection import AsyncNoiseConnection async def main(): # Server side server = AsyncNoiseConnection.from_config( { "noise_pattern": "XX", "client_prologue": b"\x01\x02\x03", "server_prologue": b"\x01\x02\x03", "static_private": server_private_key, "static_public": server_public_key, "remote_public": client_public_key, "psks": {1: b"my_psk"}, "options": {"full_connection_id": True}, } ) server.set_as_server() await server.start_handshake() # Client side client = AsyncNoiseConnection.from_config( { "noise_pattern": "XX", "client_prologue": b"\x01\x02\x03", "server_prologue": b"\x01\x02\x03", "static_private": client_private_key, "static_public": client_public_key, "remote_public": server_public_key, "psks": {1: b"my_psk"}, "options": {"full_connection_id": True}, } ) client.set_as_client() await client.start_handshake() # After handshake is complete, send and receive messages # await client.send(b"hello") # await server.receive(await client.read()) # await server.send(b"world") # await client.receive(await server.read()) asyncio.run(main()) ``` -------------------------------- ### Simple Chat Example (Python) Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md This example demonstrates a simple chat application using the Noise Protocol Framework for secure communication between two peers. It involves setting up connections, performing handshakes, and sending/receiving messages. ```python import os import threading import socket from noiseframework import NoiseConnection, NoiseTransportState, NoiseProtocolName HOST = '127.0.0.1' PORT = 12345 def handle_client(conn, addr, transport_state): """Handles communication with a connected client.""" print(f"[NEW CONNECTION] {addr} connected.") try: while True: data = conn.recv(1024) if not data: break try: message = transport_state.receive(data) print(f"[{addr}] Received: {message.decode()}") response = input("Enter response: ") encrypted_response = transport_state.send(response.encode()) conn.sendall(encrypted_response) except Exception as e: print(f"Error receiving/decrypting from {addr}: {e}") break except ConnectionResetError: print(f"[DISCONNECTED] {addr} disconnected abruptly.") finally: print(f"[CONNECTION CLOSED] {addr}") conn.close() def start_server(): """Starts the Noise Protocol chat server.""" server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((HOST, PORT)) server_socket.listen(5) print(f"[*] Server listening on {HOST}:{PORT}") # Server generates its own keypair server_keypair = NoiseConnection.generate_keypair() print(f"Server static public key: {server_keypair[0].hex()}") while True: conn, addr = server_socket.accept() # Initialize handshake for the new connection # Using XX pattern for demonstration protocol_name = NoiseProtocolName.Noise_XX_25519_ChaCha20_Poly1305 handshake_pattern = "XX" # Server acts as responder transport_state = NoiseTransportState( protocol_name=protocol_name, handshake_pattern=handshake_pattern, my_static_keypair=server_keypair, is_initiator=False, # Server is responder # Peer's static key will be learned during handshake ) # Start a new thread to handle the client thread = threading.Thread(target=handle_client, args=(conn, addr, transport_state)) thread.start() def start_client(): """Starts the Noise Protocol chat client.""" client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: client_socket.connect((HOST, PORT)) print(f"[*] Connected to {HOST}:{PORT}") # Client generates its own keypair client_keypair = NoiseConnection.generate_keypair() print(f"Client static public key: {client_keypair[0].hex()}") # Initialize handshake for the client protocol_name = NoiseProtocolName.Noise_XX_25519_ChaCha20_Poly1305 handshake_pattern = "XX" # Client acts as initiator transport_state = NoiseTransportState( protocol_name=protocol_name, handshake_pattern=handshake_pattern, my_static_keypair=client_keypair, is_initiator=True, # Client is initiator # Peer's static key is unknown initially, will be set after handshake ) # Perform handshake (simplified: assumes server sends first after accept) # In a real app, client would send first message # For this example, we'll simulate receiving the first server message # and then sending our first message. # Simulate receiving server's first handshake message (if server sent it) # In a real scenario, this would be conn.recv() # For simplicity, let's assume handshake happens implicitly or is handled # by the NoiseTransportState initialization and subsequent send/receive. # Let's simulate the handshake flow more explicitly for clarity: # 1. Client sends handshake init message handshake_msg1 = transport_state.write_message() client_socket.sendall(handshake_msg1) print("Sent initial handshake message.") # 2. Client receives server's response and sends its next message server_response = client_socket.recv(1024) transport_state.read_message(server_response) print("Received server handshake response.") handshake_msg2 = transport_state.write_message() client_socket.sendall(handshake_msg2) print("Sent second handshake message.") # 3. Client receives final handshake message from server server_final_msg = client_socket.recv(1024) transport_state.read_message(server_final_msg) print("Received final handshake message. Handshake complete.") # Now, start sending and receiving chat messages while True: message = input("Enter message: ") encrypted_message = transport_state.send(message.encode()) client_socket.sendall(encrypted_message) print(f"Sent: {message}") # Receive response (simplified: assumes server sends back immediately) response_data = client_socket.recv(1024) if not response_data: break try: decrypted_response = transport_state.receive(response_data) print(f"Received: {decrypted_response.decode()}") except Exception as e: print(f"Error receiving/decrypting response: {e}") break except ConnectionRefusedError: print("[ERROR] Connection refused. Is the server running?") except Exception as e: print(f"An error occurred: {e}") finally: print("[CONNECTION CLOSED]") client_socket.close() if __name__ == "__main__": # To run: # 1. Start the server in one terminal: python your_script_name.py server # 2. Start the client in another terminal: python your_script_name.py client import sys if len(sys.argv) > 1 and sys.argv[1] == 'server': start_server() elif len(sys.argv) > 1 and sys.argv[1] == 'client': start_client() else: print("Usage: python script.py [server|client]") ``` -------------------------------- ### XX Pattern (Mutual Authentication) Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Example demonstrating the XX handshake pattern for mutual authentication between an initiator and a responder. ```APIDOC ## XX Pattern (Mutual Authentication) ### Description Example demonstrating the XX handshake pattern for mutual authentication between an initiator and a responder. ### Request Example ```python from noiseframework import NoiseHandshake, NoiseTransport # === Setup === # Initiator (client) initiator = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") initiator.set_as_initiator() initiator.generate_static_keypair() initiator.initialize() # Responder (server) responder = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") responder.set_as_responder() responder.generate_static_keypair() responder.initialize() # === Handshake === # -> e msg1 = initiator.write_message(b"") responder.read_message(msg1) # <- e, ee, s, es msg2 = responder.write_message(b"") initiator.read_message(msg2) # -> s, se msg3 = initiator.write_message(b"") responder.read_message(msg3) # === Transport === i_send, i_recv = initiator.to_transport() r_send, r_recv = responder.to_transport() i_transport = NoiseTransport(i_send, i_recv) r_transport = NoiseTransport(r_send, r_recv) # Send encrypted messages ciphertext = i_transport.send(b"Hello, server!") plaintext = r_transport.receive(ciphertext) assert plaintext == b"Hello, server!" ``` ``` -------------------------------- ### File Encryption Example (Python) Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md This example demonstrates how to encrypt and decrypt a file using the Noise Protocol Framework. It utilizes the transport layer for secure data transfer. ```python import os from noiseframework import NoiseConnection, NoiseTransportState, NoiseProtocolName def encrypt_file(input_filepath, output_filepath, key): """Encrypts a file using AES-256-GCM.""" # For simplicity, using a fixed key. In practice, derive or manage keys securely. # Key should be 32 bytes for AES-256 if len(key) != 32: raise ValueError("Key must be 32 bytes for AES-256") # Initialize transport state with a symmetric key # Using AES-256-GCM for encryption transport_state = NoiseTransportState( protocol_name=NoiseProtocolName.Noise_AESGCM_256_25519_ChaCha20Poly1305, # Placeholder, actual AEAD choice matters symmetric_key=key, is_initiator=True # Role doesn't strictly matter for pure encryption/decryption with key ) with open(input_filepath, 'rb') as infile, open(output_filepath, 'wb') as outfile: while True: chunk = infile.read(4096) # Read in chunks if not chunk: break encrypted_chunk = transport_state.send(chunk) outfile.write(encrypted_chunk) print(f"File '{input_filepath}' encrypted to '{output_filepath}'.") def decrypt_file(input_filepath, output_filepath, key): """Decrypts a file using AES-256-GCM.""" if len(key) != 32: raise ValueError("Key must be 32 bytes for AES-256") transport_state = NoiseTransportState( protocol_name=NoiseProtocolName.Noise_AESGCM_256_25519_ChaCha20Poly1305, # Placeholder symmetric_key=key, is_initiator=False # Role doesn't strictly matter ) with open(input_filepath, 'rb') as infile, open(output_filepath, 'wb') as outfile: while True: # Read encrypted data, assuming it's already chunked appropriately or read full encrypted blob # For simplicity, reading the whole file if small, or need a delimiter/length prefix for chunks encrypted_data = infile.read() if not encrypted_data: break try: decrypted_chunk = transport_state.receive(encrypted_data) outfile.write(decrypted_chunk) except Exception as e: print(f"Decryption failed: {e}") # Handle potential authentication errors or incomplete data break print(f"File '{input_filepath}' decrypted to '{output_filepath}'.") if __name__ == "__main__": # Generate a secure key (32 bytes for AES-256) # In a real application, use a secure key generation method or key management system encryption_key = os.urandom(32) # Create a dummy file to encrypt dummy_file_content = b"This is a secret message that needs to be encrypted." with open("plaintext.txt", "wb") as f: f.write(dummy_file_content) # Encrypt the file encrypt_file("plaintext.txt", "encrypted.bin", encryption_key) # Decrypt the file decrypt_file("encrypted.bin", "decrypted.txt", encryption_key) # Verify decryption with open("decrypted.txt", "rb") as f: decrypted_content = f.read() assert decrypted_content == dummy_file_content print("Decryption verified successfully.") # Clean up dummy files os.remove("plaintext.txt") os.remove("encrypted.bin") os.remove("decrypted.txt") ``` -------------------------------- ### PSK Pattern Format Examples Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Examples of Noise protocol strings using various PSK modifiers to indicate when the key is mixed. ```text Noise_XXpsk3_25519_ChaChaPoly_SHA256 # XX with PSK after third message Noise_NNpsk0_25519_ChaChaPoly_SHA256 # NN with PSK before first message Noise_IKpsk2_448_AESGCM_BLAKE2b # IK with PSK after second message ``` -------------------------------- ### AsyncFramedReader Usage Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Examples for importing and constructing AsyncFramedReader. ```python from noiseframework import AsyncFramedReader ``` ```python AsyncFramedReader( reader: asyncio.StreamReader, max_message_size: int = 16*1024*1024, # 16 MB default logger: Optional[logging.Logger] = None ) -> AsyncFramedReader ``` -------------------------------- ### Example: Receive Framed Messages Async Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Demonstrates connecting to a server, creating an AsyncFramedReader, and receiving two framed messages. ```python import asyncio from noiseframework import AsyncFramedReader async def receive_framed(): reader, writer = await asyncio.open_connection('localhost', 8000) framed_reader = AsyncFramedReader(reader) msg1 = await framed_reader.read_message() msg2 = await framed_reader.read_message() await framed_reader.close() print(f"Received: {msg1}, {msg2}") asyncio.run(receive_framed()) ``` -------------------------------- ### Complete TCP Server Example with Noise Handshake Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Sets up a TCP server, performs a Noise XX handshake, and then exchanges encrypted messages using FramedReader and FramedWriter. ```python import socket from noiseframework import NoiseHandshake, FramedWriter, FramedReader # Server def server(): with socket.socket() as sock: sock.bind(('localhost', 8000)) sock.listen(1) conn, _ = sock.accept() # Noise handshake hs = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") hs.set_as_responder() hs.generate_static_keypair() hs.initialize() # Framed communication reader = FramedReader(conn.makefile('rb')) writer = FramedWriter(conn.makefile('wb')) # Handshake messages (3 messages for XX) msg1 = reader.read_message() msg2 = hs.read_message(msg1) msg2_out = hs.write_message(msg2) writer.write_message(msg2_out) msg3 = reader.read_message() hs.read_message(msg3) # Transport mode transport = hs.to_transport() # Receive encrypted message ciphertext = reader.read_message() plaintext = transport.receive(ciphertext) print(f"Received: {plaintext}") # Send encrypted response response = transport.send(b"Hello, Client!") writer.write_message(response) ``` -------------------------------- ### Synchronous Noise Connection Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Demonstrates setting up a synchronous Noise connection for secure communication. The server acts as a responder, and the client acts as an initiator. Handshake and transport are handled automatically. ```python from noiseframework import NoiseConnection import socket import threading def server(): """Responder side.""" server_sock = socket.socket() server_sock.bind(("localhost", 9999)) server_sock.listen(1) client_sock, _ = server_sock.accept() # Create connection and accept - handshake happens automatically with NoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "responder") as conn: conn.accept(client_sock) # Now in transport mode - send/receive encrypted messages data = conn.receive() conn.send(b"Echo: " + data) server_sock.close() # Start server in background threading.Thread(target=server, daemon=True).start() # Client (initiator side) with NoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "initiator") as conn: conn.connect(("localhost", 9999)) # Handshake happens automatically conn.send(b"Hello, NoiseFramework!") response = conn.receive() print(response) # b"Echo: Hello, NoiseFramework!" ``` -------------------------------- ### Asynchronous Noise Connection Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Illustrates setting up an asynchronous Noise connection using asyncio. The server handles clients asynchronously, and the client connects using async methods. Both handshake and transport are managed automatically. ```python import asyncio from noiseframework import AsyncNoiseConnection async def handle_client(reader, writer): """Async responder.""" async with AsyncNoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "responder") as conn: await conn.accept_streams(reader, writer) # Auto handshake data = await conn.receive() await conn.send(b"Echo: " + data) async def main(): # Start async server server = await asyncio.start_server(handle_client, "localhost", 9999) # Client async with AsyncNoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "initiator") as conn: await conn.connect(("localhost", 9999)) # Auto handshake await conn.send(b"Hello, async!") response = await conn.receive() print(response) # b"Echo: Hello, async!" server.close() await server.wait_closed() asyncio.run(main()) ``` -------------------------------- ### Async PSK Handshake Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Example of setting a PSK using the asynchronous API. ```python async def async_psk_example(): psk = os.urandom(32) handshake = AsyncNoiseHandshake("Noise_XXpsk3_25519_ChaChaPoly_SHA256") await handshake.set_as_initiator() await handshake.generate_static_keypair() await handshake.set_psk(psk) # Async PSK setting await handshake.initialize() # Continue with async handshake... ``` -------------------------------- ### Asynchronous Connection Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Demonstrates establishing a secure connection using the asynchronous AsyncNoiseConnection API with asyncio. This includes setting up an async server and an async client for communication. ```APIDOC ## Asynchronous Connection Example This example illustrates using the `AsyncNoiseConnection` class for asynchronous secure communication with `asyncio`. ### Server Side (Async) 1. Define an `async` handler function for clients. 2. Inside the handler, initialize `AsyncNoiseConnection` in responder mode. 3. Use `await conn.accept_streams(reader, writer)` to perform the handshake. 4. Use `await conn.send()` and `await conn.receive()` for encrypted communication. 5. Start an `asyncio` server using `asyncio.start_server()`. ### Client Side (Async) 1. Initialize `AsyncNoiseConnection` in initiator mode. 2. Use `await conn.connect(('host', port))` to initiate the handshake. 3. Use `await conn.send()` and `await conn.receive()` for encrypted communication. ### Code Example ```python import asyncio from noiseframework import AsyncNoiseConnection async def handle_client(reader, writer): """Async responder.""" async with AsyncNoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "responder") as conn: await conn.accept_streams(reader, writer) # Auto handshake data = await conn.receive() await conn.send(b"Echo: " + data) async def main(): # Start async server server = await asyncio.start_server(handle_client, "localhost", 9999) # Client async with AsyncNoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "initiator") as conn: await conn.connect(("localhost", 9999)) # Auto handshake await conn.send(b"Hello, async!") response = await conn.receive() print(response) # b"Echo: Hello, async!" server.close() await server.wait_closed() asyncio.run(main()) ``` ``` -------------------------------- ### AsyncFramedWriter Usage Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Examples for importing, constructing, and using AsyncFramedWriter for length-prefixed messaging. ```python from noiseframework import AsyncFramedWriter ``` ```python AsyncFramedWriter( writer: asyncio.StreamWriter, max_message_size: int = 16*1024*1024, # 16 MB default logger: Optional[logging.Logger] = None ) -> AsyncFramedWriter ``` ```python writer = AsyncFramedWriter(stream_writer) await writer.write_message(b"Hello, async!") ``` ```python await writer.close() ``` ```python count = writer.messages_sent ``` ```python import asyncio from noiseframework import AsyncFramedWriter async def send_framed(): reader, writer = await asyncio.open_connection('localhost', 8000) framed_writer = AsyncFramedWriter(writer) await framed_writer.write_message(b"Message 1") await framed_writer.write_message(b"Message 2") await framed_writer.close() asyncio.run(send_framed()) ``` -------------------------------- ### Async TCP Client Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Demonstrates a full async Noise XX handshake and encrypted communication over TCP. Requires a running Noise server on 127.0.0.1:9999. Ensure `asyncio` is available. ```python async def async_client(): # Connect to server reader, writer = await asyncio.open_connection('127.0.0.1', 9999) # Create initiator handshake handshake = AsyncNoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") await handshake.set_as_initiator() await handshake.generate_static_keypair() await handshake.initialize() # Wrap streams with framing framed_reader = AsyncFramedReader(reader) framed_writer = AsyncFramedWriter(writer) # Perform XX handshake (3 messages) msg1 = await handshake.write_message(b"") await framed_writer.write_message(msg1) msg2 = await framed_reader.read_message() await handshake.read_message(msg2) msg3 = await handshake.write_message(b"") await framed_writer.write_message(msg3) # Switch to transport mode transport = await handshake.to_transport() # Send encrypted messages for i in range(3): message = f"Message {i+1}".encode() ciphertext = await transport.send(message) await framed_writer.write_message(ciphertext) response_ct = await framed_reader.read_message() response = await transport.receive(response_ct) print(f"Server response: {response.decode()}") await framed_writer.close() asyncio.run(async_client()) ``` -------------------------------- ### Troubleshoot Authentication Errors Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/FAQ.md Examples of common causes for AuthenticationError and how to debug them. ```python # Attacker modified ciphertext ciphertext = ciphertext[:-1] + b"\x00" transport.receive(ciphertext) # AuthenticationError! ``` ```python # Must process messages in order ct1 = transport.send(b"msg1") ct2 = transport.send(b"msg2") # Don't do: transport.receive(ct2), transport.receive(ct1) ``` ```python # Both must use same pattern client = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") server = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") # Must match! ``` ```python from noiseframework.exceptions import AuthenticationError try: plaintext = transport.receive(ciphertext) except AuthenticationError as e: print(f"Decryption failed: {e}") print(f"Nonce: {transport.get_receive_nonce()}") print(f"Ciphertext length: {len(ciphertext)}") # Check for tampering, corruption, or protocol errors ``` -------------------------------- ### Logging Configuration Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Shows how to provide a logger instance to Noise framework components for detailed operational logging. The default logger uses a module.class pattern. ```python import logging from noise.connection import NoiseConnection # Create a logger instance my_logger = logging.getLogger('my_noise_app') my_logger.setLevel(logging.DEBUG) # Add a handler if not already configured if not my_logger.handlers: handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) my_logger.addHandler(handler) # Pass the logger to NoiseConnection connection = NoiseConnection.from_config( { "noise_pattern": "XX", # ... other config ... }, logger=my_logger # Pass the custom logger here ) # Handshake, transport, etc. will now use my_logger for DEBUG, INFO, ERROR messages. ``` -------------------------------- ### Noise Pipes Fallback Initialization Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Initial setup for implementing Noise Pipes fallback patterns. ```python import os from noiseframework import NoiseHandshake ``` -------------------------------- ### Synchronous Connection Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Demonstrates establishing a secure connection using the synchronous NoiseConnection API. This includes setting up a server to accept a connection and a client to initiate one, followed by sending and receiving encrypted messages. ```APIDOC ## Synchronous Connection Example This example shows how to use the `NoiseConnection` class for synchronous secure communication. ### Server Side 1. Create a standard socket and bind it to a port. 2. Listen for incoming connections. 3. Accept a client connection. 4. Initialize `NoiseConnection` in responder mode. 5. Call `conn.accept(client_sock)` to perform the handshake. 6. Use `conn.send()` and `conn.receive()` for encrypted communication. ### Client Side 1. Initialize `NoiseConnection` in initiator mode. 2. Call `conn.connect(('host', port))` to initiate the handshake. 3. Use `conn.send()` and `conn.receive()` for encrypted communication. ### Code Example ```python from noiseframework import NoiseConnection import socket import threading def server(): """Responder side.""" server_sock = socket.socket() server_sock.bind(("localhost", 9999)) server_sock.listen(1) client_sock, _ = server_sock.accept() # Create connection and accept - handshake happens automatically with NoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "responder") as conn: conn.accept(client_sock) # Now in transport mode - send/receive encrypted messages data = conn.receive() conn.send(b"Echo: " + data) server_sock.close() # Start server in background threading.Thread(target=server, daemon=True).start() # Client (initiator side) with NoiseConnection("Noise_XX_25519_ChaChaPoly_SHA256", "initiator") as conn: conn.connect(("localhost", 9999)) # Handshake happens automatically conn.send(b"Hello, NoiseFramework!") response = conn.receive() print(response) # b"Echo: Hello, NoiseFramework!" ``` ``` -------------------------------- ### Implement Async TCP Server Source: https://github.com/juliuspleunes4/noiseframework/blob/main/README.md Full example of an asynchronous server handling Noise handshakes and encrypted message streams. ```python import asyncio from noiseframework import ( AsyncNoiseHandshake, AsyncFramedReader, AsyncFramedWriter, ) async def handle_client(reader, writer): """Handle incoming client connection.""" # Create responder handshake handshake = AsyncNoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") await handshake.set_as_responder() await handshake.generate_static_keypair() await handshake.initialize() # Wrap streams with framing framed_reader = AsyncFramedReader(reader) framed_writer = AsyncFramedWriter(writer) # Perform XX handshake msg1 = await framed_reader.read_message() await handshake.read_message(msg1) msg2 = await handshake.write_message(b"") await framed_writer.write_message(msg2) msg3 = await framed_reader.read_message() await handshake.read_message(msg3) # Switch to transport mode transport = await handshake.to_transport() # Receive and process encrypted messages while True: try: ciphertext = await framed_reader.read_message() plaintext = await transport.receive(ciphertext) print(f"Received: {plaintext.decode()}") # Send encrypted response response = await transport.send(b"Message received!") await framed_writer.write_message(response) except: break await framed_writer.close() async def main(): server = await asyncio.start_server( handle_client, '127.0.0.1', 9999 ) async with server: await server.serve_forever() asyncio.run(main()) ``` -------------------------------- ### Define functions with type hints Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CONTRIBUTING.md Example of a well-structured function with type hints and docstrings. ```python # Good example def mix_hash(self, data: bytes) -> None: """Mix data into the handshake hash. Args: data: The data to mix into the hash. Raises: ValueError: If data is empty. """ if not data: raise ValueError("Cannot mix empty data") self.h = self.hash_fn(self.h + data) ``` -------------------------------- ### Async Fallback Handshake Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Demonstrates initiating and continuing a fallback handshake asynchronously. This is useful for handling unexpected handshake failures. ```python # Async fallback bob = AsyncNoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") await bob.set_as_responder() await bob.generate_static_keypair() await bob.initialize() # Extract ephemeral from failed message alice_ephemeral = failed_msg[:32] # Initiate fallback await bob.start_fallback(alice_ephemeral) # Continue with fallback handshake fallback_msg1 = await bob.write_message(b"Fallback") ``` -------------------------------- ### Complete TCP Client Example with Noise Handshake Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/API.md Connects to a TCP server, performs a Noise XX handshake, and then exchanges encrypted messages using FramedReader and FramedWriter. ```python import socket from noiseframework import NoiseHandshake, FramedWriter, FramedReader # Client def client(): with socket.socket() as sock: sock.connect(('localhost', 8000)) # Noise handshake hs = NoiseHandshake("Noise_XX_25519_ChaChaPoly_SHA256") hs.set_as_initiator() hs.generate_static_keypair() hs.initialize() # Framed communication reader = FramedReader(sock.makefile('rb')) writer = FramedWriter(sock.makefile('wb')) # Handshake messages (3 messages for XX) msg1 = hs.write_message(b"") writer.write_message(msg1) msg2 = reader.read_message() msg3_payload = hs.read_message(msg2) msg3 = hs.write_message(msg3_payload) writer.write_message(msg3) # Transport mode transport = hs.to_transport() # Send encrypted message ciphertext = transport.send(b"Hello, Server!") writer.write_message(ciphertext) # Receive encrypted response response_ciphertext = reader.read_message() response = transport.receive(response_ciphertext) print(f"Received: {response}") ``` -------------------------------- ### Simple Chat Example Source: https://github.com/juliuspleunes4/noiseframework/blob/main/docs/CHANGELOG.md Illustrates a simplified chat application using the NoiseTransport wrapper for managing cipher states and message exchange. Uses `from noiseframework import NoiseTransport`. ```python from noiseframework import NoiseTransport # Initialize transport for initiator transport = NoiseTransport(is_initiator=True) # ... handshake and message exchange ... transport.write_message(b"Hello, world!") received_message = transport.read_message() ```