Global secp256k1 context

This commit is contained in:
arkpar 2016-01-17 14:09:42 +01:00
parent 6dca77434f
commit 1e8dd6321f

View File

@ -8,6 +8,10 @@ pub type Secret = H256;
pub type Public = H512; pub type Public = H512;
pub type Signature = H520; pub type Signature = H520;
lazy_static! {
static ref SECP256K1: Secp256k1 = Secp256k1::new();
}
impl Signature { impl Signature {
/// Create a new signature from the R, S and V componenets. /// Create a new signature from the R, S and V componenets.
pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Signature { pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Signature {
@ -82,10 +86,10 @@ pub struct KeyPair {
impl KeyPair { impl KeyPair {
/// Create a pair from secret key /// Create a pair from secret key
pub fn from_secret(secret: Secret) -> Result<KeyPair, CryptoError> { pub fn from_secret(secret: Secret) -> Result<KeyPair, CryptoError> {
let context = Secp256k1::new(); let context = &SECP256K1;
let s: key::SecretKey = try!(key::SecretKey::from_slice(&context, &secret)); let s: key::SecretKey = try!(key::SecretKey::from_slice(context, &secret));
let pub_key = try!(key::PublicKey::from_secret_key(&context, &s)); let pub_key = try!(key::PublicKey::from_secret_key(context, &s));
let serialized = pub_key.serialize_vec(&context, false); let serialized = pub_key.serialize_vec(context, false);
let p: Public = Public::from_slice(&serialized[1..65]); let p: Public = Public::from_slice(&serialized[1..65]);
Ok(KeyPair { Ok(KeyPair {
secret: secret, secret: secret,
@ -94,10 +98,10 @@ impl KeyPair {
} }
/// Create a new random key pair /// Create a new random key pair
pub fn create() -> Result<KeyPair, CryptoError> { pub fn create() -> Result<KeyPair, CryptoError> {
let context = Secp256k1::new(); let context = &SECP256K1;
let mut rng = try!(OsRng::new()); let mut rng = try!(OsRng::new());
let (sec, publ) = try!(context.generate_keypair(&mut rng)); let (sec, publ) = try!(context.generate_keypair(&mut rng));
let serialized = publ.serialize_vec(&context, false); let serialized = publ.serialize_vec(context, false);
let p: Public = Public::from_slice(&serialized[1..65]); let p: Public = Public::from_slice(&serialized[1..65]);
let s: Secret = unsafe { ::std::mem::transmute(sec) }; let s: Secret = unsafe { ::std::mem::transmute(sec) };
Ok(KeyPair { Ok(KeyPair {
@ -128,10 +132,10 @@ pub mod ec {
/// Recovers Public key from signed message hash. /// Recovers Public key from signed message hash.
pub fn recover(signature: &Signature, message: &H256) -> Result<Public, CryptoError> { pub fn recover(signature: &Signature, message: &H256) -> Result<Public, CryptoError> {
use secp256k1::*; use secp256k1::*;
let context = Secp256k1::new(); let context = &crypto::SECP256K1;
let rsig = try!(RecoverableSignature::from_compact(&context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32)))); let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32))));
let publ = try!(context.recover(&try!(Message::from_slice(&message)), &rsig)); let publ = try!(context.recover(&try!(Message::from_slice(&message)), &rsig));
let serialized = publ.serialize_vec(&context, false); let serialized = publ.serialize_vec(context, false);
let p: Public = Public::from_slice(&serialized[1..65]); let p: Public = Public::from_slice(&serialized[1..65]);
//TODO: check if it's the zero key and fail if so. //TODO: check if it's the zero key and fail if so.
Ok(p) Ok(p)
@ -140,10 +144,10 @@ pub mod ec {
pub fn sign(secret: &Secret, message: &H256) -> Result<Signature, CryptoError> { pub fn sign(secret: &Secret, message: &H256) -> Result<Signature, CryptoError> {
// TODO: allow creation of only low-s signatures. // TODO: allow creation of only low-s signatures.
use secp256k1::*; use secp256k1::*;
let context = Secp256k1::new(); let context = &crypto::SECP256K1;
let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) }; let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) };
let s = try!(context.sign_recoverable(&try!(Message::from_slice(&message)), sec)); let s = try!(context.sign_recoverable(&try!(Message::from_slice(&message)), sec));
let (rec_id, data) = s.serialize_compact(&context); let (rec_id, data) = s.serialize_compact(context);
let mut signature: crypto::Signature = unsafe { ::std::mem::uninitialized() }; let mut signature: crypto::Signature = unsafe { ::std::mem::uninitialized() };
signature.clone_from_slice(&data); signature.clone_from_slice(&data);
signature[64] = rec_id.to_i32() as u8; signature[64] = rec_id.to_i32() as u8;
@ -152,15 +156,15 @@ pub mod ec {
/// Verify signature. /// Verify signature.
pub fn verify(public: &Public, signature: &Signature, message: &H256) -> Result<bool, CryptoError> { pub fn verify(public: &Public, signature: &Signature, message: &H256) -> Result<bool, CryptoError> {
use secp256k1::*; use secp256k1::*;
let context = Secp256k1::new(); let context = &crypto::SECP256K1;
let rsig = try!(RecoverableSignature::from_compact(&context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32)))); let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32))));
let sig = rsig.to_standard(&context); let sig = rsig.to_standard(context);
let mut pdata: [u8; 65] = [4u8; 65]; let mut pdata: [u8; 65] = [4u8; 65];
let ptr = pdata[1..].as_mut_ptr(); let ptr = pdata[1..].as_mut_ptr();
let src = public.as_ptr(); let src = public.as_ptr();
unsafe { ::std::ptr::copy_nonoverlapping(src, ptr, 64) }; unsafe { ::std::ptr::copy_nonoverlapping(src, ptr, 64) };
let publ = try!(key::PublicKey::from_slice(&context, &pdata)); let publ = try!(key::PublicKey::from_slice(context, &pdata));
match context.verify(&try!(Message::from_slice(&message)), &sig, &publ) { match context.verify(&try!(Message::from_slice(&message)), &sig, &publ) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(Error::IncorrectSignature) => Ok(false), Err(Error::IncorrectSignature) => Ok(false),
@ -190,17 +194,18 @@ pub mod ec {
pub mod ecdh { pub mod ecdh {
use crypto::*; use crypto::*;
use crypto::{self};
pub fn agree(secret: &Secret, public: &Public, ) -> Result<Secret, CryptoError> { pub fn agree(secret: &Secret, public: &Public, ) -> Result<Secret, CryptoError> {
use secp256k1::*; use secp256k1::*;
let context = Secp256k1::new(); let context = &crypto::SECP256K1;
let mut pdata: [u8; 65] = [4u8; 65]; let mut pdata: [u8; 65] = [4u8; 65];
let ptr = pdata[1..].as_mut_ptr(); let ptr = pdata[1..].as_mut_ptr();
let src = public.as_ptr(); let src = public.as_ptr();
unsafe { ::std::ptr::copy_nonoverlapping(src, ptr, 64) }; unsafe { ::std::ptr::copy_nonoverlapping(src, ptr, 64) };
let publ = try!(key::PublicKey::from_slice(&context, &pdata)); let publ = try!(key::PublicKey::from_slice(context, &pdata));
let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) }; let sec: &key::SecretKey = unsafe { ::std::mem::transmute(secret) };
let shared = ecdh::SharedSecret::new_raw(&context, &publ, &sec); let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec);
let s: Secret = unsafe { ::std::mem::transmute(shared) }; let s: Secret = unsafe { ::std::mem::transmute(shared) };
Ok(s) Ok(s)
} }