Irak MayerStephanie VicarteElizabeth Vicarte
Published © GPL3+

Two-Factor Authentication: Omega NFC Module and WIZ750SR

Two-factor authentication allows systems to securely confirm the identity of their users. Here is my take for a home base system.

IntermediateFull instructions provided10 hours356
Two-Factor Authentication: Omega NFC Module and WIZ750SR

Things used in this project

Hardware components

WIZ750SR-TTL-EVB Kit
WIZnet WIZ750SR-TTL-EVB Kit
×1
Omega2 Plus
Onion Corporation Omega2 Plus
×1
Onion Corporation Arduino Dock R2 for Onion Omega
×1
Onion Corporation NFC-RFID Expansion Board for Onion Omega
×1
Onion Corporation OLED Expansion Board for Onion Omega
×1
MSI Intel Celeron N3160 Mini PC
×1
NFC Bubble Stickers - Mifare Ultralight
×1
Cell phone NFC and android beam capable.
×1

Software apps and online services

Python 2.7
nfcPy Python libraries for NFC
pySerial Python library for serial communication

Story

Read more

Schematics

Full Connection System

Connection wehito5dqt

Code

Two Factor Authentication Server

Python
The server takes a client communication with a WIZ750SR and manages the registered users, send text message with verification code and grants or denies access.
#Main server program to manage two factor authentication
#Import required libraries
import socket
import re
import smtplib
import time
import random
#email library
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

#database of valid users to access the system for the NFC tags
#data index, telephone, passcode
tfaDB = (('00001','XXXXXXXXXX','123456'),('00002','XXXXXXXXXX','7890'))
serverpasscode = 'servpassword'
testcode = '123456'
rndStr = ''

#Function that creates a random code string
def CreateRandomcode():
    global rndStr
    rndStr = ''
    for x in range(6):
        rndStr += str(random.randint(0,9))
    print(rndStr)
    return True

#Function that sends a text message using Google gmail account.
def SendText(phoneNum):
    global rndStr
    fromaddr = "yourgmail@gmail.com"
    #use the number on file to text to.
    toaddr = phoneNum+"@tmomail.net"

    msg = MIMEMultipart()

    msg['From'] = fromaddr
    msg['To'] = toaddr

    #Create random code to text
    CreateRandomcode()
    body = rndStr + " 33"

    msg.attach(MIMEText(body, 'plain'))

    part = MIMEBase('application', 'octet-stream')

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(fromaddr, "password") #insert your gmail creadentials here
    text = msg.as_string()
    server.sendmail(fromaddr, toaddr, text)
    server.quit()

#Verifies that the codes are the same
def IsCodeValid(myCode):
    global rndStr
    retVal = False
    if (myCode == rndStr):
        retVal = True
    print("Code "+str(retVal))
    return retVal

#Main server function.
#Starts connection with client and verifies the passcode.
#Main loop thru tag information
#Trigger text message
#Verifies second code authentication.
def server_prog():
        #get the hostname
        host = "192.168.1.23"  #Server host
        port = 5075 #Server port

        #Create a communication socket and bind
        server_socket = socket.socket()
        server_socket.bind((host,port))

        #Wait and listen for client
        server_socket.listen(2)
        conn, address = server_socket.accept()
        print("Connection from :"+str(address))
        data = ''
        recdata = ''
        senddata = 'BL'

        #Main loop
        while True:
            data += conn.recv(1024).decode()
            #check if we got the server passcode
            found = re.search("\)", data)
            #Clean the receive string to get access to just the passcode
            if (found):
                startpass = re.search("\(", data)
                recdata = data[startpass.start() + 1:found.start()]
            #Verify passcode
            if (recdata == serverpasscode):
                #Client verified, start main loop for valid tags
                keepreading = True
                myrec = ''
                recdata = '[OK]'
                conn.send(recdata.encode())
                while keepreading == True:
                    myrec += conn.recv(1024).decode()
                    recdata = 'BT'
                    conn.send(recdata.encode())
                    # if found clean the receive string to access just the tag information
                    found = re.search("\)",myrec)
                    if found:
                        retval = False
                        keepread2 = True
                        #Get all tag fields from the received data
                        rec1 = re.split(",",myrec)
                        for tel in tfaDB:
                            #Find the record in our local array that matches the telephone sent in the record tag
                            if (tel[1] == rec1[1]):
                                found = re.search("\)", rec1[2])
                                passcode = rec1[2][:found.start()]
                                #Now, verify the passcode for the user
                                if (passcode == tel[2]):
                                    keepread2 = False
                                    retval = True
                                    myrec = ''
                                    msg="[OK]"
                                    conn.send(msg.encode())
                                    print("Found record")
                                    break
                        #if tag not in our local array, deny access
                        if (retval == False):
                            myrec = ''
                            msg = "[NG]"
                            conn.send(msg.encode())
                            print("NOT Found record")

                        #If valid user send authetication text
                        if (retval == True):
                            #send text message
                            SendText(rec1[1])
                            keepread2 = True
                            retval = False
                            myrec = ''
                            #Final loop, waiting for verification code.
                            while keepread2 == True:
                                myrec += conn.recv(4096).decode()
                                recdata = 'BL'
                                found = re.search("\)", myrec)
                                inifound = re.search("\(", myrec)
                                #flush the buffer in case the waiting is too long
                                if (not inifound):
                                    myrec = ''
                                if (found):
                                    startpass = re.search("\(",myrec)
                                    tfaVal = myrec[startpass.start()+1:found.start()]
                                    #Validate code and return the access granted or denied.
                                    if (IsCodeValid(tfaVal)):
                                        retval= True
                                        msg = "[OK]"
                                        conn.send(msg.encode())
                                        print("Granted")
                                        myrec = ''
                                    else:
                                        retval = False
                                        msg = "[DN]"
                                        conn.send(msg.encode())
                                        print("Denied")
                                        myrec = ''
                                    keepread2=False


            senddata = "BO"
            conn.send(senddata.encode())

        conn.close()

