1
$\begingroup$

I have been looking around with some new Post-Quantum secure key exchange methods, such as McEliece, NTRU and SIDH, but none of these seem to be working nicely between the browser and the BouncyCastle implementation. McEliece falls off very fast since the keys are exorbitantly large; not necessarily an issue, but not convenient.

My latest iteration is using the NewHope key exchange scheme, which looks to be simple in use and I can't see why it is not working. I found this AMCL crypto library which implement it as specced (as far as I can see), but generating a shared key is not working.

My javascript implentation is as follows (looking at their test code):

let ctx = new CTX();
let RAW=[];
let crng=new ctx.RAND(); crng.clean();
for (let i=0;i<100;i++) RAW[i]=i+2;
crng.seed(100,RAW);
let SB=[];
let UC=[];
let KEYB=[];

function nh_ss() {
    SB = hexStringToByte(document.getElementById("nh_pk").value);
    ctx.NHS.CLIENT(crng,SB,UC,KEYB);
    document.getElementById("nh_uc").innerHTML = byteToHexString(UC);
    document.getElementById("nh_result").innerHTML = byteToHexString(KEYB);
}

Here the servers' public key is input into the "nh_pk" field and converted using convenience methods:

function byteToHexString(uint8arr) {
    let hexStr = '';
    for (let i = 0; i < uint8arr.length; i++) {
        let hex = (uint8arr[i] & 0xff).toString(16);
        hex = (hex.length === 1) ? '0' + hex : hex;
        hexStr += hex;
    }
    return hexStr.toUpperCase();
}

function hexStringToByte(str) {
    let a = [];
    for (let i = 0, len = str.length; i < len; i+=2) {
        a.push(parseInt(str.substr(i,2),16));
    }
    return new Uint8Array(a);
}

The BouncyCastle implementation is simple as well, following the request-response flow as specced:

NHKeyPairGenerator keyPairGenerator = new NHKeyPairGenerator();
keyPairGenerator.init(new  KeyGenerationParameters(new SecureRandom(), 1024));
AsymmetricCipherKeyPair keyPair = keyPairGenerator.generateKeyPair();
NHPublicKeyParameters publicKey = (NHPublicKeyParameters) keyPair.getPublic();

System.out.println("public key:\n" + Util.bytes2hex(publicKey.getPubData()));
System.out.println("Enter response value: ");
Scanner scanner = new Scanner(System.in);
String response = scanner.nextLine();

byte[] bytes = Util.hex2bytes(response);
NHPublicKeyParameters keyParameters = new NHPublicKeyParameters(bytes);

NHAgreement agreement = new NHAgreement();
agreement.init(keyPair.getPrivate());
byte[] agreementValue = agreement.calculateAgreement(keyParameters);
System.out.println("agreement value:n\n" + Util.bytes2hex(agreementValue));

But the shared values are not corresponding at all, and I'm not following what is going wrong.

The same goes for the other implementations, though the test code for the client and the test application is very messy, they should work.

$\endgroup$
  • $\begingroup$ Since NewHope is a relatively new protocol that has not seen much adoption, you are probably better off contacting the authors of the software, e.g. by email, to ask about its interoperability. $\endgroup$ – Squeamish Ossifrage Mar 15 '18 at 22:25
  • $\begingroup$ @SqueamishOssifrage already did that, but have not gotten any response in a while. $\endgroup$ – Stijn van Schooten Mar 21 '18 at 8:05
  • $\begingroup$ For the Bouncy Castle implementation, I was able to get the same shared value. I am not sure what you sending to Standard Input. $\endgroup$ – anomal Mar 17 at 5:35

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.