Last active
December 28, 2015 06:59
-
-
Save aoshiman/7461123 to your computer and use it in GitHub Desktop.
sample script about totp
This file contains 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
# -*- coding: utf-8 -*- | |
""" | |
This Script base on https://github.com/nathforge/pyotp | |
and http://yamatamemo.blogspot.jp/2011/06/oath-3.html | |
and http://stackoverflow.com/questions/8529265/ \ | |
google-authenticator-implementation-in-python | |
サンプルで記載しているsecretはHexspeakの一種と認識 | |
Dartでも使っていた | |
http://pub.dartlang.org/packages/base32 | |
In [1]: import base64 | |
In [2]: import binascii | |
In [3]: binascii.hexlify(base64.b32decode("JBSWY3DPEHPK3PXP")) | |
Out[3]: '48656c6c6f21deadbeef' | |
""" | |
import time | |
from base64 import b32decode, _b32alphabet | |
import random | |
import hashlib | |
import hmac | |
import struct | |
def random_base32(length=16, random=random.SystemRandom(), | |
chars=_b32alphabet.values()): | |
return ''.join( | |
random.choice(chars) | |
for i in xrange(length) | |
) | |
def generate_otp(secret, now=time.time(),digest=hashlib.sha1): | |
base_time = int(now // 30) | |
byte_base_time = '{0:016X}'.format(base_time) | |
hmac_hash = hmac.new(b32decode(secret), byte_base_time.decode\ | |
("hex_codec"), digest).digest() | |
hmac_result = [] | |
for c in hmac_hash: | |
hmac_result.append(ord(c)) | |
offset = hmac_result[19] & 0xf | |
sn = (hmac_result[offset] & 0x7f) << 24 | \ | |
(hmac_result[offset+1] & 0xff) << 16 | \ | |
(hmac_result[offset+2] & 0xff) << 8 | \ | |
(hmac_result[offset+3] & 0xff) | |
return '{0:06d}'.format(sn % 10 ** 6) | |
def generate_otp2(secret, now=time.time(),digest=hashlib.sha1): | |
base_time = int(now // 30) | |
msg = struct.pack('>Q', base_time) | |
digest = hmac.new(b32decode(secret), msg, digest).digest() | |
ob = ord(digest[19]) | |
pos = ob & 15 | |
sn = struct.unpack('>I', digest[pos:pos + 4])[0] & 0x7fffffff | |
return '{0:06d}'.format(sn % 10 ** 6) | |
if __name__ == '__main__': | |
secret = "JBSWY3DPEHPK3PXP" | |
print generate_otp(secret) | |
print generate_otp2(secret) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment