/** * Call to save the public key (value B in the docs) when received from the server * * @param publicKey_B B * @throws SRPAuthenticationFailedException if B is invalid */ public void setServerPublicKey_B(BigInteger publicKey_B) throws SRPAuthenticationFailedException { if (fPublicKey_A == null) { throw new IllegalStateException("setSalt_s() has not been called yet."); } if (publicKey_B.mod(fConstants.largePrime_N).equals(BigInteger.ZERO)) { throw new SRPAuthenticationFailedException("B%N == 0"); } BigInteger SRP6_u = SRPUtils.calc_u(fPublicKey_A, publicKey_B); if (SRP6_u.mod(fConstants.largePrime_N).equals(BigInteger.ZERO)) { throw new SRPAuthenticationFailedException("u%N == 0"); } // S = (B - 3(g^x))^(a + ux) BigInteger three_g_pow_x = fConstants.srp6Multiplier_k.multiply( fConstants.primitiveRoot_g.modPow(fPrivateKey_x, fConstants.largePrime_N)); BigInteger B_minus_g_pow_x = publicKey_B.subtract(three_g_pow_x); BigInteger ux = SRP6_u.multiply(fPrivateKey_x); fCommonValue_S = B_minus_g_pow_x.modPow(fRandom_a.add(ux), fConstants.largePrime_N) .mod(fConstants.largePrime_N); fEvidenceValue_M1 = SRPUtils.calcM1(fPublicKey_A, publicKey_B, fCommonValue_S); // the MD5 output is the same as the AES key length fSessionKey_K = SRPUtils.hashToBytesMD5(fCommonValue_S); }
/** * Once the server sends the salt (value s in the docs), call this method to save the value * * @param salt salt from the server */ public void setSalt_s(BigInteger salt) { fPrivateKey_x = SRPUtils.makePrivateKey(fPassword, salt); fRandom_a = SRPUtils.random(fConstants); fCommonValue_S = null; fEvidenceValue_M1 = null; fSessionKey_K = null; // A = g^a fPublicKey_A = fConstants.primitiveRoot_g.modPow(fRandom_a, fConstants.largePrime_N); }
/** Call to calculate the common session key (S/K in the docs) */ public void computeCommonValue_S() { if (fPublicKey_A == null) { throw new IllegalStateException("setClientPublicKey_A() has not been called yet."); } fCommonValue_S = fPublicKey_A .multiply(fVerifier.verifier_v.modPow(fSRP6_u, fConstants.largePrime_N)) .modPow(fRandom_b, fConstants.largePrime_N); fEvidenceValue_M1 = SRPUtils.calcM1(fPublicKey_A, fPublicKey_B, fCommonValue_S); // the MD5 output is the same as the AES key length fSessionKey_K = SRPUtils.hashToBytesMD5(fCommonValue_S); }
/** * Return the value M(2) that should be sent to the client * * @return M(2) */ public BigInteger getEvidenceValue_M2() { if (fEvidenceValue_M1 == null) { throw new IllegalStateException("computeCommonValue_S() has not been called yet."); } return SRPUtils.calcM2(fPublicKey_A, fEvidenceValue_M1, fCommonValue_S); }
/** * When the client sends the public key (value A in the docs) call this method to store the value * * @param publicKey_A A * @throws SRPAuthenticationFailedException if A is invalid */ public void setClientPublicKey_A(BigInteger publicKey_A) throws SRPAuthenticationFailedException { if (publicKey_A.mod(fConstants.largePrime_N).equals(BigInteger.ZERO)) { throw new SRPAuthenticationFailedException("A%N == 0"); } fPublicKey_A = publicKey_A; fSRP6_u = SRPUtils.calc_u(fPublicKey_A, fPublicKey_B); if (fSRP6_u.mod(fConstants.largePrime_N).equals(BigInteger.ZERO)) { throw new SRPAuthenticationFailedException("u%N == 0"); } }
/** * When the server sends M(2), call this method to validate the number. * * @param evidenceValueFromServer_M2 M(2) from the server. * @throws SRPAuthenticationFailedException if M(2) is incorrect */ public void validateServerEvidenceValue_M2(BigInteger evidenceValueFromServer_M2) throws SRPAuthenticationFailedException { if (fEvidenceValue_M1 == null) { throw new IllegalStateException("computeCommonValue_S() has not been called yet."); } BigInteger M2 = SRPUtils.calcM2(fPublicKey_A, fEvidenceValue_M1, fCommonValue_S); if (!evidenceValueFromServer_M2.equals(M2)) { throw new SRPAuthenticationFailedException("M(2) is incorrect"); } }
/** * @param constants constants to use * @param verifier the verifier as returned from {@link SRPFactory#makeVerifier(byte[])} */ public SRPServerSession(SRPConstants constants, SRPVerifier verifier) { fConstants = constants; fVerifier = verifier; fRandom_b = SRPUtils.random(fConstants); fSRP6_u = null; fPublicKey_A = null; fCommonValue_S = null; fEvidenceValue_M1 = null; fSessionKey_K = null; // B = 3v + g^b fPublicKey_B = fVerifier .verifier_v .multiply(constants.srp6Multiplier_k) .add(fConstants.primitiveRoot_g.modPow(fRandom_b, fConstants.largePrime_N)); }