Initialization request is an HTTP POST request to
with Content-type "application/octet-stream". The plaintext of the request has the following format:
| function code | response encryption key | region code | mobile model |
| 1 byte | 37 bytes | 2 bytes | 16 bytes |
The plaintext is then encrypted with RSA-1024 (upper bytes of the RSA-block are padded with zeros). The modulus is
0x955e4bd989f3917d2f15544a7e0504eb9d7bb66b6f8a2fe470e453c779200e5e 3ad2e43a02d06c4adbd8d328f1a426b83658e88bfd949b2af4eaf30054673a14 19a250fa4cc1278d12855b5b25818d162c6e6ee2ab4a350d401d78f6ddb99711 e72626b48bd8b5b0b7f3acf9ea3c9e0005fee59e19136cdb7c83f2ab8b0a2a99
(big endian) and the public exponent is "0x101" (257). The resulting 128 encrypted bytes are sent to the server within the HTTP-POST-request. Europe and North America are using the same keys for RSA.
The HTTP body of the response has the following format:
| current server time | encrypted initialization data |
| 8 bytes | 37 bytes |
After decryption the initialization information has the following format:
| secret key for code calculation | authenticator serial number |
| 20 bytes | 17 bytes |
Synchronization request is simply an HTTP GET request to
The HTTP body of the response has the following format:
| current server time |
| 8 bytes |
Starting point of the calculation are the secret key (returned by the server within the authenticator initialization response) and the current code interval number. Code interval length is 30 seconds (every 30 seconds a new code is generated). To calculate the current code interval number the current server time in milliseconds (as returned from the time synchronization request) has to be known and is simply divided by 30,000 (midnight, January 1, 1970 UTC started with code interval 0 and every 30 seconds the code interval counter is incremented by 1).
If there is a local clock with enough accuracy available, it is not necessary to request the server time for every code calculation. It is enough to store the time difference between server and local clock when doing the initialization of the authenticator and calculate the current server time from the local time and the stored time difference. Only if the divergence between server and local clock has significantly changed, a new synchronization has to be done.
The code interval number is stored in 8 bytes (big endian order) and is used as message for HMAC-SHA1 (the key is the secret key from the initialization response). The result is a 20 bytes MAC of the code interval number. From this 20 bytes MAC 4 bytes are selected as the current code. The last 4 bit of the MAC determine the starting byte of the 4 selected bytes.
Finally the last 8 digits (radix 10) of the 4 selected bytes (big endian order) are displayed by the authenticator as the current code.
Short form:
// calculate current interval number long intervalNumber = (CLIENT_TIME_IN_MILLISECONDS + TIME_DIFFERENCE_TO_SERVER) / 30000 // calculate HMAC-SHA1 from secret key and interval number byte[20] mac = HMAC-SHA1(SECRET_KEY, intervalNumber) // determine which 4 bytes of the MAC are taken as the current code // last 4 bit of the MAC points to the starting byte int startPos = mac[19] & 0x0F // select the byte at starting position and the following 3 bytes int selectedInt = mac[startPos .. startPos + 3] // use the lowest 8 decimal digits from the selected integer as the // current authenticator code return selectedInt % 100000000