Add `Secp256k1::new_deterministic` constructor for applications which don't need randomness

This commit is contained in:
Andrew Poelstra 2015-04-11 13:21:58 -05:00
parent 96e1844c25
commit 6b39f97f51
2 changed files with 41 additions and 28 deletions

View File

@ -67,8 +67,8 @@ impl SecretKey {
/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
#[inline]
pub fn from_slice<R: Rng>(secp: &Secp256k1<R>, data: &[u8])
-> Result<SecretKey, Error> {
pub fn from_slice<R>(secp: &Secp256k1<R>, data: &[u8])
-> Result<SecretKey, Error> {
match data.len() {
constants::SECRET_KEY_SIZE => {
let mut ret = [0; constants::SECRET_KEY_SIZE];
@ -88,10 +88,10 @@ impl SecretKey {
#[inline]
/// Adds one secret key to another, modulo the curve order
pub fn add_assign<R: Rng>(&mut self,
secp: &Secp256k1<R>,
other: &SecretKey)
-> Result<(), Error> {
pub fn add_assign<R>(&mut self,
secp: &Secp256k1<R>,
other: &SecretKey)
-> Result<(), Error> {
unsafe {
if ffi::secp256k1_ec_privkey_tweak_add(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 {
Err(Unknown)
@ -117,10 +117,10 @@ impl PublicKey {
/// Creates a new public key from a secret key.
#[inline]
pub fn from_secret_key<R: Rng>(secp: &Secp256k1<R>,
sk: &SecretKey,
compressed: bool)
-> PublicKey {
pub fn from_secret_key<R>(secp: &Secp256k1<R>,
sk: &SecretKey,
compressed: bool)
-> PublicKey {
let mut pk = PublicKey::new(compressed);
let compressed = if compressed {1} else {0};
let mut len = 0;
@ -139,8 +139,8 @@ impl PublicKey {
/// Creates a public key directly from a slice
#[inline]
pub fn from_slice<R: Rng>(secp: &Secp256k1<R>, data: &[u8])
-> Result<PublicKey, Error> {
pub fn from_slice<R>(secp: &Secp256k1<R>, data: &[u8])
-> Result<PublicKey, Error> {
match data.len() {
constants::COMPRESSED_PUBLIC_KEY_SIZE => {
let mut ret = [0; constants::COMPRESSED_PUBLIC_KEY_SIZE];
@ -212,10 +212,10 @@ impl PublicKey {
#[inline]
/// Adds the pk corresponding to `other` to the pk `self` in place
pub fn add_exp_assign<R: Rng>(&mut self,
secp: &Secp256k1<R>,
other: &SecretKey)
-> Result<(), Error> {
pub fn add_exp_assign<R>(&mut self,
secp: &Secp256k1<R>,
other: &SecretKey)
-> Result<(), Error> {
unsafe {
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, self.as_mut_ptr(),
self.len() as ::libc::c_int,

View File

@ -209,17 +209,28 @@ impl fmt::Display for Error {
}
/// The secp256k1 engine, used to execute all signature operations
pub struct Secp256k1<R: Rng = Fortuna> {
pub struct Secp256k1<R = Fortuna> {
ctx: ffi::Context,
rng: R
}
impl<R: Rng> Drop for Secp256k1<R> {
impl<R> Drop for Secp256k1<R> {
fn drop(&mut self) {
unsafe { ffi::secp256k1_context_destroy(self.ctx); }
}
}
impl Secp256k1<()> {
/// Constructs a new secp256k1 engine without a RNG. This is
/// useful for, e.g. BIP32 implementations, where all keys are
/// computed externally to the secp256k1 engine. Note that if
/// you try to use this for `SecretKey::new`, which generates
/// a random key, it will panic.
pub fn new_deterministic() -> Secp256k1<()> {
Secp256k1::with_rng(()).unwrap()
}
}
impl Secp256k1<Fortuna> {
/// Constructs a new secp256k1 engine with the default key-generation Rng
/// (a Fortuna seeded with randomness from the OS during `new`)
@ -233,15 +244,6 @@ impl Secp256k1<Fortuna> {
}
impl<R: Rng> Secp256k1<R> {
/// Constructs a new secp256k1 engine with its key-generation RNG specified
pub fn with_rng(rng: R) -> io::Result<Secp256k1<R>> {
let ctx = unsafe {
ffi::secp256k1_context_create(ffi::SECP256K1_START_VERIFY |
ffi::SECP256K1_START_SIGN)
};
Ok(Secp256k1 { ctx: ctx, rng: rng })
}
/// Generates a random keypair. Convenience function for `key::SecretKey::new`
/// and `key::PublicKey::from_secret_key`; call those functions directly for
/// batch key generation.
@ -252,6 +254,17 @@ impl<R: Rng> Secp256k1<R> {
let pk = key::PublicKey::from_secret_key(self, &sk, compressed);
(sk, pk)
}
}
impl<R> Secp256k1<R> {
/// Constructs a new secp256k1 engine with its key-generation RNG specified
pub fn with_rng(rng: R) -> io::Result<Secp256k1<R>> {
let ctx = unsafe {
ffi::secp256k1_context_create(ffi::SECP256K1_START_VERIFY |
ffi::SECP256K1_START_SIGN)
};
Ok(Secp256k1 { ctx: ctx, rng: rng })
}
/// Constructs a signature for `msg` using the secret key `sk` and nonce `nonce`
pub fn sign(&self, msg: &Message, sk: &key::SecretKey)
@ -349,7 +362,7 @@ mod tests {
#[test]
fn invalid_pubkey() {
let s = Secp256k1::new().unwrap();
let s = Secp256k1::new_deterministic();
let sig = Signature::from_slice(&[0; 72]).unwrap();
let pk = PublicKey::new(true);
let mut msg = [0u8; 32];