[jboss-cvs] Picketbox SVN: r109 - in trunk/security-spi/spi/src: main/java/org/jboss/security/otp and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Sep 15 15:41:51 EDT 2010


Author: anil.saldhana at jboss.com
Date: 2010-09-15 15:41:51 -0400 (Wed, 15 Sep 2010)
New Revision: 109

Added:
   trunk/security-spi/spi/src/main/java/org/jboss/security/otp/
   trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTP.java
   trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTPUtil.java
   trunk/security-spi/spi/src/test/java/org/jboss/test/security/otp/
   trunk/security-spi/spi/src/test/java/org/jboss/test/security/otp/HOTPUnitTestCase.java
Log:
SECURITY-526: otp library

Added: trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTP.java
===================================================================
--- trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTP.java	                        (rev 0)
+++ trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTP.java	2010-09-15 19:41:51 UTC (rev 109)
@@ -0,0 +1,192 @@
+/*
+ * 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.otp;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Based on IETF RFC 4226 (http://tools.ietf.org/html/rfc4226)
+ * Code is derived from OATH HOTP algorithm 
+ * @author Anil.Saldhana at redhat.com
+ * @since Sep 13, 2010
+ */
+public class HOTP
+{
+   private static final int[] doubleDigits = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 };
+
+   // 0   1   2     3    4     5      6       7        8
+   private static final int[] DIGITS_POWER = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
+
+   /**
+    * This method generates an OTP value for the given set of parameters.
+    *
+    * @param secret       the shared secret
+    * @param movingFactor the counter, time, or other value that
+    *                     changes on a per use basis.
+    * @param codeDigits   the number of digits in the OTP, not
+    *                     including the checksum, if any.
+    * @param addChecksum  a flag that indicates if a checksum digit
+
+    *                     should be appended to the OTP.
+    * @param truncationOffset the offset into the MAC result to
+    *                     begin truncation.  If this value is out of
+    *                     the range of 0 ... 15, then dynamic
+    *                     truncation  will be used.
+    *                     Dynamic truncation is when the last 4
+    *                     bits of the last byte of the MAC are
+    *                     used to determine the start offset.
+    * @throws NoSuchAlgorithmException if no provider makes
+    *                     either HmacSHA1 or HMAC-SHA-1
+    *                     digest algorithms available.
+    * @throws InvalidKeyException
+    *                     The secret provided was not
+    *                     a valid HMAC-SHA-1 key.
+    *
+    * @return A numeric String in base 10 that includes
+    * {@link codeDigits} digits plus the optional checksum
+    * digit if requested.
+    */
+   public static String generateOTP(byte[] secret,
+         long movingFactor,
+         int codeDigits,
+         boolean addChecksum,
+         int truncationOffset)
+   throws NoSuchAlgorithmException, InvalidKeyException
+   {  
+      // put movingFactor value into text byte array
+      String result = null;
+      int digits = addChecksum ? (codeDigits + 1) : codeDigits;
+      byte[] text = new byte[8];
+
+      for (int i = text.length - 1; i >= 0; i--) 
+      {
+         text[i] = (byte) (movingFactor & 0xff);
+         movingFactor >>= 8;
+      }
+
+      // compute hmac hash
+      byte[] hash = hmac_sha1(secret, text);
+
+      // put selected bytes into result int
+      int offset = hash[hash.length - 1] & 0xf;
+      if ( (0<=truncationOffset) &&
+            (truncationOffset<(hash.length-4)) ) 
+      {
+         offset = truncationOffset;
+      }
+      
+      int binary =
+         ((hash[offset] & 0x7f) << 24)
+         | ((hash[offset + 1] & 0xff) << 16)
+         | ((hash[offset + 2] & 0xff) << 8)
+         | (hash[offset + 3] & 0xff);
+
+      int otp = binary % DIGITS_POWER[codeDigits];
+      if (addChecksum) 
+      {
+         otp =  (otp * 10) + calcChecksum(otp, codeDigits);
+      }
+      result = Integer.toString(otp);
+      
+      while (result.length() < digits) 
+      {
+         result = "0" + result;
+      }
+      return result;
+   }
+   
+   /**
+    * Calculates the checksum using the credit card algorithm.
+    * This algorithm has the advantage that it detects any single
+    * mistyped digit and any single transposition of
+    * adjacent digits.
+    *
+    * @param num the number to calculate the checksum for
+    * @param digits number of significant places in the number
+    *
+    * @return the checksum of num
+    */
+   private static int calcChecksum(long num, int digits) 
+   {
+      boolean doubleDigit = true;
+
+      int     total = 0;
+
+      while (0 < digits--) 
+      {
+         int digit = (int) (num % 10);
+         num /= 10;
+         if (doubleDigit) 
+         {
+            digit = doubleDigits[digit];
+         }
+         total += digit;
+         doubleDigit = !doubleDigit;
+      }
+
+      int result = total % 10;
+
+      if (result > 0) 
+      {
+         result = 10 - result;
+      }
+      return result;
+   }
+   
+   /**
+    * This method uses the JCE to provide the HMAC-SHA-1 algorithm.
+    * HMAC computes a Hashed Message Authentication Code and
+    * in this case SHA1 is the hash algorithm used.
+    *
+    * @param keyBytes   the bytes to use for the HMAC-SHA-1 key
+    * @param text       the message or text to be authenticated.
+    *
+    * @throws NoSuchAlgorithmException if no provider makes
+    *       either HmacSHA1 or HMAC-SHA-1
+    *       digest algorithms available.
+    * @throws InvalidKeyException
+    *       The secret provided was not a valid HMAC-SHA-1 key.
+    *
+    */ 
+   private static byte[] hmac_sha1( byte[] keyBytes, byte[] text )
+   throws NoSuchAlgorithmException, InvalidKeyException
+   { 
+      Mac hmacSha1;
+      try 
+      {
+         hmacSha1 = Mac.getInstance("HmacSHA1");
+      } 
+      catch (NoSuchAlgorithmException nsae) 
+      {
+         hmacSha1 = Mac.getInstance("HMAC-SHA-1");
+      }
+      
+      SecretKeySpec macKey =  new SecretKeySpec(keyBytes, "RAW");
+      hmacSha1.init(macKey);
+      
+      return hmacSha1.doFinal(text);
+   }
+}
\ No newline at end of file

Added: trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTPUtil.java
===================================================================
--- trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTPUtil.java	                        (rev 0)
+++ trunk/security-spi/spi/src/main/java/org/jboss/security/otp/HOTPUtil.java	2010-09-15 19:41:51 UTC (rev 109)
@@ -0,0 +1,75 @@
+/*
+ * 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.otp;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Utility class for {@code HOTP}
+ * @author Anil.Saldhana at redhat.com
+ * @since Sep 15, 2010
+ */
+public class HOTPUtil
+{
+   private static final int MILISECOND_BUFFER = 50; 
+   
+   /**
+    * Validate a submitted OTP string
+    * @param submittedOTP OTP string to validate
+    * @param secret Shared secret
+    * @param timeValueInMins How many mins back we need to check?
+    * @return
+    * @throws InvalidKeyException
+    * @throws NoSuchAlgorithmException
+    */
+   public static boolean validate( String submittedOTP, byte[] secret, int timeValueInMins ) throws InvalidKeyException, NoSuchAlgorithmException
+   {
+      int codeDigits = 6;
+      boolean addChecksum = false;
+      int truncationOffset = 0;
+      
+      TimeZone utc = TimeZone.getTimeZone( "UTC" );
+      Calendar currentDateTime = Calendar.getInstance( utc );
+      
+      long timeInMilis = currentDateTime.getTimeInMillis();
+      long movingFactor = timeInMilis;
+             
+      String otp = HOTP.generateOTP( secret, movingFactor, codeDigits, addChecksum, truncationOffset );
+      
+      if( otp.equals( submittedOTP ) )
+         return true;
+      
+      int endLimit = timeValueInMins * 60* 1000 + MILISECOND_BUFFER;
+      
+      for( int i = 1; i < endLimit ; i++ )
+      {
+         movingFactor --; 
+         otp = HOTP.generateOTP( secret, movingFactor, codeDigits, addChecksum, truncationOffset );
+         if( otp.equals( submittedOTP ) )
+            return true;   
+      }
+      return false; 
+   } 
+}
\ No newline at end of file

Added: trunk/security-spi/spi/src/test/java/org/jboss/test/security/otp/HOTPUnitTestCase.java
===================================================================
--- trunk/security-spi/spi/src/test/java/org/jboss/test/security/otp/HOTPUnitTestCase.java	                        (rev 0)
+++ trunk/security-spi/spi/src/test/java/org/jboss/test/security/otp/HOTPUnitTestCase.java	2010-09-15 19:41:51 UTC (rev 109)
@@ -0,0 +1,85 @@
+/*
+ * 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.security.otp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import org.jboss.security.otp.HOTP;
+import org.jboss.security.otp.HOTPUtil;
+import org.junit.Test;
+
+/**
+ * Unit test the {@code HOTP}
+ * @author Anil.Saldhana at redhat.com
+ * @since Sep 13, 2010
+ */
+public class HOTPUnitTestCase
+{
+   private String userCode = "SomeCode";
+
+   private int codeDigits = 6;
+   private boolean addChecksum = false;
+   private int truncationOffset = 0; 
+   
+   byte[] secret = userCode.getBytes();
+   
+   int SLEEP_TIME = 10;
+   
+   @Test
+   public void testHOTP() throws Exception
+   {
+      TimeZone utc = TimeZone.getTimeZone( "UTC" );
+      Calendar currentDateTime = Calendar.getInstance( utc ); 
+    
+      String otp1 = this.getOTP(secret, currentDateTime);
+      String otp2 = this.getOTP(secret, currentDateTime);
+      
+      assertEquals( otp1, otp2 ); 
+   }
+   
+   @Test
+   public void testSubmittedHOTP() throws Exception
+   { 
+      TimeZone utc = TimeZone.getTimeZone( "UTC" );
+      Calendar currentDateTime = Calendar.getInstance( utc );
+      String otp1 = this.getOTP( secret, currentDateTime );
+      
+      //System.out.println( "OTP Generated at " + currentDateTime);
+      
+      System.out.println( "We are going to sleep for " + SLEEP_TIME + " secs" );
+      Thread.sleep( SLEEP_TIME * 1000 ); //20 secs
+      
+      assertTrue( HOTPUtil.validate( otp1, secret,  2 ) );
+   }
+   
+   private String getOTP( byte[] secret, Calendar currentDateTime ) throws Exception
+   { 
+      long timeInMilis = currentDateTime.getTimeInMillis();
+      long movingFactor = timeInMilis;
+
+      return HOTP.generateOTP( secret, movingFactor, codeDigits, addChecksum, truncationOffset );
+   }
+}
\ No newline at end of file



More information about the jboss-cvs-commits mailing list