Quantcast

How to calculate shared secret in ECDH protocol

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to calculate shared secret in ECDH protocol

ziggi slaw
I have to implement a protocol where the client sends his EC public key and my fist step is to generate my own ephemeral EC public/private key pair and then calculate shared secret, which will be used later to generate session keys.

The elliptic curve in question is brainpoolP224r1. Below is my code (with hardcoded values), which either returs wrong result or throws an expection 'The multiplicator cannot be negative'. Any help would be very appreciated.

public static byte[] CalculateSharedSecret()
{
    // Public key from the client.
    var iccPublicKey = "1A4C233D49F62BF7F419EBE6E2B81E936E88A93599BFDDE9205DA4DF984969C62695FD825A73F0207AB2D0CF9D5EF0DAAEA92360628032A0";

    // My ephemeral EC key pair.
    var privateKey = "5744E0ED24B7C374DA05F6EBDD3BFDE0F0E629BF93294279B5F169BD";
    var publicKey = "32924227C99ACAA858343C658D08C023316BFB87FE88E22D1F3A7E8D43ADCA39EBEF36904D64BAC677F11ECBEE501C9017808D4FA1AB8988";

    // This is the expected result, but my function returns 32FF74B40D904AE021BCB32B43B56C2D1E09752A47BE089CCED33197.
    var expectedShareSecret = "6CBE1E0F401F55B2479D44921068DCB19445E8A808ACEAE9B8E73505";

    // Curve and curve parameters.
    var curveParameters = TeleTrusTNamedCurves.GetByName("brainpoolp224r1");
    var curve = curveParameters.Curve;
    var curveIdentifier = TeleTrusTObjectIdentifiers.BrainpoolP224R1;

    // Calculate shared secret.
    var iccPublicKeyLengthInBytes = iccPublicKey.Length / 2;
    var iccPublicKeyX = iccPublicKey.Substring(0, iccPublicKeyLengthInBytes);
    var iccPublicKeyY = iccPublicKey.Substring(iccPublicKeyLengthInBytes);
    var iccPublicKeyPoint = new ECPublicKeyParameters(
        "ECDH",
        new FpPoint(
            curve,
            new FpFieldElement(((FpCurve)curve).Q, new BigInteger(Conversions.HexStringToByteArray(iccPublicKeyX))),
            new FpFieldElement(((FpCurve)curve).Q, new BigInteger(Conversions.HexStringToByteArray(iccPublicKeyY)))
        ),
        curveIdentifier
    );
    var spec = new ECDomainParameters(curve, curveParameters.G, curveParameters.N, curveParameters.H);
    var keyParameters = new ECPrivateKeyParameters(new BigInteger(Conversions.HexStringToByteArray(privateKey)), spec);
    var agreement = new ECDHBasicAgreement();
    agreement.Init(keyParameters);
    return agreement.CalculateAgreement(iccPublicKeyPoint).ToByteArray();
}

Thanks!
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: How to calculate shared secret in ECDH protocol

Edward Ned Harvey (bouncycastle)

This might or might not help with the problem that you know about, but it should help with the problem you don't yet know about - e.g. hash the shared secret.

 

This is C#. Adjust accordingly for java.

 

using System;

using System.Security.Cryptography;

using Org.BouncyCastle.Crypto;

using Org.BouncyCastle.X509;

using Org.BouncyCastle.Security;

using Org.BouncyCastle.Crypto.Agreement;

public static byte[] GetPublicKeyDerEncoded(AsymmetricCipherKeyPair AsymmetricKey)

{

                return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(AsymmetricKey.Public).GetDerEncoded();

}

public static byte[] GetSharedSecret(AsymmetricCipherKeyPair localKeyWithPrivate, byte[] remotePublicKeyDerEncoded)

{

                var remotePublicKey = PublicKeyFactory.CreateKey(remotePublicKeyDerEncoded);

                var agreement = new ECDHBasicAgreement();

                agreement.Init(localKeyWithPrivate.Private);

                using (var sha = SHA256.Create()) {

                                // CalculateAgreement returns a BigInteger, whose length is variable, and bits are not whitened.

                                // So hash it.

                                return sha.ComputeHash(agreement.CalculateAgreement(remotePublicKey).ToByteArray());

                }

}

 

 

 

From: ziggi slaw [mailto:[hidden email]]
Sent: Friday, March 17, 2017 4:53 AM
To: [hidden email]
Subject: [dev-crypto] How to calculate shared secret in ECDH protocol

 

I have to implement a protocol where the client sends his EC public key and my fist step is to generate my own ephemeral EC public/private key pair and then calculate shared secret, which will be used later to generate session keys.

The elliptic curve in question is brainpoolP224r1. Below is my code (with hardcoded values), which either returs wrong result or throws an expection 'The multiplicator cannot be negative'. Any help would be very appreciated.

