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. A valid use case 015 * for generating a verifier using server code would be if a user lost their 016 * password and you were generating a temporary password and verifier to email 017 * out to the client. 018 * 019 * Certainly you SHOULD avoid this code ever being run against a real user password 020 * which is transmitted to the server which is something which SRP is designed to avoid. 021 */ 022public class HexHashedVerifierGenerator { 023 protected final SRP6CryptoParams config; 024 025 public HexHashedVerifierGenerator(final SRP6CryptoParams config) { 026 this.config = config; 027 } 028 029 /** 030 * @param N 031 * The large safe prime in radix10 032 * @param g 033 * The safe prime generator in radix10 034 * @param hashName 035 * The name of the hashing algorithm e.g. SHA256 036 */ 037 public HexHashedVerifierGenerator(String N, String g, String hashName) { 038 config = new SRP6CryptoParams( 039 SRP6JavascriptServerSession.fromDecimal(N), 040 SRP6JavascriptServerSession.fromDecimal(g), hashName); 041 } 042 043 private String hashCredentials(String salt, String identity, String password) { 044 MessageDigest digest = config.getMessageDigestInstance(); 045 return HexHashedRoutines.hashCredentials(digest, salt, 046 identity, password); 047 } 048 049 // matches javascript client library does which is H(s | H(i | ":" | p)) 050 private BigInteger generateX(String salt, String identity, String password) { 051 String hash = hashCredentials(salt, identity, password); 052 return fromHex(hash).mod(config.N); 053 } 054 055 /** 056 * Browser does string concat version of x = H(s | H(i | ":" | p)). 057 * Specification is RFC 5054 Which we repeat here to be able to reset the 058 * password in a java client. 059 * 060 * @param salt 061 * The random salt stored at user registration 062 * @param identity 063 * The user username 064 * @param password 065 * The user password. Note this should only ever be on java 066 * clients and never sent to the java server. 067 * @return An SRP password verifier 068 */ 069 public String generateVerifier(String salt, String identity, String password) { 070 BigInteger x = generateX(salt, identity, password); 071 BigInteger v = config.g.modPow(x, config.N); 072 return toHex(v).toLowerCase(); 073 } 074 075}