Add a `Sequence` iterator for generating sequential keypairs; fix tests
This commit is contained in:
parent
204524117c
commit
770ebbafc4
40
src/key.rs
40
src/key.rs
|
@ -32,6 +32,12 @@ impl_array_newtype!(Nonce, u8, constants::NONCE_SIZE)
|
|||
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);
|
||||
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE)
|
||||
|
||||
/// The number 1 encoded as a secret key
|
||||
pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1]);
|
||||
|
||||
/// Public key
|
||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
||||
pub struct PublicKey(PublicKeyData);
|
||||
|
@ -76,13 +82,14 @@ impl SecretKey {
|
|||
/// Creates a new random secret key
|
||||
#[inline]
|
||||
pub fn new<R:Rng>(rng: &mut R) -> SecretKey {
|
||||
init();
|
||||
let mut data = random_32_bytes(rng);
|
||||
unsafe {
|
||||
while ffi::secp256k1_ecdsa_seckey_verify(data.as_ptr()) == 0 {
|
||||
data = random_32_bytes(rng);
|
||||
}
|
||||
}
|
||||
SecretKey(random_32_bytes(rng))
|
||||
SecretKey(data)
|
||||
}
|
||||
|
||||
/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
|
||||
|
@ -121,6 +128,27 @@ impl SecretKey {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns an iterator for the (sk, pk) pairs starting one after this one,
|
||||
/// and incrementing by one each time
|
||||
pub fn sequence(&self, compressed: bool) -> Sequence {
|
||||
Sequence { last_sk: *self, compressed: compressed }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator of keypairs `(sk + 1, pk*G)`, `(sk + 2, pk*2G)`, ...
|
||||
pub struct Sequence {
|
||||
compressed: bool,
|
||||
last_sk: SecretKey,
|
||||
}
|
||||
|
||||
impl<'a> Iterator<(SecretKey, PublicKey)> for Sequence {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(SecretKey, PublicKey)> {
|
||||
self.last_sk.add_assign(&ONE).unwrap();
|
||||
Some((self.last_sk, PublicKey::from_secret_key(&self.last_sk, self.compressed)))
|
||||
}
|
||||
}
|
||||
|
||||
impl PublicKey {
|
||||
|
@ -293,6 +321,8 @@ impl fmt::Show for SecretKey {
|
|||
mod test {
|
||||
use std::rand::task_rng;
|
||||
|
||||
use test::Bencher;
|
||||
|
||||
use super::super::{Secp256k1, InvalidNonce, InvalidPublicKey, InvalidSecretKey};
|
||||
use super::{Nonce, PublicKey, SecretKey};
|
||||
|
||||
|
@ -383,6 +413,14 @@ mod test {
|
|||
assert!(pk2.add_exp_assign(&sk1).is_ok());
|
||||
assert_eq!(PublicKey::from_secret_key(&sk2, true), pk2);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn sequence_iterate(bh: &mut Bencher) {
|
||||
let mut s = Secp256k1::new().unwrap();
|
||||
let (sk, _) = s.generate_keypair(true);
|
||||
let mut iter = sk.sequence(true);
|
||||
bh.iter(|| iter.next())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ impl Secp256k1 {
|
|||
/// Generates a random keypair. Convenience function for `key::SecretKey::new`
|
||||
/// and `key::PublicKey::from_secret_key`; call those functions directly for
|
||||
/// batch key generation.
|
||||
#[inline]
|
||||
pub fn generate_keypair(&mut self, compressed: bool)
|
||||
-> (key::SecretKey, key::PublicKey) {
|
||||
let sk = key::SecretKey::new(&mut self.rng);
|
||||
|
@ -145,6 +146,7 @@ impl Secp256k1 {
|
|||
|
||||
/// Generates a random nonce. Convenience function for `key::Nonce::new`; call
|
||||
/// that function directly for batch nonce generation
|
||||
#[inline]
|
||||
pub fn generate_nonce(&mut self) -> key::Nonce {
|
||||
key::Nonce::new(&mut self.rng)
|
||||
}
|
||||
|
@ -205,6 +207,7 @@ impl Secp256k1 {
|
|||
|
||||
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
|
||||
/// key `pubkey`. Returns `Ok(true)` on success.
|
||||
#[inline]
|
||||
pub fn verify(msg: &[u8], sig: &[u8], pk: &key::PublicKey) -> Result<()> {
|
||||
init(); // This is a static function, so we have to init
|
||||
let res = unsafe {
|
||||
|
@ -229,7 +232,7 @@ mod tests {
|
|||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
|
||||
use test::Bencher;
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
use key::PublicKey;
|
||||
use super::Secp256k1;
|
||||
|
@ -237,15 +240,13 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn invalid_pubkey() {
|
||||
let s = Secp256k1::new().unwrap();
|
||||
|
||||
let mut msg = Vec::from_elem(32, 0u8);
|
||||
let sig = Vec::from_elem(32, 0u8);
|
||||
let pk = PublicKey::new(true);
|
||||
|
||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
||||
|
||||
assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidPublicKey));
|
||||
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidPublicKey));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -259,7 +260,7 @@ mod tests {
|
|||
|
||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
||||
|
||||
assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
|
||||
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -272,7 +273,7 @@ mod tests {
|
|||
|
||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
||||
|
||||
assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
|
||||
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -300,7 +301,7 @@ mod tests {
|
|||
|
||||
let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();
|
||||
|
||||
assert_eq!(s.verify(msg.as_slice(), sig.as_slice(), &pk), Ok(()));
|
||||
assert_eq!(Secp256k1::verify(msg.as_slice(), sig.as_slice(), &pk), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -316,7 +317,7 @@ mod tests {
|
|||
let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();
|
||||
|
||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
||||
assert_eq!(s.verify(msg.as_slice(), sig.as_slice(), &pk), Err(IncorrectSignature));
|
||||
assert_eq!(Secp256k1::verify(msg.as_slice(), sig.as_slice(), &pk), Err(IncorrectSignature));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -338,7 +339,9 @@ mod tests {
|
|||
pub fn generate_compressed(bh: &mut Bencher) {
|
||||
let mut s = Secp256k1::new().unwrap();
|
||||
bh.iter( || {
|
||||
let (_, _) = s.generate_keypair(true);
|
||||
let (sk, pk) = s.generate_keypair(true);
|
||||
black_box(sk);
|
||||
black_box(pk);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -346,7 +349,9 @@ mod tests {
|
|||
pub fn generate_uncompressed(bh: &mut Bencher) {
|
||||
let mut s = Secp256k1::new().unwrap();
|
||||
bh.iter( || {
|
||||
let (_, _) = s.generate_keypair(false);
|
||||
let (sk, pk) = s.generate_keypair(false);
|
||||
black_box(sk);
|
||||
black_box(pk);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue