📜 ⬆️ ⬇️

Generate one-time passwords using a smartphone

Prologue: this article was prepared during the last week and was sent as an article for the sandbox on Sunday night. Today I received an invite, but I also found an article with a similar theme - On the issue of two-factor authentication using mobile devices , so I completely agree with the author of this article - “that there have been too many recent coincidences”. I decided to publish the article as it was originally conceived, adding only links to the sources.

After recent publications on Habrahabr devoted to security, passwords, brute force passwords, etc. I came up with the idea of ​​authorization using one-time passwords generated by a special application on users' smartphones. The idea is very similar to the idea used in SecureID devices (and which were also recently covered in Habrahabr). Modern smartphones are available to more and more people and their capabilities are enough to implement such a scheme. In this article, I want to describe the idea of ​​interaction between the smartphone + web site and some implementation features and show a working prototype.


')
The idea is simple - when registering on the site, the user can optionally be given the opportunity to use a special application installed on the smartphone for authorization to generate one-time passwords. To do this, on the server side each user is generated a unique secret key, which must be transferred to the smartphone. Further, on the basis of this key, the application on the side of the smartphone will generate one-time passwords. The lifetime of each password is limited. Because All modern smartphones are equipped with cameras, the easiest way to transfer a secret key, in my opinion, is to read and recognize a QR code that contains a secret key using a smartphone’s camera. You can of course enter the key manually, send it via SMS, download the key file using the link generated by the server, but such solutions are not always convenient. This method does not claim to be the main method of authorization on sites, but can be used as an optional authorization tool.

The sequence of user actions during registration on the site is as follows:


QR codes were chosen because of a fairly widespread occurrence, using QR codes you can also transfer quite large amounts of data (hundreds and thousands of characters), but nothing prevents you from using any other methods of data coding.
The HOTP algorithm was taken as the basis for generating one-time passwords. The algorithm is an open standard and is freely available. There is also a corresponding RFC 4226 for it.

To implement and test the idea, a bunch of Google App Engine + Android-based smartphone was chosen. The demo version of the site is located at http://grey-box.appspot.com/ there is also a link to a small demo application for a smartphone based on Android, Android OS versions 1.6 and higher are supported. Both applications are quite simple, so I will not describe them in detail, I will focus only on the most interesting points.

The basis of both applications is the calculation of one-time passwords. Every time a user wants to log in to the site, he generates a one-time password on the smartphone using a special application. Passwords are time bound and have a limited duration. When a user enters a created password, the server performs the same actions — it generates a password on its side. If the passwords match, then the authorization is successful. To generate the same passwords, the server and the smartphone must create passwords based on the same initial data. This initial data is the user's secret key and current time. When the server generates a secret key, it also saves at what point in time the key was generated (as a unix timestamp). The secret key and the key generation time are encoded into a QR code and transmitted to the smartphone. The application on the smartphone reads the secret key and the key generation time and calculates the difference between the time on the server side and the side of the smartphone. In the future, this difference is used to synchronize the time.

On the server side, 3 basic actions should be performed:

Below are the relevant parts of the Python code.
#   . import time import hmac from hashlib import sha1 ... OTP_TTL = 300 #    ,   #   username = request.get(“username”) timestamp = int(time.time()) / OTP_TTL #    secret_key = hmac.new(str(timestamp) + username, digestmod=sha1).hexdigest().upper() #       .. 


To generate a picture with a QR code, the simplest option is to use any service to generate various bar codes. There are quite a few such services; in this system, a service was provided by Google - Google Charts Tools . This service allows you to generate various graphs, charts and various bar codes as well. This method was used solely for reasons of ease of implementation; for real systems, it is better to generate bar codes on the server side.

 QR_TPL = "https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=%s&choe=UTF-8" qr_url = QR_TPL % ('%s:%s' % (secret_key, timestamp)) #      HTML   . ... 


