Score:1

Verifying result of (EC-)Diffie-Hellman

in flag

I received a public key by JSON.

For the example, I have 4 keys: 2 public keys and 2 private keys.

public A : co2D0pNxZJIeQ4RZlCRJYBDzNXSLluETdztid0M+HGzN1uGJ4JWZsenjWgRrmkLh3yqHQqzOBMl/wHVH97A6+g==

private A : TXxii5Ka8LMvuc9arHu63qTmNKxGlgti+wpR3YhBGew=

public B : nUblC+OKdl94iBiWk0941wmYBiMt7C90CjOJPI2BPr8K7xGuC1XsR5DtwFCoM3Iew2BjBG+5SqrYwAPTJF7gdA==

private B : sm6V7+hChvkFSeLNoR+5tItiX8gH5tT47xBkFaV6SDU=

I can't make an ECDH exchange from a public key A and a private key B that I receive in JSON.

How can I verify : (public key A + private key B) == (public key B + private key A) ?

Michael Fehr avatar
gb flag
The keys in the JSON file are Base64 encoded keys and usually can get imported with the key spec's. Then generate a shared secret using [public key A + private key B] and [public key B + private key A] and if the secrets are equal you have verified that have 2 working key pairs. Kindly edit your question and add some code as Stackoverflow is not a free code writing service, thanks.
Maarten Bodewes avatar
in flag
Note that ECDH exchange does not use "addition", it uses point multiplication as underlying mathematical construct.
fgrieu avatar
ng flag
Hint: decode the Base64, rule out that the content is ASN.1, tentatively guess it's big-endian raw bytes, conclude from sizes that the public keys probably have X and Y concatenated, use the high redundancy there to (hopefully) figure out a common curve (perhaps one of [these](https://www.secg.org/sec2-v2.pdf#subsection.2.4)), and check $a\,B=b\,A$ as asked. Alternatively, check if $a\,G=A$ and $b\,G=B$ (that is public and private keys match), which would prove $a\,B=b\,A$ without further computation. That [reference](https://www.secg.org/sec1-v2.pdf#subsubsection.2.2.1) may help (YMMV).
Score:6
in flag

Usually the result of the (Elliptic Curve) Diffie-Hellman calculation is called a master secret. This master key is commonly used as input keying material (IKM) for a Key Derivation Function (KDF). Using the KDF multiple keys can be derived from the master secret. What you are looking for is called "key conformation".

There are various ways of confirming symmetric keys:

  1. One of these keys can be used as input to a challenge response protocol. A challenge response protocol is a symmetric method to validate that an entity has access to the correct secret key.

  2. Another way is to use the key as input to a MAC over a string known to both sides. That way the MAC shows that the entity has access to the correct key. For instance, TLS (1.3) uses a MAC over the entire handshake in the final "Finished" message of the handshake:

    Finished: A MAC (Message Authentication Code) over the entire handshake. This message provides key confirmation, binds the endpoint's identity to the exchanged keys, and in PSK mode also authenticates the handshake. [Section 4.4.4]

  3. You could also imagine that one party can sign the resulting secret and send the signature to the other party.

  4. Finally, the confirmation that the resulting keys and thus secret are identical can also be performed implicitly when the first authenticated message is send from one party to the other party. This however is generally avoided, as it means that you cannot distinguish between data transmission and handshake errors; it can therefore play merry hell in protocol implementation.

Notes:

  • If you confirm one key then the validity of the secret and any other derived key is also confirmed (barring implementation mistakes).
  • It may be that the (static) public key of the DH can be trusted by other means, in which case additional verification of the resulting secret may not be required for the authenticated party; only the non-authenticated parties are required to send a challenge-response, MAC or signature value.
Score:0
in flag

So this is how I solved my problem :

My keys in strings :

public A : co2D0pNxZJIeQ4RZlCRJYBDzNXSLluETdztid0M+HGzN1uGJ4JWZsenjWgRrmkLh3yqHQqzOBMl/wHVH97A6+g==

private A : TXxii5Ka8LMvuc9arHu63qTmNKxGlgti+wpR3YhBGew=

public B : nUblC+OKdl94iBiWk0941wmYBiMt7C90CjOJPI2BPr8K7xGuC1XsR5DtwFCoM3Iew2BjBG+5SqrYwAPTJF7gdA==

