I'm taking advantage of the CC0 license on any of David's code to
give me permission to do this :). Almost all of it is my code by
this point so I am also morally in the clear.
-a
This reverts commit 9889090784.
This is not ready for primetime -- the move prevention also prevents
reborrowing, which makes secret keys nearly unusable.
Using the `secretdata` library, we can store SecretKeys in such a way
that they cannot be moved or copied, and their memory is zeroed out on
drop. This gives us some assurance that in the case of memory unsafety,
there is not secret key data lying around anywhere that we don't expect.
Unfortunately, it means that we cannot construct secret keys and then
return them, which forces the interface to change a fair bit. I removed
the `generate_keypair` function from Secp256k1, then `generate_nonce`
for symmetry, then dropped the `Secp256k1` struct entirely because it
turned out that none of the remaining functions used the `self` param.
So here we are. I bumped the version number. Sorry about this.
The typesafe version could not accept illegally padded signatures because
`Signature` is a fixed-width type. Unfortunately such signatures are on
the blockchain, and we need a way to verify them.
When creating a Secp256k1, we attach a Fortuna CSRNG seeded from the
OS RNG, rather than using the OS RNG all the time. This moves the
potential RNG failure to the creation of the object, rather than at
every single place that keys are generated. It also reduces trust
in the operating system RNG.
This does mean that Secp256k1::new() now returns an IoResult while
the generate_* methods no longer return Results, so this is a breaking
change.
Also add a benchmark for key generation. On my system I get:
test tests::generate_compressed ... bench: 492990 ns/iter (+/- 27981)
test tests::generate_uncompressed ... bench: 495148 ns/iter (+/- 29829)
Contrast the numbers with OsRng:
test tests::generate_compressed ... bench: 66691 ns/iter (+/- 3640)
test tests::generate_uncompressed ... bench: 67148 ns/iter (+/- 3806)
Not too shabby :)
[breaking-change]
It turns out I need to run `init` before pretty-much every FFI function,
which means that most everything would have to be marked unsafe if I'm
expecting the Rust user to do this. This is unacceptable -- users who
need to sacrifice safety for speed can just use the `ffi::` functions
instead.
Also, I noticed that I was locking up in `PublicKey::from_secret_key`.
Fix to return an error value -- unfortunately a breaking change since
it changes the function signature.
[breaking-change]
As @dpc observes, embedded systems do not necessarily have allocators, so we
should avoid using them if it is not too much hassle. (And it is no hassle at
all.)
Verifying signatures does not require any randomness, but requires the user
to create a `Secp256k1` object nonetheless (this is just a way to guarantee
that `init` is called --- an alternate API would be to have an independent
unsafe `verify` function). If a Rng can't be created, rather than failing
the `Secp256k1` initialization, fail the functions that actually try to use
the Rng.
This way signing and verifying, which require no randomness beyond that input
to them, will work correctly.
To avoid checking for a working Rng on each call to `generate_keypair` and
`generate_nonce` (which is probably trivial next to the cost of actually
generating the randomness, but w/e, user knows best), the user should use
the generation functions in the `key` module, which take an Rng as input.