19 April 2013

OTP (One Time Password) generator


I recently, worked on a project that was to develop a platform for electronic validation.
And I implemented an authentication system by OTP (using google algorithm)


OTP?:

OTP(one time password) is an authentication system, used to check a user identity without asking him his real password.
The first step is to have a secret (password) shared between the client and the server, and then every 30 sec a new OTP can be generated on both side using this secret and the current time. a generated OTP is only valid for 30 sec.

Advantage:
  - The real secret is never exchanged between the client and the server during authentication
  - In case your password is stolen, by keylogger or network sniffer for example, it is impossible to reuse it 30s after his generation.

disadvantages:
  - The main problem of this system is the time synchronization between the client and the server:
because if the server and the client is not synchronized in time (which is very likely), they can generated at the same time two different OTP, which leads to an authentication failure


OTP generator
OTP generator with color notification
On the screenshot you can see that  for a generated OTP, user is notified of the time remaining before its expiration and also the OTP is green if it is in the first 10 seconds, in yellow for the second ones and finally red if the OTP is in the last 10 seconds and will very shortly expire.
#!/usr/bin/python
import base64,time,hmac,sys, datetime
from hashlib import sha1
import struct

class otp_google:
 def __init__(self,secret):
  self._secret = secret
  
 
 def compute(self, date):
  key = base64.b32decode(self._secret,True)
  temps = int(date / 30)
  message = struct.pack('>q', temps)
  hashed = hmac.new(key, message, sha1)
  hexa = hashed.digest().encode('hex')
  lastBit = hexa[-1]
  offset = int(lastBit,16)
  offsetStart = 0 if offset == 0 else 2*offset
  offsetEnd = offsetStart + 8
  truncated = hexa[offsetStart:offsetEnd]
  token_base = int(truncated,16) & 0x7fffffff  
  token = token_base % 1000000
  return str(token).zfill(6)
#!/usr/bin/python
# -*- coding: utf-8 -*-
from Tkinter import *

import time,os,datetime,Otp

coul = ["green", "yellow", "red" ]
i = 0
secret = "ggnpvfgvmedxeroz"
OTP = Otp.otp_google(b'%s'%secret)


    
def update():
    global i
    sec = int(datetime.datetime.now().strftime("%S"))%30
    chrono.configure(text="OTP generated since: %2s sec"%sec)
    otp.configure( fg = coul[i], text=OTP.compute(int(time.time())))
    i= (sec)/10
    fen.after(1000, update)


def setSecret():
    global OTP,secret
    newSecr = entree.get()
    if not newSecr or len(newSecr)!=16:
        entree.configure(bg = "red")
        return
    secret = entree.get()
    OTP = Otp.otp_google(b'%s'%secret)
    update()
    return

fen = Tk()
fen.title("OTP generator")
L,l = 300,100
can = Canvas( width=L, height=l)
can.pack(side=TOP)
can.create_text(L/2,30,text="OTP GENERATOR",fill="Blue",font="Helvetica 20 ")
#can.bind('',start)
Label(text="Secret :").pack(side=TOP)

entree = Entry(show="*")
entree.pack(side=TOP)

Button(text=" O K ", bg = "#00f", fg= "#fff", width=10, command=setSecret).pack(side=TOP)

chrono = Label(fen, text= "OTP generated since: %2s sec"%0)
chrono.pack(side=BOTTOM)
otp=Label(fen,text="000000", font="Helvetica 50 ",fg="#ccc")
otp.pack(side=BOTTOM)
fen.mainloop()



No comments:

Post a Comment