if __name__ == '__main__':
    server_prog()

Two Factor Authentication client manager.

Python
Manages the NFC expansion board and uses the WIZ750SR to establish a link with the access server.
#Two Factor Authentication 
#client program
#NFC interface for data exchange.

#Load required libraries
import nfc
import nfc.clf
import nfc.ndef
import re
import serial
import time

from OmegaExpansion import oledExp

#Define the server class for NDEF data exchange 
class DefaultSnepServer(nfc.snep.SnepServer):
    def __init__(self, llc):
        nfc.snep.SnepServer.__init__(self, llc, "urn:nfc:sn:snep")

    def put(self, ndef_message):
    	global CodeStr
        print "client has put an NDEF message"
        print ndef_message.type
        print ndef_message.pretty()
        myrec = ndef_message.pop()
        print myrec.type
        print myrec.data
        find = re.search("/",myrec.data)
        CodeStr = "(" + myrec.data[find.start()+2:-1] + ")"
        return nfc.snep.Success

#Initialize server task for NFC
def startup(llc):
    global my_snep_server
    my_snep_server = DefaultSnepServer(llc)
    return llc

#Start server for NFC
def connected(llc):
    my_snep_server.start()
    return True

#Verify serial communication with the server via WIZ750SR
def InitServer():
	retVal = False
	#open serial port
	com0 = serial.Serial("/dev/ttyS0",115200)
	com0.write("(servpassword)")
	#wait until complete reply is received
	incoming = com0.read_until("]")
	print incoming
	find = re.search("\[",incoming)
	last = re.search("\]",incoming)
	resStr = incoming[find.start()+1:last.start()]
	print resStr
	if (resStr == 'OK'):
		retVal = True
	#close port
	com0.close()
	return retVal
	
#Send the tag data to the server 
def SendTagData():
	global TagStr
	retVal = False
	#open serial port
	com0 = serial.Serial("/dev/ttyS0",115200)
	com0.write(TagStr.encode())
	#wait until complete reply is received
	incoming = com0.read_until("]")
	print incoming
	find = re.search("\[",incoming)
	last = re.search("\]",incoming)
	resStr = incoming[find.start()+1:last.start()]
	print resStr
	if (resStr == 'OK'):
		retVal = True
	#close serial port
	com0.close()
	return retVal
	
#Send verification code to server
def SendCode():
	global CodeStr
	retVal = False
	#open serial port
	com0 = serial.Serial("/dev/ttyS0",115200)
	com0.write(CodeStr.encode())
	incoming = com0.read_until("]")
	print incoming
	find = re.search("\[",incoming)
	last = re.search("\]",incoming)
	resStr = incoming[find.start()+1:last.start()]
	print resStr
	if (resStr == 'OK'):
		retVal = True
	#close serial port
	com0.close()
	return retVal
	
#Initialize the Onion Omega NFC expansion board 
def InitNFC():
	global clf
	clf = nfc.ContactlessFrontend()
	clf.open('tty:ttyS1:pn532')
	return True

#Start NFC transaction and wait for a tag to be presented
def ReadTag():
    global clf
    global TagStr
	#Read tag
    tag = clf.connect(rdwr={'on-connect': lambda tag: False})
	#Build the tag record to be submitted to the server
    if tag.ndef is not None:
    	TagStr = "("
        for record in tag.ndef.records:
            print(record)
            print(record.text)
            TagStr += record.text + ","
        TagStr = TagStr[:-1]+")"
    clf.close()
    return True

#Read verification code received as a text and transmitted thru Android Beam    
def Read_NDEF():
	global clf
	global CodeStr
	clf = nfc.ContactlessFrontend("tty:ttyS1:pn532")
	clf.connect(llcp={'on-startup': startup, 'on-connect': connected})
	return True
	
#Initialize Onion Omega OLED expansion board
def OLED_Init():
    oledExp.setVerbosity(0)

    # initialize
    ret = oledExp.driverInit()
    print "driverInit return: ", ret
    if (ret != 0):
        exit()

#Welcome Message on OLED
def OLED_Welcome():
    # clear the display
    ret = oledExp.clear()
    print "clear return: ", ret
    if (ret != 0):
        exit()
    time.sleep(2)

    # draw an image
    ret = oledExp.drawFromFile("./lcd/welcome.lcd")
    print "drawFromFile return: ", ret
    if (ret != 0):
        exit()
    time.sleep(2)
    return True

#Tag is valid message displayed on OLED    
def OLED_TagValid():
    ret = oledExp.setDisplayMode(0)
    print "SetDisplayMode return", ret
    if (ret != 0):
    	exit()
    	
    ret = oledExp.clear()
    print "clear return: ",ret
    if (ret!=0):
    	exit()
    	
    ret = oledExp.write("Valid Tag Detected")
    print "write return: ", ret
    if (ret!=0):
    	exit()

    ret = oledExp.setCursor(3,0)
    print "write return: ",ret
    if (ret!=0):
    	exit()
    	
    ret = oledExp.write("Sending Verification")
    print "write return: ", ret
    if (ret != 0):
    	exit()
    	
    ret = oledExp.setCursor(5,0)
    print "write return: ",ret
    if (ret!=0):
    	exit()
    	
    ret = oledExp.write("       Code")
    print "write return: ", ret
    if (ret != 0):
    	exit()
    time.sleep(2)
    return True

#Access Granted display message
def OLED_Granted():
    # clear the display
    ret = oledExp.clear()
    print "clear return: ", ret
    if (ret != 0):
        exit()
    time.sleep(2)

    # draw an image
    ret = oledExp.drawFromFile("./lcd/granted.lcd")
    print "drawFromFile return: ", ret
    if (ret != 0):
        exit()
    time.sleep(2)
    return True

#Access Denied display message
def OLED_Deny():
    # clear the display
    ret = oledExp.clear()
    print "clear return: ", ret
    if (ret != 0):
        exit()
    time.sleep(2)

    # draw an image
    ret = oledExp.drawFromFile("./lcd/Deny.lcd")
    print "drawFromFile return: ", ret
    if (ret != 0):
        exit()
    time.sleep(2)
    return True

#Tag invalid display on OLED    
def OLED_TagInvalid():
    ret = oledExp.setDisplayMode(0)
    print "SetDisplayMode return", ret
    if (ret != 0):
        exit()

    ret = oledExp.clear()
    print "clear return: ", ret
    if (ret != 0):
        exit()

    ret = oledExp.write("Tag NOT Valid")
    print "write return: ", ret
    if (ret != 0):
        exit()

    ret = oledExp.setCursor(3, 0)
    print "write return: ", ret
    if (ret != 0):
        exit()

    ret = oledExp.write("Try a different Tag")
    print "write return: ", ret
    if (ret != 0):
        exit()

    time.sleep(2)
    return True

#Define global variables
my_snep_server = None
clf = None
TagStr = ''
CodeStr = ''

#Main loop
try:
	#Initialize server
	if (not InitServer()):
		print("Failed Init Server")
		exit()
	#Initialize OLED 
	OLED_Init()
	while True:
		#Welcome message
		OLED_Welcome()
		#Initialize NFC
		InitNFC()
		print "Finish Init NFC"
		#Read NFC tag
		ReadTag()
		print TagStr
		print "Finish Read Tag"
		#Send Tag data to server and send text message
		if (not SendTagData()):
			print("Failed No Record Found")
			OLED_TagInvalid()
			continue
		
		#Display Tag valid 
		OLED_TagValid()
		print "Reading NDEF"
		#Read verification code
		Read_NDEF()
		print CodeStr
		#Send code to server
		if (SendCode()):
			OLED_Granted()
		else:
			OLED_Deny()
	print "End of program"
except nfc.clf.CommunicationError:
	print("Communication error")
    
    
    
    
    
    
    

Credits

Irak Mayer

Irak Mayer

3 projects • 2 followers
Stephanie Vicarte

Stephanie Vicarte

3 projects • 4 followers
Elizabeth Vicarte

Elizabeth Vicarte

3 projects • 3 followers

Comments