Move FFI functions into separate module; add documentation and style lints
This commit is contained in:
parent
15e0995585
commit
448f4829e7
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
//! FFI bindings
|
||||||
|
use libc::{c_int, c_uchar};
|
||||||
|
|
||||||
|
#[link(name = "secp256k1")]
|
||||||
|
extern "C" {
|
||||||
|
pub fn secp256k1_start();
|
||||||
|
pub fn secp256k1_stop();
|
||||||
|
pub fn secp256k1_ecdsa_verify(
|
||||||
|
msg : *const c_uchar, msglen : c_int,
|
||||||
|
sig : *const c_uchar, siglen : c_int,
|
||||||
|
pubkey : *const c_uchar, pubkeylen : c_int
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn secp256k1_ecdsa_pubkey_create(
|
||||||
|
pubkey : *mut c_uchar,
|
||||||
|
pubkeylen : *mut c_int,
|
||||||
|
seckey : *const c_uchar,
|
||||||
|
compressed : c_int
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn secp256k1_ecdsa_sign(
|
||||||
|
msg : *const c_uchar, msglen : c_int,
|
||||||
|
sig : *mut c_uchar, siglen : *mut c_int,
|
||||||
|
seckey : *const c_uchar,
|
||||||
|
nonce : *const c_uchar
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn secp256k1_ecdsa_sign_compact(
|
||||||
|
msg : *const c_uchar, msglen : c_int,
|
||||||
|
sig64 : *mut c_uchar,
|
||||||
|
seckey : *const c_uchar,
|
||||||
|
nonce : *const c_uchar,
|
||||||
|
recid : *mut c_int
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
pub fn secp256k1_ecdsa_recover_compact(
|
||||||
|
msg : *const c_uchar, msglen : c_int,
|
||||||
|
sig64 : *const c_uchar,
|
||||||
|
pubkey : *mut c_uchar,
|
||||||
|
pubkeylen : *mut c_int,
|
||||||
|
compressed : c_int,
|
||||||
|
recid : c_int
|
||||||
|
) -> c_int;
|
||||||
|
}
|
||||||
|
|
101
src/secp256k1.rs
101
src/secp256k1.rs
|
@ -1,3 +1,11 @@
|
||||||
|
|
||||||
|
//! # Secp256k1
|
||||||
|
//! Rust bindings for Pieter Wuille's secp256k1 library, which is used for
|
||||||
|
//! fast and accurate manipulation of ECDSA signatures on the secp256k1
|
||||||
|
//! curve. Such signatures are used extensively by the Bitcoin network
|
||||||
|
//! and its derivatives.
|
||||||
|
//!
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![crate_type = "dylib"]
|
#![crate_type = "dylib"]
|
||||||
|
@ -6,95 +14,76 @@
|
||||||
#![feature(phase)]
|
#![feature(phase)]
|
||||||
#![feature(globs)] // for tests only
|
#![feature(globs)] // for tests only
|
||||||
|
|
||||||
|
// Coding conventions
|
||||||
|
#![deny(non_uppercase_pattern_statics)]
|
||||||
|
#![deny(uppercase_variables)]
|
||||||
|
#![deny(non_camel_case_types)]
|
||||||
|
#![deny(non_snake_case_functions)]
|
||||||
|
#![deny(unused_mut)]
|
||||||
|
#![warn(missing_doc)]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate sync;
|
extern crate sync;
|
||||||
|
|
||||||
use libc::{c_int, c_uchar};
|
use libc::c_int;
|
||||||
use sync::one::{Once, ONCE_INIT};
|
use sync::one::{Once, ONCE_INIT};
|
||||||
|
|
||||||
#[link(name = "secp256k1")]
|
pub mod ffi;
|
||||||
extern "C" {
|
|
||||||
pub fn secp256k1_start();
|
|
||||||
pub fn secp256k1_stop();
|
|
||||||
pub fn secp256k1_ecdsa_verify(
|
|
||||||
msg : *const c_uchar, msglen : c_int,
|
|
||||||
sig : *const c_uchar, siglen : c_int,
|
|
||||||
pubkey : *const c_uchar, pubkeylen : c_int
|
|
||||||
) -> c_int;
|
|
||||||
|
|
||||||
pub fn secp256k1_ecdsa_pubkey_create(
|
|
||||||
pubkey : *mut c_uchar,
|
|
||||||
pubkeylen : *mut c_int,
|
|
||||||
seckey : *const c_uchar,
|
|
||||||
compressed : c_int
|
|
||||||
) -> c_int;
|
|
||||||
|
|
||||||
pub fn secp256k1_ecdsa_sign(
|
|
||||||
msg : *const c_uchar, msglen : c_int,
|
|
||||||
sig : *mut c_uchar, siglen : *mut c_int,
|
|
||||||
seckey : *const c_uchar,
|
|
||||||
nonce : *const c_uchar
|
|
||||||
) -> c_int;
|
|
||||||
|
|
||||||
pub fn secp256k1_ecdsa_sign_compact(
|
|
||||||
msg : *const c_uchar, msglen : c_int,
|
|
||||||
sig64 : *mut c_uchar,
|
|
||||||
seckey : *const c_uchar,
|
|
||||||
nonce : *const c_uchar,
|
|
||||||
recid : *mut c_int
|
|
||||||
) -> c_int;
|
|
||||||
|
|
||||||
pub fn secp256k1_ecdsa_recover_compact(
|
|
||||||
msg : *const c_uchar, msglen : c_int,
|
|
||||||
sig64 : *const c_uchar,
|
|
||||||
pubkey : *mut c_uchar,
|
|
||||||
pubkeylen : *mut c_int,
|
|
||||||
compressed : c_int,
|
|
||||||
recid : c_int
|
|
||||||
) -> c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// A secret 256-bit nonce used as `k` in an ECDSA signature
|
||||||
pub type Nonce = [u8, ..32];
|
pub type Nonce = [u8, ..32];
|
||||||
|
|
||||||
|
/// A secret 256-bit key used as `x` in an ECDSA signature
|
||||||
pub type SecKey = [u8, ..32];
|
pub type SecKey = [u8, ..32];
|
||||||
pub type PubKeyCompressed = [u8, ..33];
|
|
||||||
pub type PubKeyUncompressed = [u8, ..65];
|
/// A public key
|
||||||
pub enum PubKey {
|
pub enum PubKey {
|
||||||
Compressed(PubKeyCompressed),
|
/// A compressed (1-bit x-coordinate) EC public key
|
||||||
Uncompressed(PubKeyUncompressed)
|
Compressed([u8, ..33]),
|
||||||
|
/// An uncompressed (full x-coordinate) EC public key
|
||||||
|
Uncompressed([u8, ..65])
|
||||||
}
|
}
|
||||||
|
/// An ECDSA signature
|
||||||
pub type Signature = Vec<u8>;
|
pub type Signature = Vec<u8>;
|
||||||
|
|
||||||
|
/// An ECDSA error
|
||||||
#[deriving(Show)]
|
#[deriving(Show)]
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
#[deriving(PartialEq)]
|
#[deriving(PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Bad public key
|
||||||
InvalidPublicKey,
|
InvalidPublicKey,
|
||||||
|
/// Bad signature
|
||||||
InvalidSignature,
|
InvalidSignature,
|
||||||
|
/// Bad secret key
|
||||||
InvalidSecretKey,
|
InvalidSecretKey,
|
||||||
|
/// Bad nonce
|
||||||
InvalidNonce,
|
InvalidNonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
#[deriving(PartialEq)]
|
#[deriving(PartialEq)]
|
||||||
|
/// Result of verifying a signature
|
||||||
pub type VerifyResult = Result<bool, Error>;
|
pub type VerifyResult = Result<bool, Error>;
|
||||||
|
|
||||||
static mut Secp256k1_init : Once = ONCE_INIT;
|
static mut Secp256k1_init : Once = ONCE_INIT;
|
||||||
|
|
||||||
|
/// The secp256k1 engine, used to execute all signature operations
|
||||||
pub struct Secp256k1;
|
pub struct Secp256k1;
|
||||||
|
|
||||||
|
|
||||||
impl Secp256k1 {
|
impl Secp256k1 {
|
||||||
|
/// Constructs a new secp256k1 engine.
|
||||||
pub fn new() -> Secp256k1 {
|
pub fn new() -> Secp256k1 {
|
||||||
unsafe {
|
unsafe {
|
||||||
Secp256k1_init.doit(|| {
|
Secp256k1_init.doit(|| {
|
||||||
secp256k1_start();
|
ffi::secp256k1_start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Secp256k1
|
Secp256k1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determines the public key corresponding to a given private key.
|
||||||
pub fn pubkey_create(
|
pub fn pubkey_create(
|
||||||
&self,
|
&self,
|
||||||
pubkey : &mut PubKey,
|
pubkey : &mut PubKey,
|
||||||
|
@ -107,7 +96,7 @@ impl Secp256k1 {
|
||||||
};
|
};
|
||||||
let mut len = pub_len as c_int;
|
let mut len = pub_len as c_int;
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
secp256k1_ecdsa_pubkey_create(
|
ffi::secp256k1_ecdsa_pubkey_create(
|
||||||
pub_ptr, &mut len,
|
pub_ptr, &mut len,
|
||||||
seckey.as_ptr(),
|
seckey.as_ptr(),
|
||||||
if compressed {1} else {0}
|
if compressed {1} else {0}
|
||||||
|
@ -123,6 +112,7 @@ impl Secp256k1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a signature for `msg` using the secret key `seckey`
|
||||||
pub fn sign(&self, sig : &mut Signature, msg : &[u8], seckey : &SecKey, nonce : &Nonce) -> Result<(), Error> {
|
pub fn sign(&self, sig : &mut Signature, msg : &[u8], seckey : &SecKey, nonce : &Nonce) -> Result<(), Error> {
|
||||||
|
|
||||||
let origlen = 72u;
|
let origlen = 72u;
|
||||||
|
@ -133,7 +123,7 @@ impl Secp256k1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
secp256k1_ecdsa_sign(
|
ffi::secp256k1_ecdsa_sign(
|
||||||
msg.as_ptr(), msg.len() as c_int,
|
msg.as_ptr(), msg.len() as c_int,
|
||||||
sig.as_mut_ptr(), &mut siglen,
|
sig.as_mut_ptr(), &mut siglen,
|
||||||
seckey.as_ptr(),
|
seckey.as_ptr(),
|
||||||
|
@ -152,6 +142,7 @@ impl Secp256k1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a compact signature for `msg` using the secret key `seckey`
|
||||||
pub fn sign_compact(
|
pub fn sign_compact(
|
||||||
&self,
|
&self,
|
||||||
sig : &mut [u8],
|
sig : &mut [u8],
|
||||||
|
@ -169,7 +160,7 @@ impl Secp256k1 {
|
||||||
let mut recid = 0;
|
let mut recid = 0;
|
||||||
|
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
secp256k1_ecdsa_sign_compact(
|
ffi::secp256k1_ecdsa_sign_compact(
|
||||||
msg.as_ptr(), msg.len() as c_int,
|
msg.as_ptr(), msg.len() as c_int,
|
||||||
sig.as_mut_ptr(),
|
sig.as_mut_ptr(),
|
||||||
seckey.as_ptr(),
|
seckey.as_ptr(),
|
||||||
|
@ -185,6 +176,8 @@ impl Secp256k1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determines the public key for which `sig` is a valid signature for
|
||||||
|
/// `msg`. Returns through the out-pointer `pubkey`.
|
||||||
pub fn recover_compact(
|
pub fn recover_compact(
|
||||||
&self,
|
&self,
|
||||||
msg : &[u8],
|
msg : &[u8],
|
||||||
|
@ -206,7 +199,7 @@ impl Secp256k1 {
|
||||||
|
|
||||||
let mut len = pub_len as c_int;
|
let mut len = pub_len as c_int;
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
secp256k1_ecdsa_recover_compact(
|
ffi::secp256k1_ecdsa_recover_compact(
|
||||||
msg.as_ptr(), msg.len() as i32,
|
msg.as_ptr(), msg.len() as i32,
|
||||||
sig.as_ptr(),
|
sig.as_ptr(),
|
||||||
pub_ptr, &mut len,
|
pub_ptr, &mut len,
|
||||||
|
@ -225,6 +218,8 @@ impl Secp256k1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
|
||||||
|
/// key `pubkey`. Returns `Ok(true)` on success.
|
||||||
pub fn verify(&self, msg : &[u8], sig : &[u8], pubkey : &PubKey) -> VerifyResult {
|
pub fn verify(&self, msg : &[u8], sig : &[u8], pubkey : &PubKey) -> VerifyResult {
|
||||||
|
|
||||||
let (pub_ptr, pub_len) = match *pubkey {
|
let (pub_ptr, pub_len) = match *pubkey {
|
||||||
|
@ -233,7 +228,7 @@ impl Secp256k1 {
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
secp256k1_ecdsa_verify(
|
ffi::secp256k1_ecdsa_verify(
|
||||||
msg.as_ptr(), msg.len() as c_int,
|
msg.as_ptr(), msg.len() as c_int,
|
||||||
sig.as_ptr(), sig.len() as c_int,
|
sig.as_ptr(), sig.len() as c_int,
|
||||||
pub_ptr, pub_len as c_int
|
pub_ptr, pub_len as c_int
|
||||||
|
|
Loading…
Reference in New Issue