public static byte[] CalculateSharedSecret()
{
    // Public key from the client.
    var iccPublicKey = "1A4C233D49F62BF7F419EBE6E2B81E936E88A93599BFDDE9205DA4DF984969C62695FD825A73F0207AB2D0CF9D5EF0DAAEA92360628032A0";

    // My ephemeral EC key pair.
    var privateKey = "5744E0ED24B7C374DA05F6EBDD3BFDE0F0E629BF93294279B5F169BD";
    var publicKey = "32924227C99ACAA858343C658D08C023316BFB87FE88E22D1F3A7E8D43ADCA39EBEF36904D64BAC677F11ECBEE501C9017808D4FA1AB8988";

    // This is the expected result, but my function returns 32FF74B40D904AE021BCB32B43B56C2D1E09752A47BE089CCED33197.
    var expectedShareSecret = "6CBE1E0F401F55B2479D44921068DCB19445E8A808ACEAE9B8E73505";

    // Curve and curve parameters.
    var curveParameters = TeleTrusTNamedCurves.GetByName("brainpoolp224r1");
    var curve = curveParameters.Curve;
    var curveIdentifier = TeleTrusTObjectIdentifiers.BrainpoolP224R1;

    // Calculate shared secret.
    var iccPublicKeyLengthInBytes = iccPublicKey.Length / 2;
    var iccPublicKeyX = iccPublicKey.Substring(0, iccPublicKeyLengthInBytes);
    var iccPublicKeyY = iccPublicKey.Substring(iccPublicKeyLengthInBytes);
    var iccPublicKeyPoint = new ECPublicKeyParameters(
        "ECDH",
        new FpPoint(
            curve,
            new FpFieldElement(((FpCurve)curve).Q, new BigInteger(Conversions.HexStringToByteArray(iccPublicKeyX))),
            new FpFieldElement(((FpCurve)curve).Q, new BigInteger(Conversions.HexStringToByteArray(iccPublicKeyY)))
        ),
        curveIdentifier
    );
    var spec = new ECDomainParameters(curve, curveParameters.G, curveParameters.N, curveParameters.H);
    var keyParameters = new ECPrivateKeyParameters(new BigInteger(Conversions.HexStringToByteArray(privateKey)), spec);
    var agreement = new ECDHBasicAgreement();
    agreement.Init(keyParameters);
    return agreement.CalculateAgreement(iccPublicKeyPoint).ToByteArray();
}

Thanks!

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to calculate shared secret in ECDH protocol

David Hook-3
In reply to this post by ziggi slaw

I think the issue is that it is interpreting the byte arrays as signed
numbers, whereas the hex strings are actually for unsigned BigInts.

Try:

new BigInteger(hexValue, 16);

rather than:

new BigInteger(Conversions.HexStringToByteArray(hexValue));

Regards,

David

On 17/03/17 19:53, ziggi slaw wrote:

> I have to implement a protocol where the client sends his EC public
> key and my fist step is to generate my own ephemeral EC public/private
> key pair and then calculate shared secret, which will be used later to
> generate session keys.
>
> The elliptic curve in question is brainpoolP224r1. Below is my code
> (with hardcoded values), which either returs wrong result or throws an
> expection 'The multiplicator cannot be negative'. Any help would be
> very appreciated.
>
> public static byte[] CalculateSharedSecret()
> {
>     // Public key from the client.
>     var iccPublicKey =
> "1A4C233D49F62BF7F419EBE6E2B81E936E88A93599BFDDE9205DA4DF984969C62695FD825A73F0207AB2D0CF9D5EF0DAAEA92360628032A0";
>
>     // My ephemeral EC key pair.
>     var privateKey =
> "5744E0ED24B7C374DA05F6EBDD3BFDE0F0E629BF93294279B5F169BD";
>     var publicKey =
> "32924227C99ACAA858343C658D08C023316BFB87FE88E22D1F3A7E8D43ADCA39EBEF36904D64BAC677F11ECBEE501C9017808D4FA1AB8988";
>
>     // This is the expected result, but my function returns
> 32FF74B40D904AE021BCB32B43B56C2D1E09752A47BE089CCED33197.
>     var expectedShareSecret =
> "6CBE1E0F401F55B2479D44921068DCB19445E8A808ACEAE9B8E73505";
>
>     // Curve and curve parameters.
>     var curveParameters =
> TeleTrusTNamedCurves.GetByName("brainpoolp224r1");
>     var curve = curveParameters.Curve;
>     var curveIdentifier = TeleTrusTObjectIdentifiers.BrainpoolP224R1;
>
>     // Calculate shared secret.
>     var iccPublicKeyLengthInBytes = iccPublicKey.Length / 2;
>     var iccPublicKeyX = iccPublicKey.Substring(0,
> iccPublicKeyLengthInBytes);
>     var iccPublicKeyY = iccPublicKey.Substring(iccPublicKeyLengthInBytes);
>     var iccPublicKeyPoint = new ECPublicKeyParameters(
>         "ECDH",
>         new FpPoint(
>             curve,
>             new FpFieldElement(((FpCurve)curve).Q, new
> BigInteger(Conversions.HexStringToByteArray(iccPublicKeyX))),
>             new FpFieldElement(((FpCurve)curve).Q, new
> BigInteger(Conversions.HexStringToByteArray(iccPublicKeyY)))
>         ),
>         curveIdentifier
>     );
>     var spec = new ECDomainParameters(curve, curveParameters.G,
> curveParameters.N, curveParameters.H);
>     var keyParameters = new ECPrivateKeyParameters(new
> BigInteger(Conversions.HexStringToByteArray(privateKey)), spec);
>     var agreement = new ECDHBasicAgreement();
>     agreement.Init(keyParameters);
>     return agreement.CalculateAgreement(iccPublicKeyPoint).ToByteArray();
> }
>
> Thanks!



Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to calculate shared secret in ECDH protocol

