From 86856f497377aa0c9b39551a2df013b915be21ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 12 Mar 2013 18:23:11 +0100 Subject: Gonna try jboss srp implementation, because if I implement myself one we will have to audit it. --- src/org/jboss/security/srp/SRPClientSession.java | 289 ++++++++++++++++++++++ src/org/jboss/security/srp/SRPConf.java | 113 +++++++++ src/org/jboss/security/srp/SRPParameters.java | 150 +++++++++++ src/org/jboss/security/srp/SRPPermission.java | 66 +++++ src/org/jboss/security/srp/SRPServerListener.java | 42 ++++ src/org/jboss/security/srp/SRPServerSession.java | 285 +++++++++++++++++++++ src/org/jboss/security/srp/SRPSessionKey.java | 78 ++++++ src/org/jboss/security/srp/SRPVerifierStore.java | 115 +++++++++ src/org/jboss/security/srp/SerialObjectStore.java | 216 ++++++++++++++++ 9 files changed, 1354 insertions(+) create mode 100644 src/org/jboss/security/srp/SRPClientSession.java create mode 100644 src/org/jboss/security/srp/SRPConf.java create mode 100644 src/org/jboss/security/srp/SRPParameters.java create mode 100644 src/org/jboss/security/srp/SRPPermission.java create mode 100644 src/org/jboss/security/srp/SRPServerListener.java create mode 100644 src/org/jboss/security/srp/SRPServerSession.java create mode 100644 src/org/jboss/security/srp/SRPSessionKey.java create mode 100644 src/org/jboss/security/srp/SRPVerifierStore.java create mode 100644 src/org/jboss/security/srp/SerialObjectStore.java (limited to 'src/org/jboss/security') diff --git a/src/org/jboss/security/srp/SRPClientSession.java b/src/org/jboss/security/srp/SRPClientSession.java new file mode 100644 index 00000000..bafc4842 --- /dev/null +++ b/src/org/jboss/security/srp/SRPClientSession.java @@ -0,0 +1,289 @@ +/* + * 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.srp; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import org.jboss.crypto.CryptoUtil; +import org.jboss.logging.Logger; + +/** The client side logic to the SRP protocol. The class is intended to be used + * with a SRPServerSession object via the SRPServerInterface. The SRP algorithm + * using these classes consists of: + * + * 1. Get server, SRPServerInterface server = (SRPServerInterface) Naming.lookup(...); + * 2. Get SRP parameters, SRPParameters params = server.getSRPParameters(username); + * 3. Create a client session, SRPClientSession client = new SRPClientSession(username, + * password, params); + * 4. Exchange public keys, byte[] A = client.exponential(); + * byte[] B = server.init(username, A); + * 5. Exchange challenges, byte[] M1 = client.response(B); + * byte[] M2 = server.verify(username, M1); + * 6. Verify the server response, if( client.verify(M2) == false ) + * throw new SecurityException("Failed to validate server reply"); + * 7. Validation complete + * + * Note that these steps are stateful. They must be performed in order and a + * step cannot be repeated to update the session state. + * + * This product uses the 'Secure Remote Password' cryptographic + * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU). + * + * @author Scott.Stark@jboss.org + * @version $Revision: 81038 $ + */ +public class SRPClientSession +{ + private static Logger log = Logger.getLogger(SRPClientSession.class); + private SRPParameters params; + private BigInteger N; + private BigInteger g; + private BigInteger x; + private BigInteger v; + private byte[] s; + private BigInteger a; + private BigInteger A; + private byte[] K; + /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */ + private MessageDigest clientHash; + /** The M2 = H(A | M | K) hash */ + private MessageDigest serverHash; + + private static int A_LEN = 64; + + /** Creates a new SRP server session object from the username, password + verifier, + @param username, the user ID + @param password, the user clear text password + @param params, the SRP parameters for the session + */ + public SRPClientSession(String username, char[] password, SRPParameters params) + { + this(username, password, params, null); + } + + /** Creates a new SRP server session object from the username, password + verifier, + @param username, the user ID + @param password, the user clear text password + @param params, the SRP parameters for the session + @param abytes, the random exponent used in the A public key. This must be + 8 bytes in length. + */ + public SRPClientSession(String username, char[] password, SRPParameters params, + byte[] abytes) + { + try + { + // Initialize the secure random number and message digests + CryptoUtil.init(); + } + catch(NoSuchAlgorithmException e) + { + } + this.params = params; + this.g = new BigInteger(1, params.g); + this.N = new BigInteger(1, params.N); + if( abytes != null ) + { + if( 8*abytes.length != A_LEN ) + throw new IllegalArgumentException("The abytes param must be " + +(A_LEN/8)+" in length, abytes.length="+abytes.length); + this.a = new BigInteger(abytes); + } + + if( log.isTraceEnabled() ) + log.trace("g: "+CryptoUtil.tob64(params.g)); + // Calculate x = H(s | H(U | ':' | password)) + byte[] xb = CryptoUtil.calculatePasswordHash(username, password, params.s); + if( log.isTraceEnabled() ) + log.trace("x: "+CryptoUtil.tob64(xb)); + this.x = new BigInteger(1, xb); + this.v = g.modPow(x, N); // g^x % N + if( log.isTraceEnabled() ) + log.trace("v: "+CryptoUtil.tob64(v.toByteArray())); + + serverHash = CryptoUtil.newDigest(); + clientHash = CryptoUtil.newDigest(); + // H(N) + byte[] hn = CryptoUtil.newDigest().digest(params.N); + if( log.isTraceEnabled() ) + log.trace("H(N): "+CryptoUtil.tob64(hn)); + // H(g) + byte[] hg = CryptoUtil.newDigest().digest(params.g); + if( log.isTraceEnabled() ) + log.trace("H(g): "+CryptoUtil.tob64(hg)); + // clientHash = H(N) xor H(g) + byte[] hxg = CryptoUtil.xor(hn, hg, 20); + if( log.isTraceEnabled() ) + log.trace("H(N) xor H(g): "+CryptoUtil.tob64(hxg)); + clientHash.update(hxg); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g)]: "+CryptoUtil.tob64(tmp.digest())); + } + // clientHash = H(N) xor H(g) | H(U) + clientHash.update(CryptoUtil.newDigest().digest(username.getBytes())); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U)]: "+CryptoUtil.tob64(tmp.digest())); + } + // clientHash = H(N) xor H(g) | H(U) | s + clientHash.update(params.s); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s]: "+CryptoUtil.tob64(tmp.digest())); + } + K = null; + } + + /** + * @returns The exponential residue (parameter A) to be sent to the server. + */ + public byte[] exponential() + { + byte[] Abytes = null; + if(A == null) + { + /* If the random component of A has not been specified use a random + number */ + if( a == null ) + { + BigInteger one = BigInteger.ONE; + do + { + a = new BigInteger(A_LEN, CryptoUtil.getPRNG()); + } while(a.compareTo(one) <= 0); + } + A = g.modPow(a, N); + Abytes = CryptoUtil.trim(A.toByteArray()); + // clientHash = H(N) xor H(g) | H(U) | A + clientHash.update(Abytes); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s | A]: "+CryptoUtil.tob64(tmp.digest())); + } + // serverHash = A + serverHash.update(Abytes); + } + return Abytes; + } + + /** + @returns M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) + @exception NoSuchAlgorithmException thrown if the session key + MessageDigest algorithm cannot be found. + */ + public byte[] response(byte[] Bbytes) throws NoSuchAlgorithmException + { + // clientHash = H(N) xor H(g) | H(U) | s | A | B + clientHash.update(Bbytes); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s | A | B]: "+CryptoUtil.tob64(tmp.digest())); + } + // Calculate u as the first 32 bits of H(B) + byte[] hB = CryptoUtil.newDigest().digest(Bbytes); + byte[] ub = + {hB[0], hB[1], hB[2], hB[3]}; + // Calculate S = (B - g^x) ^ (a + u * x) % N + BigInteger B = new BigInteger(1, Bbytes); + if( log.isTraceEnabled() ) + log.trace("B: "+CryptoUtil.tob64(B.toByteArray())); + if( B.compareTo(v) < 0 ) + B = B.add(N); + if( log.isTraceEnabled() ) + log.trace("B': "+CryptoUtil.tob64(B.toByteArray())); + if( log.isTraceEnabled() ) + log.trace("v: "+CryptoUtil.tob64(v.toByteArray())); + BigInteger u = new BigInteger(1, ub); + if( log.isTraceEnabled() ) + log.trace("u: "+CryptoUtil.tob64(u.toByteArray())); + BigInteger B_v = B.subtract(v); + if( log.isTraceEnabled() ) + log.trace("B - v: "+CryptoUtil.tob64(B_v.toByteArray())); + BigInteger a_ux = a.add(u.multiply(x)); + if( log.isTraceEnabled() ) + log.trace("a + u * x: "+CryptoUtil.tob64(a_ux.toByteArray())); + BigInteger S = B_v.modPow(a_ux, N); + if( log.isTraceEnabled() ) + log.trace("S: "+CryptoUtil.tob64(S.toByteArray())); + // K = SessionHash(S) + MessageDigest sessionDigest = MessageDigest.getInstance(params.hashAlgorithm); + K = sessionDigest.digest(S.toByteArray()); + if( log.isTraceEnabled() ) + log.trace("K: "+CryptoUtil.tob64(K)); + // clientHash = H(N) xor H(g) | H(U) | A | B | K + clientHash.update(K); + byte[] M1 = clientHash.digest(); + if( log.isTraceEnabled() ) + log.trace("M1: H[H(N) xor H(g) | H(U) | s | A | B | K]: "+CryptoUtil.tob64(M1)); + serverHash.update(M1); + serverHash.update(K); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(serverHash); + log.trace("H[A | M1 | K]: "+CryptoUtil.tob64(tmp.digest())); + } + return M1; + } + /** + * @param M2 The server's response to the client's challenge + * @returns True if and only if the server's response was correct. + */ + public boolean verify(byte[] M2) + { + // M2 = H(A | M1 | K) + byte[] myM2 = serverHash.digest(); + boolean valid = Arrays.equals(M2, myM2); + if( log.isTraceEnabled() ) + { + log.trace("verify serverM2: "+CryptoUtil.tob64(M2)); + log.trace("verify M2: "+CryptoUtil.tob64(myM2)); + } + return valid; + } + + /** Returns the negotiated session K, K = SHA_Interleave(S) + @return the private session K byte[] + @throws SecurityException - if the current thread does not have an + getSessionKey SRPPermission. + */ + public byte[] getSessionKey() throws SecurityException + { + SecurityManager sm = System.getSecurityManager(); + if( sm != null ) + { + SRPPermission p = new SRPPermission("getSessionKey"); + sm.checkPermission(p); + } + return K; + } +} diff --git a/src/org/jboss/security/srp/SRPConf.java b/src/org/jboss/security/srp/SRPConf.java new file mode 100644 index 00000000..c9b69428 --- /dev/null +++ b/src/org/jboss/security/srp/SRPConf.java @@ -0,0 +1,113 @@ +/* + * 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.srp; + +import java.math.BigInteger; + +import org.jboss.crypto.CryptoUtil; + +/** A port of the libsrp/t_conf.c predefined constants for the N & g parameters +of the SRP algorithm. It contains a collection of "good" primes for N and the +corresponding the corresponding generator g. + +This product includes software developed by Tom Wu and Eugene +Jhong for the SRP Distribution (http://srp.stanford.edu/srp/). + +@author Scott.Stark@jboss.org +@version $Revision: 81038 $ +*/ +public class SRPConf +{ + /* Master builtin parameter storage object */ + public static class SRPParams + { + String modb64; + String genb64; + String comment; + BigInteger N; + BigInteger g; + SRPParams(String modb64, String genb64, String comment) + { + this.modb64 = modb64; + this.genb64 = genb64; + this.comment = comment; + } + public byte[] Nbytes() + { + return CryptoUtil.fromb64(modb64); + } + public byte[] gbytes() + { + return CryptoUtil.fromb64(genb64); + } + public BigInteger N() + { + if( N == null ) + N = new BigInteger(1, CryptoUtil.fromb64(modb64)); + return N; + } + public BigInteger g() + { + if( g == null ) + g = new BigInteger(1, CryptoUtil.fromb64(genb64)); + return g; + } + public String getComment() + { + return comment; + } + } + + static SRPParams[] pre_params = { + new SRPParams("3Kn/YYiomHkFkfM1x4kayR125MGkzpLUDy3y14FlTMwYnhZkjrMXnoC2TcFAecNlU5kFzgcpKYUbBOPZFRtyf3", + "2", null), + new SRPParams("CbDP.jR6YD6wAj2ByQWxQxQZ7.9J9xkn2.Uqb3zVm16vQyizprhBw9hi80psatZ8k54vwZfiIeEHZVsDnyqeWSSIpWso.wh5GD4OFgdhVI3", + "2", null), + new SRPParams("iqJ7nFZ4bGCRjE1F.FXEwL085Zb0kLM2TdHDaVVCdq0cKxvnH/0FLskJTKlDtt6sDl89dc//aEULTVFGtcbA/tDzc.bnFE.DWthQOu2n2JwKjgKfgCR2lZFWXdnWmoOh", + "2", null), + new SRPParams("///////////93zgY8MZ2DCJ6Oek0t1pHAG9E28fdp7G22xwcEnER8b5A27cED0JTxvKPiyqwGnimAmfjybyKDq/XDMrjKS95v8MrTc9UViRqJ4BffZes8F//////////", + "7", "oakley prime 1"), + new SRPParams("Ewl2hcjiutMd3Fu2lgFnUXWSc67TVyy2vwYCKoS9MLsrdJVT9RgWTCuEqWJrfB6uE3LsE9GkOlaZabS7M29sj5TnzUqOLJMjiwEzArfiLr9WbMRANlF68N5AVLcPWvNx6Zjl3m5Scp0BzJBz9TkgfhzKJZ.WtP3Mv/67I/0wmRZ", + "2", null), + new SRPParams("F//////////oG/QeY5emZJ4ncABWDmSqIa2JWYAPynq0Wk.fZiJco9HIWXvZZG4tU.L6RFDEaCRC2iARV9V53TFuJLjRL72HUI5jNPYNdx6z4n2wQOtxMiB/rosz0QtxUuuQ/jQYP.bhfya4NnB7.P9A6PHxEPJWV//////////", + "5", "oakley prime 2"), + new SRPParams("3NUKQ2Re4P5BEK0TLg2dX3gETNNNECPoe92h4OVMaDn3Xo/0QdjgG/EvM.hiVV1BdIGklSI14HA38Mpe5k04juR5/EXMU0r1WtsLhNXwKBlf2zEfoOh0zVmDvqInpU695f29Iy7sNW3U5RIogcs740oUp2Kdv5wuITwnIx84cnO.e467/IV1lPnvMCr0pd1dgS0a.RV5eBJr03Q65Xy61R", + "2", null), + new SRPParams("dUyyhxav9tgnyIg65wHxkzkb7VIPh4o0lkwfOKiPp4rVJrzLRYVBtb76gKlaO7ef5LYGEw3G.4E0jbMxcYBetDy2YdpiP/3GWJInoBbvYHIRO9uBuxgsFKTKWu7RnR7yTau/IrFTdQ4LY/q.AvoCzMxV0PKvD9Odso/LFIItn8PbTov3VMn/ZEH2SqhtpBUkWtmcIkEflhX/YY/fkBKfBbe27/zUaKUUZEUYZ2H2nlCL60.JIPeZJSzsu/xHDVcx", + "2", null), + new SRPParams("2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp", + "2", null), + }; + + public int getPredefinedCount() + { + return pre_params.length; + } + public static SRPParams getPredefinedParams(int n) + { + return pre_params[n]; + } + public static SRPParams getDefaultParams() + { + return pre_params[6]; + } +} diff --git a/src/org/jboss/security/srp/SRPParameters.java b/src/org/jboss/security/srp/SRPParameters.java new file mode 100644 index 00000000..43e2dad2 --- /dev/null +++ b/src/org/jboss/security/srp/SRPParameters.java @@ -0,0 +1,150 @@ +/* + * 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.srp; + +import java.io.Serializable; +import java.util.Arrays; + +import org.jboss.crypto.CryptoUtil; + +/** The RFC2945 algorithm session parameters that the client and server +agree to use. In addition to the base RFC2945 parameters, one can choose an +alternate hash algorithm for the private session key. + +@author Scott.Stark@jboss.org +@version $Revision: 81038 $ +*/ +public class SRPParameters implements Cloneable, Serializable +{ + /** The serial version ID. + * @since 1.2.4.1 + */ + private static final long serialVersionUID = 6438772808805276693L; + + /** The algorithm safe-prime modulus */ + public final byte[] N; + /** The algorithm primitive generator */ + public final byte[] g; + /** The random password salt originally used to verify the password */ + public final byte[] s; + /** The algorithm to hash the session key to produce K. To be consistent + with the RFC2945 description this must be SHA_Interleave as implemented + by the JBossSX security provider. For compatibility with earlier JBossSX + SRP releases the algorithm must be SHA_ReverseInterleave. This name is + passed to java.security.MessageDigest.getInstance(). */ + public final String hashAlgorithm; + /** The algorithm to use for any encryption of data. + */ + public final String cipherAlgorithm; + /** The cipher intialization vector bytes + */ + public byte[] cipherIV; + + /** Creates a new instance of SRPParameters */ + public SRPParameters(byte[] N, byte[] g, byte[] s) + { + this(N, g, s, "SHA_Interleave", null); + } + public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm) + { + this(N, g, s, hashAlgorithm, null); + } + public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm, + String cipherAlgorithm) + { + this(N, g, s, hashAlgorithm, cipherAlgorithm, null); + } + public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm, + String cipherAlgorithm, byte[] cipherIV) + { + this.N = N; + this.g = g; + this.s = s; + if( hashAlgorithm == null ) + hashAlgorithm = "SHA_Interleave"; + this.hashAlgorithm = hashAlgorithm; + this.cipherAlgorithm = cipherAlgorithm; + this.cipherIV = cipherIV; + } + + public Object clone() + { + Object clone = null; + try + { + clone = super.clone(); + } + catch(CloneNotSupportedException e) + { + } + return clone; + } + + public int hashCode() + { + int hashCode = hashAlgorithm.hashCode(); + for(int i = 0; i < N.length; i ++) + hashCode += N[i]; + for(int i = 0; i < g.length; i ++) + hashCode += g[i]; + for(int i = 0; i < s.length; i ++) + hashCode += s[i]; + return hashCode; + } + + public boolean equals(Object obj) + { + boolean equals = false; + if( obj instanceof SRPParameters ) + { + SRPParameters p = (SRPParameters) obj; + equals = hashAlgorithm.equals(p.hashAlgorithm); + if( equals == true ) + equals = Arrays.equals(N, p.N); + if( equals == true ) + equals = Arrays.equals(g, p.g); + if( equals == true ) + equals = Arrays.equals(s, p.s); + } + return equals; + } + + public String toString() + { + StringBuffer tmp = new StringBuffer(super.toString()); + tmp.append('{'); + tmp.append("N: "); + tmp.append(CryptoUtil.encodeBase64(N)); + tmp.append("|g: "); + tmp.append(CryptoUtil.encodeBase64(g)); + tmp.append("|s: "); + tmp.append(CryptoUtil.encodeBase64(s)); + tmp.append("|hashAlgorithm: "); + tmp.append(hashAlgorithm); + tmp.append("|cipherAlgorithm: "); + tmp.append(cipherAlgorithm); + tmp.append("|cipherIV: "); + tmp.append(cipherIV); + tmp.append('}'); + return tmp.toString(); + } +} diff --git a/src/org/jboss/security/srp/SRPPermission.java b/src/org/jboss/security/srp/SRPPermission.java new file mode 100644 index 00000000..d1a77d64 --- /dev/null +++ b/src/org/jboss/security/srp/SRPPermission.java @@ -0,0 +1,66 @@ +/* + * 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.srp; + +import java.security.BasicPermission; + +/** A custom permission class for protecting access to sensitive SRP information +like the private session key and private key. + +The following table lists all the possible SRPPermission target names, +and for each provides a description of what the permission allows +and a discussion of the risks of granting code the permission. + + + + + + + + + + + + + +
Permission Target NameWhat the Permission AllowsRisks of Allowing this Permission
getSessionKeyAccess the private SRP session keyThis provides access the the private session key that results from +the SRP negiotation. Access to this key will allow one to encrypt/decrypt msgs +that have been encrypted with the session key. +
+ +@author Scott.Stark@jboss.org +@version $Revision: 81038 $ +*/ +public class SRPPermission extends BasicPermission +{ + + /** Creates new SRPPermission */ + public SRPPermission(String name) + { + super(name); + } + public SRPPermission(String name, String actions) + { + super(name, actions); + } + +} diff --git a/src/org/jboss/security/srp/SRPServerListener.java b/src/org/jboss/security/srp/SRPServerListener.java new file mode 100644 index 00000000..a9e22cbb --- /dev/null +++ b/src/org/jboss/security/srp/SRPServerListener.java @@ -0,0 +1,42 @@ +/* + * 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.srp; + +/** A callback interface for SRP session events. + +@author Scott.Stark@jboss.org +@version $Revision: 81038 $ +*/ +public interface SRPServerListener +{ + /** Called when a user has successfully completed the SRP handshake and any auxillary + * challenge verification. + * @param key, the {username, sessionID} pair + * @param session, the server SRP session information + */ + public void verifiedUser(SRPSessionKey key, SRPServerSession session); + /** Called when a user requests that a session be closed + * + * @param key, the {username, sessionID} pair + */ + public void closedUserSession(SRPSessionKey key); +} diff --git a/src/org/jboss/security/srp/SRPServerSession.java b/src/org/jboss/security/srp/SRPServerSession.java new file mode 100644 index 00000000..11dc6d4c --- /dev/null +++ b/src/org/jboss/security/srp/SRPServerSession.java @@ -0,0 +1,285 @@ +/* + * 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.srp; + +import java.io.Serializable; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import org.jboss.logging.Logger; +import org.jboss.crypto.CryptoUtil; + +/** The server side logic to the SRP protocol. The class is the server side + equivalent of the SRPClientSession object. An implementation of + SRPServerInterface creates an SRPServerSession on the start of a login + session. + + The client side algorithm using these classes consists of: + + 1. Get server, SRPServerInterface server = (SRPServerInterface) Naming.lookup(...); + 2. Get SRP parameters, SRPParameters params = server.getSRPParameters(username); + 3. Create a client session, SRPClientSession client = new SRPClientSession(username, password, params); + 4. Exchange public keys, byte[] A = client.exponential(); + byte[] B = server.init(username, A); + 5. Exchange challenges, byte[] M1 = client.response(B); + byte[] M2 = server.verify(username, M1); + 6. Verify the server response, if( client.verify(M2) == false ) + throw new SecurityException("Failed to validate server reply"); + 7. Validation complete + + Note that these steps are stateful. They must be performed in order and a + step cannot be repeated to update the session state. + + This product uses the 'Secure Remote Password' cryptographic + authentication system developed by Tom Wu (tjw@CS.Stanford.EDU). + + @author Scott.Stark@jboss.org + @version $Revision: 81038 $ + */ +public class SRPServerSession implements Serializable +{ + /** The serial version ID + @since 1.6 + */ + static final long serialVersionUID = -2448005747721323704L; + private static int B_LEN = 64; // 64 bits for 'b' + private static Logger log = Logger.getLogger(SRPServerSession.class); + + private SRPParameters params; + private BigInteger N; + private BigInteger g; + private BigInteger v; + private BigInteger b; + private BigInteger B; + private byte[] K; + /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */ + private transient MessageDigest clientHash; + private byte[] M1; + /** The M2 = H(A | M | K) hash */ + private transient MessageDigest serverHash; + private byte[] M2; + + /** Creates a new SRP server session object from the username, password + verifier, and session parameters. + @param username, the user ID + @param vb, the password verifier byte sequence + @param params, the SRP parameters for the session + */ + public SRPServerSession(String username, byte[] vb, SRPParameters params) + { + this.params = params; + this.v = new BigInteger(1, vb); + this.g = new BigInteger(1, params.g); + this.N = new BigInteger(1, params.N); + if( log.isTraceEnabled() ) + log.trace("g: "+CryptoUtil.tob64(params.g)); + if( log.isTraceEnabled() ) + log.trace("v: "+CryptoUtil.tob64(vb)); + serverHash = CryptoUtil.newDigest(); + clientHash = CryptoUtil.newDigest(); + // H(N) + byte[] hn = CryptoUtil.newDigest().digest(params.N); + if( log.isTraceEnabled() ) + log.trace("H(N): "+CryptoUtil.tob64(hn)); + // H(g) + byte[] hg = CryptoUtil.newDigest().digest(params.g); + if( log.isTraceEnabled() ) + log.trace("H(g): "+CryptoUtil.tob64(hg)); + // clientHash = H(N) xor H(g) + byte[] hxg = CryptoUtil.xor(hn, hg, 20); + if( log.isTraceEnabled() ) + log.trace("H(N) xor H(g): "+CryptoUtil.tob64(hxg)); + clientHash.update(hxg); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g)]: "+CryptoUtil.tob64(tmp.digest())); + } + // clientHash = H(N) xor H(g) | H(U) + clientHash.update(CryptoUtil.newDigest().digest(username.getBytes())); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U)]: "+CryptoUtil.tob64(tmp.digest())); + } + // clientHash = H(N) xor H(g) | H(U) | s + clientHash.update(params.s); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s]: "+CryptoUtil.tob64(tmp.digest())); + } + K = null; + } + + /** + * @returns The user's password salt + */ + public SRPParameters getParameters() + { + return params; + } + + /** + * @returns The exponential residue (parameter B) to be sent to the + * client. + */ + public byte[] exponential() + { + if(B == null) + { + BigInteger one = BigInteger.valueOf(1); + do + { + b = new BigInteger(B_LEN, CryptoUtil.getPRNG()); + } while(b.compareTo(one) <= 0); + B = v.add(g.modPow(b, N)); + if(B.compareTo(N) >= 0) + B = B.subtract(N); + } + return CryptoUtil.trim(B.toByteArray()); + } + + /** + @param ab The client's exponential (parameter A). + @returns The secret shared session K between client and server + @exception NoSuchAlgorithmException thrown if the session key + MessageDigest algorithm cannot be found. + */ + public void buildSessionKey(byte[] ab) throws NoSuchAlgorithmException + { + if( log.isTraceEnabled() ) + log.trace("A: "+CryptoUtil.tob64(ab)); + byte[] nb = CryptoUtil.trim(B.toByteArray()); + // clientHash = H(N) xor H(g) | H(U) | s | A + clientHash.update(ab); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s | A]: "+CryptoUtil.tob64(tmp.digest())); + } + // clientHash = H(N) xor H(g) | H(U) | A | B + clientHash.update(nb); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s | A | B]: "+CryptoUtil.tob64(tmp.digest())); + } + // serverHash = A + serverHash.update(ab); + // Calculate u as the first 32 bits of H(B) + byte[] hB = CryptoUtil.newDigest().digest(nb); + byte[] ub = + {hB[0], hB[1], hB[2], hB[3]}; + // Calculate S = (A * v^u) ^ b % N + BigInteger A = new BigInteger(1, ab); + if( log.isTraceEnabled() ) + log.trace("A: "+CryptoUtil.tob64(A.toByteArray())); + if( log.isTraceEnabled() ) + log.trace("B: "+CryptoUtil.tob64(B.toByteArray())); + if( log.isTraceEnabled() ) + log.trace("v: "+CryptoUtil.tob64(v.toByteArray())); + BigInteger u = new BigInteger(1, ub); + if( log.isTraceEnabled() ) + log.trace("u: "+CryptoUtil.tob64(u.toByteArray())); + BigInteger A_v2u = A.multiply(v.modPow(u, N)).mod(N); + if( log.isTraceEnabled() ) + log.trace("A * v^u: "+CryptoUtil.tob64(A_v2u.toByteArray())); + BigInteger S = A_v2u.modPow(b, N); + if( log.isTraceEnabled() ) + log.trace("S: "+CryptoUtil.tob64(S.toByteArray())); + // K = SessionHash(S) + MessageDigest sessionDigest = MessageDigest.getInstance(params.hashAlgorithm); + K = sessionDigest.digest(S.toByteArray()); + if( log.isTraceEnabled() ) + log.trace("K: "+CryptoUtil.tob64(K)); + // clientHash = H(N) xor H(g) | H(U) | A | B | K + clientHash.update(K); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(clientHash); + log.trace("H[H(N) xor H(g) | H(U) | s | A | B | K]: "+CryptoUtil.tob64(tmp.digest())); + } + } + + /** Returns the negotiated session K, K = SessionHash(S) + @return the private session K byte[] + @throws SecurityException - if the current thread does not have an + getSessionKey SRPPermission. + */ + public byte[] getSessionKey() throws SecurityException + { + SecurityManager sm = System.getSecurityManager(); + if( sm != null ) + { + SRPPermission p = new SRPPermission("getSessionKey"); + sm.checkPermission(p); + } + return K; + } + + /** + @returns M2 = H(A | M | K) + */ + public byte[] getServerResponse() + { + if( M2 == null ) + M2 = serverHash.digest(); + return M2; + } + public byte[] getClientResponse() + { + return M1; + } + + /** + * @param resp The client's response to the server's challenge + * @returns True if and only if the client's response was correct. + */ + public boolean verify(byte[] clientM1) + { + boolean valid = false; + // M1 = H(H(N) xor H(g) | H(U) | A | B | K) + M1 = clientHash.digest(); + if( log.isTraceEnabled() ) + { + log.trace("verify M1: "+CryptoUtil.tob64(M1)); + log.trace("verify clientM1: "+CryptoUtil.tob64(clientM1)); + } + if( Arrays.equals(clientM1, M1) ) + { + // serverHash = A | M + serverHash.update(M1); + // serverHash = A | M | K + serverHash.update(K); + if( log.isTraceEnabled() ) + { + MessageDigest tmp = CryptoUtil.copy(serverHash); + log.trace("H(A | M1 | K)"+CryptoUtil.tob64(tmp.digest())); + } + valid = true; + } + return valid; + } +} diff --git a/src/org/jboss/security/srp/SRPSessionKey.java b/src/org/jboss/security/srp/SRPSessionKey.java new file mode 100644 index 00000000..e0f21310 --- /dev/null +++ b/src/org/jboss/security/srp/SRPSessionKey.java @@ -0,0 +1,78 @@ +/* + * 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.srp; + +import java.io.Serializable; + +/* An encapsulation of an SRP username and session id. + * @author Scott.Stark@jboss.org + * @version $Revision: 81038 $ + */ +public class SRPSessionKey implements Serializable +{ + private static final long serialVersionUID = -7783783206948014409L; + public static final Integer NO_SESSION_ID = new Integer(0); + private String username; + private int sessionID; + + public SRPSessionKey(String username) + { + this(username, NO_SESSION_ID); + } + public SRPSessionKey(String username, int sessionID) + { + this.username = username; + this.sessionID = sessionID; + } + public SRPSessionKey(String username, Integer sessionID) + { + this.username = username; + if( sessionID != null ) + this.sessionID = sessionID.intValue(); + } + + public boolean equals(Object obj) + { + SRPSessionKey key = (SRPSessionKey) obj; + return this.username.equals(key.username) && this.sessionID == key.sessionID; + } + + public int hashCode() + { + return this.username.hashCode() + this.sessionID; + } + + public int getSessionID() + { + return sessionID; + } + + public String getUsername() + { + return username; + } + + public String toString() + { + return "{username="+username+", sessionID="+sessionID+"}"; + } +} diff --git a/src/org/jboss/security/srp/SRPVerifierStore.java b/src/org/jboss/security/srp/SRPVerifierStore.java new file mode 100644 index 00000000..b4487ddc --- /dev/null +++ b/src/org/jboss/security/srp/SRPVerifierStore.java @@ -0,0 +1,115 @@ +/* + * 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.srp; + +import java.io.IOException; +import java.io.Serializable; +import java.io.ObjectStreamField; +import java.security.KeyException; + +/** An interface describing the requirements of a password verifier store. +This is an abstraction that allows the information +needed by the server to be plugged in from various sources. E.g., LDAP +servers, databases, files, etc. + + @author Scott.Stark@jboss.org + @version $Revision: 81038 $ +*/ +public interface SRPVerifierStore +{ + public static class VerifierInfo implements Serializable + { + /** The serial version UID @since 1.2.4.1 */ + private static final long serialVersionUID = 7420301687504271098L; + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("username", String.class), + new ObjectStreamField("verifier", byte[].class), + new ObjectStreamField("salt", byte[].class), + new ObjectStreamField("g", byte[].class), + new ObjectStreamField("N", byte[].class), + new ObjectStreamField("hashAlgorithm", String.class), + new ObjectStreamField("cipherAlgorithm", String.class), + new ObjectStreamField("cipherIV", byte[].class) + }; + + /** The username the information applies to. Perhaps redundant but it + * makes the object self contained. + * @serialField username String username + */ + public String username; + /** The SRP password verifier hash + * @serialField verifier byte[] password verifier + */ + public byte[] verifier; + /** The random password salt originally used to verify the password + * @serialField salt originally used to verify the password + */ + public byte[] salt; + /** The SRP algorithm primitive generator + * @serialField g primitive generator + */ + public byte[] g; + /** The algorithm safe-prime modulus + * @serialField N safe-prime modulus + */ + public byte[] N; + /** The algorithm to hash the session key to produce K. To be consistent + with the RFC2945 description this must be SHA_Interleave as implemented + by the JBossSX security provider. For compatibility with earlier JBossSX + SRP releases the algorithm must be SHA_ReverseInterleave. This name is + passed to java.security.MessageDigest.getInstance(). + * @serialField hashAlgorithm algorithm to hash the session key + * @since 1.2.4.2 + */ + public String hashAlgorithm; + /** The algorithm to use for any encryption of data. + * @serialField cipherAlgorithm algorithm to use for any encryption + * @since 1.2.4.2 + */ + public String cipherAlgorithm; + /** The initialization vector to use for any encryption of data. + * @serialField cipherIV initialization vector to use for any encryption + * @since 1.6 + */ + public byte[] cipherIV; + } + + /** Get the indicated user's password verifier information. + */ + public VerifierInfo getUserVerifier(String username) + throws KeyException, IOException; + /** Set the indicated users' password verifier information. This is equivalent + to changing a user's password and should generally invalidate any existing + SRP sessions and caches. + */ + public void setUserVerifier(String username, VerifierInfo info) + throws IOException; + + /** Verify an optional auxillary challenge sent from the client to the server. The + * auxChallenge object will have been decrypted if it was sent encrypted from the + * client. An example of a auxillary challenge would be the validation of a hardware + * token (SafeWord, SecureID, iButton) that the server validates to further strengthen + * the SRP password exchange. + */ + public void verifyUserChallenge(String username, Object auxChallenge) + throws SecurityException; +} diff --git a/src/org/jboss/security/srp/SerialObjectStore.java b/src/org/jboss/security/srp/SerialObjectStore.java new file mode 100644 index 00000000..3170488f --- /dev/null +++ b/src/org/jboss/security/srp/SerialObjectStore.java @@ -0,0 +1,216 @@ +/* + * 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.srp; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.KeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.jboss.logging.Logger; +import org.jboss.crypto.CryptoUtil; +import org.jboss.security.srp.SRPConf; +import org.jboss.security.srp.SRPVerifierStore; +import org.jboss.security.srp.SRPVerifierStore.VerifierInfo; + +/** A simple implementation of the SRPVerifierStore that uses a +file store made up of VerifierInfo serialized objects. Users and +be added or removed using the addUser and delUser methods. User passwords +are never stored in plaintext either in memory or in the serialized file. +Note that usernames and passwords are logged when a user is added +via the addUser operation. This is a development class and its use in +a production environment is not advised. + +@see #addUser(String, String) +@see #delUser(String) + +@author Scott.Stark@jboss.org +@version $Revision: 81038 $ +*/ +public class SerialObjectStore implements SRPVerifierStore +{ + private static Logger log = Logger.getLogger(SerialObjectStore.class); + private Map infoMap; + private BigInteger g; + private BigInteger N; + + /** Create an in memory store and load any VerifierInfo found in + ./SerialObjectStore.ser if it exists. + */ + public SerialObjectStore() throws IOException + { + this(null); + } + /** Create an in memory store and load any VerifierInfo found in + the storeFile archive if it exists. + */ + public SerialObjectStore(File storeFile) throws IOException + { + if( storeFile == null ) + storeFile = new File("SerialObjectStore.ser"); + if( storeFile.exists() == true ) + { + FileInputStream fis = new FileInputStream(storeFile); + ObjectInputStream ois = new ObjectInputStream(fis); + try + { + infoMap = (Map) ois.readObject(); + } + catch(ClassNotFoundException e) + { + } + ois.close(); + fis.close(); + } + else + { + infoMap = Collections.synchronizedMap(new HashMap()); + } + + try + { + CryptoUtil.init(); + } + catch(NoSuchAlgorithmException e) + { + e.printStackTrace(); + throw new IOException("Failed to initialzed security utils: "+e.getMessage()); + } + N = SRPConf.getDefaultParams().N(); + g = SRPConf.getDefaultParams().g(); + log.trace("N: "+CryptoUtil.tob64(N.toByteArray())); + log.trace("g: "+CryptoUtil.tob64(g.toByteArray())); + byte[] hn = CryptoUtil.newDigest().digest(N.toByteArray()); + log.trace("H(N): "+CryptoUtil.tob64(hn)); + byte[] hg = CryptoUtil.newDigest().digest(g.toByteArray()); + log.trace("H(g): "+CryptoUtil.tob64(hg)); + } + +// --- Begin SRPVerifierStore interface methods + public VerifierInfo getUserVerifier(String username) throws KeyException, IOException + { + VerifierInfo info = null; + if( infoMap != null ) + info = (VerifierInfo) infoMap.get(username); + if( info == null ) + throw new KeyException("username: "+username+" not found"); + return info; + } + public void setUserVerifier(String username, VerifierInfo info) + { + infoMap.put(username, info); + } + + public void verifyUserChallenge(String username, Object auxChallenge) + throws SecurityException + { + throw new SecurityException("verifyUserChallenge not supported"); + } +// --- End SRPVerifierStore interface methods + + /** Save the current in memory map of VerifierInfo to the indicated + storeFile by simply serializing the map to the file. + */ + public void save(File storeFile) throws IOException + { + FileOutputStream fos = new FileOutputStream(storeFile); + ObjectOutputStream oos = new ObjectOutputStream(fos); + synchronized( infoMap ) + { + oos.writeObject(infoMap); + } + oos.close(); + fos.close(); + } + + public void addUser(String username, String password) + { + log.trace("addUser, username='"+username+"', password='"+password+"'"); + VerifierInfo info = new VerifierInfo(); + info.username = username; + /* + long r = Util.nextLong(); + String rs = Long.toHexString(r); + */ + String rs = "123456"; + info.salt = rs.getBytes(); + try + { + char[] pass = password.toCharArray(); + info.verifier = CryptoUtil.calculateVerifier(username, pass, + info.salt, N, g); + info.g = g.toByteArray(); + info.N = N.toByteArray(); + if( log.isTraceEnabled() ) + { + log.trace("N: "+CryptoUtil.tob64(info.N)); + log.trace("g: "+CryptoUtil.tob64(info.g)); + log.trace("s: "+CryptoUtil.tob64(info.salt)); + byte[] xb = CryptoUtil.calculatePasswordHash(username, pass, info.salt); + log.trace("x: "+CryptoUtil.tob64(xb)); + log.trace("v: "+CryptoUtil.tob64(info.verifier)); + byte[] hn = CryptoUtil.newDigest().digest(info.N); + log.trace("H(N): "+CryptoUtil.tob64(hn)); + byte[] hg = CryptoUtil.newDigest().digest(info.g); + log.trace("H(g): "+CryptoUtil.tob64(hg)); + } + } + catch(Throwable t) + { + log.error("Failed to calculate verifier", t); + return; + } + + setUserVerifier(username, info); + } + public void delUser(String username) + { + infoMap.remove(username); + } + + public static void main(String[] args) throws IOException + { + File storeFile = new File("SerialObjectStore.ser"); + SerialObjectStore store = new SerialObjectStore(); + + for(int a = 0; a < args.length; a ++) + { + if( args[a].startsWith("-a") ) + { + store.addUser(args[a+1], args[a+2]); + } + else if( args[a].startsWith("-d") ) + { + store.delUser(args[a+1]); + } + } + store.save(storeFile); + } +} -- cgit v1.2.3 From 49747e858649fa7ed68e4a038d5602ec2bae6df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 12 Mar 2013 19:14:10 +0100 Subject: Error using CryptoUtil.calculatePasswordHash. Going to hit some bugs before continuing with this work. --- src/org/jboss/security/srp/SRPClientSession.java | 2 +- src/org/jboss/security/srp/SRPConf.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/org/jboss/security') diff --git a/src/org/jboss/security/srp/SRPClientSession.java b/src/org/jboss/security/srp/SRPClientSession.java index bafc4842..c6bc1f35 100644 --- a/src/org/jboss/security/srp/SRPClientSession.java +++ b/src/org/jboss/security/srp/SRPClientSession.java @@ -27,7 +27,7 @@ import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.jboss.crypto.CryptoUtil; -import org.jboss.logging.Logger; +import org.jboss.logging.Logger; /** The client side logic to the SRP protocol. The class is intended to be used * with a SRPServerSession object via the SRPServerInterface. The SRP algorithm diff --git a/src/org/jboss/security/srp/SRPConf.java b/src/org/jboss/security/srp/SRPConf.java index c9b69428..2c9bd4af 100644 --- a/src/org/jboss/security/srp/SRPConf.java +++ b/src/org/jboss/security/srp/SRPConf.java @@ -96,6 +96,8 @@ public class SRPConf "2", null), new SRPParams("2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp", "2", null), + new SRPParams("2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp", + "2", null), }; public int getPredefinedCount() -- cgit v1.2.3 From 57ab546646e3e2814be547dd4666ca2de4548597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 19 Mar 2013 16:29:09 +0100 Subject: Trying to find a jar from JBoss to use their SRP implementation. Imports errors because of classes not yet found. --- src/org/jboss/security/srp/SRPClientSession.java | 289 ---------------------- src/org/jboss/security/srp/SRPConf.java | 115 --------- src/org/jboss/security/srp/SRPParameters.java | 150 ----------- src/org/jboss/security/srp/SRPPermission.java | 66 ----- src/org/jboss/security/srp/SRPServerListener.java | 42 ---- src/org/jboss/security/srp/SRPServerSession.java | 285 --------------------- src/org/jboss/security/srp/SRPSessionKey.java | 78 ------ src/org/jboss/security/srp/SRPVerifierStore.java | 115 --------- src/org/jboss/security/srp/SerialObjectStore.java | 216 ---------------- 9 files changed, 1356 deletions(-) delete mode 100644 src/org/jboss/security/srp/SRPClientSession.java delete mode 100644 src/org/jboss/security/srp/SRPConf.java delete mode 100644 src/org/jboss/security/srp/SRPParameters.java delete mode 100644 src/org/jboss/security/srp/SRPPermission.java delete mode 100644 src/org/jboss/security/srp/SRPServerListener.java delete mode 100644 src/org/jboss/security/srp/SRPServerSession.java delete mode 100644 src/org/jboss/security/srp/SRPSessionKey.java delete mode 100644 src/org/jboss/security/srp/SRPVerifierStore.java delete mode 100644 src/org/jboss/security/srp/SerialObjectStore.java (limited to 'src/org/jboss/security') diff --git a/src/org/jboss/security/srp/SRPClientSession.java b/src/org/jboss/security/srp/SRPClientSession.java deleted file mode 100644 index c6bc1f35..00000000 --- a/src/org/jboss/security/srp/SRPClientSession.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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.srp; - -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import org.jboss.crypto.CryptoUtil; -import org.jboss.logging.Logger; - -/** The client side logic to the SRP protocol. The class is intended to be used - * with a SRPServerSession object via the SRPServerInterface. The SRP algorithm - * using these classes consists of: - * - * 1. Get server, SRPServerInterface server = (SRPServerInterface) Naming.lookup(...); - * 2. Get SRP parameters, SRPParameters params = server.getSRPParameters(username); - * 3. Create a client session, SRPClientSession client = new SRPClientSession(username, - * password, params); - * 4. Exchange public keys, byte[] A = client.exponential(); - * byte[] B = server.init(username, A); - * 5. Exchange challenges, byte[] M1 = client.response(B); - * byte[] M2 = server.verify(username, M1); - * 6. Verify the server response, if( client.verify(M2) == false ) - * throw new SecurityException("Failed to validate server reply"); - * 7. Validation complete - * - * Note that these steps are stateful. They must be performed in order and a - * step cannot be repeated to update the session state. - * - * This product uses the 'Secure Remote Password' cryptographic - * authentication system developed by Tom Wu (tjw@CS.Stanford.EDU). - * - * @author Scott.Stark@jboss.org - * @version $Revision: 81038 $ - */ -public class SRPClientSession -{ - private static Logger log = Logger.getLogger(SRPClientSession.class); - private SRPParameters params; - private BigInteger N; - private BigInteger g; - private BigInteger x; - private BigInteger v; - private byte[] s; - private BigInteger a; - private BigInteger A; - private byte[] K; - /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */ - private MessageDigest clientHash; - /** The M2 = H(A | M | K) hash */ - private MessageDigest serverHash; - - private static int A_LEN = 64; - - /** Creates a new SRP server session object from the username, password - verifier, - @param username, the user ID - @param password, the user clear text password - @param params, the SRP parameters for the session - */ - public SRPClientSession(String username, char[] password, SRPParameters params) - { - this(username, password, params, null); - } - - /** Creates a new SRP server session object from the username, password - verifier, - @param username, the user ID - @param password, the user clear text password - @param params, the SRP parameters for the session - @param abytes, the random exponent used in the A public key. This must be - 8 bytes in length. - */ - public SRPClientSession(String username, char[] password, SRPParameters params, - byte[] abytes) - { - try - { - // Initialize the secure random number and message digests - CryptoUtil.init(); - } - catch(NoSuchAlgorithmException e) - { - } - this.params = params; - this.g = new BigInteger(1, params.g); - this.N = new BigInteger(1, params.N); - if( abytes != null ) - { - if( 8*abytes.length != A_LEN ) - throw new IllegalArgumentException("The abytes param must be " - +(A_LEN/8)+" in length, abytes.length="+abytes.length); - this.a = new BigInteger(abytes); - } - - if( log.isTraceEnabled() ) - log.trace("g: "+CryptoUtil.tob64(params.g)); - // Calculate x = H(s | H(U | ':' | password)) - byte[] xb = CryptoUtil.calculatePasswordHash(username, password, params.s); - if( log.isTraceEnabled() ) - log.trace("x: "+CryptoUtil.tob64(xb)); - this.x = new BigInteger(1, xb); - this.v = g.modPow(x, N); // g^x % N - if( log.isTraceEnabled() ) - log.trace("v: "+CryptoUtil.tob64(v.toByteArray())); - - serverHash = CryptoUtil.newDigest(); - clientHash = CryptoUtil.newDigest(); - // H(N) - byte[] hn = CryptoUtil.newDigest().digest(params.N); - if( log.isTraceEnabled() ) - log.trace("H(N): "+CryptoUtil.tob64(hn)); - // H(g) - byte[] hg = CryptoUtil.newDigest().digest(params.g); - if( log.isTraceEnabled() ) - log.trace("H(g): "+CryptoUtil.tob64(hg)); - // clientHash = H(N) xor H(g) - byte[] hxg = CryptoUtil.xor(hn, hg, 20); - if( log.isTraceEnabled() ) - log.trace("H(N) xor H(g): "+CryptoUtil.tob64(hxg)); - clientHash.update(hxg); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g)]: "+CryptoUtil.tob64(tmp.digest())); - } - // clientHash = H(N) xor H(g) | H(U) - clientHash.update(CryptoUtil.newDigest().digest(username.getBytes())); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U)]: "+CryptoUtil.tob64(tmp.digest())); - } - // clientHash = H(N) xor H(g) | H(U) | s - clientHash.update(params.s); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s]: "+CryptoUtil.tob64(tmp.digest())); - } - K = null; - } - - /** - * @returns The exponential residue (parameter A) to be sent to the server. - */ - public byte[] exponential() - { - byte[] Abytes = null; - if(A == null) - { - /* If the random component of A has not been specified use a random - number */ - if( a == null ) - { - BigInteger one = BigInteger.ONE; - do - { - a = new BigInteger(A_LEN, CryptoUtil.getPRNG()); - } while(a.compareTo(one) <= 0); - } - A = g.modPow(a, N); - Abytes = CryptoUtil.trim(A.toByteArray()); - // clientHash = H(N) xor H(g) | H(U) | A - clientHash.update(Abytes); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s | A]: "+CryptoUtil.tob64(tmp.digest())); - } - // serverHash = A - serverHash.update(Abytes); - } - return Abytes; - } - - /** - @returns M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) - @exception NoSuchAlgorithmException thrown if the session key - MessageDigest algorithm cannot be found. - */ - public byte[] response(byte[] Bbytes) throws NoSuchAlgorithmException - { - // clientHash = H(N) xor H(g) | H(U) | s | A | B - clientHash.update(Bbytes); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s | A | B]: "+CryptoUtil.tob64(tmp.digest())); - } - // Calculate u as the first 32 bits of H(B) - byte[] hB = CryptoUtil.newDigest().digest(Bbytes); - byte[] ub = - {hB[0], hB[1], hB[2], hB[3]}; - // Calculate S = (B - g^x) ^ (a + u * x) % N - BigInteger B = new BigInteger(1, Bbytes); - if( log.isTraceEnabled() ) - log.trace("B: "+CryptoUtil.tob64(B.toByteArray())); - if( B.compareTo(v) < 0 ) - B = B.add(N); - if( log.isTraceEnabled() ) - log.trace("B': "+CryptoUtil.tob64(B.toByteArray())); - if( log.isTraceEnabled() ) - log.trace("v: "+CryptoUtil.tob64(v.toByteArray())); - BigInteger u = new BigInteger(1, ub); - if( log.isTraceEnabled() ) - log.trace("u: "+CryptoUtil.tob64(u.toByteArray())); - BigInteger B_v = B.subtract(v); - if( log.isTraceEnabled() ) - log.trace("B - v: "+CryptoUtil.tob64(B_v.toByteArray())); - BigInteger a_ux = a.add(u.multiply(x)); - if( log.isTraceEnabled() ) - log.trace("a + u * x: "+CryptoUtil.tob64(a_ux.toByteArray())); - BigInteger S = B_v.modPow(a_ux, N); - if( log.isTraceEnabled() ) - log.trace("S: "+CryptoUtil.tob64(S.toByteArray())); - // K = SessionHash(S) - MessageDigest sessionDigest = MessageDigest.getInstance(params.hashAlgorithm); - K = sessionDigest.digest(S.toByteArray()); - if( log.isTraceEnabled() ) - log.trace("K: "+CryptoUtil.tob64(K)); - // clientHash = H(N) xor H(g) | H(U) | A | B | K - clientHash.update(K); - byte[] M1 = clientHash.digest(); - if( log.isTraceEnabled() ) - log.trace("M1: H[H(N) xor H(g) | H(U) | s | A | B | K]: "+CryptoUtil.tob64(M1)); - serverHash.update(M1); - serverHash.update(K); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(serverHash); - log.trace("H[A | M1 | K]: "+CryptoUtil.tob64(tmp.digest())); - } - return M1; - } - /** - * @param M2 The server's response to the client's challenge - * @returns True if and only if the server's response was correct. - */ - public boolean verify(byte[] M2) - { - // M2 = H(A | M1 | K) - byte[] myM2 = serverHash.digest(); - boolean valid = Arrays.equals(M2, myM2); - if( log.isTraceEnabled() ) - { - log.trace("verify serverM2: "+CryptoUtil.tob64(M2)); - log.trace("verify M2: "+CryptoUtil.tob64(myM2)); - } - return valid; - } - - /** Returns the negotiated session K, K = SHA_Interleave(S) - @return the private session K byte[] - @throws SecurityException - if the current thread does not have an - getSessionKey SRPPermission. - */ - public byte[] getSessionKey() throws SecurityException - { - SecurityManager sm = System.getSecurityManager(); - if( sm != null ) - { - SRPPermission p = new SRPPermission("getSessionKey"); - sm.checkPermission(p); - } - return K; - } -} diff --git a/src/org/jboss/security/srp/SRPConf.java b/src/org/jboss/security/srp/SRPConf.java deleted file mode 100644 index 2c9bd4af..00000000 --- a/src/org/jboss/security/srp/SRPConf.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.srp; - -import java.math.BigInteger; - -import org.jboss.crypto.CryptoUtil; - -/** A port of the libsrp/t_conf.c predefined constants for the N & g parameters -of the SRP algorithm. It contains a collection of "good" primes for N and the -corresponding the corresponding generator g. - -This product includes software developed by Tom Wu and Eugene -Jhong for the SRP Distribution (http://srp.stanford.edu/srp/). - -@author Scott.Stark@jboss.org -@version $Revision: 81038 $ -*/ -public class SRPConf -{ - /* Master builtin parameter storage object */ - public static class SRPParams - { - String modb64; - String genb64; - String comment; - BigInteger N; - BigInteger g; - SRPParams(String modb64, String genb64, String comment) - { - this.modb64 = modb64; - this.genb64 = genb64; - this.comment = comment; - } - public byte[] Nbytes() - { - return CryptoUtil.fromb64(modb64); - } - public byte[] gbytes() - { - return CryptoUtil.fromb64(genb64); - } - public BigInteger N() - { - if( N == null ) - N = new BigInteger(1, CryptoUtil.fromb64(modb64)); - return N; - } - public BigInteger g() - { - if( g == null ) - g = new BigInteger(1, CryptoUtil.fromb64(genb64)); - return g; - } - public String getComment() - { - return comment; - } - } - - static SRPParams[] pre_params = { - new SRPParams("3Kn/YYiomHkFkfM1x4kayR125MGkzpLUDy3y14FlTMwYnhZkjrMXnoC2TcFAecNlU5kFzgcpKYUbBOPZFRtyf3", - "2", null), - new SRPParams("CbDP.jR6YD6wAj2ByQWxQxQZ7.9J9xkn2.Uqb3zVm16vQyizprhBw9hi80psatZ8k54vwZfiIeEHZVsDnyqeWSSIpWso.wh5GD4OFgdhVI3", - "2", null), - new SRPParams("iqJ7nFZ4bGCRjE1F.FXEwL085Zb0kLM2TdHDaVVCdq0cKxvnH/0FLskJTKlDtt6sDl89dc//aEULTVFGtcbA/tDzc.bnFE.DWthQOu2n2JwKjgKfgCR2lZFWXdnWmoOh", - "2", null), - new SRPParams("///////////93zgY8MZ2DCJ6Oek0t1pHAG9E28fdp7G22xwcEnER8b5A27cED0JTxvKPiyqwGnimAmfjybyKDq/XDMrjKS95v8MrTc9UViRqJ4BffZes8F//////////", - "7", "oakley prime 1"), - new SRPParams("Ewl2hcjiutMd3Fu2lgFnUXWSc67TVyy2vwYCKoS9MLsrdJVT9RgWTCuEqWJrfB6uE3LsE9GkOlaZabS7M29sj5TnzUqOLJMjiwEzArfiLr9WbMRANlF68N5AVLcPWvNx6Zjl3m5Scp0BzJBz9TkgfhzKJZ.WtP3Mv/67I/0wmRZ", - "2", null), - new SRPParams("F//////////oG/QeY5emZJ4ncABWDmSqIa2JWYAPynq0Wk.fZiJco9HIWXvZZG4tU.L6RFDEaCRC2iARV9V53TFuJLjRL72HUI5jNPYNdx6z4n2wQOtxMiB/rosz0QtxUuuQ/jQYP.bhfya4NnB7.P9A6PHxEPJWV//////////", - "5", "oakley prime 2"), - new SRPParams("3NUKQ2Re4P5BEK0TLg2dX3gETNNNECPoe92h4OVMaDn3Xo/0QdjgG/EvM.hiVV1BdIGklSI14HA38Mpe5k04juR5/EXMU0r1WtsLhNXwKBlf2zEfoOh0zVmDvqInpU695f29Iy7sNW3U5RIogcs740oUp2Kdv5wuITwnIx84cnO.e467/IV1lPnvMCr0pd1dgS0a.RV5eBJr03Q65Xy61R", - "2", null), - new SRPParams("dUyyhxav9tgnyIg65wHxkzkb7VIPh4o0lkwfOKiPp4rVJrzLRYVBtb76gKlaO7ef5LYGEw3G.4E0jbMxcYBetDy2YdpiP/3GWJInoBbvYHIRO9uBuxgsFKTKWu7RnR7yTau/IrFTdQ4LY/q.AvoCzMxV0PKvD9Odso/LFIItn8PbTov3VMn/ZEH2SqhtpBUkWtmcIkEflhX/YY/fkBKfBbe27/zUaKUUZEUYZ2H2nlCL60.JIPeZJSzsu/xHDVcx", - "2", null), - new SRPParams("2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp", - "2", null), - new SRPParams("2iQzj1CagQc/5ctbuJYLWlhtAsPHc7xWVyCPAKFRLWKADpASkqe9djWPFWTNTdeJtL8nAhImCn3Sr/IAdQ1FrGw0WvQUstPx3FO9KNcXOwisOQ1VlL.gheAHYfbYyBaxXL.NcJx9TUwgWDT0hRzFzqSrdGGTN3FgSTA1v4QnHtEygNj3eZ.u0MThqWUaDiP87nqha7XnT66bkTCkQ8.7T8L4KZjIImrNrUftedTTBi.WCi.zlrBxDuOM0da0JbUkQlXqvp0yvJAPpC11nxmmZOAbQOywZGmu9nhZNuwTlxjfIro0FOdthaDTuZRL9VL7MRPUDo/DQEyW.d4H.UIlzp", - "2", null), - }; - - public int getPredefinedCount() - { - return pre_params.length; - } - public static SRPParams getPredefinedParams(int n) - { - return pre_params[n]; - } - public static SRPParams getDefaultParams() - { - return pre_params[6]; - } -} diff --git a/src/org/jboss/security/srp/SRPParameters.java b/src/org/jboss/security/srp/SRPParameters.java deleted file mode 100644 index 43e2dad2..00000000 --- a/src/org/jboss/security/srp/SRPParameters.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.srp; - -import java.io.Serializable; -import java.util.Arrays; - -import org.jboss.crypto.CryptoUtil; - -/** The RFC2945 algorithm session parameters that the client and server -agree to use. In addition to the base RFC2945 parameters, one can choose an -alternate hash algorithm for the private session key. - -@author Scott.Stark@jboss.org -@version $Revision: 81038 $ -*/ -public class SRPParameters implements Cloneable, Serializable -{ - /** The serial version ID. - * @since 1.2.4.1 - */ - private static final long serialVersionUID = 6438772808805276693L; - - /** The algorithm safe-prime modulus */ - public final byte[] N; - /** The algorithm primitive generator */ - public final byte[] g; - /** The random password salt originally used to verify the password */ - public final byte[] s; - /** The algorithm to hash the session key to produce K. To be consistent - with the RFC2945 description this must be SHA_Interleave as implemented - by the JBossSX security provider. For compatibility with earlier JBossSX - SRP releases the algorithm must be SHA_ReverseInterleave. This name is - passed to java.security.MessageDigest.getInstance(). */ - public final String hashAlgorithm; - /** The algorithm to use for any encryption of data. - */ - public final String cipherAlgorithm; - /** The cipher intialization vector bytes - */ - public byte[] cipherIV; - - /** Creates a new instance of SRPParameters */ - public SRPParameters(byte[] N, byte[] g, byte[] s) - { - this(N, g, s, "SHA_Interleave", null); - } - public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm) - { - this(N, g, s, hashAlgorithm, null); - } - public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm, - String cipherAlgorithm) - { - this(N, g, s, hashAlgorithm, cipherAlgorithm, null); - } - public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm, - String cipherAlgorithm, byte[] cipherIV) - { - this.N = N; - this.g = g; - this.s = s; - if( hashAlgorithm == null ) - hashAlgorithm = "SHA_Interleave"; - this.hashAlgorithm = hashAlgorithm; - this.cipherAlgorithm = cipherAlgorithm; - this.cipherIV = cipherIV; - } - - public Object clone() - { - Object clone = null; - try - { - clone = super.clone(); - } - catch(CloneNotSupportedException e) - { - } - return clone; - } - - public int hashCode() - { - int hashCode = hashAlgorithm.hashCode(); - for(int i = 0; i < N.length; i ++) - hashCode += N[i]; - for(int i = 0; i < g.length; i ++) - hashCode += g[i]; - for(int i = 0; i < s.length; i ++) - hashCode += s[i]; - return hashCode; - } - - public boolean equals(Object obj) - { - boolean equals = false; - if( obj instanceof SRPParameters ) - { - SRPParameters p = (SRPParameters) obj; - equals = hashAlgorithm.equals(p.hashAlgorithm); - if( equals == true ) - equals = Arrays.equals(N, p.N); - if( equals == true ) - equals = Arrays.equals(g, p.g); - if( equals == true ) - equals = Arrays.equals(s, p.s); - } - return equals; - } - - public String toString() - { - StringBuffer tmp = new StringBuffer(super.toString()); - tmp.append('{'); - tmp.append("N: "); - tmp.append(CryptoUtil.encodeBase64(N)); - tmp.append("|g: "); - tmp.append(CryptoUtil.encodeBase64(g)); - tmp.append("|s: "); - tmp.append(CryptoUtil.encodeBase64(s)); - tmp.append("|hashAlgorithm: "); - tmp.append(hashAlgorithm); - tmp.append("|cipherAlgorithm: "); - tmp.append(cipherAlgorithm); - tmp.append("|cipherIV: "); - tmp.append(cipherIV); - tmp.append('}'); - return tmp.toString(); - } -} diff --git a/src/org/jboss/security/srp/SRPPermission.java b/src/org/jboss/security/srp/SRPPermission.java deleted file mode 100644 index d1a77d64..00000000 --- a/src/org/jboss/security/srp/SRPPermission.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.srp; - -import java.security.BasicPermission; - -/** A custom permission class for protecting access to sensitive SRP information -like the private session key and private key. - -The following table lists all the possible SRPPermission target names, -and for each provides a description of what the permission allows -and a discussion of the risks of granting code the permission. - - - - - - - - - - - - - -
Permission Target NameWhat the Permission AllowsRisks of Allowing this Permission
getSessionKeyAccess the private SRP session keyThis provides access the the private session key that results from -the SRP negiotation. Access to this key will allow one to encrypt/decrypt msgs -that have been encrypted with the session key. -
- -@author Scott.Stark@jboss.org -@version $Revision: 81038 $ -*/ -public class SRPPermission extends BasicPermission -{ - - /** Creates new SRPPermission */ - public SRPPermission(String name) - { - super(name); - } - public SRPPermission(String name, String actions) - { - super(name, actions); - } - -} diff --git a/src/org/jboss/security/srp/SRPServerListener.java b/src/org/jboss/security/srp/SRPServerListener.java deleted file mode 100644 index a9e22cbb..00000000 --- a/src/org/jboss/security/srp/SRPServerListener.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.srp; - -/** A callback interface for SRP session events. - -@author Scott.Stark@jboss.org -@version $Revision: 81038 $ -*/ -public interface SRPServerListener -{ - /** Called when a user has successfully completed the SRP handshake and any auxillary - * challenge verification. - * @param key, the {username, sessionID} pair - * @param session, the server SRP session information - */ - public void verifiedUser(SRPSessionKey key, SRPServerSession session); - /** Called when a user requests that a session be closed - * - * @param key, the {username, sessionID} pair - */ - public void closedUserSession(SRPSessionKey key); -} diff --git a/src/org/jboss/security/srp/SRPServerSession.java b/src/org/jboss/security/srp/SRPServerSession.java deleted file mode 100644 index 11dc6d4c..00000000 --- a/src/org/jboss/security/srp/SRPServerSession.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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.srp; - -import java.io.Serializable; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -import org.jboss.logging.Logger; -import org.jboss.crypto.CryptoUtil; - -/** The server side logic to the SRP protocol. The class is the server side - equivalent of the SRPClientSession object. An implementation of - SRPServerInterface creates an SRPServerSession on the start of a login - session. - - The client side algorithm using these classes consists of: - - 1. Get server, SRPServerInterface server = (SRPServerInterface) Naming.lookup(...); - 2. Get SRP parameters, SRPParameters params = server.getSRPParameters(username); - 3. Create a client session, SRPClientSession client = new SRPClientSession(username, password, params); - 4. Exchange public keys, byte[] A = client.exponential(); - byte[] B = server.init(username, A); - 5. Exchange challenges, byte[] M1 = client.response(B); - byte[] M2 = server.verify(username, M1); - 6. Verify the server response, if( client.verify(M2) == false ) - throw new SecurityException("Failed to validate server reply"); - 7. Validation complete - - Note that these steps are stateful. They must be performed in order and a - step cannot be repeated to update the session state. - - This product uses the 'Secure Remote Password' cryptographic - authentication system developed by Tom Wu (tjw@CS.Stanford.EDU). - - @author Scott.Stark@jboss.org - @version $Revision: 81038 $ - */ -public class SRPServerSession implements Serializable -{ - /** The serial version ID - @since 1.6 - */ - static final long serialVersionUID = -2448005747721323704L; - private static int B_LEN = 64; // 64 bits for 'b' - private static Logger log = Logger.getLogger(SRPServerSession.class); - - private SRPParameters params; - private BigInteger N; - private BigInteger g; - private BigInteger v; - private BigInteger b; - private BigInteger B; - private byte[] K; - /** The M1 = H(H(N) xor H(g) | H(U) | s | A | B | K) hash */ - private transient MessageDigest clientHash; - private byte[] M1; - /** The M2 = H(A | M | K) hash */ - private transient MessageDigest serverHash; - private byte[] M2; - - /** Creates a new SRP server session object from the username, password - verifier, and session parameters. - @param username, the user ID - @param vb, the password verifier byte sequence - @param params, the SRP parameters for the session - */ - public SRPServerSession(String username, byte[] vb, SRPParameters params) - { - this.params = params; - this.v = new BigInteger(1, vb); - this.g = new BigInteger(1, params.g); - this.N = new BigInteger(1, params.N); - if( log.isTraceEnabled() ) - log.trace("g: "+CryptoUtil.tob64(params.g)); - if( log.isTraceEnabled() ) - log.trace("v: "+CryptoUtil.tob64(vb)); - serverHash = CryptoUtil.newDigest(); - clientHash = CryptoUtil.newDigest(); - // H(N) - byte[] hn = CryptoUtil.newDigest().digest(params.N); - if( log.isTraceEnabled() ) - log.trace("H(N): "+CryptoUtil.tob64(hn)); - // H(g) - byte[] hg = CryptoUtil.newDigest().digest(params.g); - if( log.isTraceEnabled() ) - log.trace("H(g): "+CryptoUtil.tob64(hg)); - // clientHash = H(N) xor H(g) - byte[] hxg = CryptoUtil.xor(hn, hg, 20); - if( log.isTraceEnabled() ) - log.trace("H(N) xor H(g): "+CryptoUtil.tob64(hxg)); - clientHash.update(hxg); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g)]: "+CryptoUtil.tob64(tmp.digest())); - } - // clientHash = H(N) xor H(g) | H(U) - clientHash.update(CryptoUtil.newDigest().digest(username.getBytes())); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U)]: "+CryptoUtil.tob64(tmp.digest())); - } - // clientHash = H(N) xor H(g) | H(U) | s - clientHash.update(params.s); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s]: "+CryptoUtil.tob64(tmp.digest())); - } - K = null; - } - - /** - * @returns The user's password salt - */ - public SRPParameters getParameters() - { - return params; - } - - /** - * @returns The exponential residue (parameter B) to be sent to the - * client. - */ - public byte[] exponential() - { - if(B == null) - { - BigInteger one = BigInteger.valueOf(1); - do - { - b = new BigInteger(B_LEN, CryptoUtil.getPRNG()); - } while(b.compareTo(one) <= 0); - B = v.add(g.modPow(b, N)); - if(B.compareTo(N) >= 0) - B = B.subtract(N); - } - return CryptoUtil.trim(B.toByteArray()); - } - - /** - @param ab The client's exponential (parameter A). - @returns The secret shared session K between client and server - @exception NoSuchAlgorithmException thrown if the session key - MessageDigest algorithm cannot be found. - */ - public void buildSessionKey(byte[] ab) throws NoSuchAlgorithmException - { - if( log.isTraceEnabled() ) - log.trace("A: "+CryptoUtil.tob64(ab)); - byte[] nb = CryptoUtil.trim(B.toByteArray()); - // clientHash = H(N) xor H(g) | H(U) | s | A - clientHash.update(ab); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s | A]: "+CryptoUtil.tob64(tmp.digest())); - } - // clientHash = H(N) xor H(g) | H(U) | A | B - clientHash.update(nb); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s | A | B]: "+CryptoUtil.tob64(tmp.digest())); - } - // serverHash = A - serverHash.update(ab); - // Calculate u as the first 32 bits of H(B) - byte[] hB = CryptoUtil.newDigest().digest(nb); - byte[] ub = - {hB[0], hB[1], hB[2], hB[3]}; - // Calculate S = (A * v^u) ^ b % N - BigInteger A = new BigInteger(1, ab); - if( log.isTraceEnabled() ) - log.trace("A: "+CryptoUtil.tob64(A.toByteArray())); - if( log.isTraceEnabled() ) - log.trace("B: "+CryptoUtil.tob64(B.toByteArray())); - if( log.isTraceEnabled() ) - log.trace("v: "+CryptoUtil.tob64(v.toByteArray())); - BigInteger u = new BigInteger(1, ub); - if( log.isTraceEnabled() ) - log.trace("u: "+CryptoUtil.tob64(u.toByteArray())); - BigInteger A_v2u = A.multiply(v.modPow(u, N)).mod(N); - if( log.isTraceEnabled() ) - log.trace("A * v^u: "+CryptoUtil.tob64(A_v2u.toByteArray())); - BigInteger S = A_v2u.modPow(b, N); - if( log.isTraceEnabled() ) - log.trace("S: "+CryptoUtil.tob64(S.toByteArray())); - // K = SessionHash(S) - MessageDigest sessionDigest = MessageDigest.getInstance(params.hashAlgorithm); - K = sessionDigest.digest(S.toByteArray()); - if( log.isTraceEnabled() ) - log.trace("K: "+CryptoUtil.tob64(K)); - // clientHash = H(N) xor H(g) | H(U) | A | B | K - clientHash.update(K); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(clientHash); - log.trace("H[H(N) xor H(g) | H(U) | s | A | B | K]: "+CryptoUtil.tob64(tmp.digest())); - } - } - - /** Returns the negotiated session K, K = SessionHash(S) - @return the private session K byte[] - @throws SecurityException - if the current thread does not have an - getSessionKey SRPPermission. - */ - public byte[] getSessionKey() throws SecurityException - { - SecurityManager sm = System.getSecurityManager(); - if( sm != null ) - { - SRPPermission p = new SRPPermission("getSessionKey"); - sm.checkPermission(p); - } - return K; - } - - /** - @returns M2 = H(A | M | K) - */ - public byte[] getServerResponse() - { - if( M2 == null ) - M2 = serverHash.digest(); - return M2; - } - public byte[] getClientResponse() - { - return M1; - } - - /** - * @param resp The client's response to the server's challenge - * @returns True if and only if the client's response was correct. - */ - public boolean verify(byte[] clientM1) - { - boolean valid = false; - // M1 = H(H(N) xor H(g) | H(U) | A | B | K) - M1 = clientHash.digest(); - if( log.isTraceEnabled() ) - { - log.trace("verify M1: "+CryptoUtil.tob64(M1)); - log.trace("verify clientM1: "+CryptoUtil.tob64(clientM1)); - } - if( Arrays.equals(clientM1, M1) ) - { - // serverHash = A | M - serverHash.update(M1); - // serverHash = A | M | K - serverHash.update(K); - if( log.isTraceEnabled() ) - { - MessageDigest tmp = CryptoUtil.copy(serverHash); - log.trace("H(A | M1 | K)"+CryptoUtil.tob64(tmp.digest())); - } - valid = true; - } - return valid; - } -} diff --git a/src/org/jboss/security/srp/SRPSessionKey.java b/src/org/jboss/security/srp/SRPSessionKey.java deleted file mode 100644 index e0f21310..00000000 --- a/src/org/jboss/security/srp/SRPSessionKey.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.srp; - -import java.io.Serializable; - -/* An encapsulation of an SRP username and session id. - * @author Scott.Stark@jboss.org - * @version $Revision: 81038 $ - */ -public class SRPSessionKey implements Serializable -{ - private static final long serialVersionUID = -7783783206948014409L; - public static final Integer NO_SESSION_ID = new Integer(0); - private String username; - private int sessionID; - - public SRPSessionKey(String username) - { - this(username, NO_SESSION_ID); - } - public SRPSessionKey(String username, int sessionID) - { - this.username = username; - this.sessionID = sessionID; - } - public SRPSessionKey(String username, Integer sessionID) - { - this.username = username; - if( sessionID != null ) - this.sessionID = sessionID.intValue(); - } - - public boolean equals(Object obj) - { - SRPSessionKey key = (SRPSessionKey) obj; - return this.username.equals(key.username) && this.sessionID == key.sessionID; - } - - public int hashCode() - { - return this.username.hashCode() + this.sessionID; - } - - public int getSessionID() - { - return sessionID; - } - - public String getUsername() - { - return username; - } - - public String toString() - { - return "{username="+username+", sessionID="+sessionID+"}"; - } -} diff --git a/src/org/jboss/security/srp/SRPVerifierStore.java b/src/org/jboss/security/srp/SRPVerifierStore.java deleted file mode 100644 index b4487ddc..00000000 --- a/src/org/jboss/security/srp/SRPVerifierStore.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.srp; - -import java.io.IOException; -import java.io.Serializable; -import java.io.ObjectStreamField; -import java.security.KeyException; - -/** An interface describing the requirements of a password verifier store. -This is an abstraction that allows the information -needed by the server to be plugged in from various sources. E.g., LDAP -servers, databases, files, etc. - - @author Scott.Stark@jboss.org - @version $Revision: 81038 $ -*/ -public interface SRPVerifierStore -{ - public static class VerifierInfo implements Serializable - { - /** The serial version UID @since 1.2.4.1 */ - private static final long serialVersionUID = 7420301687504271098L; - private static final ObjectStreamField[] serialPersistentFields = { - new ObjectStreamField("username", String.class), - new ObjectStreamField("verifier", byte[].class), - new ObjectStreamField("salt", byte[].class), - new ObjectStreamField("g", byte[].class), - new ObjectStreamField("N", byte[].class), - new ObjectStreamField("hashAlgorithm", String.class), - new ObjectStreamField("cipherAlgorithm", String.class), - new ObjectStreamField("cipherIV", byte[].class) - }; - - /** The username the information applies to. Perhaps redundant but it - * makes the object self contained. - * @serialField username String username - */ - public String username; - /** The SRP password verifier hash - * @serialField verifier byte[] password verifier - */ - public byte[] verifier; - /** The random password salt originally used to verify the password - * @serialField salt originally used to verify the password - */ - public byte[] salt; - /** The SRP algorithm primitive generator - * @serialField g primitive generator - */ - public byte[] g; - /** The algorithm safe-prime modulus - * @serialField N safe-prime modulus - */ - public byte[] N; - /** The algorithm to hash the session key to produce K. To be consistent - with the RFC2945 description this must be SHA_Interleave as implemented - by the JBossSX security provider. For compatibility with earlier JBossSX - SRP releases the algorithm must be SHA_ReverseInterleave. This name is - passed to java.security.MessageDigest.getInstance(). - * @serialField hashAlgorithm algorithm to hash the session key - * @since 1.2.4.2 - */ - public String hashAlgorithm; - /** The algorithm to use for any encryption of data. - * @serialField cipherAlgorithm algorithm to use for any encryption - * @since 1.2.4.2 - */ - public String cipherAlgorithm; - /** The initialization vector to use for any encryption of data. - * @serialField cipherIV initialization vector to use for any encryption - * @since 1.6 - */ - public byte[] cipherIV; - } - - /** Get the indicated user's password verifier information. - */ - public VerifierInfo getUserVerifier(String username) - throws KeyException, IOException; - /** Set the indicated users' password verifier information. This is equivalent - to changing a user's password and should generally invalidate any existing - SRP sessions and caches. - */ - public void setUserVerifier(String username, VerifierInfo info) - throws IOException; - - /** Verify an optional auxillary challenge sent from the client to the server. The - * auxChallenge object will have been decrypted if it was sent encrypted from the - * client. An example of a auxillary challenge would be the validation of a hardware - * token (SafeWord, SecureID, iButton) that the server validates to further strengthen - * the SRP password exchange. - */ - public void verifyUserChallenge(String username, Object auxChallenge) - throws SecurityException; -} diff --git a/src/org/jboss/security/srp/SerialObjectStore.java b/src/org/jboss/security/srp/SerialObjectStore.java deleted file mode 100644 index 3170488f..00000000 --- a/src/org/jboss/security/srp/SerialObjectStore.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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.srp; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.math.BigInteger; -import java.security.KeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.jboss.logging.Logger; -import org.jboss.crypto.CryptoUtil; -import org.jboss.security.srp.SRPConf; -import org.jboss.security.srp.SRPVerifierStore; -import org.jboss.security.srp.SRPVerifierStore.VerifierInfo; - -/** A simple implementation of the SRPVerifierStore that uses a -file store made up of VerifierInfo serialized objects. Users and -be added or removed using the addUser and delUser methods. User passwords -are never stored in plaintext either in memory or in the serialized file. -Note that usernames and passwords are logged when a user is added -via the addUser operation. This is a development class and its use in -a production environment is not advised. - -@see #addUser(String, String) -@see #delUser(String) - -@author Scott.Stark@jboss.org -@version $Revision: 81038 $ -*/ -public class SerialObjectStore implements SRPVerifierStore -{ - private static Logger log = Logger.getLogger(SerialObjectStore.class); - private Map infoMap; - private BigInteger g; - private BigInteger N; - - /** Create an in memory store and load any VerifierInfo found in - ./SerialObjectStore.ser if it exists. - */ - public SerialObjectStore() throws IOException - { - this(null); - } - /** Create an in memory store and load any VerifierInfo found in - the storeFile archive if it exists. - */ - public SerialObjectStore(File storeFile) throws IOException - { - if( storeFile == null ) - storeFile = new File("SerialObjectStore.ser"); - if( storeFile.exists() == true ) - { - FileInputStream fis = new FileInputStream(storeFile); - ObjectInputStream ois = new ObjectInputStream(fis); - try - { - infoMap = (Map) ois.readObject(); - } - catch(ClassNotFoundException e) - { - } - ois.close(); - fis.close(); - } - else - { - infoMap = Collections.synchronizedMap(new HashMap()); - } - - try - { - CryptoUtil.init(); - } - catch(NoSuchAlgorithmException e) - { - e.printStackTrace(); - throw new IOException("Failed to initialzed security utils: "+e.getMessage()); - } - N = SRPConf.getDefaultParams().N(); - g = SRPConf.getDefaultParams().g(); - log.trace("N: "+CryptoUtil.tob64(N.toByteArray())); - log.trace("g: "+CryptoUtil.tob64(g.toByteArray())); - byte[] hn = CryptoUtil.newDigest().digest(N.toByteArray()); - log.trace("H(N): "+CryptoUtil.tob64(hn)); - byte[] hg = CryptoUtil.newDigest().digest(g.toByteArray()); - log.trace("H(g): "+CryptoUtil.tob64(hg)); - } - -// --- Begin SRPVerifierStore interface methods - public VerifierInfo getUserVerifier(String username) throws KeyException, IOException - { - VerifierInfo info = null; - if( infoMap != null ) - info = (VerifierInfo) infoMap.get(username); - if( info == null ) - throw new KeyException("username: "+username+" not found"); - return info; - } - public void setUserVerifier(String username, VerifierInfo info) - { - infoMap.put(username, info); - } - - public void verifyUserChallenge(String username, Object auxChallenge) - throws SecurityException - { - throw new SecurityException("verifyUserChallenge not supported"); - } -// --- End SRPVerifierStore interface methods - - /** Save the current in memory map of VerifierInfo to the indicated - storeFile by simply serializing the map to the file. - */ - public void save(File storeFile) throws IOException - { - FileOutputStream fos = new FileOutputStream(storeFile); - ObjectOutputStream oos = new ObjectOutputStream(fos); - synchronized( infoMap ) - { - oos.writeObject(infoMap); - } - oos.close(); - fos.close(); - } - - public void addUser(String username, String password) - { - log.trace("addUser, username='"+username+"', password='"+password+"'"); - VerifierInfo info = new VerifierInfo(); - info.username = username; - /* - long r = Util.nextLong(); - String rs = Long.toHexString(r); - */ - String rs = "123456"; - info.salt = rs.getBytes(); - try - { - char[] pass = password.toCharArray(); - info.verifier = CryptoUtil.calculateVerifier(username, pass, - info.salt, N, g); - info.g = g.toByteArray(); - info.N = N.toByteArray(); - if( log.isTraceEnabled() ) - { - log.trace("N: "+CryptoUtil.tob64(info.N)); - log.trace("g: "+CryptoUtil.tob64(info.g)); - log.trace("s: "+CryptoUtil.tob64(info.salt)); - byte[] xb = CryptoUtil.calculatePasswordHash(username, pass, info.salt); - log.trace("x: "+CryptoUtil.tob64(xb)); - log.trace("v: "+CryptoUtil.tob64(info.verifier)); - byte[] hn = CryptoUtil.newDigest().digest(info.N); - log.trace("H(N): "+CryptoUtil.tob64(hn)); - byte[] hg = CryptoUtil.newDigest().digest(info.g); - log.trace("H(g): "+CryptoUtil.tob64(hg)); - } - } - catch(Throwable t) - { - log.error("Failed to calculate verifier", t); - return; - } - - setUserVerifier(username, info); - } - public void delUser(String username) - { - infoMap.remove(username); - } - - public static void main(String[] args) throws IOException - { - File storeFile = new File("SerialObjectStore.ser"); - SerialObjectStore store = new SerialObjectStore(); - - for(int a = 0; a < args.length; a ++) - { - if( args[a].startsWith("-a") ) - { - store.addUser(args[a+1], args[a+2]); - } - else if( args[a].startsWith("-d") ) - { - store.delUser(args[a+1]); - } - } - store.save(storeFile); - } -} -- cgit v1.2.3 From 65e2f56a8a10877964fb9fc57963d1bf8104801a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Thu, 20 Jun 2013 17:47:07 +0200 Subject: No binary library needed. I've decided not to include any lib, but to copy the SRPParameters class to our codebase and Util.trim method to ConfigHelper. --- src/org/jboss/security/srp/SRPParameters.java | 150 ++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/org/jboss/security/srp/SRPParameters.java (limited to 'src/org/jboss/security') diff --git a/src/org/jboss/security/srp/SRPParameters.java b/src/org/jboss/security/srp/SRPParameters.java new file mode 100644 index 00000000..4b188cb3 --- /dev/null +++ b/src/org/jboss/security/srp/SRPParameters.java @@ -0,0 +1,150 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2006, 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.srp; + +import java.io.Serializable; +import java.util.Arrays; + +import org.spongycastle.util.encoders.Base64; + +/** The RFC2945 algorithm session parameters that the client and server +agree to use. In addition to the base RFC2945 parameters, one can choose an +alternate hash algorithm for the private session key. + +@author Scott.Stark@jboss.org +@version $Revision: 57210 $ +*/ +public class SRPParameters implements Cloneable, Serializable +{ + /** The serial version ID. + * @since 1.2.4.1 + */ + private static final long serialVersionUID = 6438772808805276693L; + + /** The algorithm safe-prime modulus */ + public final byte[] N; + /** The algorithm primitive generator */ + public final byte[] g; + /** The random password salt originally used to verify the password */ + public final byte[] s; + /** The algorithm to hash the session key to produce K. To be consistent + with the RFC2945 description this must be SHA_Interleave as implemented + by the JBossSX security provider. For compatibility with earlier JBossSX + SRP releases the algorithm must be SHA_ReverseInterleave. This name is + passed to java.security.MessageDigest.getInstance(). */ + public final String hashAlgorithm; + /** The algorithm to use for any encryption of data. + */ + public final String cipherAlgorithm; + /** The cipher intialization vector bytes + */ + public byte[] cipherIV; + + /** Creates a new instance of SRPParameters */ + public SRPParameters(byte[] N, byte[] g, byte[] s) + { + this(N, g, s, "SHA_Interleave", null); + } + public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm) + { + this(N, g, s, hashAlgorithm, null); + } + public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm, + String cipherAlgorithm) + { + this(N, g, s, hashAlgorithm, cipherAlgorithm, null); + } + public SRPParameters(byte[] N, byte[] g, byte[] s, String hashAlgorithm, + String cipherAlgorithm, byte[] cipherIV) + { + this.N = N; + this.g = g; + this.s = s; + if( hashAlgorithm == null ) + hashAlgorithm = "SHA_Interleave"; + this.hashAlgorithm = hashAlgorithm; + this.cipherAlgorithm = cipherAlgorithm; + this.cipherIV = cipherIV; + } + + public Object clone() + { + Object clone = null; + try + { + clone = super.clone(); + } + catch(CloneNotSupportedException e) + { + } + return clone; + } + + public int hashCode() + { + int hashCode = hashAlgorithm.hashCode(); + for(int i = 0; i < N.length; i ++) + hashCode += N[i]; + for(int i = 0; i < g.length; i ++) + hashCode += g[i]; + for(int i = 0; i < s.length; i ++) + hashCode += s[i]; + return hashCode; + } + + public boolean equals(Object obj) + { + boolean equals = false; + if( obj instanceof SRPParameters ) + { + SRPParameters p = (SRPParameters) obj; + equals = hashAlgorithm.equals(p.hashAlgorithm); + if( equals == true ) + equals = Arrays.equals(N, p.N); + if( equals == true ) + equals = Arrays.equals(g, p.g); + if( equals == true ) + equals = Arrays.equals(s, p.s); + } + return equals; + } + + public String toString() + { + StringBuffer tmp = new StringBuffer(super.toString()); + tmp.append('{'); + tmp.append("N: "); + tmp.append(Base64.encode(N)); + tmp.append("|g: "); + tmp.append(Base64.encode(g)); + tmp.append("|s: "); + tmp.append(Base64.encode(s)); + tmp.append("|hashAlgorithm: "); + tmp.append(hashAlgorithm); + tmp.append("|cipherAlgorithm: "); + tmp.append(cipherAlgorithm); + tmp.append("|cipherIV: "); + tmp.append(cipherIV); + tmp.append('}'); + return tmp.toString(); + } +} -- cgit v1.2.3