Created
August 30, 2016 11:27
-
-
Save href/dad244512c320bd9b5d6ff50e7c7e0b2 to your computer and use it in GitHub Desktop.
Calculate the Yubikey serial number from the OTP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# adapted from Java: | |
# https://github.com/Yubico/yubikey-salesforce-client/blob/ | |
# e38e46ee90296a852374a8b744555e99d16b6ca7/src/classes/Modhex.cls | |
ALPHABET = 'cbdefghijklnrtuv' | |
def yubikey_otp_to_serial(otp): | |
""" Takes a Yubikey OTP and calculates the serial number of the key. | |
The serial key is printed on the yubikey, in decimal and as a QR code. | |
Example: | |
>>> yubikey_otp_to_serial( | |
'ccccccdefghdefghdefghdefghdefghdefghdefghklv') | |
2311522 | |
""" | |
token = 'cccc' + otp[:12] | |
toggle = False | |
keep = 0 | |
bytesarray = [] | |
for char in token: | |
n = ALPHABET.index(char) | |
toggle = not toggle | |
if toggle: | |
keep = n | |
else: | |
bytesarray.append((keep << 4) | n) | |
value = 0 | |
# in Java, shifts on integers are masked with 0x1f using AND | |
# https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.19 | |
mask_value = 0x1f | |
for i in range(0, 8): | |
shift = (4 - 1 - i) * 8 | |
value += (bytesarray[i] & 255) << (shift & mask_value) | |
return value | |
if __name__ == '__main__': | |
assert yubikey_otp_to_serial( | |
'ccccccdefghdefghdefghdefghdefghdefghdefghklv') == 2311522 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment