I am trying to use one-time passwords that can be generated using Google Authenticator application.
What Google Authenticator does
Basically, Google Authenticator implements two types of passwords:
HOTP - HMAC-based One-Time Password, which means the password is changed with each call, in compliance to RFC4226, and
TOTP - Time-based One-Time Password, which changes for every 30-seconds period (as far as I know).
Google Authenticator is also available as Open Source here: code.google.com/p/google-authenticator
Current code
I was looking for existing solutions to generate HOTP and TOTP passwords, but did not find much. The code I have is the following snippet responsible for generating HOTP:
import hmac, base64, struct, hashlib, time
def get_token(secret, digest_mode=hashlib.sha1, intervals_no=None):
if intervals_no == None:
intervals_no = int(time.time()) // 30
key = base64.b32decode(secret)
msg = struct.pack(">Q", intervals_no)
h = hmac.new(key, msg, digest_mode).digest()
o = ord(h[19]) & 15
h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
return h
The problem I am facing is that the password I generate using the above code is not the same as generated using Google Authenticator app for Android. Even though I tried multiple intervals_no values (exactly first 10000, beginning with intervals_no = 0), with secret being equal to key provided within the GA app.
Questions I have
My questions are:
What am I doing wrong?
How can I generate HOTP and/or TOTP in Python?
Are there any existing Python libraries for this?
To sum up: please give me any clues that will help me implement Google Authenticator authentication within my Python code.
I wanted to set a bounty on my question, but I have succeeded in creating solution. My problem seemed to be connected with incorrect value of secret key (it must be correct parameter for base64.b32decode() function).
Below I post full working solution with explanation on how to use it.
Code
The following code is enough. I have also uploaded it to GitHub as separate module called onetimepass (available here: https://github.com/tadeck/onetimepass).
import hmac, base64, struct, hashlib, time
def get_hotp_token(secret, intervals_no):
key = base64.b32decode(secret, True)
msg = struct.pack(">Q", intervals_no)
h = hmac.new(key, msg, hashlib.sha1).digest()
o = ord(h[19]) & 15
h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
return h
def get_totp_token(secret):
return get_hotp_token(secret, intervals_no=int(time.time())//30)
It has two functions:
get_hotp_token() generates one-time token (that should invalidate after single use),
get_totp_token() generates token based on time (changed in 30-second intervals),
Parameters
When it comes to parameters:
secret is a secret value known to server (the above script) and client (Google Authenticator, by providing it as password within application),
intervals_no is the number incremeneted after each generation of the token (this should be probably resolved on the server by checking some finite number of integers after last successful one checked in the past)
How to use it
Generate secret (it must be correct parameter for base64.b32decode()) - preferably 16-char (no = signs), as it surely worked for both script and Google Authenticator.
Use get_hotp_token() if you want one-time passwords invalidated after each use. In Google Authenticator this type of passwords i mentioned as based on the counter. For checking it on the server you will need to check several values of intervals_no (as you have no quarantee that user did not generate the pass between the requests for some reason), but not less than the last working intervals_no value (thus you should probably store it somewhere).
Use get_totp_token(), if you want a token working in 30-second intervals. You have to make sure both systems have correct time set (meaning that they both generate the same Unix timestamp in any given moment in time).
Make sure to protect yourself from brute-force attack. If time-based password is used, then trying 1000000 values in less than 30 seconds gives 100% chance of guessing the password. In case of HMAC-based passowrds (HOTPs) it seems to be even worse.
Example
When using the following code for one-time HMAC-based password:
secret = 'MZXW633PN5XW6MZX'
for i in xrange(1, 10):
print i, get_hotp_token(secret, intervals_no=i)
you will get the following result:
1 448400
2 656122
3 457125
4 35022
5 401553
6 581333
7 16329
8 529359
9 171710
which is corresponding to the tokens generated by the Google Authenticator app (except if shorter than 6 signs, app adds zeros to the beginning to reach a length of 6 chars).
I wanted a python script to generate TOTP password. So, I wrote the python script. This is my implementation. I have this info on wikipedia and some knowledge about HOTP and TOTP to write this script.
import hmac, base64, struct, hashlib, time, array
def Truncate(hmac_sha1):
"""
Truncate represents the function that converts an HMAC-SHA-1
value into an HOTP value as defined in Section 5.3.
http://tools.ietf.org/html/rfc4226#section-5.3
"""
offset = int(hmac_sha1[-1], 16)
binary = int(hmac_sha1[(offset * 2):((offset * 2) + 8)], 16) & 0x7fffffff
return str(binary)
def _long_to_byte_array(long_num):
"""
helper function to convert a long number into a byte array
"""
byte_array = array.array('B')
for i in reversed(range(0, 8)):
byte_array.insert(0, long_num & 0xff)
long_num >>= 8
return byte_array
def HOTP(K, C, digits=6):
"""
HOTP accepts key K and counter C
optional digits parameter can control the response length
returns the OATH integer code with {digits} length
"""
C_bytes = _long_to_byte_array(C)
hmac_sha1 = hmac.new(key=K, msg=C_bytes, digestmod=hashlib.sha1).hexdigest()
return Truncate(hmac_sha1)[-digits:]
def TOTP(K, digits=6, window=30):
"""
TOTP is a time-based variant of HOTP.
It accepts only key K, since the counter is derived from the current time
optional digits parameter can control the response length
optional window parameter controls the time window in seconds
returns the OATH integer code with {digits} length
"""
C = long(time.time() / window)
return HOTP(K, C, digits=digits)
By following the correct answer from #tadeck and #Anish-Shah, there is a simpler method to get the code without using struct and avoiding extra imports:
""" TOTP """
import hmac
import time
def totp(key: bytes):
""" Calculate TOTP using time and key """
now = int(time.time() // 30)
msg = now.to_bytes(8, "big")
digest = hmac.new(key, msg, "sha1").digest()
offset = digest[19] & 0xF
code = digest[offset : offset + 4]
code = int.from_bytes(code, "big") & 0x7FFFFFFF
code = code % 1000000
return "{:06d}".format(code)
This works with Python 3.
You can get the current TOTP code by calling totp(key) where the "key" is a bytes (commonly the base 32 decoded key).
Related
I would like to create a finite state machine that my users cannot see, but can import as a module; or possibly as an encrypted text file to be decrypted and eval(); or ??? I'm open to suggestion as I'm really unsure how to proceed.
It must be able to handle NumPy arrays.
The remainder of the script must be open source to the user.
Use of the machine would eventually expire.
The state machine must remain NATURAL INTELLECTUAL PROPERTY; 100% secure hidden.
How would I go about this? Here is a sample of what I'm looking to do:
import random
import time
import numpy as np
def state_machine(a,b,c):
# This machine should be hidden from users
expiration = 1500000000
if time.time() < expiration:
state = 0
if a[-1]>b[-1]<c[-1]:
state = 1
elif a[-1]<b[-1]<c[-1]:
state = -1
return state
else:
return 'subscription expired'
def generate_3_random():
# Generate some random data for testing purposes
a = np.random.random(2)
b = np.random.random(2)
c = np.random.random(2)
return a,b,c
a,b,c = generate_3_random()
print [a,b,c]
state = state_machine(a,b,c)
print state
Sample output
>>>[array([ 0.320481 , 0.83016095]), array([ 0.15776184, 0.35658263]), array([ 0.96922252, 0.78727468])]
3
Taking a module path, the user version would then look like this:
import my_encrypted_machine
import random
import time
import numpy as np
def generate_3_random():
# Generate some random data for testing purposes
a = np.random.random(2)
b = np.random.random(2)
c = np.random.random(2)
return a,b,c
a,b,c = generate_3_random()
print [a,b,c]
state = my_encrypted_machine.state_machine(a,b,c)
print state
Output would then be in the same format as the non protected version above.
Depending on what you're trying to achieve, you could do a few things:
Completely hide the inner workings of the state machine
If you really don't want them to be able to see the code, put it on a server, and give them a remote API (REST or so) to access it over the network. (and secure the server!) Then unless they hack into your box, they won't be able to see your code.
Temporarily prevent your users from figuring out how it works / prevent casual hackers from seeing your code
Obfuscate the code. See How do I protect Python code? or how to encrypt python source code? for thoughts on this topic. TLDR; it's not easy. Use something else than python :)
What you're describing with an encrypted textfile would require you to provide the user with a decryption key, which probably means they can decrypt themselves.
Im planning to integrate twilio for two factor authentication in my Django application.
Now, I have installed twilio python module and sent some random messages to my number.
The next step is for me to send some random 6 digit numbers that's done in banking application or google two factor authentication.
How can I generate these numbers in my DJango application?
In addition to Matthias' answer (I upvoted his answer);
Django provides a shortcut function for this purpose:
from django.utils.crypto import get_random_string
get_random_string(length=6, allowed_chars='1234567890')
Which is more readable and memorable.
And also if you are really concerned about randomness of this string, you may want to use random module from pycrypto because standard library implementations of random function in programming languages are not "random" enough for cryptographic and security related issues.
You can use random.choice to determine each digit. choice will give you one element from the given sequence.
The code could look like this:
import random
pin = ''.join(random.choice('0123456789') for _ in range(6))
you could also do
import random
random.SystemRandom().randint(100000,999999)
Twilio developer evangelist here.
There have been some great answers to help you generate a random 6 digit string, however I just wanted to add one more suggestion.
Authy is part of Twilio and provides Two Factor Authentication as a service. It supports sending codes by SMS (which goes via Twilio), generating codes in the Authy application and even two factor authentication without copying a code from an app/sms to your login screen with Authy OneTouch. You can implement your entire 2FA flow with just 3 API calls.
There is a tutorial on how to use Authy with Flask, which I'm sure you could translate to Django.
Let me know if this helps at all.
rand(1000, 9999); == 4 digit
rand(100000, 999999); == 6 digit
$client = $this->_initTwilioClient();
$fromNo = $this->_helperPot->getTwilioPhone();
$code = rand(1000, 9999);
try {
$result = $client->messages->create(
$toNo,
[
'from' => $this->_helperPot->getTwilioPhone(),
'body' => "Verification code: $code"
]
);
$output = [];
$output['status'] = "success";
$output['code'] = $code;
return $output;
} catch (\Exception $e) {
$output = [];
$output['status'] = "failure";
$output['message'] = $e->getMessage();
return $output;
}
I use a Raspberry Pi to collect sensor data and set digital outputs, to make it easy for other applications to set and get values I'm using a socket server. But I am having some problems finding an elegant way of making all the data available on the socket server without having to write a function for each data type.
Some examples of values and methods I have that I would like to make available on the socket server:
do[2].set_low() # set digital output 2 low
do[2].value=0 # set digital output 2 low
do[2].toggle() # toggle digital output 2
di[0].value # read value for digital input 0
ai[0].value # read value for analog input 0
ai[0].average # get the average calculated value for analog input 0
ao[4].value=255 # set analog output 4 to byte value 255
ao[4].percent=100 # set analog output 4 to 100%
I've tried eval() and exec():
self.request.sendall(str.encode(str(eval('item.' + recv_string)) + '\n'))
eval() works unless I am using equal sign (=), but I'm not to happy about the solution because of dangers involved. exec() does the work but does not return any value, also dangerous.
I've also tried getattr():
recv_string = bytes.decode(self.data).lower().split(';')
values = getattr(item, recv_string[0])
self.request.sendall(str.encode(str(values[int(recv_string[1])].value) + '\n'))
^^^^^
This works for getting my attributes, and the above example works for getting the value of the attribute I am getting with getattr(). But I can not figure out how to use getattr() on the value attribute as well.
The semi-colon (;) is used to split the incoming command, I've experimented with multiple ways of formatting the commands:
# unit means that I want to talk to a I/O interface module,
# and the name specified which one
unit;unit_name;get;do;1
unit;unit_name;get;do[1]
unit;unit_name;do[1].value
I am free to choose the format since I am also writing the software that uses these commands. I have not yet found a good format which covers all my needs.
Any suggestions how I can write an elegant way of accessing and returning the data above? Preferably with having to add new methods to the socket server every time a new value type or method is added to my I/O ports.
Edit: This is not public, it's only available on my LAN.
Suggestions
Make your API all methods so that eval can always be used:
def value_m(self, newValue=None):
if newValue is not None:
self.value = newValue
return self.value
Then you can always do
result = str(eval(message))
self.request.sendall(str.encode(result + '\n'))
For your message, I would suggest that your messages are formatted to include the exact syntax of the command exactly so that it can be evaled as-is, e.g.
message = 'do[1].value_m()' # read a value, alternatively...
message = 'do[1].value_m(None)'
or to write
message = 'do[1].value_m(0)' # write a value
This will make it easy to keep your messages up-to-date with your API, because they must match exactly, you won't have a second DSL to deal with. You really don't want to have to maintain a second API, on top of your IO one.
This is a very simple scheme, suitable for a home project. I would suggest some error handling in evaluation, like so:
import traceback
try:
result = str(eval(message))
except Exception:
result = traceback.format_exc()
self.request.sendall(str.encode(result + '\n'))
This way your caller will receive a printout of the exception traceback in the returned message. This will make it much, much easier to debug bad calls.
NOTE If this is public-facing, you cannot do this. All input must be sanitised. You will have to parse each instruction and compare it to the list of available (and desirable) commands, and verify input validity and validity ranges for everything. For such a scenario you are better off simply using one of the input validation systems used for web services, where this problem receives a great deal of attention.
I want to generate a password reset token for a User model that I have with Google App Engine. Apparently we're not allowed to use Django that easily with GAE, so the raw code for the Django method for generating tokens is:
def _make_token_with_timestamp(self, user, timestamp):
# timestamp is number of days since 2001-1-1. Converted to
# base 36, this gives us a 3 digit string until about 2121
ts_b36 = int_to_base36(timestamp)
# By hashing on the internal state of the user and using state
# that is sure to change (the password salt will change as soon as
# the password is set, at least for current Django auth, and
# last_login will also change), we produce a hash that will be
# invalid as soon as it is used.
# We limit the hash to 20 chars to keep URL short
key_salt = "django.contrib.auth.tokens.PasswordResetTokenGenerator"
# Ensure results are consistent across DB backends
login_timestamp = user.last_login.replace(microsecond=0, tzinfo=None)
value = (unicode(user.id) + user.password +
unicode(login_timestamp) + unicode(timestamp))
hash = salted_hmac(key_salt, value).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash)
Python is not my language of expertise, so I'll need some help writing a custom method similar to the one above. I just have a couple questions. First, what is the purpose of the timestamp? And Django has its own User system, while I'm using a simple custom User model of my own. What aspects from the above code will I need to retain, and which ones can I do away with?
well, the check_token-method looks like this:
def check_token(self, user, token):
"""
Check that a password reset token is correct for a given user.
"""
# Parse the token
try:
ts_b36, hash = token.split("-")
except ValueError:
return False
try:
ts = base36_to_int(ts_b36)
except ValueError:
return False
# Check that the timestamp/uid has not been tampered with
if not constant_time_compare(self._make_token_with_timestamp(user, ts), token):
return False
# Check the timestamp is within limit
if (self._num_days(self._today()) - ts) > settings.PASSWORD_RESET_TIMEOUT_DAYS:
return False
return True
first the timestamp part of the token is converted back to integer
then a new token is generated using that timestamp and compared to the old token. Note that when generating a token the timestamp of the last login is one of the parameters used to calculate the hash. That means that after a user login the old token would become invalid, which makes sense for a password reset token.
lastly a check is performed to see if the token hasn't alerady timed out.
it's a fairly simple process, and also fairly secure. If you wanted to use the reset-system to break into an account, you'd have to know the user's password and last login timestamp to calculate the hash. And if you knew that wouldn't need to break into the account...
So if you want to make a system like that, it's important when generating the hast to use parameters that are not easy to guess, and of course to use a good, salted hash function. Django uses sha1, using other hashlib digests would of course be easily possible.
Another way would be to generate a random password reset token and store it in the database, but this potentially wastes a lot of space as the token-column would probably be empty for most of the users.
I have a python script which is using htpasswd authentication. I wish to modify the script depending on the user who has logged in currently. This application is web-enabled. eg.
if current_username = 'ABC':
m = 2
elif current_username = 'PQE':
m = 4
else:
m = 6
Any of the user can log in any time / simultaneously. Want the simplest and most efficient solution. Can anybody help? How do I know which of the user has logged in at any point of time? import getpass getpass.getuser() in the script ?
If you are looking to retrieve a value for specific usernames, you could use a dictionary to store the mapping between username and value. For example, your code above could be rewritten:
username_mapping = {"ABC": 2, "PQE": 4}
# The second argument to get will be returned if the key could not be found
# in the dictionary
m = username_mapping.get(current_username, 6)
For a larger system, you might want to look into a distributed key value store (redis would be a good place to start).