Here's the relevant source code from what I did. It has not yet been
committed to pycryptopp trunk. I intend at some point to publicize
this, request comments from other experts, submit patches to get such
a thing included in Crypto++ itself, and write unit tests with test
vectors.
Regards,
Zooko
[1] http://allmydata.org/trac/pycryptopp
[2] http://allmydata.org/trac/pycryptopp/ticket/2
---
http://allmydata.org -- Tahoe, the Least-Authority Filesystem
http://allmydata.com -- back up all your files for $5/month
------- begin appended C++ source code
OID curve;
Integer grouporder;
byte privexpbytes[24] = {0};
Integer privexponent;
privexponent.Decode(privexpbytes, sizeof(privexpbytes)); assert
(priveexponent == 0); // just checking..
curve = ASN1::secp192r1();
grouporder = DL_GroupParameters_EC<ECP>(curve).GetGroupOrder();
Tiger t;
static const byte* TAG_AND_SALT = reinterpret_cast<const byte*>( \
"102:pycryptopp v0.5.3 key derivation algorithm using Tiger
hash to generate ECDSA 192-bit secret exponents," \
"16:H1yGNvUONoc0FD1d," \
);
t.Update(TAG_AND_SALT, sizeof(TAG_AND_SALT));
t.Update(reinterpret_cast<const byte*>(seed), seedlen);
t.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE);
privexponent.Decode(privexpbytes, sizeof(privexpbytes));
while ((privexponent >= grouporder) || (privexponent == 0)) {
Tiger t2;
t2.Update(TAG_AND_SALT, sizeof(TAG_AND_SALT));
t2.Update(privexpbytes, sizeof(privexpbytes));
t2.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE);
privexponent.Decode(privexpbytes, sizeof(privexpbytes));
}
SigningKey* signer = new SigningKey;
signer->k = ECDSA<ECP, Tiger>::Signer(curve, privexponent);
> entropy coming from a source which doesn't support the
> CryptoPP::RandomNumberGenerator...
I'm not sure what exactly you're trying to accomplish, but here goes...
* the library offers a NullRNG object if you need to satisfy an API,
but don't have a pseudo random source. It is located in cryptlib
classes.
* given a seed, you can use IncorporateEntropy (const byte *input,
size_t length) of RandomNumberGenerator to try and keep objects in
lock step. I suppose you would use this case if you are trying to
create the same key given the same inputs in different libraries
(similar to validation parameters?). See
http://cryptopp.com/docs/ref/class_random_number_generator.html
Jeff
> I'm not sure what exactly you're trying to accomplish, but here
> goes...
The goal is to generate a 192-bit ECC private key from a 96-bit
secret value, such that
a) anyone who starts with the same 96-bit secret value can regenerate
the same 192-bit ECC private key, and
b) anyone who doesn't start with the same 96-bit secret value
can't. ;-)
> * the library offers a NullRNG object if you need to satisfy an API,
> but don't have a pseudo random source. It is located in cryptlib
> classes.
This would fail criterion b, of course.
> * given a seed, you can use IncorporateEntropy (const byte *input,
> size_t length) of RandomNumberGenerator to try and keep objects in
> lock step. I suppose you would use this case if you are trying to
> create the same key given the same inputs in different libraries
> (similar to validation parameters?). See
> http://cryptopp.com/docs/ref/class_random_number_generator.html
If I recall correctly, I tried this first, and was surprised to learn
that it actually went ahead and incorporated other entropy in
addition to the seed I had given it, thus failing criterion a.
Also, I looked at the source code of the built-in RNG, and it seemed
like it would be potentially more complicated to document (e.g. to
facilitate independent, compatible re-implementation) than the
simpler algorithm that I posted in my previous note.
The fact that Patrick came up with a very similar algorithm
independently to solve a similar problem is encouraging in that way.
By the way, we're having a contest in which anyone who finds a
significant security flaw in our decentralized file-sharing system
gets a customized t-shirt with their exploit printed on it and a big
thank-you from us:
Regards,
Zooko