1 22 package org.jboss.security.srp; 23 24 import java.math.BigInteger ; 25 import java.security.MessageDigest ; 26 import java.security.NoSuchAlgorithmException ; 27 import java.util.Arrays ; 28 29 import org.jboss.logging.Logger; 30 import org.jboss.security.Util; 31 32 57 public class SRPClientSession 58 { 59 private static Logger log = Logger.getLogger(SRPClientSession.class); 60 private SRPParameters params; 61 private BigInteger N; 62 private BigInteger g; 63 private BigInteger x; 64 private BigInteger v; 65 private byte[] s; 66 private BigInteger a; 67 private BigInteger A; 68 private byte[] K; 69 70 private MessageDigest clientHash; 71 72 private MessageDigest serverHash; 73 74 private static int A_LEN = 64; 75 76 82 public SRPClientSession(String username, char[] password, SRPParameters params) 83 { 84 this(username, password, params, null); 85 } 86 87 95 public SRPClientSession(String username, char[] password, SRPParameters params, 96 byte[] abytes) 97 { 98 try 99 { 100 Util.init(); 102 } 103 catch(NoSuchAlgorithmException e) 104 { 105 } 106 this.params = params; 107 this.g = new BigInteger (1, params.g); 108 this.N = new BigInteger (1, params.N); 109 if( abytes != null ) 110 { 111 if( 8*abytes.length != A_LEN ) 112 throw new IllegalArgumentException ("The abytes param must be " 113 +(A_LEN/8)+" in length, abytes.length="+abytes.length); 114 this.a = new BigInteger (abytes); 115 } 116 117 if( log.isTraceEnabled() ) 118 log.trace("g: "+Util.tob64(params.g)); 119 byte[] xb = Util.calculatePasswordHash(username, password, params.s); 121 if( log.isTraceEnabled() ) 122 log.trace("x: "+Util.tob64(xb)); 123 this.x = new BigInteger (1, xb); 124 this.v = g.modPow(x, N); if( log.isTraceEnabled() ) 126 log.trace("v: "+Util.tob64(v.toByteArray())); 127 128 serverHash = Util.newDigest(); 129 clientHash = Util.newDigest(); 130 byte[] hn = Util.newDigest().digest(params.N); 132 if( log.isTraceEnabled() ) 133 log.trace("H(N): "+Util.tob64(hn)); 134 byte[] hg = Util.newDigest().digest(params.g); 136 if( log.isTraceEnabled() ) 137 log.trace("H(g): "+Util.tob64(hg)); 138 byte[] hxg = Util.xor(hn, hg, 20); 140 if( log.isTraceEnabled() ) 141 log.trace("H(N) xor H(g): "+Util.tob64(hxg)); 142 clientHash.update(hxg); 143 if( log.isTraceEnabled() ) 144 { 145 MessageDigest tmp = Util.copy(clientHash); 146 log.trace("H[H(N) xor H(g)]: "+Util.tob64(tmp.digest())); 147 } 148 clientHash.update(Util.newDigest().digest(username.getBytes())); 150 if( log.isTraceEnabled() ) 151 { 152 MessageDigest tmp = Util.copy(clientHash); 153 log.trace("H[H(N) xor H(g) | H(U)]: "+Util.tob64(tmp.digest())); 154 } 155 clientHash.update(params.s); 157 if( log.isTraceEnabled() ) 158 { 159 MessageDigest tmp = Util.copy(clientHash); 160 log.trace("H[H(N) xor H(g) | H(U) | s]: "+Util.tob64(tmp.digest())); 161 } 162 K = null; 163 } 164 165 168 public byte[] exponential() 169 { 170 byte[] Abytes = null; 171 if(A == null) 172 { 173 175 if( a == null ) 176 { 177 BigInteger one = BigInteger.ONE; 178 do 179 { 180 a = new BigInteger (A_LEN, Util.getPRNG()); 181 } while(a.compareTo(one) <= 0); 182 } 183 A = g.modPow(a, N); 184 Abytes = Util.trim(A.toByteArray()); 185 clientHash.update(Abytes); 187 if( log.isTraceEnabled() ) 188 { 189 MessageDigest tmp = Util.copy(clientHash); 190 log.trace("H[H(N) xor H(g) | H(U) | s | A]: "+Util.tob64(tmp.digest())); 191 } 192 serverHash.update(Abytes); 194 } 195 return Abytes; 196 } 197 198 203 public byte[] response(byte[] Bbytes) throws NoSuchAlgorithmException 204 { 205 clientHash.update(Bbytes); 207 if( log.isTraceEnabled() ) 208 { 209 MessageDigest tmp = Util.copy(clientHash); 210 log.trace("H[H(N) xor H(g) | H(U) | s | A | B]: "+Util.tob64(tmp.digest())); 211 } 212 byte[] hB = Util.newDigest().digest(Bbytes); 214 byte[] ub = 215 {hB[0], hB[1], hB[2], hB[3]}; 216 BigInteger B = new BigInteger (1, Bbytes); 218 if( log.isTraceEnabled() ) 219 log.trace("B: "+Util.tob64(B.toByteArray())); 220 if( B.compareTo(v) < 0 ) 221 B = B.add(N); 222 if( log.isTraceEnabled() ) 223 log.trace("B': "+Util.tob64(B.toByteArray())); 224 if( log.isTraceEnabled() ) 225 log.trace("v: "+Util.tob64(v.toByteArray())); 226 BigInteger u = new BigInteger (1, ub); 227 if( log.isTraceEnabled() ) 228 log.trace("u: "+Util.tob64(u.toByteArray())); 229 BigInteger B_v = B.subtract(v); 230 if( log.isTraceEnabled() ) 231 log.trace("B - v: "+Util.tob64(B_v.toByteArray())); 232 BigInteger a_ux = a.add(u.multiply(x)); 233 if( log.isTraceEnabled() ) 234 log.trace("a + u * x: "+Util.tob64(a_ux.toByteArray())); 235 BigInteger S = B_v.modPow(a_ux, N); 236 if( log.isTraceEnabled() ) 237 log.trace("S: "+Util.tob64(S.toByteArray())); 238 MessageDigest sessionDigest = MessageDigest.getInstance(params.hashAlgorithm); 240 K = sessionDigest.digest(S.toByteArray()); 241 if( log.isTraceEnabled() ) 242 log.trace("K: "+Util.tob64(K)); 243 clientHash.update(K); 245 byte[] M1 = clientHash.digest(); 246 if( log.isTraceEnabled() ) 247 log.trace("M1: H[H(N) xor H(g) | H(U) | s | A | B | K]: "+Util.tob64(M1)); 248 serverHash.update(M1); 249 serverHash.update(K); 250 if( log.isTraceEnabled() ) 251 { 252 MessageDigest tmp = Util.copy(serverHash); 253 log.trace("H[A | M1 | K]: "+Util.tob64(tmp.digest())); 254 } 255 return M1; 256 } 257 261 public boolean verify(byte[] M2) 262 { 263 byte[] myM2 = serverHash.digest(); 265 boolean valid = Arrays.equals(M2, myM2); 266 if( log.isTraceEnabled() ) 267 { 268 log.trace("verify serverM2: "+Util.tob64(M2)); 269 log.trace("verify M2: "+Util.tob64(myM2)); 270 } 271 return valid; 272 } 273 274 279 public byte[] getSessionKey() throws SecurityException 280 { 281 SecurityManager sm = System.getSecurityManager(); 282 if( sm != null ) 283 { 284 SRPPermission p = new SRPPermission("getSessionKey"); 285 sm.checkPermission(p); 286 } 287 return K; 288 } 289 } 290 | Popular Tags |