Benutzer:Mihi/TinyTOTP: Unterschied zwischen den Versionen
Mihi (Diskussion | Beiträge) Die Seite wurde neu angelegt: „==TinyTOTP== Goal: Time based One Time Passwords in a small embedded device. Basically cloning the functionality of my RSA SecurID ==Design Thoughts== Want to …“ |
Mihi (Diskussion | Beiträge) |
||
Zeile 18: | Zeile 18: | ||
===HOTP=== | ===HOTP=== | ||
HOTP is defined by RFC 4226, | |||
basically it works like this: | |||
HOTP=Truncate(HMAC-SHA1(K,C)) | |||
Where K is Key, C is count and Truncate is an algorithm to produce n (usually n=6) decimal digits from the returned HMAC hash. | |||
Truncate works as follows: | |||
hs=HMAC-SHA1(K,C) | |||
offset=hs & 0xf | |||
hs[offset..offset+3] & 0x7fffffff 0x7f to discard the most significant bits here, some processors calculate sha1 slightly different (according to the RFC). | |||
return hs % 10^n (n is our digits) | |||
Sample implementation in python: | |||
<pre> | |||
#!/usr/bin/python | |||
import hmac | |||
import hashlib | |||
class hotp: | |||
def __init__(self,key,digits=6): | |||
self.key=key | |||
self.digits=digits | |||
def dynamictruncate(self,s): | |||
"""dynamically truncate the string""" | |||
offset=int(s,16)&0xf | |||
return "%016x" % (int(s[offset*2:offset*2+8],16) | |||
&0x7fffffff) | |||
def intto16string(self,c): | |||
"""convert an int to a 16 byte string""" | |||
c="%016x" %count | |||
return "".join([chr(int(c[i*2:i*2+2],16)) for i in range | |||
(0,8)]) | |||
def get(self,count): | |||
""" calculates the HOTP for key and count """ | |||
count=self.intto16string(count) | |||
hc=hmac.new(self.key,count,hashlib.sha1) | |||
s=hc.hexdigest() | |||
ts=self.dynamictruncate(s) | |||
snum=int(ts,16) | |||
return snum % (10 ** self.digits) | |||
return hotp.get(self,count) | |||
if __name__=="__main__": | |||
h=hotp("12345678901234567890") | |||
for count in range (0,6): | |||
print h.get(count) | |||
</pre> |