ziggi slaw
Yes, I think that's it! This was a nasty bug to find, thanks!

On Fri, Mar 17, 2017 at 9:46 PM, David Hook <[hidden email]> wrote:

I think the issue is that it is interpreting the byte arrays as signed
numbers, whereas the hex strings are actually for unsigned BigInts.

Try:

new BigInteger(hexValue, 16);

rather than:

new BigInteger(Conversions.HexStringToByteArray(hexValue));

Regards,

David

On 17/03/17 19:53, ziggi slaw wrote:
> I have to implement a protocol where the client sends his EC public
> key and my fist step is to generate my own ephemeral EC public/private
> key pair and then calculate shared secret, which will be used later to
> generate session keys.
>
> The elliptic curve in question is brainpoolP224r1. Below is my code
> (with hardcoded values), which either returs wrong result or throws an
> expection 'The multiplicator cannot be negative'. Any help would be
> very appreciated.
>
> public static byte[] CalculateSharedSecret()
> {
>     // Public key from the client.
>     var iccPublicKey =
> "1A4C233D49F62BF7F419EBE6E2B81E936E88A93599BFDDE9205DA4DF984969C62695FD825A73F0207AB2D0CF9D5EF0DAAEA92360628032A0";
>
>     // My ephemeral EC key pair.
>     var privateKey =
> "5744E0ED24B7C374DA05F6EBDD3BFDE0F0E629BF93294279B5F169BD";
>     var publicKey =
> "32924227C99ACAA858343C658D08C023316BFB87FE88E22D1F3A7E8D43ADCA39EBEF36904D64BAC677F11ECBEE501C9017808D4FA1AB8988";
>
>     // This is the expected result, but my function returns
> 32FF74B40D904AE021BCB32B43B56C2D1E09752A47BE089CCED33197.
>     var expectedShareSecret =
> "6CBE1E0F401F55B2479D44921068DCB19445E8A808ACEAE9B8E73505";
>
>     // Curve and curve parameters.
>     var curveParameters =
> TeleTrusTNamedCurves.GetByName("brainpoolp224r1");
>     var curve = curveParameters.Curve;
>     var curveIdentifier = TeleTrusTObjectIdentifiers.BrainpoolP224R1;
>
>     // Calculate shared secret.
>     var iccPublicKeyLengthInBytes = iccPublicKey.Length / 2;
>     var iccPublicKeyX = iccPublicKey.Substring(0,
> iccPublicKeyLengthInBytes);
>     var iccPublicKeyY = iccPublicKey.Substring(iccPublicKeyLengthInBytes);
>     var iccPublicKeyPoint = new ECPublicKeyParameters(
>         "ECDH",
>         new FpPoint(
>             curve,
>             new FpFieldElement(((FpCurve)curve).Q, new
> BigInteger(Conversions.HexStringToByteArray(iccPublicKeyX))),
>             new FpFieldElement(((FpCurve)curve).Q, new
> BigInteger(Conversions.HexStringToByteArray(iccPublicKeyY)))
>         ),
>         curveIdentifier
>     );
>     var spec = new ECDomainParameters(curve, curveParameters.G,
> curveParameters.N, curveParameters.H);
>     var keyParameters = new ECPrivateKeyParameters(new
> BigInteger(Conversions.HexStringToByteArray(privateKey)), spec);
>     var agreement = new ECDHBasicAgreement();
>     agreement.Init(keyParameters);
>     return agreement.CalculateAgreement(iccPublicKeyPoint).ToByteArray();
> }
>
> Thanks!




Loading...