PWDComputations extends KeyExchangeComputations { public static Point computePasswordElement(Chooser chooser, EllipticCurve curve) throws CryptoException { MacAlgorithm randomFunction = getMacAlgorithm(chooser.getSelectedCipherSuite()); BigInteger prime = curve.getModulus(); byte[] base; byte[] salt = chooser.getServerPWDSalt(); if (salt == null && chooser.getSelectedProtocolVersion() != ProtocolVersion.TLS13) { salt = chooser.getConfig().getDefaultServerPWDSalt(); } if (salt == null) { Digest digest = TlsUtils.createHash(HashAlgorithm.sha256); base = new byte[digest.getDigestSize()]; byte[] usernamePW = (chooser.getClientPWDUsername() + chooser.getPWDPassword()).getBytes(); digest.update(usernamePW, 0, usernamePW.length); digest.doFinal(base, 0); } else { base = StaticTicketCrypto.generateHMAC(MacAlgorithm.HMAC_SHA256, (chooser.getClientPWDUsername() + chooser.getPWDPassword()).getBytes(), salt); } boolean found = false; int counter = 0; int n = (curve.getModulus().bitLength() + 64) / Bits.IN_A_BYTE; byte[] context; if (chooser.getSelectedProtocolVersion().isTLS13()) { context = chooser.getClientRandom(); } else { context = ArrayConverter.concatenate(chooser.getClientRandom(), chooser.getServerRandom()); } Point createdPoint = null; byte[] savedSeed = null; do { counter++; byte[] seedInput = ArrayConverter.concatenate(base, ArrayConverter.intToBytes(counter, 1), ArrayConverter.bigIntegerToByteArray(prime)); byte[] seed = StaticTicketCrypto.generateHMAC(randomFunction, seedInput, new byte[4]); byte[] tmp = prf(chooser, seed, context, n); BigInteger tmpX = new BigInteger(1, tmp).mod(prime.subtract(BigInteger.ONE)).add(BigInteger.ONE); Point tempPoint = curve.createAPointOnCurve(tmpX); if (!found && curve.isOnCurve(tempPoint)) { createdPoint = tempPoint; savedSeed = seed.clone(); found = true; chooser.getContext().getBadSecureRandom().nextBytes(base); } if (counter > 1000) { savedSeed = seed.clone(); createdPoint = tempPoint; LOGGER.warn("Could not find a useful pwd point"); break; } } while (!found || counter < chooser.getConfig().getDefaultPWDIterations()); int lsbSeed = savedSeed[0] & 1; int lsbY = createdPoint.getY().getData().getLowestSetBit() == 0 ? 1 : 0; if (lsbSeed == lsbY) { createdPoint = curve.inverse(createdPoint); } return createdPoint; }  static Point computePasswordElement(Chooser chooser, EllipticCurve curve); static PWDKeyMaterial generateKeyMaterial(EllipticCurve curve, Point passwordElement, Chooser chooser); @Override void setSecretsInConfig(Config config); Point getPasswordElement(); void setPasswordElement(Point passwordElement); BigInteger getPrivateKeyScalar(); void setPrivateKeyScalar(BigInteger privateKeyScalar);  }
@Test public void computePE() throws CryptoException { TlsContext context = new TlsContext(); context.setSelectedCipherSuite(CipherSuite.TLS_ECCPWD_WITH_AES_128_GCM_SHA256); context.setSelectedProtocolVersion(ProtocolVersion.TLS12); context.setClientRandom(ArrayConverter .hexStringToByteArray("528fbf52175de2c869845fdbfa8344f7d732712ebfa679d8643cd31a880e043d")); context.setServerRandom(ArrayConverter .hexStringToByteArray("528fbf524378a1b13b8d2cbd247090721369f8bfa3ceeb3cfcd85cbfcdd58eaa")); context.setClientPWDUsername("fred"); context.getConfig().setDefaultPWDPassword("barney"); EllipticCurve curve = CurveFactory.getCurve(NamedGroup.BRAINPOOLP256R1); Point passwordElement = PWDComputations.computePasswordElement(context.getChooser(), curve); BigInteger expectedX = new BigInteger("686B0D3FC49894DD621EC04F925E029B2B1528EDEDCA46007254281E9A6EDC", 16); assertArrayEquals(ArrayConverter.bigIntegerToByteArray(expectedX), ArrayConverter.bigIntegerToByteArray(passwordElement.getX().getData())); context.setSelectedProtocolVersion(ProtocolVersion.TLS13); passwordElement = PWDComputations.computePasswordElement(context.getChooser(), curve); expectedX = new BigInteger("0BA387CE8123BEA05A4327520F5A2A66B038F2024F239F330038DA0A2744F79B", 16); assertArrayEquals(ArrayConverter.bigIntegerToByteArray(expectedX), ArrayConverter.bigIntegerToByteArray(passwordElement.getX().getData())); }