001package com.bitbucket.thinbus.srp6.js; 002 003import static com.nimbusds.srp6.BigIntegerUtils.fromHex; 004import static com.nimbusds.srp6.BigIntegerUtils.toHex; 005 006import java.math.BigInteger; 007import java.security.MessageDigest; 008 009import com.nimbusds.srp6.SRP6CryptoParams; 010 011/** 012 * Generates a SRP6 verifier. WARNING: You should use the JavaScript client not 013 * the Java client for generating the verifier. See the 014 * TestSRP6JavascriptClientSessionSHA256.js for an example. This class is only 015 * for systems which let users login from Java clients in addition to JavaScript 016 * clients who additionally wish to implement user registration of password 017 * reset logic in their Java clients which subsequently let users login via a 018 * browser. It is probably better to implement user registration or password 019 * rest logic only via the browser. Certainly you SHOULD to avoid this code ever 020 * being run on the server as that would require the password to be transmitted 021 * to the server which is something which SRP is designed to avoid. 022 */ 023public class HexHashedVerifierGenerator { 024 protected final SRP6CryptoParams config; 025 026 /** 027 * @param N 028 * The large safe prime in radix10 029 * @param g 030 * The safe prime generator in radix10 031 * @param hashName 032 * The name of the hashing algorithm e.g. SHA256 033 */ 034 public HexHashedVerifierGenerator(String N, String g, String hashName) { 035 config = new SRP6CryptoParams( 036 SRP6JavascriptServerSession.fromDecimal(N), 037 SRP6JavascriptServerSession.fromDecimal(g), hashName); 038 } 039 040 private String hashCredentials(String salt, String identity, String password) { 041 MessageDigest digest = config.getMessageDigestInstance(); 042 return HexHashedRoutines.hashCredentials(digest, salt, 043 identity, password); 044 } 045 046 // matches javascript client library does which is H(s | H(i | ":" | p)) 047 private BigInteger generateX(String salt, String identity, String password) { 048 String hash = hashCredentials(salt, identity, password); 049 return fromHex(hash).mod(config.N); 050 } 051 052 /** 053 * Browser does string concat version of x = H(s | H(i | ":" | p)). 054 * Specification is RFC 5054 Which we repeat here to be able to reset the 055 * password in a java client. 056 * 057 * @param salt 058 * The random salt stored at user registration 059 * @param identity 060 * The user username 061 * @param password 062 * The user password. Note this should only ever be on java 063 * clients and never sent to the java server. 064 * @return An SRP password verifier 065 */ 066 public String generateVerifier(String salt, String identity, String password) { 067 BigInteger x = generateX(salt, identity, password); 068 BigInteger v = config.g.modPow(x, config.N); 069 return toHex(v).toLowerCase(); 070 } 071 072}