private B : sm6V7+hChvkFSeLNoR+5tItiX8gH5tT47xBkFaV6SDU=

Functions to get private key :

public static PrivateKey getPrivateKey(byte[] encodedPrivateKey) {
   BigInteger s = new BigInteger(1,encodedPrivateKey);
   ECNamedCurveParameterSpec ecCurve = ECNamedCurveTable.getParameterSpec("secp256r1");
   ECParameterSpec ecParameterSpec = new ECNamedCurveSpec("secp256r1", ecCurve.getCurve(), ecCurve.getG(), ecCurve.getN(), ecCurve.getH(), ecCurve.getSeed());
   ECPrivateKeySpec privateKeySpec = new ECPrivateKeySpec(s, ecParameterSpec);
   try {
       KeyFactory keyFactory = KeyFactory.getInstance("EC");
       return keyFactory.generatePrivate(privateKeySpec);
    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
        return null;
   }
}

public static PublicKey rawToEncodedECPublicKey(String curveName, byte[] rawBytes) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidParameterSpecException {
   KeyFactory kf = KeyFactory.getInstance("EC");
   byte[] x = Arrays.copyOfRange(rawBytes, 0, rawBytes.length/2);
   byte[] y = Arrays.copyOfRange(rawBytes, rawBytes.length/2, rawBytes.length);
   ECPoint w = new ECPoint(new BigInteger(1,x), new BigInteger(1,y));
   return kf.generatePublic(new ECPublicKeySpec(w, ecParameterSpecForCurve(curveName)));
}

public static java.security.spec.ECParameterSpec ecParameterSpecForCurve(String curveName) throws NoSuchAlgorithmException, InvalidParameterSpecException {
   AlgorithmParameters params = AlgorithmParameters.getInstance("EC");
   params.init(new ECGenParameterSpec(curveName));
   return params.getParameterSpec(ECParameterSpec.class);
}

We need to create 2 pairs of keys via keys public/private in string and check if both are equal :

byte [] cle_publique_a_decode = Base64.getDecoder().decode(cle_publique_a);
byte [] cle_privee_a_decode = Base64.getDecoder().decode(cle_privee_a);
byte [] cle_publique_b_decode = Base64.getDecoder().decode(cle_publique_b);
byte [] cle_privee_b_decode = Base64.getDecoder().decode(cle_privee_b);

try {
     PublicKey PublicKeyA = rawToEncodedECPublicKey("secp256r1",cle_publique_a_decode);
     PublicKey PublicKeyB = rawToEncodedECPublicKey("secp256r1",cle_publique_b_decode);

     PrivateKey PrivateKeyA =  getPrivateKey(cle_privee_a_decode);
     PrivateKey PrivateKeyB =  getPrivateKey(cle_privee_b_decode);

     // Secret #1
     // PrivateKeyA + PublicKeyB = generateSecret
     KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
     keyAgreement.init(PrivateKeyA);
     keyAgreement.doPhase(PublicKeyB, true);
     byte[] generateSecret = keyAgreement.generateSecret();
     String base64_generateSecret = Base64.getEncoder().encodeToString(generateSecret);

     // Secret #2
     // PrivateKeyB + PublicKeyA = generateSecret2
     KeyAgreement keyAgreement2 = KeyAgreement.getInstance("ECDH");
     keyAgreement.init(PrivateKeyB);
     keyAgreement.doPhase(PublicKeyA, true);
     byte[] generateSecret2 = keyAgreement.generateSecret();
     String base64_generateSecret2 = Base64.getEncoder().encodeToString(generateSecret);

     // compare 2 secrets
     // (public key A + private key B) == (public key B + private key A)
     if(base64_generateSecret.equals(base64_generateSecret2)){
          // Good : Secrets are same
          // continue..
     }
     else{
          // Not good : Secrets are differents
     }
}
catch{
     throw new IllegalArgumentException(e.getMessage(), e);
}

Keys are equal, I can begin to encrypt.

Maarten Bodewes avatar
in flag
The whole idea of DH is that you generate secrets at two locations. You cannot directly compare secrets by using `equals` as that would mean that you can copy the value from one location to another. If you can do that then you don't need DH.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.