### Complete SCRAM Authentication Flow (Python) Source: https://context7.com/truenas/truenas_scram/llms.txt Illustrates a full four-message SCRAM authentication exchange between a client and server, including mutual authentication verification. This example covers client and server message generation, parsing, and verification steps using the truenas_pyscram library. It requires user credentials and API key ID as input and outputs success or failure messages. ```python import truenas_pyscram def authenticate_user(username: str, api_key_id: int = 0): """Complete SCRAM authentication flow with mutual verification.""" # SERVER SETUP: Generate and store auth data for user # In production, this would be stored in database during user registration auth_data = truenas_pyscram.generate_scram_auth_data() stored_credentials = { "salt": auth_data.salt, "iterations": auth_data.iterations, "stored_key": auth_data.stored_key, "server_key": auth_data.server_key, # For this example, client also needs these (normally derived from password) "client_key": auth_data.client_key, } # STEP 1: Client creates first message client_first = truenas_pyscram.ClientFirstMessage( username=username, api_key_id=api_key_id ) client_first_str = str(client_first) print(f"1. Client -> Server: {client_first_str[:50]}...") # STEP 2: Server parses client first and creates server first parsed_client_first = truenas_pyscram.ClientFirstMessage(rfc_string=client_first_str) server_first = truenas_pyscram.ServerFirstMessage( client_first=parsed_client_first, salt=stored_credentials["salt"], iterations=stored_credentials["iterations"] ) server_first_str = str(server_first) print(f"2. Server -> Client: {server_first_str[:50]}...") # STEP 3: Client creates final message with proof parsed_server_first = truenas_pyscram.ServerFirstMessage(rfc_string=server_first_str) client_final = truenas_pyscram.ClientFinalMessage( client_first=client_first, server_first=parsed_server_first, client_key=stored_credentials["client_key"], stored_key=stored_credentials["stored_key"] ) client_final_str = str(client_final) print(f"3. Client -> Server: {client_final_str[:50]}...") # STEP 4: Server verifies client and creates final message parsed_client_final = truenas_pyscram.ClientFinalMessage(rfc_string=client_final_str) try: truenas_pyscram.verify_client_final_message( client_first=parsed_client_first, server_first=server_first, client_final=parsed_client_final, stored_key=stored_credentials["stored_key"] ) print(" Server verified client successfully!") except truenas_pyscram.ScramError as e: print(f" Authentication failed: {e}") return False server_final = truenas_pyscram.ServerFinalMessage( client_first=parsed_client_first, server_first=server_first, client_final=parsed_client_final, stored_key=stored_credentials["stored_key"], server_key=stored_credentials["server_key"] ) server_final_str = str(server_final) print(f"4. Server -> Client: {server_final_str}") # STEP 5: Client verifies server (mutual authentication) parsed_server_final = truenas_pyscram.ServerFinalMessage(rfc_string=server_final_str) try: truenas_pyscram.verify_server_signature( client_first=client_first, server_first=parsed_server_first, client_final=client_final, server_final=parsed_server_final, server_key=stored_credentials["server_key"] ) print(" Client verified server successfully!") except truenas_pyscram.ScramError as e: print(f" Server verification failed: {e}") return False print("\nAuthentication successful! Mutual authentication complete.") return True # Run authentication authenticate_user("alice", api_key_id=12345) ``` -------------------------------- ### Handling SCRAM Exceptions in Python Source: https://context7.com/truenas/truenas_scram/llms.txt This example demonstrates how to use a try-except block to catch and handle potential `ScramError` exceptions raised by the truenas_pyscram library during authentication data generation. It also shows how to access the error code and its corresponding name. ```python import truenas_pyscram try: # Invalid: providing salted_password without salt/iterations salted_password = truenas_pyscram.generate_nonce() truenas_pyscram.generate_scram_auth_data(salted_password=salted_password) except truenas_pyscram.ScramError as e: print(f"Caught ScramError: {e}") print(f"Error code: {e.code}") print(f"Error name: {truenas_pyscram.errorcode.get(e.code, 'UNKNOWN')}") ``` -------------------------------- ### Create and Serialize ServerFinalMessage Source: https://context7.com/truenas/truenas_scram/llms.txt Demonstrates how to instantiate a ServerFinalMessage to provide the server's authentication proof. It also shows how to serialize the message to an RFC 5802 string and reconstruct it from that string. ```python import truenas_pyscram client_first = truenas_pyscram.ClientFirstMessage(username="alice") auth_data = truenas_pyscram.generate_scram_auth_data() server_first = truenas_pyscram.ServerFirstMessage(client_first=client_first, salt=auth_data.salt, iterations=auth_data.iterations) client_final = truenas_pyscram.ClientFinalMessage(client_first=client_first, server_first=server_first, client_key=auth_data.client_key, stored_key=auth_data.stored_key) server_final = truenas_pyscram.ServerFinalMessage(client_first=client_first, server_first=server_first, client_final=client_final, stored_key=auth_data.stored_key, server_key=auth_data.server_key) serialized = str(server_final) parsed_server_final = truenas_pyscram.ServerFinalMessage(rfc_string=serialized) print(f"Messages match: {str(server_final) == str(parsed_server_final)}") ``` -------------------------------- ### Initialize and Serialize ServerFirstMessage Source: https://context7.com/truenas/truenas_scram/llms.txt Shows how to generate a ServerFirstMessage using client authentication data, salt, and iteration counts. It covers serialization and parsing of the server response. ```python import truenas_pyscram client_first = truenas_pyscram.ClientFirstMessage(username="testuser") auth_data = truenas_pyscram.generate_scram_auth_data() # Create server first message server_first = truenas_pyscram.ServerFirstMessage( client_first=client_first, salt=auth_data.salt, iterations=auth_data.iterations ) # Parse from RFC string (client-side) parsed_server = truenas_pyscram.ServerFirstMessage(rfc_string=str(server_first)) ``` -------------------------------- ### Initialize and Serialize ClientFirstMessage Source: https://context7.com/truenas/truenas_scram/llms.txt Demonstrates how to create a ClientFirstMessage object with optional API keys or channel binding headers. It also shows how to serialize the object to an RFC 5802 string and parse it back. ```python import truenas_pyscram # Basic client first message client_first = truenas_pyscram.ClientFirstMessage(username="alice") # RFC 5802 serialization serialized = str(client_first) # With API key ID client_with_api = truenas_pyscram.ClientFirstMessage(username="bob", api_key_id=12345) # Parse from RFC string (server-side) parsed_client = truenas_pyscram.ClientFirstMessage(rfc_string=serialized) ``` -------------------------------- ### Implement SCRAM with Channel Binding Source: https://github.com/truenas/truenas_scram/blob/master/README.md Shows how to incorporate TLS channel binding into the SCRAM authentication process for enhanced security. ```python client_first = truenas_pyscram.ClientFirstMessage("alice", gs2_header="p=tls-unique") channel_binding = truenas_pyscram.CryptoDatum(tls_channel_binding_data) client_final = truenas_pyscram.ClientFinalMessage(client_first, server_first, auth_data.client_key, auth_data.stored_key, channel_binding) ``` -------------------------------- ### Verify Server Signature with Wrong Key (Python) Source: https://context7.com/truenas/truenas_scram/llms.txt Demonstrates how to verify a server's signature using a client-side SCRAM implementation. This snippet specifically shows the expected failure when an incorrect server key is provided, indicating a potential server impersonation attempt. It catches the specific ScramError. ```python import truenas_pyscram wrong_auth_data = truenas_pyscram.generate_scram_auth_data() try: truenas_pyscram.verify_server_signature( client_first=client_first, server_first=server_first, client_final=client_final, server_final=server_final, server_key=wrong_auth_data.server_key ) except truenas_pyscram.ScramError as e: print(f"Server impersonation detected!") print(f"Error code: {e.code}") # Error code: -7 (SCRAM_E_AUTH_FAILED) ``` -------------------------------- ### Verification with Wrong Server Key Source: https://context7.com/truenas/truenas_scram/llms.txt Illustrates how to detect possible server impersonation by using an incorrect server key during verification. ```APIDOC # Verification with wrong server key (failure - possible server impersonation) wrong_auth_data = truenas_pyscram.generate_scram_auth_data() try: truenas_pyscram.verify_server_signature( client_first=client_first, server_first=server_first, client_final=client_final, server_final=server_final, server_key=wrong_auth_data.server_key ) except truenas_pyscram.ScramError as e: print(f"Server impersonation detected!") print(f"Error code: {e.code}") # Error code: -7 (SCRAM_E_AUTH_FAILED) ``` -------------------------------- ### Initialize SCRAM Authentication Messages Source: https://github.com/truenas/truenas_scram/blob/master/README.md Demonstrates the creation of the four-part SCRAM message exchange sequence between a client and a server using the truenas_pyscram library. ```python client_first = truenas_pyscram.ClientFirstMessage("username") auth_data = truenas_pyscram.generate_scram_auth_data() server_first = truenas_pyscram.ServerFirstMessage(client_first, auth_data.salt, auth_data.iterations) client_final = truenas_pyscram.ClientFinalMessage(client_first, server_first, auth_data.client_key, auth_data.stored_key) server_final = truenas_pyscram.ServerFinalMessage(client_first, server_first, client_final, auth_data.stored_key, auth_data.server_key) ``` -------------------------------- ### Verify Server Signature Source: https://context7.com/truenas/truenas_scram/llms.txt Demonstrates the client-side process of verifying the server's signature using the verify_server_signature function. This ensures the server possesses the correct authentication data. ```python import truenas_pyscram # ... (setup code omitted for brevity) ... result = truenas_pyscram.verify_server_signature( client_first=client_first, server_first=server_first, client_final=client_final, server_final=server_final, server_key=auth_data.server_key ) print(f"Server verification result: {result}") ``` -------------------------------- ### Initialize and Serialize ClientFinalMessage Source: https://context7.com/truenas/truenas_scram/llms.txt Constructs the final SCRAM message containing the cryptographic proof and optional channel binding data. This message verifies the client's knowledge of the password. ```python import truenas_pyscram # Create client final message client_final = truenas_pyscram.ClientFinalMessage( client_first=client_first, server_first=server_first, client_key=auth_data.client_key, stored_key=auth_data.stored_key ) # With channel binding channel_binding = truenas_pyscram.CryptoDatum(b"tls_channel_binding_data") client_final_cb = truenas_pyscram.ClientFinalMessage( client_first=client_first_cb, server_first=server_first_cb, client_key=auth_data.client_key, stored_key=auth_data.stored_key, channel_binding=channel_binding ) ``` -------------------------------- ### Verify Client Authentication Proof Source: https://context7.com/truenas/truenas_scram/llms.txt Uses the verify_client_final_message function to validate a client's authentication attempt on the server. It demonstrates both successful verification and error handling when authentication fails. ```python import truenas_pyscram # ... (setup code omitted for brevity) ... try: result = truenas_pyscram.verify_client_final_message( client_first=client_first, server_first=server_first, client_final=client_final, stored_key=auth_data.stored_key ) except truenas_pyscram.ScramError as e: print(f"Error code: {e.code}") ``` -------------------------------- ### Error Handling and Constants Source: https://context7.com/truenas/truenas_scram/llms.txt Details the `ScramError` exception class for managing authentication errors and highlights the availability of error codes and configuration constants. ```APIDOC ## Error Handling and Constants The library provides comprehensive error handling through the `ScramError` exception class and exposes error codes and configuration constants for proper error management and secure configuration. ```python import truenas_pyscram ``` ``` -------------------------------- ### Accessing SCRAM Configuration Constants in Python Source: https://context7.com/truenas/truenas_scram/llms.txt This snippet shows how to access important configuration constants defined within the truenas_pyscram library, such as default, minimum, and maximum iteration counts for PBKDF2, and the maximum username length. ```python import truenas_pyscram print(f"Default iterations: {truenas_pyscram.SCRAM_DEFAULT_ITERS}") # 500000 print(f"Minimum iterations: {truenas_pyscram.SCRAM_MIN_ITERS}") # 50000 print(f"Maximum iterations: {truenas_pyscram.SCRAM_MAX_ITERS}") # 5000000 print(f"Max username length: {truenas_pyscram.SCRAM_MAX_USERNAME_LEN}") # 256 ``` -------------------------------- ### Generate SCRAM Authentication Keys Source: https://context7.com/truenas/truenas_scram/llms.txt Derives SCRAM authentication components including salt, client key, stored key, and server key. It supports custom iteration counts and can regenerate keys from existing salted passwords. ```python import truenas_pyscram # Generate with default parameters (500,000 iterations) auth_data = truenas_pyscram.generate_scram_auth_data() print(f"Iterations: {auth_data.iterations}") print(f"Salt length: {len(auth_data.salt)}") print(f"Salted password length: {len(auth_data.salted_password)}") print(f"Client key length: {len(auth_data.client_key)}") print(f"Stored key length: {len(auth_data.stored_key)}") print(f"Server key length: {len(auth_data.server_key)}") # Generate with custom iteration count auth_data_custom = truenas_pyscram.generate_scram_auth_data(iterations=100000) print(f"Custom iterations: {auth_data_custom.iterations}") # Generate with provided salt salt = truenas_pyscram.CryptoDatum(bytes(truenas_pyscram.generate_nonce())[:16]) auth_data_with_salt = truenas_pyscram.generate_scram_auth_data(salt=salt, iterations=200000) print(f"Salt matches: {auth_data_with_salt.salt == salt}") # Regenerate from existing salted password (for stored credentials) regenerated = truenas_pyscram.generate_scram_auth_data( salted_password=auth_data.salted_password, salt=auth_data.salt, iterations=auth_data.iterations ) print(f"Client key matches: {regenerated.client_key == auth_data.client_key}") print(f"Stored key matches: {regenerated.stored_key == auth_data.stored_key}") print(f"Server key matches: {regenerated.server_key == auth_data.server_key}") ``` -------------------------------- ### Complete SCRAM Authentication Flow Source: https://context7.com/truenas/truenas_scram/llms.txt Demonstrates a complete four-message SCRAM authentication exchange between client and server, including mutual authentication verification. ```APIDOC ## Complete SCRAM Authentication Flow This example demonstrates a complete four-message SCRAM authentication exchange between client and server, including mutual authentication verification. ```python import truenas_pyscram def authenticate_user(username: str, api_key_id: int = 0): """Complete SCRAM authentication flow with mutual verification.""" # SERVER SETUP: Generate and store auth data for user # In production, this would be stored in database during user registration auth_data = truenas_pyscram.generate_scram_auth_data() stored_credentials = { "salt": auth_data.salt, "iterations": auth_data.iterations, "stored_key": auth_data.stored_key, "server_key": auth_data.server_key, # For this example, client also needs these (normally derived from password) "client_key": auth_data.client_key, } # STEP 1: Client creates first message client_first = truenas_pyscram.ClientFirstMessage( username=username, api_key_id=api_key_id ) client_first_str = str(client_first) print(f"1. Client -> Server: {client_first_str[:50]}...") # STEP 2: Server parses client first and creates server first parsed_client_first = truenas_pyscram.ClientFirstMessage(rfc_string=client_first_str) server_first = truenas_pyscram.ServerFirstMessage( client_first=parsed_client_first, salt=stored_credentials["salt"], iterations=stored_credentials["iterations"] ) server_first_str = str(server_first) print(f"2. Server -> Client: {server_first_str[:50]}...") # STEP 3: Client creates final message with proof parsed_server_first = truenas_pyscram.ServerFirstMessage(rfc_string=server_first_str) client_final = truenas_pyscram.ClientFinalMessage( client_first=client_first, server_first=parsed_server_first, client_key=stored_credentials["client_key"], stored_key=stored_credentials["stored_key"] ) client_final_str = str(client_final) print(f"3. Client -> Server: {client_final_str[:50]}...") # STEP 4: Server verifies client and creates final message parsed_client_final = truenas_pyscram.ClientFinalMessage(rfc_string=client_final_str) try: truenas_pyscram.verify_client_final_message( client_first=parsed_client_first, server_first=server_first, client_final=parsed_client_final, stored_key=stored_credentials["stored_key"] ) print(" Server verified client successfully!") except truenas_pyscram.ScramError as e: print(f" Authentication failed: {e}") return False server_final = truenas_pyscram.ServerFinalMessage( client_first=parsed_client_first, server_first=server_first, client_final=parsed_client_final, stored_key=stored_credentials["stored_key"], server_key=stored_credentials["server_key"] ) server_final_str = str(server_final) print(f"4. Server -> Client: {server_final_str}") # STEP 5: Client verifies server (mutual authentication) parsed_server_final = truenas_pyscram.ServerFinalMessage(rfc_string=server_final_str) try: truenas_pyscram.verify_server_signature( client_first=client_first, server_first=parsed_server_first, client_final=client_final, server_final=parsed_server_final, server_key=stored_credentials["server_key"] ) print(" Client verified server successfully!") except truenas_pyscram.ScramError as e: print(f" Server verification failed: {e}") return False print("\nAuthentication successful! Mutual authentication complete.") return True # Run authentication authenticate_user("alice", api_key_id=12345) ``` ``` -------------------------------- ### generate_nonce() Source: https://context7.com/truenas/truenas_scram/llms.txt Generates a cryptographically secure 32-byte random nonce using OpenSSL's random number generator. Nonces are essential for preventing replay attacks in SCRAM authentication and ensuring authentication freshness. ```APIDOC ## generate_nonce() ### Description Generates a cryptographically secure 32-byte random nonce using OpenSSL's random number generator. Nonces are essential for preventing replay attacks in SCRAM authentication and ensuring authentication freshness. ### Usage ```python import truenas_pyscram # Generate cryptographically secure nonce nonce = truenas_pyscram.generate_nonce() # Verify nonce properties print(f"Nonce type: {type(nonce).__name__}") print(f"Nonce length: {len(nonce)}") # Convert to bytes for inspection nonce_bytes = bytes(nonce) print(f"Nonce bytes length: {len(nonce_bytes)}") # Each call generates unique nonce nonce2 = truenas_pyscram.generate_nonce() print(f"Nonces different: {nonce != nonce2}") # Generate multiple nonces nonces = [truenas_pyscram.generate_nonce() for _ in range(5)] unique_count = len(set(nonces)) print(f"All unique: {unique_count == 5}") ``` ### Returns - **CryptoDatum**: A 32-byte cryptographically secure nonce. ``` -------------------------------- ### Error Handling and Constants (Python) Source: https://context7.com/truenas/truenas_scram/llms.txt This section highlights the error handling capabilities of the truenas_pyscram library. It mentions the `ScramError` exception class for managing authentication failures and the availability of error codes and configuration constants for secure operations and debugging. ```python import truenas_pyscram ``` -------------------------------- ### generate_scram_auth_data() Source: https://context7.com/truenas/truenas_scram/llms.txt Generates complete SCRAM authentication data including salt, salted password, client key, stored key, and server key. This function handles all cryptographic key derivation internally using PBKDF2 with HMAC-SHA-512. ```APIDOC ## generate_scram_auth_data() ### Description Generates complete SCRAM authentication data including salt, salted password, client key, stored key, and server key. This function handles all cryptographic key derivation internally using PBKDF2 with HMAC-SHA-512. ### Usage ```python import truenas_pyscram # Generate with default parameters (500,000 iterations) auth_data = truenas_pyscram.generate_scram_auth_data() print(f"Iterations: {auth_data.iterations}") print(f"Salt length: {len(auth_data.salt)}") print(f"Salted password length: {len(auth_data.salted_password)}") print(f"Client key length: {len(auth_data.client_key)}") print(f"Stored key length: {len(auth_data.stored_key)}") print(f"Server key length: {len(auth_data.server_key)}") # Generate with custom iteration count auth_data_custom = truenas_pyscram.generate_scram_auth_data(iterations=100000) print(f"Custom iterations: {auth_data_custom.iterations}") # Generate with provided salt salt = truenas_pyscram.CryptoDatum(bytes(truenas_pyscram.generate_nonce())[:16]) auth_data_with_salt = truenas_pyscram.generate_scram_auth_data(salt=salt, iterations=200000) print(f"Salt matches: {auth_data_with_salt.salt == salt}") # Regenerate from existing salted password (for stored credentials) regenerated = truenas_pyscram.generate_scram_auth_data( salted_password=auth_data.salted_password, salt=auth_data.salt, iterations=auth_data.iterations ) print(f"Client key matches: {regenerated.client_key == auth_data.client_key}") print(f"Stored key matches: {regenerated.stored_key == auth_data.stored_key}") print(f"Server key matches: {regenerated.server_key == auth_data.server_key}") ``` ### Parameters - **iterations** (int, optional): The number of PBKDF2 iterations. Defaults to 500,000. Range: 50,000 to 5,000,000. - **salt** (CryptoDatum, optional): The salt to use for key derivation. If not provided, a random salt is generated. - **salted_password** (CryptoDatum, optional): The pre-salted password. If provided, client_key, stored_key, and server_key are derived from it. ### Returns - **SCRAMAuthData**: An object containing: - **iterations** (int): The number of iterations used. - **salt** (CryptoDatum): The generated or provided salt. - **salted_password** (CryptoDatum): The salted password. - **client_key** (CryptoDatum): The derived client key. - **stored_key** (CryptoDatum): The derived stored key. - **server_key** (CryptoDatum): The derived server key. ``` -------------------------------- ### Verify SCRAM Authentication Messages Source: https://github.com/truenas/truenas_scram/blob/master/README.md Provides methods for both the server and client to verify the authenticity of the exchanged messages during the SCRAM flow. ```python truenas_pyscram.verify_client_final_message(client_first, server_first, client_final, stored_key) truenas_pyscram.verify_server_signature(client_first, server_first, client_final, server_final, server_key) ``` -------------------------------- ### Accessing SCRAM Error Codes in Python Source: https://context7.com/truenas/truenas_scram/llms.txt This snippet demonstrates how to access and print various predefined error codes provided by the truenas_pyscram library. It shows the mapping between error codes and their symbolic names. ```python import truenas_pyscram print(f"Success: {truenas_pyscram.SCRAM_E_SUCCESS}") # 0 print(f"Invalid request: {truenas_pyscram.SCRAM_E_INVALID_REQUEST}") # -1 print(f"Memory error: {truenas_pyscram.SCRAM_E_MEMORY_ERROR}") # -2 print(f"Crypto error: {truenas_pyscram.SCRAM_E_CRYPTO_ERROR}") # -3 print(f"Base64 error: {truenas_pyscram.SCRAM_E_BASE64_ERROR}") # -4 print(f"Parse error: {truenas_pyscram.SCRAM_E_PARSE_ERROR}") # -5 print(f"Format error: {truenas_pyscram.SCRAM_E_FORMAT_ERROR}") # -6 print(f"Auth failed: {truenas_pyscram.SCRAM_E_AUTH_FAILED}") # -7 # Error code to name mapping print(f"Error codes: {truenas_pyscram.errorcode}") ``` -------------------------------- ### Generate Secure Authentication Nonces Source: https://context7.com/truenas/truenas_scram/llms.txt This function generates a cryptographically secure 32-byte random nonce using OpenSSL. Nonces are critical for ensuring authentication freshness and preventing replay attacks. ```python import truenas_pyscram # Generate cryptographically secure nonce nonce = truenas_pyscram.generate_nonce() # Verify nonce properties print(f"Nonce type: {type(nonce).__name__}") print(f"Nonce length: {len(nonce)}") # Convert to bytes for inspection nonce_bytes = bytes(nonce) print(f"Nonce bytes length: {len(nonce_bytes)}") # Each call generates unique nonce nonce2 = truenas_pyscram.generate_nonce() print(f"Nonces different: {nonce != nonce2}") # Generate multiple nonces nonces = [truenas_pyscram.generate_nonce() for _ in range(5)] unique_count = len(set(nonces)) print(f"All unique: {unique_count == 5}") ``` -------------------------------- ### Handling Type Validation Errors in Python Source: https://context7.com/truenas/truenas_scram/llms.txt This snippet illustrates how to catch `TypeError` exceptions that occur when incorrect data types are passed to SCRAM functions, such as `verify_client_final_message`. It highlights the importance of providing the correct object types for function arguments. ```python import truenas_pyscram try: auth_data = truenas_pyscram.generate_scram_auth_data() client_first = truenas_pyscram.ClientFirstMessage(username="test") truenas_pyscram.verify_client_final_message( client_first="invalid", # Should be ClientFirstMessage server_first=None, client_final=None, stored_key=auth_data.stored_key ) except TypeError as e: print(f"Type error: {e}") # client_first must be a ClientFirstMessage instance ``` -------------------------------- ### SCRAM Authentication Flow API Source: https://github.com/truenas/truenas_scram/blob/master/README.md Endpoints and methods for performing the four-step SCRAM authentication handshake. ```APIDOC ## SCRAM Authentication Handshake ### Description The SCRAM authentication process involves a four-message exchange between client and server to securely verify credentials without transmitting passwords. ### Methods - **ClientFirstMessage(username, gs2_header)**: Generates the initial client message. - **ServerFirstMessage(client_first, salt, iterations)**: Generates the server's challenge response. - **ClientFinalMessage(client_first, server_first, client_key, stored_key, channel_binding)**: Generates the client's final proof. - **ServerFinalMessage(client_first, server_first, client_final, stored_key, server_key)**: Generates the server's final signature. ### Verification - **verify_client_final_message(client_first, server_first, client_final, stored_key)**: Server-side verification of client proof. - **verify_server_signature(client_first, server_first, client_final, server_final, server_key)**: Client-side verification of server authenticity. ### Request Example ```python client_first = truenas_pyscram.ClientFirstMessage("alice") server_first = truenas_pyscram.ServerFirstMessage(client_first, salt, iterations) ``` ### Response - **Success**: Returns a message object containing the formatted SCRAM string (e.g., 'n,,n=username,r=nonce'). ``` -------------------------------- ### Manage Secure Cryptographic Data with CryptoDatum Source: https://context7.com/truenas/truenas_scram/llms.txt The CryptoDatum class provides a secure container for sensitive cryptographic bytes. It supports the Python buffer protocol and includes a clear() method to securely wipe memory after use. ```python import truenas_pyscram # Create CryptoDatum from bytes datum = truenas_pyscram.CryptoDatum(b"secret_key_data") # Access length and content print(f"Length: {len(datum)}") # Index access returns integer (byte value) first_byte = datum[0] print(f"First byte: {first_byte}") # Slice access returns bytes first_half = datum[:8] print(f"Slice: {first_half}") # Convert to bytes via buffer protocol raw_bytes = bytes(datum) print(f"As bytes: {raw_bytes}") # Comparison operations other_datum = truenas_pyscram.CryptoDatum(b"secret_key_data") print(f"Equal: {datum == other_datum}") # Secure memory clearing datum.clear() print(f"After clear length: {len(datum)}") ``` -------------------------------- ### CryptoDatum Class Source: https://context7.com/truenas/truenas_scram/llms.txt The CryptoDatum class is a secure container for cryptographic data that supports the Python buffer protocol, enabling seamless integration with bytes operations while providing secure memory handling with explicit clearing capabilities. ```APIDOC ## CryptoDatum Class ### Description A secure container for cryptographic data that supports the Python buffer protocol, enabling seamless integration with bytes operations while providing secure memory handling with explicit clearing capabilities. ### Usage ```python import truenas_pyscram # Create CryptoDatum from bytes datum = truenas_pyscram.CryptoDatum(b"secret_key_data") # Access length and content print(f"Length: {len(datum)}") # Index access returns integer (byte value) first_byte = datum[0] print(f"First byte: {first_byte}") # Slice access returns bytes first_half = datum[:8] print(f"Slice: {first_half}") # Convert to bytes via buffer protocol raw_bytes = bytes(datum) print(f"As bytes: {raw_bytes}") # Comparison operations other_datum = truenas_pyscram.CryptoDatum(b"secret_key_data") print(f"Equal: {datum == other_datum}") # Secure memory clearing datum.clear() print(f"After clear length: {len(datum)}") ``` ### Methods - **__init__(self, data: bytes)**: Initializes CryptoDatum with provided bytes. - **__len__(self)**: Returns the length of the data. - **__getitem__(self, index)**: Returns the byte at the specified index. - **__bytes__(self)**: Converts the data to bytes. - **__eq__(self, other)**: Compares this CryptoDatum with another. - **clear(self)**: Securely clears the contained data. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.