15

What is an OTP number in a login authentication system? Is there any specific algorithm for generating OTP numbers using java (android). Or is an OTP something like random number? How can this be achieved, with optimization.

Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46
Android Developer
  • 223
  • 1
  • 2
  • 6

11 Answers11

32

Please do not reinvent the wheel - especially in case of security and cryptography. You might end up in a really bad state.

Use algorithms, that the community agreed upon like the HOTP and TOTP algorithm specified by the Open Authentication Iniative. These algorithms are also used by the google authenticater and specified in these RFCs. Read them. They are simple.

https://www.rfc-editor.org/rfc/rfc4226

https://www.rfc-editor.org/rfc/rfc6238

Community
  • 1
  • 1
cornelinux
  • 877
  • 1
  • 9
  • 17
  • 6
    +1 for providing the `ietf` links. For future visitors find the [java implementation](https://svn.forgerock.org/openam/tags/10.0.0-docs/products/amserver/source/com/sun/identity/authentication/modules/hotp/HOTPAlgorithm.java) – Mohammad Faisal Dec 18 '15 at 05:41
  • 1
    can anyone please suggest any library which have these implementation . maven repo will do excellent. – Saif Sep 28 '16 at 06:57
  • I would not recommend implementing 2FA directly in your application. If you want to use the 2nd factor for another application, you should not enroll a 2nd factor for the 2nd and 3rd application. You should manage your 2nd factor centrally and connect your application(s) to this central 2FA auth system. As I am involved I of course recommend https://privacyidea.org. There are already several plugins for web applications available. Alas, not for maven. But it is as easy as calling a Ajax request. http://privacyidea.readthedocs.io/en/latest/modules/api/validate.html#post--validate-check – cornelinux Sep 28 '16 at 13:05
  • 1
    Your answer doesn't help at all.If you do not want people to re-invent the wheel then why linking to the RFCs? It could have been better if you had given links to libraries instead. – TheRealChx101 Nov 03 '18 at 02:42
  • 2
    @TheRealChx101 funny you! The OP asked for an algorithm that should be used, not a library. I am no android or java guru. So why should I recommend a library. The information posted should be enough for him to use google to find his preferred library. You can do it, too! Just give it a try! – cornelinux Nov 05 '18 at 14:19
  • You don't know his use case though. If there's no intention to allow the user to save the seed to their own device then there's no need to use TOTP or HOTP. – xxyyxx Oct 22 '20 at 12:57
6

Check google authenticator. : https://github.com/google/google-authenticator it is open source project with OTP functionality

Source code for android app https://code.google.com/p/google-authenticator/source/browse/?repo=android

Here is source code for server side https://github.com/chregu/GoogleAuthenticator.php

Wikipedia article http://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm

Rajan Bhavsar
  • 1,977
  • 11
  • 25
5

Easiest way is to just use DecimalFormat with Random class.

String otp= new DecimalFormat("000000").format(new Random().nextInt(999999));
System.out.println(otp);

Sample Outputs,

002428
445307
409185
989828
794486
213934
REMITH
  • 1,049
  • 12
  • 12
  • 10
    _"Instances of java.util.Random are not cryptographically secure. Consider instead using SecureRandom to get a cryptographically secure pseudo-random number generator for use by security-sensitive applications."_ https://docs.oracle.com/javase/8/docs/api/java/util/Random.html – Madbreaks Feb 04 '20 at 22:38
2
protected void onCreate(Bundle savedInstanceState)
 {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Random otp  =new Random();

        StringBuilder builder=new StringBuilder();
        for(int count=0; count<=10;count++) {
            builder.append(otp.nextInt(10));
        }
        Log.d("Number", " " + builder.toString());

        TextView txt = (TextView) findViewById(R.id.txt);

        txt.setText(builder.toString());
   }
  • first i created an instance of Random class "otp"...loop is for number of digits i mention 10 ... for OTP count<6 after that otp.nextInt(10) tell that upto which digit it will take number ... 10 is specifying 0-10..if you don't want 0 just add 1 (1+otp.nextInt(10)) and last for just for print in textView i cast it into string . – Aditya Vats Feb 28 '17 at 17:45
1

I have the same difficulty to find simple rule about it.

There are a lot of content explaining about OTP like "Time Synchronized" etc..., however I was looking for a simple solution while keeping the system's security.

In my case I keep the 2FA (Two Factor Authentication), that already gives a lot of security.

A relevant info about JAVA for random generator (see: SecureRandom) Important if you want a unique number generation, avoiding repeats.

Examples:

https://www.securecoding.cert.org/confluence/display/java/MSC02-J.+Generate+strong+random+numbers

Details about it: http://resources.infosecinstitute.com/random-number-generation-java/

Based on examples above I implemented the following snippet:

public class SimpleOTPGenerator {


    protected SimpleOTPGenerator() {
    }

    public static String random(int size) {

        StringBuilder generatedToken = new StringBuilder();
        try {
            SecureRandom number = SecureRandom.getInstance("SHA1PRNG");
            // Generate 20 integers 0..20
            for (int i = 0; i < size; i++) {
                generatedToken.append(number.nextInt(9));
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return generatedToken.toString();
    }
}
Eduardo Fabricio
  • 2,151
  • 2
  • 25
  • 32
1

As stated in other answers, the rules on how to generate TOTP (RFC 6238) and HOTP (RFC 4226) codes are defined in RFC's. However if you don't want to implement them manually. You could always use a library.

For example, I created a library for creating one-time passwords: OTP-Java

Or you also look through the code on how the codes are generated if you prefer to implement it yourself.

Bastiaan
  • 67
  • 1
  • 6
1

Disclaimer: Not sure on the security front of the implementation. If you're generating short lived OTP, this can be a viable solution.

This method can be used for generating random numbers of specific length.

RandomStringUtils.randomNumeric(length)

Reference: https://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/RandomStringUtils.html#randomNumeric-int-

Mohamed Anees A
  • 4,119
  • 1
  • 22
  • 35
0

Java 8 introduced SplittableRandom in it's java.util package. You can use it's nextInt(int origin, int bound) to get a random number between the specified bound.

StringBuilder generatedOTP = new StringBuilder();
SplittableRandom splittableRandom = new SplittableRandom();

for (int i = 0; i < lengthOfOTP; i++) {

    int randomNumber = splittableRandom.nextInt(0, 9);
    generatedOTP.append(randomNumber);
}
return generatedOTP.toString();

But I will recommend to use SecureRandom class. It provides a cryptographically strong random number and available in the package java.security.

StringBuilder generatedOTP = new StringBuilder();
SecureRandom secureRandom = new SecureRandom();

try {

    secureRandom = SecureRandom.getInstance(secureRandom.getAlgorithm());

    for (int i = 0; i < lengthOfOTP; i++) {
        generatedOTP.append(secureRandom.nextInt(9));
    }
} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
}

return generatedOTP.toString();

You may get more info from Java 8- OTP Generator

Atul Rai
  • 332
  • 1
  • 10
  • 25
-1
public static void main(String []args){
            java.util.Random r=new java.util.Random();
            int otp = r.nextInt(1000000); // no. of zeros depends on the OTP digit
            System.out.println(otp);
}
Zoha Irshad
  • 427
  • 5
  • 5
  • It prints number between 0 and 1 000 000. There's no guarantee it will return number with 6 digits. – barbsan Nov 23 '18 at 08:57
  • It will give 6 digits OTP because I am using random package of until. – Zoha Irshad Nov 23 '18 at 11:29
  • See the [docs](https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#nextInt-int-): *public int nextInt(int bound)* Returns a pseudorandom, uniformly distributed int value **between 0 (inclusive) and the specified value (exclusive)** – barbsan Nov 23 '18 at 11:31
-1
First of all OTP stands for one time password it is used for the authentication and 
verification this is code is for java implemented in netbeans IDE
 You have to register on the msg91.com for the api genration and that gives free 250 
 msgs.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Random;
import javax.swing.JOptionPane;
 public class SMS {
String num,otp;
SMS(String mob)
{
    num=mob;

}
 static String otpGenerator() 
{ 
    String numbers = "0123456789"; 
    String x="";
    Random rndm_method = new Random(); 
    char[] otp = new char[4]; 
    for (int i = 0; i <4; i++) 
    { 
        otp[i]=numbers.charAt(rndm_method.nextInt(numbers.length())); 
        x=x+otp[i];
    } 

    return x; 
}//this is the function for the random number generator for otp
 public void sms(String otp)
{
        try {

        String apiKey = "api key on msg91.com";
        String message = otp;
        String sender = "TESTIN";
        String numbers = num;
                    String a="http://api.msg91.com/api/sendhttp.php? 
          country=91&sender="+ sender +"&route=4&mobiles=" + numbers +"&authkey=api 
           key on msg91.com&message="+message+" ";
                    //System.out.println(a);
                    // Send data
        HttpURLConnection conn = (HttpURLConnection) new URL(a).openConnection();
        String data = apiKey + numbers + message + sender;
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Length", Integer.toString(data.length()));
        conn.getOutputStream().write(data.getBytes("UTF-8"));
        final BufferedReader rd = new BufferedReader(new 
         InputStreamReader(conn.getInputStream()));
        final StringBuffer stringBuffer = new StringBuffer();
        String line;
        while ((line = rd.readLine()) != null) {
            //stringBuffer.append(line);
                        //JOptionPane.showMessageDialog(null, "message"+line);
                        System.out.println("OTP SENT !");
        }
        rd.close();

        //return stringBuffer.toString();
    } catch (Exception e) {
                JOptionPane.showMessageDialog(null,e);

    }

}
//now you have to call this function and send your number as the parameter
 public Start() {
    this.setUndecorated(true);

    initComponents();

    jPasswordField1.setBackground(new Color(0, 0, 0, 0));

    jPasswordField1.setOpaque(false);  
    //jPasswordField1.setBorder(null); 
    this.setBounds(300, 200, 707, 390);
    SMS otp=new SMS("your number");
    x=otp.otpGenerator();
    otp.sms(x); 
    }
-2
import java.util.*;

public class OTP2 {
  static char[] OTP(int len) {
    System.out.println("Generating OTP using random ()");
    System.out.print("Your OTP is:");

    // Using numeric values
    String numbers = "0123456789";

    // Using random method 
    Random rndm_method = new Random();
    char[] otp = new char[len];
    for(int i=0; i<len;i++) {
      // use of charAt() method : to get character value
      // use of nextInt() as it is scanning the value as int 
      otp[i] = numbers.charAt(rndm_method.nextInt(numbers.length()));
    }
    return otp;
  }

  public static void main(String args[]) {
    int length = 6;
    System.out.println(OTP(length));
  }
}
Styx
  • 9,863
  • 8
  • 43
  • 53