Generate a one-time password.

 import time import hmac from hashlib import sha1 … OTP_TTL = 300 #    ,   TRUNCATE_MASK = 0x7FFFFFFF #       MOD = 1000000 #         #   username = request.get("username") password = request.get("password") #       st = storage.gql("where user = :1", username).get() secret_key =st.secret_key #  timestamp timestamp = int(time.time()) / OTP_TTL #    ... one_time_password = str((int(hmac.new(secret_key, str(timestamp), sha1).hexdigest(), 16) & TRUNCATE_MASK) % MOD) # ...         if password == one_time_password: #   else: #  


On the side of the smartphone, there are 2 main actions:

For reading and recognizing barcodes, there are several libraries, perhaps the most widely used and popular is the open source Zxing library. This library supports a number of platforms, including Google Android and Apple iOS. Based on this library, the open- source Barcode Scanner application is also implemented, this application is also quite common and is often pre-installed on many modern Android-based smartphones. It was originally intended to integrate this library into the application, but after a long search in the Internet and documentation, it came to the realization that this is not the fastest and easiest way. It was decided to use the intent call mechanism which is provided by the Android platform. With this approach, it is much easier to integrate the necessary functionality into the application, although users will have to additionally install Barcode Scanner if necessary. This is a drawback of this approach, but there are also pluses - you don’t have to accompany and support all possible smartphone models, current and future ones - the Zxing development team is engaged in this. You can also implement support for other barcode recognition applications and not be limited to Barcode Scanner .

The following is a small snippet of Java code that is used to invoke and process a response from the Barcode Scanner application.
 ... //  Barcode Scanner Intent,      Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); startActivityForResult(intent, 0); ... //           Barcode Scanner public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == 0) { if (resultCode == RESULT_OK) { //      String contents = intent.getStringExtra("SCAN_RESULT"); // …      … } } } ... 


Generate a one-time password.

 //   import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; ... // ,       long OTP_TTL = 300; long TRUNCATE_MASK = 0x7FFFFFFF; long MOD = 1000000; ... //     String secret_key = key_storage.getString("secret_key", ""); //     long time_delta = key_storage.getLong("time_delta", 0); long local_time = (System.currentTimeMillis()/1000) / TIME_MASK; long server_time = local_time + time_delta; try { SecretKeySpec keySpec = new SecretKeySpec(secret_key.getBytes(), "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(keySpec); byte[] result = mac.doFinal(Long.toString(server_time).getBytes()); password = Long.toString((new BigInteger(1, result).intValue() & TRUNCATE_MASK) % MOD); } catch (NoSuchAlgorithmException e) { ... } catch (InvalidKeyException e) { ... } //     ... 


A simple prototype of the site and a demo application for smartphones is available at http://grey-box.appspot.com/ . The Android application is called Auth ID and does not require any special permissions or access rights to work. The only requirement is the availability of the Barcode Scanner application, which is used to scan QR codes. At the moment, the functionality of the Auth ID application is minimal, the application can only store the key for one user and only for the demo site. If you register under a different user, the secret key will be overwritten by the existing one. In the future, you can add key saving for various sites and users, all this of course, provided that this authorization scheme will be distributed. I will be glad to any comments and suggestions.

References:
http://ru.wikipedia.org/wiki/QR-%D0%BA%D0%BE%D0%B4 - what are QR codes
http://en.wikipedia.org/wiki/HOTP - description of the HOTP algorithm
http://tools.ietf.org/html/rfc4226 - RFC 4226 for the HOTP algorithm
https://chart.googleapis.com - Google Chart Tools
http://code.google.com/p/zxing/ - Zxing library for scanning and recognizing various barcodes.
http://grey-box.appspot.com/ - demo site and applications illustrating the idea.

PS Source codes are available after test registration and login. The test code was created solely to test the performance of the idea; it is not recommended for actual use.

Source: https://habr.com/ru/post/122927/


All Articles