How to Generate a 10-Digit TOTP Password Using HMAC-SHA-512 and a Shared Secret
Generating a 10-digit Time-Based One-Time Password (TOTP) using the HMAC-SHA-512 algorithm and a shared secret is a secure and widely-used method for authentication. TOTP typically relies on HMAC-SHA-1, but it is entirely feasible to adapt the process to use HMAC-SHA-512 for enhanced security. This article will guide you through the step-by-step process of generating a 10-digit TOTP using HMAC-SHA-512 and a shared secret.
Step-by-Step Guide
Prepare the Shared Secret
First, you need to encode the shared secret using Base32 encoding to ensure its security and integrity. This encoding provides a format that is both human-readable and machine-readable, making it a robust choice for authentication purposes.
Get the Current Time
Next, obtain the current Unix timestamp in seconds. Typically, the time step used for TOTP is 30 seconds. Once you have the current Unix timestamp, calculate the number of time steps elapsed since the reference epoch (usually 1970-01-01T00:00:00Z UTC). Divide the current Unix timestamp by 30 seconds to get the time counter (the number of time steps).
Generate the TOTP
Convert the time counter to an 8-byte binary array. This is done using big-endian byte order, ensuring that the most significant byte comes first.
Compute the HMAC-SHA-512 hash of the binary time counter using the encoded shared secret as the key. This hash will be a 64-byte (512-bit) value.
Extract the offset (the last byte) of the HMAC-SHA-512 result. This offset helps to locate the portion of the hash that will be used to generate the TOTP value.
Use the offset to extract a 4-byte (32-bit) integer from the HMAC-SHA-512 result. The remaining 24 bits of this integer are typically discarded, and the last 4 bits are taken modulo 10^10 to produce a 10-digit number.
Format the Output
Finally, ensure that the output is a 10-digit number. If the calculated TOTP is less than 10 digits, add leading zeros to make it a 10-digit number.
Sample Code in Python
Below is a Python example that implements the above process:
import base64 import hmac import hashlib import time import struct def generate_totp(shared_secret: str) - str: # Step 1: Decode the base32 secret key base64.b32decode(shared_secret, casefoldTrue) # Step 2: Get the current time step time_step 30 current_time int(time.time()) time_counter current_time // time_step # Time as number of time steps # Step 3: Create a byte array for the time counter counter_bytes ("!Q", time_counter) # Step 4: Generate HMAC-SHA-512 hmac_result (key, counter_bytes, ).digest() # Step 5: Extract the offset offset hmac_result[-1] F truncated_hash hmac_result[offset:offset 4] # Step 6: Apply modulo to get a 10-digit number code struct.unpack("!I", truncated_hash)[0] % 10000000000 # Step 7: Format the result as a zero-padded 10-digit string totp str(code).zfill(10) return totp # Example usage shared_secret print(generate_totp(shared_secret))Make sure that the shared secret is properly encoded in Base32. The standard time step is 30 seconds, but it can vary depending on the implementation. For standard and backward compatibility, you might consider using HMAC-SHA-1 instead of HMAC-SHA-512.
Important Notes
Base32 Encoding: Ensure your shared secret is correctly Base32 encoded to maintain its integrity.
Time Step: The default time step is 30 seconds, but it can be adjusted based on your specific requirements.
HMAC Algorithm: While TOTP typically uses HMAC-SHA-1, this example demonstrates the use of HMAC-SHA-512. For standard implementations, you can opt for HMAC-SHA-1 to ensure compatibility with existing systems.
This code will generate a 10-digit TOTP based on the current time and the provided shared secret. Adjust the shared secret as needed for your application.