I want to implement a ECC Key Agreement with a Brainpool curve brainpoolP512r1 or brainpoolP512t1.

I'm not clear about whichseed value to use (and how). In this document http://www.ecc-brainpool.org/download/Domain-parameters.pdf are two seed values are mentioned.

And RFC http://www.ietf.org/rfc/rfc5639.txt

5.1 Generation of prime numbers

6636920D871574E69A458FEA3F4933D7E0D95748 for ECC 512

5.2 Generation of pseudo-random curves

02AC60ACC93ED874422A52ECB238FEEE5AB6AD for ECC 512

  • So which seed should I use in the ECDomainParameters constructor?
  • Is the seed value for the twisted curve the same? I find only seed values for brainpoolP512r1 and not for brainpoolP512t1
  • Is the implementation rigth?

        // ECC 512 = AES 256 = RSA 15360
        var ecP = TeleTrusTNamedCurves.GetByName("brainpoolp512t1");
        // because ecP.GetSeed() is null !?
        // see spec "ECC Brainpool Standard Curves and Curve Generation" site 7
        // 5.1 Generation of prime numbers
        var seed_p_512PrimeNumbers = StringToByteArray("6636920D871574E69A458FEA3F4933D7E0D95748");
        // 5.2 Generation of pseudo-random curves
        var seed_p_512PseudoRandomCurves = StringToByteArray("02AC60ACC93ED874422A52ECB238FEEE5AB6AD");
        var ecSpec = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, seed_p_512PseudoRandomCurves);
        // Alice
        var enc = new UTF8Encoding();
        var secretPlain = "This is a secret.";
        var secretPlainBytes = enc.GetBytes(secretPlain);
        IAsymmetricCipherKeyPairGenerator aliceGenerator = GeneratorUtilities.GetKeyPairGenerator("ECDH");
        aliceGenerator.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
        AsymmetricCipherKeyPair aliceKeyPair = aliceGenerator.GenerateKeyPair();
        IBasicAgreement aliceBasicAgreement = AgreementUtilities.GetBasicAgreement("ECDH");
        // Bob
        IAsymmetricCipherKeyPairGenerator bobGenerator = GeneratorUtilities.GetKeyPairGenerator("ECDH");
        bobGenerator.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
        AsymmetricCipherKeyPair bobKeyPair = bobGenerator.GenerateKeyPair();
        IBasicAgreement bobBasicAgreement = AgreementUtilities.GetBasicAgreement("ECDH");
        // generate shared key
        var k1 = bobBasicAgreement.CalculateAgreement(aliceKeyPair.Public).ToByteArray();
        var k2 = aliceBasicAgreement.CalculateAgreement(bobKeyPair.Public).ToByteArray();
        for (int i = 0; i < k1.Length; i++)
            if (k1[i] != k2[i])
                throw new Exception("Secrets are not equal.");

Thanks a lot!


1 Answer 1


You don't have to specify a seed at all.

An elliptic curve is specified by a handful of parameters:

  • the definition of the field you are playing on (here, the field consists in the integers modulo a given prime p);
  • the curve equation, here Y2 = X3 + aX + b for two constants a and b;
  • a conventional generator G, which is a curve point (i.e. a pair of coordinates (X,Y) which matches the curve equation);
  • the order n of the generator, and its cofactor h.

The order n is the smallest non-zero integer such that nG = 0; h is such that the total number of points in the curve is equal to nh. Normally, we choose the curve such that n is prime and h = 1, i.e. the generator generates the whole curve, and with a prime order suitable for Diffie-Hellman or DSA.

The seed is not needed at all to compute things with the curve. The seed was used to generate the curve itself. It is about "nothing-up-my-sleeve numbers". It is mathematically possible (or at least it may be) to generate special parameters with a hidden structure (p, a and b in the notations above) such that the curve looks good, but is in fact weak against cryptanalysis. Normal, honest curve generation looks like this: we generate completely random p, a and b, and then check the requirements in section 2 of RFC 5639; if they are not all met, try again. Special-form parameters which induce weaknesses are extremely rare, so random generation is fine.

To demonstrate that this normal process was followed, and, therefore, that the curve parameters were not crafted to be especially weak, it is customary to fully specify the PRNG used to produce all the random values, complete with its starting seed(s). Thus, third parties (e.g., you) can rerun the PRNG and the curve generation process, and see that they obtain, indeed, the same curve parameters. For the Brainpool curves, this PRNG is specified in appendix A. Here, they have two seeds because they first generate p, and only then a and b, as two distinct steps, each with its own seed.

However, there is no need to do it every time. When you do such a re-generation of the curve, you do it once, just to make sure that the parameters that you are found in the RFC are legit. In fact you don't need to do it yourself, you just need to convince yourself that someone, somewhere, has done it. In any case, the curve parameters that you are about to use are already in Bouncy Castle.

To just use the curve, the seed is not needed and can be set to null. There is a room in the ECDomainParameters class to specify a seed because some (but not all) standards for encoding the curve parameters have some provision to support including such a seed. However, this does not really apply to your case:

  • Your code will talk to your code; both parties thus already know what curve is used, and have no need to encode the curve parameters anywhere at all.
  • Even if you encode the parameters, you won't need to rerun the curve generation process, because each party will use its own, hardcoded, parameters, not the ones sent by the peer.
  • In any case, there is no standard for the parameter generation PRNG. Brainpool has its own, but there is no agreed-upon PRNG which would fit everybody (contrary to DSA parameters, where the standard itself includes it, see appendix A). Indeed, this can be seen in the fact that the Brainpool process uses two seeds, not one.

So, right now, the inclusion of the seed in encoded parameters, and in the ECDomainParameters class, is pure dead weight. Just set it to null and move on.

Not being myself a practitioner of the Bouncy Castle C# API, I cannot really comment on your use of it, but from a cursory look, things seem fine. Your secretPlainBytes variable seems spurious; I suppose it is the message which you will then encrypt with the agreed-upon key (resulting from the DH key exchange), using code which you don't show.

  • secretPlainBytes is for a later use. I stretch the 512 bit to 3x256 bit. And then encrypt the plain text with Aes, Twofish and Serpent.
    – hdev
    Sep 13, 2013 at 13:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .