[jboss-cvs] Picketbox SVN: r114 - in trunk: security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp and 4 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Sep 21 17:09:14 EDT 2010
Author: anil.saldhana at jboss.com
Date: 2010-09-21 17:09:13 -0400 (Tue, 21 Sep 2010)
New Revision: 114
Added:
trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/
trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/JBossTimeBasedOTPLoginModule.java
trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/SecurityActions.java
trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/JBossTimeBasedOTPLoginModuleUnitTestCase.java
trunk/security-jboss-sx/jbosssx/src/test/resources/otp-users.properties
Modified:
trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/util/TestHttpServletRequest.java
trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTP.java
trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTPUtil.java
Log:
SECURITY-530: totp based login module
Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/JBossTimeBasedOTPLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/JBossTimeBasedOTPLoginModule.java (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/JBossTimeBasedOTPLoginModule.java 2010-09-21 21:09:13 UTC (rev 114)
@@ -0,0 +1,286 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.auth.spi.otp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.otp.TimeBasedOTP;
+import org.jboss.security.otp.TimeBasedOTPUtil;
+
+/**
+ * <p>
+ * Login Module that can be configured to validate a Time based OTP.
+ * </p>
+ *
+ * <p>
+ * Usage:
+ * This login module needs to be configured along with one of the other JBoss login modules such
+ * as {@code org.jboss.security.auth.spi.DatabaseServerLoginModule} or
+ * {@code org.jboss.security.auth.spi.LdapLoginModule}
+ * </p>
+ * Example configuration:
+ * <p>
+ * <pre>
+ * {@code
+ * <application-policy name="otp">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
+ flag="required">
+ <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
+ <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
+ </login-module>
+ <login-module code="org.jboss.security.auth.spi.otp.JBossTimeBasedOTPLoginModule" />
+ </authentication>
+ </application-policy>
+ * }
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * Configurable Options:
+ * </p>
+ * <p>
+ * <ul>
+ * <li>algorithm: either "HmacSHA1", "HmacSHA256" or "HmacSHA512" [Default: "HmacSHA1"]</li>
+ * <li>numOfDigits: Number of digits in the TOTP. Default is 6.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>
+ * This login module requires the presence of "otp-users.properties" on the class path with the format:
+ * username=key
+ * </p>
+ *
+ * <p>
+ * An example of otp-users.properties is:
+ * </p>
+ * <p>
+ * <pre>
+ admin=35cae61d6d51a7b3af
+ </pre>
+ * </p>
+ *
+ *
+ * @author Anil.Saldhana at redhat.com
+ * @since Sep 21, 2010
+ */
+public class JBossTimeBasedOTPLoginModule implements LoginModule
+{
+ private static Logger log = Logger.getLogger( JBossTimeBasedOTPLoginModule.class );
+ private boolean trace = log.isTraceEnabled();
+
+ public static final String TOTP = "totp";
+
+ private Map<String,Object> lmSharedState = new HashMap<String,Object>();
+ private Map<String, Object> lmOptions = new HashMap<String,Object>();
+ private CallbackHandler callbackHandler;
+ private boolean useFirstPass;
+
+ //This is the number of digits in the totp
+ private int NUMBER_OF_DIGITS = 6;
+
+ /**
+ * Default algorithm is HMAC_SHA1
+ */
+ private String algorithm = TimeBasedOTP.HMAC_SHA1; //Default
+
+ public void initialize( Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+ Map<String, ?> options )
+ {
+ this.callbackHandler = callbackHandler;
+ this.lmSharedState.putAll( sharedState );
+ this.lmOptions.putAll( options );
+
+ /* Check for password sharing options. Any non-null value for
+ password_stacking sets useFirstPass as this module has no way to
+ validate any shared password.
+ */
+ String passwordStacking = (String) options.get("password-stacking");
+ if( passwordStacking != null && passwordStacking.equalsIgnoreCase("useFirstPass") )
+ useFirstPass = true;
+
+ //Option for number of digits
+ String numDigitString = (String) options.get( "numOfDigits" );
+ if( numDigitString != null && numDigitString.length() > 0 )
+ NUMBER_OF_DIGITS = Integer.parseInt( numDigitString );
+
+ //Algorithm
+ String algorithmStr = (String) options.get( "algorithm" );
+ if( algorithmStr != null && algorithmStr != "" )
+ {
+ if( algorithmStr.equalsIgnoreCase( TimeBasedOTP.HMAC_SHA256) )
+ algorithm = TimeBasedOTP.HMAC_SHA256;
+ if( algorithmStr.equalsIgnoreCase( TimeBasedOTP.HMAC_SHA512 ))
+ algorithm = TimeBasedOTP.HMAC_SHA512;
+ }
+ }
+
+ /**
+ * @see {@code LoginModule#login()}
+ */
+ public boolean login() throws LoginException
+ {
+ String username = null;
+
+
+ if( useFirstPass == true )
+ {
+ username = (String) lmSharedState.get("javax.security.auth.login.name");
+ }
+ else
+ {
+ NameCallback nc = new NameCallback("User name: ", "guest");
+ Callback[] callbacks = { nc };
+ try
+ {
+ callbackHandler.handle(callbacks);
+ }
+ catch ( Exception e )
+ {
+ LoginException le = new LoginException();
+ le.initCause( e );
+ throw le;
+ }
+
+ username = nc.getName();
+ }
+
+ //Load the otp-users.properties file
+ ClassLoader tcl = SecurityActions.getContextClassLoader();
+ InputStream is = tcl.getResourceAsStream( "otp-users.properties" );
+
+ Properties otp = new Properties();
+ try
+ {
+ otp.load( is );
+ }
+ catch (IOException e )
+ {
+ LoginException le = new LoginException( "Unable to load the otp users properties");
+ le.initCause( e );
+ throw le;
+ }
+
+ String seed = otp.getProperty( username );
+
+ String submittedTOTP = this.getTimeBasedOTPFromRequest();
+ if( submittedTOTP == null || submittedTOTP.length() == 0 )
+ {
+ if( trace )
+ {
+ log.trace( "Either the TOTP in request was null or was of zero length::TOTP=" + submittedTOTP );
+ }
+ throw new LoginException();
+ }
+
+ try
+ {
+ boolean result = false;
+
+ if( algorithm.equals( TimeBasedOTP.HMAC_SHA1 ))
+ {
+ result = TimeBasedOTPUtil.validate( submittedTOTP, seed.getBytes() , NUMBER_OF_DIGITS );
+ }
+ else if( algorithm.equals( TimeBasedOTP.HMAC_SHA256 ))
+ {
+ result = TimeBasedOTPUtil.validate256( submittedTOTP, seed.getBytes() , NUMBER_OF_DIGITS );
+ }
+ else if( algorithm.equals( TimeBasedOTP.HMAC_SHA512 ))
+ {
+ result = TimeBasedOTPUtil.validate512( submittedTOTP, seed.getBytes() , NUMBER_OF_DIGITS );
+ }
+
+ if( result == false )
+ throw new LoginException();
+
+ return result;
+ }
+ catch (GeneralSecurityException e)
+ {
+ LoginException le = new LoginException();
+ le.initCause( e );
+ throw le;
+ }
+ }
+
+ /**
+ * @see {@code LoginModule#commit()}
+ */
+ public boolean commit() throws LoginException
+ {
+ return true;
+ }
+
+ /**
+ * @see {@code LoginModule#abort()}
+ */
+ public boolean abort() throws LoginException
+ {
+ return true;
+ }
+
+ /**
+ * @see {@code LoginModule#logout()}
+ */
+ public boolean logout() throws LoginException
+ {
+ return true;
+ }
+
+ private String getTimeBasedOTPFromRequest()
+ {
+ String totp = null;
+
+ //This is JBoss AS specific mechanism
+ String WEB_REQUEST_KEY = "javax.servlet.http.HttpServletRequest";
+
+ try
+ {
+ HttpServletRequest request = (HttpServletRequest) PolicyContext.getContext(WEB_REQUEST_KEY);
+ totp = request.getParameter( TOTP );
+ }
+ catch (PolicyContextException e)
+ {
+ if( log.isTraceEnabled() )
+ {
+ log.trace( "Error getting request::", e );
+ }
+ }
+ return totp;
+ }
+}
\ No newline at end of file
Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/SecurityActions.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/SecurityActions.java (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/otp/SecurityActions.java 2010-09-21 21:09:13 UTC (rev 114)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.auth.spi.otp;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+
+/**
+ * Privileged Blocks
+ * @author Anil.Saldhana at redhat.com
+ * @since Sep 26, 2007
+ * @version $Revision$
+ */
+class SecurityActions
+{
+ static ClassLoader getContextClassLoader()
+ {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+ {
+ public ClassLoader run()
+ {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ }
+}
\ No newline at end of file
Added: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/JBossTimeBasedOTPLoginModuleUnitTestCase.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/JBossTimeBasedOTPLoginModuleUnitTestCase.java (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/JBossTimeBasedOTPLoginModuleUnitTestCase.java 2010-09-21 21:09:13 UTC (rev 114)
@@ -0,0 +1,147 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.authentication.jaas;
+
+import static org.junit.Assert.fail;
+
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import javax.security.jacc.PolicyContextHandler;
+
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.callback.JBossCallbackHandler;
+import org.jboss.security.auth.spi.otp.JBossTimeBasedOTPLoginModule;
+import org.jboss.security.otp.TimeBasedOTP;
+import org.jboss.test.util.TestHttpServletRequest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Unit Test the {@code JBossTimeBasedOTPLoginModule}
+ * @author Anil.Saldhana at redhat.com
+ * @since Sep 21, 2010
+ */
+public class JBossTimeBasedOTPLoginModuleUnitTestCase
+{
+ static String seed = "3132333435363738393031323334353637383930";
+
+ static final String WEB_REQUEST_KEY = "javax.servlet.http.HttpServletRequest";
+
+ @BeforeClass
+ public static void setUp() throws Exception
+ {
+ try
+ {
+ String totp = TimeBasedOTP.generateTOTP( seed, 6 ) ;
+ PolicyContext.registerHandler( WEB_REQUEST_KEY, getHandler(totp), true );
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new RuntimeException( e );
+ }
+ }
+
+ @Test
+ public void testTOTP() throws Exception
+ {
+ Principal principal = new SimplePrincipal( "anil" );
+
+ Subject subject = new Subject();
+ CallbackHandler callbackHandler = new JBossCallbackHandler(principal, seed );
+ Map<String,Object> sharedState = new HashMap<String,Object>();
+ Map<String, Object> options = new HashMap<String,Object>();
+
+ JBossTimeBasedOTPLoginModule jtp = new JBossTimeBasedOTPLoginModule();
+ jtp.initialize(subject, callbackHandler, sharedState, options);
+ jtp.login();
+ }
+
+ @Test
+ public void testInvalidAuth() throws Exception
+ {
+ PolicyContext.registerHandler( WEB_REQUEST_KEY, getHandler( "ArbitraryDummy" ), true );
+
+ Principal principal = new SimplePrincipal( "anil" );
+
+ Subject subject = new Subject();
+ CallbackHandler callbackHandler = new JBossCallbackHandler(principal, seed );
+ Map<String,Object> sharedState = new HashMap<String,Object>();
+ Map<String, Object> options = new HashMap<String,Object>();
+
+ JBossTimeBasedOTPLoginModule jtp = new JBossTimeBasedOTPLoginModule();
+ jtp.initialize(subject, callbackHandler, sharedState, options);
+ try
+ {
+ jtp.login();
+ fail( "Should have failed auth" );
+ }
+ catch( LoginException le )
+ {
+ //pass
+ }
+ }
+
+ /**
+ * Create a JACC Policy Context Handler that takes in a totp string
+ * and returns a {@code HttpServletRequest} with the totp as parameter
+ * @param totp
+ * @return
+ */
+ private static PolicyContextHandler getHandler( final String totp )
+ {
+ return new PolicyContextHandler()
+ {
+ public Object getContext(String key, Object data) throws PolicyContextException
+ {
+ if( WEB_REQUEST_KEY.equals( key ))
+ {
+ TestHttpServletRequest tsr = new TestHttpServletRequest();
+ tsr.setParameter( "totp", totp );
+
+ return tsr;
+ }
+ return null;
+ }
+
+ public String[] getKeys() throws PolicyContextException
+ {
+ return null;
+ }
+
+ public boolean supports(String key) throws PolicyContextException
+ {
+ if( WEB_REQUEST_KEY.equals( key ))
+ return true;
+
+ return false;
+ }
+ };
+ }
+}
\ No newline at end of file
Modified: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/util/TestHttpServletRequest.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/util/TestHttpServletRequest.java 2010-09-21 17:09:46 UTC (rev 113)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/util/TestHttpServletRequest.java 2010-09-21 21:09:13 UTC (rev 114)
@@ -53,6 +53,9 @@
private Map<String,Object> parameterMap = new HashMap<String,Object>();
+ public TestHttpServletRequest()
+ {
+ }
public TestHttpServletRequest(Principal p, String uri, String meth)
{
this.p = p;
@@ -326,4 +329,10 @@
public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException
{
}
+
+ //Non-standard methods
+ public void setParameter( String key, Object value )
+ {
+ parameterMap.put(key, value);
+ }
}
Added: trunk/security-jboss-sx/jbosssx/src/test/resources/otp-users.properties
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/resources/otp-users.properties (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/test/resources/otp-users.properties 2010-09-21 21:09:13 UTC (rev 114)
@@ -0,0 +1 @@
+anil=3132333435363738393031323334353637383930
\ No newline at end of file
Modified: trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTP.java
===================================================================
--- trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTP.java 2010-09-21 17:09:46 UTC (rev 113)
+++ trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTP.java 2010-09-21 21:09:13 UTC (rev 114)
@@ -40,11 +40,11 @@
*/
public class TimeBasedOTP
{
- private static final String HMAC_SHA1 = "HmacSHA1";
+ public static final String HMAC_SHA1 = "HmacSHA1";
- private static final String HMAC_SHA256 = "HmacSHA256";
+ public static final String HMAC_SHA256 = "HmacSHA256";
- private static final String HMAC_SHA512 = "HmacSHA512";
+ public static final String HMAC_SHA512 = "HmacSHA512";
// 0 1 2 3 4 5 6 7 8
private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
@@ -77,6 +77,52 @@
}
/**
+ * Generate a TOTP value using HMAC_SHA256
+ * @param key
+ * @param returnDigits
+ * @return
+ * @throws GeneralSecurityException
+ */
+ public static String generateTOTP256( String key, int returnDigits ) throws GeneralSecurityException
+ {
+ TimeZone utc = TimeZone.getTimeZone( "UTC" );
+ Calendar currentDateTime = Calendar.getInstance( utc );
+ long timeInMilis = currentDateTime.getTimeInMillis();
+
+ String steps = "0";
+ long T = ( timeInMilis - TIME_ZERO ) / TIME_SLICE_X ;
+ steps = Long.toHexString( T ).toUpperCase();
+
+ // Just get a 16 digit string
+ while(steps.length() < 16)
+ steps = "0" + steps;
+ return TimeBasedOTP.generateTOTP256( key, steps, returnDigits);
+ }
+
+ /**
+ * Generate a TOTP value using HMAC_SHA512
+ * @param key
+ * @param returnDigits
+ * @return
+ * @throws GeneralSecurityException
+ */
+ public static String generateTOTP512( String key, int returnDigits ) throws GeneralSecurityException
+ {
+ TimeZone utc = TimeZone.getTimeZone( "UTC" );
+ Calendar currentDateTime = Calendar.getInstance( utc );
+ long timeInMilis = currentDateTime.getTimeInMillis();
+
+ String steps = "0";
+ long T = ( timeInMilis - TIME_ZERO ) / TIME_SLICE_X ;
+ steps = Long.toHexString( T ).toUpperCase();
+
+ // Just get a 16 digit string
+ while(steps.length() < 16)
+ steps = "0" + steps;
+ return TimeBasedOTP.generateTOTP512( key, steps, returnDigits);
+ }
+
+ /**
* This method generates an TOTP value for the given
* set of parameters.
*
Modified: trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTPUtil.java
===================================================================
--- trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTPUtil.java 2010-09-21 17:09:46 UTC (rev 113)
+++ trunk/security-spi/spi/src/main/java/org/jboss/security/otp/TimeBasedOTPUtil.java 2010-09-21 21:09:13 UTC (rev 114)
@@ -22,6 +22,8 @@
package org.jboss.security.otp;
import java.security.GeneralSecurityException;
+import java.util.Calendar;
+import java.util.TimeZone;
/**
* Utility class associated with the {@code TimeBasedOTP} class
@@ -30,6 +32,8 @@
*/
public class TimeBasedOTPUtil
{
+ private static long TIME_INTERVAL = 30 * 1000; //30 secs
+
/**
* Validate a submitted OTP string
* @param submittedOTP OTP string to validate
@@ -39,9 +43,108 @@
*/
public static boolean validate( String submittedOTP, byte[] secret, int numDigits ) throws GeneralSecurityException
{
- String generatedTOTP = TimeBasedOTP.generateTOTP( new String( secret ) , numDigits );
+ TimeZone utc = TimeZone.getTimeZone( "UTC" );
+ Calendar currentDateTime = Calendar.getInstance( utc );
- System.out.println( "Generated[" + generatedTOTP + "]::Submitted[" + submittedOTP );
- return generatedTOTP.equals( submittedOTP );
- }
+ String generatedTOTP = TimeBasedOTP.generateTOTP( new String( secret ) , numDigits );
+ boolean result = generatedTOTP.equals( submittedOTP );
+
+ if( !result )
+ {
+ //Step back time interval
+ long timeInMilis = currentDateTime.getTimeInMillis();
+
+ timeInMilis -= TIME_INTERVAL;
+
+ generatedTOTP = TimeBasedOTP.generateTOTP( new String( secret ) , "" + timeInMilis, numDigits );
+ result = generatedTOTP.equals( submittedOTP );
+ }
+
+ if( !result )
+ {
+ //Step ahead time interval
+ long timeInMilis = currentDateTime.getTimeInMillis();
+ timeInMilis += TIME_INTERVAL;
+ generatedTOTP = TimeBasedOTP.generateTOTP( new String( secret ) , "" + timeInMilis, numDigits );
+ result = generatedTOTP.equals( submittedOTP );
+ }
+
+ return result;
+ }
+
+ /**
+ * Validate a submitted OTP string using HMAC_256
+ * @param submittedOTP OTP string to validate
+ * @param secret Shared secret
+ * @return
+ * @throws GeneralSecurityException
+ */
+ public static boolean validate256( String submittedOTP, byte[] secret, int numDigits ) throws GeneralSecurityException
+ {
+ TimeZone utc = TimeZone.getTimeZone( "UTC" );
+ Calendar currentDateTime = Calendar.getInstance( utc );
+
+ String generatedTOTP = TimeBasedOTP.generateTOTP256( new String( secret ) , numDigits );
+ boolean result = generatedTOTP.equals( submittedOTP );
+
+ if( !result )
+ {
+ //Step back time interval
+ long timeInMilis = currentDateTime.getTimeInMillis();
+ timeInMilis -= TIME_INTERVAL;
+
+ generatedTOTP = TimeBasedOTP.generateTOTP256( new String( secret ) , "" + timeInMilis, numDigits );
+ result = generatedTOTP.equals( submittedOTP );
+ }
+
+ if( !result )
+ {
+ //Step ahead time interval
+ long timeInMilis = currentDateTime.getTimeInMillis();
+ timeInMilis += TIME_INTERVAL;
+
+ generatedTOTP = TimeBasedOTP.generateTOTP256( new String( secret ) , "" + timeInMilis, numDigits );
+ result = generatedTOTP.equals( submittedOTP );
+ }
+
+ return result;
+ }
+
+ /**
+ * Validate a submitted OTP string using HMAC_512
+ * @param submittedOTP OTP string to validate
+ * @param secret Shared secret
+ * @return
+ * @throws GeneralSecurityException
+ */
+ public static boolean validate512( String submittedOTP, byte[] secret, int numDigits ) throws GeneralSecurityException
+ {
+ TimeZone utc = TimeZone.getTimeZone( "UTC" );
+ Calendar currentDateTime = Calendar.getInstance( utc );
+
+ String generatedTOTP = TimeBasedOTP.generateTOTP512( new String( secret ) , numDigits );
+ boolean result = generatedTOTP.equals( submittedOTP );
+
+ if( !result )
+ {
+ //Step back time interval
+ long timeInMilis = currentDateTime.getTimeInMillis();
+ timeInMilis -= TIME_INTERVAL;
+
+ generatedTOTP = TimeBasedOTP.generateTOTP512( new String( secret ) , "" + timeInMilis, numDigits );
+ result = generatedTOTP.equals( submittedOTP );
+ }
+
+ if( !result )
+ {
+ //Step ahead time interval
+ long timeInMilis = currentDateTime.getTimeInMillis();
+ timeInMilis += TIME_INTERVAL;
+
+ generatedTOTP = TimeBasedOTP.generateTOTP512( new String( secret ) , "" + timeInMilis, numDigits );
+ result = generatedTOTP.equals( submittedOTP );
+ }
+
+ return result;
+ }
}
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list