Update for rustc changes

We can compile now, but not link -- there have been too many changes
in libsecp256k1 behind the scenes. Next commit :)
This commit is contained in:
Andrew Poelstra 2015-01-17 10:13:45 -06:00
parent 9cab4e023d
commit d495d9ca06
4 changed files with 176 additions and 161 deletions

View File

@ -16,25 +16,25 @@
//! Constants
/// The size (in bytes) of a nonce
pub static NONCE_SIZE: uint = 32;
pub const NONCE_SIZE: usize = 32;
/// The size (in bytes) of a secret key
pub static SECRET_KEY_SIZE: uint = 32;
pub const SECRET_KEY_SIZE: usize = 32;
/// The size (in bytes) of an uncompressed public key
pub static UNCOMPRESSED_PUBLIC_KEY_SIZE: uint = 65;
pub const UNCOMPRESSED_PUBLIC_KEY_SIZE: usize = 65;
/// The size (in bytes) of a compressed public key
pub static COMPRESSED_PUBLIC_KEY_SIZE: uint = 33;
pub const COMPRESSED_PUBLIC_KEY_SIZE: usize = 33;
/// The maximum size of a signature
pub static MAX_SIGNATURE_SIZE: uint = 72;
pub const MAX_SIGNATURE_SIZE: usize = 72;
/// The maximum size of a compact signature
pub static MAX_COMPACT_SIGNATURE_SIZE: uint = 64;
pub const MAX_COMPACT_SIGNATURE_SIZE: usize = 64;
/// The order of the secp256k1 curve
pub static CURVE_ORDER: [u8, ..32] = [
pub const CURVE_ORDER: [u8; 32] = [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
@ -42,7 +42,7 @@ pub static CURVE_ORDER: [u8, ..32] = [
];
/// The X coordinate of the generator
pub static GENERATOR_X: [u8, ..32] = [
pub const GENERATOR_X: [u8; 32] = [
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
@ -50,7 +50,7 @@ pub static GENERATOR_X: [u8, ..32] = [
];
/// The Y coordinate of the generator
pub static GENERATOR_Y: [u8, ..32] = [
pub const GENERATOR_Y: [u8; 32] = [
0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65,
0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,
0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,

View File

@ -27,17 +27,18 @@ use crypto::hmac::Hmac;
use crypto::mac::Mac;
use super::init;
use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey, Unknown};
use super::Result;
use super::Error::{InvalidNonce, InvalidPublicKey, InvalidSecretKey, Unknown};
use constants;
use ffi;
/// Secret 256-bit nonce used as `k` in an ECDSA signature
pub struct Nonce([u8, ..constants::NONCE_SIZE]);
impl_array_newtype!(Nonce, u8, constants::NONCE_SIZE)
pub struct Nonce([u8; constants::NONCE_SIZE]);
impl_array_newtype!(Nonce, u8, constants::NONCE_SIZE);
/// Secret 256-bit key used as `x` in an ECDSA signature
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_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,
@ -46,23 +47,25 @@ pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1]);
/// Public key
#[deriving(Clone, PartialEq, Eq, Show)]
#[derive(Clone, PartialEq, Eq, Show)]
pub struct PublicKey(PublicKeyData);
impl Copy for PublicKey {}
enum PublicKeyData {
Compressed([u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]),
Uncompressed([u8, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
Compressed([u8; constants::COMPRESSED_PUBLIC_KEY_SIZE]),
Uncompressed([u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE])
}
impl Copy for PublicKeyData {}
fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8, ..32] {
let mut ret = [0u8, ..32];
rng.fill_bytes(ret);
fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8; 32] {
let mut ret = [0u8; 32];
rng.fill_bytes(&mut ret);
ret
}
/// As described in RFC 6979
fn bits2octets(data: &[u8]) -> [u8, ..32] {
let mut ret = [0, ..32];
fn bits2octets(data: &[u8]) -> [u8; 32] {
let mut ret = [0; 32];
unsafe {
copy_nonoverlapping_memory(ret.as_mut_ptr(),
data.as_ptr(),
@ -83,7 +86,7 @@ impl Nonce {
pub fn from_slice(data: &[u8]) -> Result<Nonce> {
match data.len() {
constants::NONCE_SIZE => {
let mut ret = [0, ..constants::NONCE_SIZE];
let mut ret = [0; constants::NONCE_SIZE];
unsafe {
copy_nonoverlapping_memory(ret.as_mut_ptr(),
data.as_ptr(),
@ -99,54 +102,54 @@ impl Nonce {
#[inline]
#[allow(non_snake_case)] // so we can match the names in the RFC
pub fn deterministic(msg: &[u8], key: &SecretKey) -> Nonce {
static HMAC_SIZE: uint = 64;
const HMAC_SIZE: usize = 64;
macro_rules! hmac(
($res:expr <- key $key:expr, data $($data:expr),+) => ({
macro_rules! hmac {
($res:expr; key $key:expr, data $($data:expr),+) => ({
let mut hmacker = Hmac::new(Sha512::new(), $key.as_slice());
$(hmacker.input($data.as_slice());)+
hmacker.raw_result($res.as_mut_slice());
})
)
}
// Section 3.2a
// Goofy block just to avoid marking `msg_hash` as mutable
let mut hasher = Sha512::new();
hasher.input(msg);
let mut x = [0, ..HMAC_SIZE];
let mut x = [0; HMAC_SIZE];
hasher.result(x.as_mut_slice());
let msg_hash = bits2octets(x.as_slice());
// Section 3.2b
let mut V = [0x01u8, ..HMAC_SIZE];
let mut V = [0x01u8; HMAC_SIZE];
// Section 3.2c
let mut K = [0x00u8, ..HMAC_SIZE];
let mut K = [0x00u8; HMAC_SIZE];
// Section 3.2d
hmac!(K <- key K, data V, [0x00], key, msg_hash)
hmac!(K; key K, data V, [0x00], key, msg_hash);
// Section 3.2e
hmac!(V <- key K, data V)
hmac!(V; key K, data V);
// Section 3.2f
hmac!(K <- key K, data V, [0x01], key, msg_hash)
hmac!(K; key K, data V, [0x01], key, msg_hash);
// Section 3.2g
hmac!(V <- key K, data V)
hmac!(V; key K, data V);
// Section 3.2
let mut k = Err(InvalidSecretKey);
while k.is_err() {
// Try to generate the nonce
let mut T = [0x00u8, ..HMAC_SIZE];
hmac!(T <- key K, data V)
let mut T = [0x00u8; HMAC_SIZE];
hmac!(T; key K, data V);
k = Nonce::from_slice(T.slice_to(constants::NONCE_SIZE));
// Replace K, V
if k.is_err() {
hmac!(K <- key K, data V, [0x00])
hmac!(V <- key K, data V)
hmac!(K; key K, data V, [0x00]);
hmac!(V; key K, data V);
}
}
@ -174,7 +177,7 @@ impl SecretKey {
init();
match data.len() {
constants::SECRET_KEY_SIZE => {
let mut ret = [0, ..constants::SECRET_KEY_SIZE];
let mut ret = [0; constants::SECRET_KEY_SIZE];
unsafe {
if ffi::secp256k1_ecdsa_seckey_verify(data.as_ptr()) == 0 {
return Err(InvalidSecretKey);
@ -218,8 +221,11 @@ pub struct Sequence {
compressed: bool,
last_sk: SecretKey,
}
impl Copy for Sequence {}
impl Iterator for Sequence {
type Item = (SecretKey, PublicKey);
impl<'a> Iterator<(SecretKey, PublicKey)> for Sequence {
#[inline]
fn next(&mut self) -> Option<(SecretKey, PublicKey)> {
self.last_sk.add_assign(&ONE).unwrap();
@ -232,8 +238,11 @@ impl PublicKey {
#[inline]
pub fn new(compressed: bool) -> PublicKey {
PublicKey(
if compressed { Compressed([0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]) }
else { Uncompressed([0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) }
if compressed {
PublicKeyData::Compressed([0; constants::COMPRESSED_PUBLIC_KEY_SIZE])
} else {
PublicKeyData::Uncompressed([0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE])
}
)
}
@ -252,7 +261,7 @@ impl PublicKey {
pk.as_mut_ptr(), &mut len,
sk.as_ptr(), compressed), 1);
}
assert_eq!(len as uint, pk.len());
assert_eq!(len as usize, pk.len());
pk
}
@ -261,7 +270,7 @@ impl PublicKey {
pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
match data.len() {
constants::COMPRESSED_PUBLIC_KEY_SIZE => {
let mut ret = [0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE];
let mut ret = [0; constants::COMPRESSED_PUBLIC_KEY_SIZE];
unsafe {
if ffi::secp256k1_ecdsa_pubkey_verify(data.as_ptr(),
data.len() as ::libc::c_int) == 0 {
@ -271,16 +280,16 @@ impl PublicKey {
data.as_ptr(),
data.len());
}
Ok(PublicKey(Compressed(ret)))
Ok(PublicKey(PublicKeyData::Compressed(ret)))
}
constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => {
let mut ret = [0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
let mut ret = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
unsafe {
copy_nonoverlapping_memory(ret.as_mut_ptr(),
data.as_ptr(),
data.len());
}
Ok(PublicKey(Uncompressed(ret)))
Ok(PublicKey(PublicKeyData::Uncompressed(ret)))
}
_ => Err(InvalidPublicKey)
}
@ -291,18 +300,18 @@ impl PublicKey {
pub fn is_compressed(&self) -> bool {
let &PublicKey(ref data) = self;
match *data {
Compressed(_) => true,
Uncompressed(_) => false
PublicKeyData::Compressed(_) => true,
PublicKeyData::Uncompressed(_) => false
}
}
/// Returns the length of the public key
#[inline]
pub fn len(&self) -> uint {
pub fn len(&self) -> usize {
let &PublicKey(ref data) = self;
match *data {
Compressed(ref x) => x.len(),
Uncompressed(ref x) => x.len()
PublicKeyData::Compressed(ref x) => x.len(),
PublicKeyData::Uncompressed(ref x) => x.len()
}
}
@ -319,8 +328,8 @@ impl PublicKey {
pub fn as_ptr(&self) -> *const u8 {
let &PublicKey(ref data) = self;
match *data {
Compressed(ref x) => x.as_ptr(),
Uncompressed(ref x) => x.as_ptr()
PublicKeyData::Compressed(ref x) => x.as_ptr(),
PublicKeyData::Uncompressed(ref x) => x.as_ptr()
}
}
@ -328,10 +337,10 @@ impl PublicKey {
/// with the FFI functions
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
let &PublicKey(ref mut data) = self;
let &mut PublicKey(ref mut data) = self;
match *data {
Compressed(ref mut x) => x.as_mut_ptr(),
Uncompressed(ref mut x) => x.as_mut_ptr()
PublicKeyData::Compressed(ref mut x) => x.as_mut_ptr(),
PublicKeyData::Uncompressed(ref mut x) => x.as_mut_ptr()
}
}
@ -355,8 +364,8 @@ impl PublicKeyData {
#[inline]
fn as_slice<'a>(&'a self) -> &'a [u8] {
match *self {
Compressed(ref x) => x.as_slice(),
Uncompressed(ref x) => x.as_slice()
PublicKeyData::Compressed(ref x) => x.as_slice(),
PublicKeyData::Uncompressed(ref x) => x.as_slice()
}
}
}
@ -387,26 +396,26 @@ impl fmt::Show for PublicKeyData {
}
}
impl<D: Decoder<E>, E> Decodable<D, E> for PublicKey {
fn decode(d: &mut D) -> ::std::prelude::Result<PublicKey, E> {
impl Decodable for PublicKey {
fn decode<D: Decoder>(d: &mut D) -> ::std::result::Result<PublicKey, D::Error> {
d.read_seq(|d, len| {
if len == constants::UNCOMPRESSED_PUBLIC_KEY_SIZE {
unsafe {
use std::mem;
let mut ret: [u8, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized();
let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized();
for i in range(0, len) {
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
}
Ok(PublicKey(Uncompressed(ret)))
Ok(PublicKey(PublicKeyData::Uncompressed(ret)))
}
} else if len == constants::COMPRESSED_PUBLIC_KEY_SIZE {
unsafe {
use std::mem;
let mut ret: [u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized();
let mut ret: [u8; constants::COMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized();
for i in range(0, len) {
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
}
Ok(PublicKey(Compressed(ret)))
Ok(PublicKey(PublicKeyData::Compressed(ret)))
}
} else {
Err(d.error("Invalid length"))
@ -415,9 +424,9 @@ impl<D: Decoder<E>, E> Decodable<D, E> for PublicKey {
}
}
impl <E: Encoder<S>, S> Encodable<E, S> for PublicKey {
fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> {
self.as_slice().encode(e)
impl Encodable for PublicKey {
fn encode<S: Encoder>(&self, s: &mut S) -> ::std::result::Result<(), S::Error> {
self.as_slice().encode(s)
}
}
@ -430,41 +439,42 @@ impl fmt::Show for SecretKey {
#[cfg(test)]
mod test {
use serialize::hex::FromHex;
use std::rand::task_rng;
use std::rand::thread_rng;
use test::Bencher;
use super::super::{Secp256k1, InvalidNonce, InvalidPublicKey, InvalidSecretKey};
use super::super::Secp256k1;
use super::super::Error::{InvalidNonce, InvalidPublicKey, InvalidSecretKey};
use super::{Nonce, PublicKey, SecretKey};
#[test]
fn nonce_from_slice() {
let n = Nonce::from_slice([1, ..31]);
let n = Nonce::from_slice(&[1; 31]);
assert_eq!(n, Err(InvalidNonce));
let n = SecretKey::from_slice([1, ..32]);
let n = SecretKey::from_slice(&[1; 32]);
assert!(n.is_ok());
}
#[test]
fn skey_from_slice() {
let sk = SecretKey::from_slice([1, ..31]);
let sk = SecretKey::from_slice(&[1; 31]);
assert_eq!(sk, Err(InvalidSecretKey));
let sk = SecretKey::from_slice([1, ..32]);
let sk = SecretKey::from_slice(&[1; 32]);
assert!(sk.is_ok());
}
#[test]
fn pubkey_from_slice() {
assert_eq!(PublicKey::from_slice([]), Err(InvalidPublicKey));
assert_eq!(PublicKey::from_slice([1, 2, 3]), Err(InvalidPublicKey));
assert_eq!(PublicKey::from_slice(&[]), Err(InvalidPublicKey));
assert_eq!(PublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey));
let uncompressed = PublicKey::from_slice([4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]);
let uncompressed = PublicKey::from_slice(&[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]);
assert!(uncompressed.is_ok());
assert!(!uncompressed.unwrap().is_compressed());
let compressed = PublicKey::from_slice([3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]);
let compressed = PublicKey::from_slice(&[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]);
assert!(compressed.is_ok());
assert!(compressed.unwrap().is_compressed());
}
@ -484,7 +494,7 @@ mod test {
#[test]
fn nonce_slice_round_trip() {
let mut rng = task_rng();
let mut rng = thread_rng();
let nonce = Nonce::new(&mut rng);
assert_eq!(Nonce::from_slice(nonce.as_slice()), Ok(nonce));
}
@ -492,19 +502,19 @@ mod test {
#[test]
fn invalid_secret_key() {
// Zero
assert_eq!(SecretKey::from_slice([0, ..32]), Err(InvalidSecretKey));
assert_eq!(SecretKey::from_slice(&[0; 32]), Err(InvalidSecretKey));
// -1
assert_eq!(SecretKey::from_slice([0xff, ..32]), Err(InvalidSecretKey));
assert_eq!(SecretKey::from_slice(&[0xff; 32]), Err(InvalidSecretKey));
// Top of range
assert!(SecretKey::from_slice([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40]).is_ok());
assert!(SecretKey::from_slice(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40]).is_ok());
// One past top of range
assert!(SecretKey::from_slice([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err());
assert!(SecretKey::from_slice(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err());
}
#[test]
@ -536,7 +546,7 @@ mod test {
let sk = SecretKey::from_slice(hex_slice!("09e918bbea76205445e9a73eaad2080a135d1e33e9dd1b3ca8a9a1285e7c1f81")).unwrap();
// "%x" % rfc6979.generate_k(SECP256k1.generator, sk, hashlib.sha512, hashlib.sha512('').digest())
let nonce = Nonce::deterministic([], &sk);
let nonce = Nonce::deterministic(&[], &sk);
assert_eq!(nonce.as_slice(),
hex_slice!("d954eddd184cac2b60edcd0e6be9ec54d93f633b28b366420d38ed9c346ffe27"));
@ -550,7 +560,7 @@ mod test {
let sk = SecretKey::from_slice(hex_slice!("09e918bbea76205445e9a73eaad2080a135d1e33e9dd1b3ca8a9a1285e7c1f80")).unwrap();
// "%x" % rfc6979.generate_k(SECP256k1.generator, sk, hashlib.sha512, hashlib.sha512('').digest())
let nonce = Nonce::deterministic([], &sk);
let nonce = Nonce::deterministic(&[], &sk);
assert_eq!(nonce.as_slice(),
hex_slice!("9f45f8d0a28e8956673c8da6db3db86ca4f172f0a2dbd62364fdbf786c7d96df"));

View File

@ -13,11 +13,11 @@
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//
#![macro_escape]
// This is a macro that routinely comes in handy
macro_rules! impl_array_newtype(
macro_rules! impl_array_newtype {
($thing:ident, $ty:ty, $len:expr) => {
impl Copy for $thing {}
impl $thing {
#[inline]
/// Provides an immutable view into the object
@ -28,21 +28,21 @@ macro_rules! impl_array_newtype(
#[inline]
/// Provides an immutable view into the object from index `s` inclusive to `e` exclusive
pub fn slice<'a>(&'a self, s: uint, e: uint) -> &'a [$ty] {
pub fn slice<'a>(&'a self, s: usize, e: usize) -> &'a [$ty] {
let &$thing(ref dat) = self;
dat.slice(s, e)
}
#[inline]
/// Provides an immutable view into the object, up to index `n` exclusive
pub fn slice_to<'a>(&'a self, n: uint) -> &'a [$ty] {
pub fn slice_to<'a>(&'a self, n: usize) -> &'a [$ty] {
let &$thing(ref dat) = self;
dat.slice_to(n)
}
#[inline]
/// Provides an immutable view into the object, starting from index `n`
pub fn slice_from<'a>(&'a self, n: uint) -> &'a [$ty] {
pub fn slice_from<'a>(&'a self, n: usize) -> &'a [$ty] {
let &$thing(ref dat) = self;
dat.slice_from(n)
}
@ -57,13 +57,13 @@ macro_rules! impl_array_newtype(
#[inline]
/// Converts the object to a mutable raw pointer for FFI interfacing
pub fn as_mut_ptr(&mut self) -> *mut $ty {
let &$thing(ref mut dat) = self;
let &mut $thing(ref mut dat) = self;
dat.as_mut_ptr()
}
#[inline]
/// Returns the length of the object as an array
pub fn len(&self) -> uint { $len }
pub fn len(&self) -> usize { $len }
}
impl PartialEq for $thing {
@ -90,8 +90,8 @@ macro_rules! impl_array_newtype(
}
}
impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for $thing {
fn decode(d: &mut D) -> ::std::prelude::Result<$thing, E> {
impl ::serialize::Decodable for $thing {
fn decode<D: ::serialize::Decoder>(d: &mut D) -> ::std::result::Result<$thing, D::Error> {
use serialize::Decodable;
::assert_type_is_copy::<$ty>();
@ -102,7 +102,7 @@ macro_rules! impl_array_newtype(
} else {
unsafe {
use std::mem;
let mut ret: [$ty, ..$len] = mem::uninitialized();
let mut ret: [$ty; $len] = mem::uninitialized();
for i in range(0, len) {
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
}
@ -113,19 +113,20 @@ macro_rules! impl_array_newtype(
}
}
impl<E: ::serialize::Encoder<S>, S> ::serialize::Encodable<E, S> for $thing {
fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> {
self.as_slice().encode(e)
impl ::serialize::Encodable for $thing {
fn encode<S: ::serialize::Encoder>(&self, s: &mut S)
-> ::std::result::Result<(), S::Error> {
self.as_slice().encode(s)
}
}
}
)
}
// for testing
macro_rules! hex_slice(
macro_rules! hex_slice {
($s:expr) => (
$s.from_hex().unwrap().as_slice()
)
)
}

View File

@ -24,33 +24,32 @@
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![crate_name = "bitcoin-secp256k1-rs"]
#![comment = "Bindings and wrapper functions for bitcoin secp256k1 library."]
#![feature(phase)]
#![feature(macro_rules)]
#![feature(globs)] // for tests only
// Keep this until 1.0 I guess; it's needed for `black_box` at least
#![allow(unstable)]
// Coding conventions
#![deny(non_uppercase_statics)]
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_doc)]
#![warn(missing_docs)]
extern crate "rust-crypto" as crypto;
extern crate crypto;
extern crate libc;
extern crate serialize;
extern crate sync;
extern crate test;
use std::intrinsics::copy_nonoverlapping_memory;
use std::io::IoResult;
use std::rand::{OsRng, Rng, SeedableRng};
use std::sync::{Once, ONCE_INIT};
use libc::c_int;
use sync::one::{Once, ONCE_INIT};
use crypto::fortuna::Fortuna;
#[macro_use]
mod macros;
pub mod constants;
pub mod ffi;
@ -61,9 +60,11 @@ fn assert_type_is_copy<T: Copy>() { }
/// A tag used for recovering the public key from a compact signature
pub struct RecoveryId(i32);
impl Copy for RecoveryId {}
/// An ECDSA signature
pub struct Signature(uint, [u8, ..constants::MAX_SIGNATURE_SIZE]);
pub struct Signature(usize, [u8; constants::MAX_SIGNATURE_SIZE]);
impl Copy for Signature {}
impl Signature {
/// Converts the signature to a raw pointer suitable for use
@ -78,7 +79,7 @@ impl Signature {
/// with the FFI functions
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
let &Signature(_, ref mut data) = self;
let &mut Signature(_, ref mut data) = self;
data.as_mut_slice().as_mut_ptr()
}
@ -91,7 +92,7 @@ impl Signature {
/// Returns the length of the signature
#[inline]
pub fn len(&self) -> uint {
pub fn len(&self) -> usize {
let &Signature(len, _) = self;
len
}
@ -100,7 +101,7 @@ impl Signature {
#[inline]
pub fn from_slice(data: &[u8]) -> Result<Signature> {
if data.len() <= constants::MAX_SIGNATURE_SIZE {
let mut ret = [0, ..constants::MAX_SIGNATURE_SIZE];
let mut ret = [0; constants::MAX_SIGNATURE_SIZE];
unsafe {
copy_nonoverlapping_memory(ret.as_mut_ptr(),
data.as_ptr(),
@ -108,13 +109,13 @@ impl Signature {
}
Ok(Signature(data.len(), ret))
} else {
Err(InvalidSignature)
Err(Error::InvalidSignature)
}
}
}
/// An ECDSA error
#[deriving(PartialEq, Eq, Clone, Show)]
#[derive(PartialEq, Eq, Clone, Show)]
pub enum Error {
/// Signature failed verification
IncorrectSignature,
@ -129,11 +130,12 @@ pub enum Error {
/// Boolean-returning function returned the wrong boolean
Unknown
}
impl Copy for Error {}
/// Result type
pub type Result<T> = ::std::prelude::Result<T, Error>;
pub type Result<T> = ::std::result::Result<T, 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 {
@ -147,7 +149,7 @@ pub struct Secp256k1 {
/// `key::PublicKey::from_secret_key`.
pub fn init() {
unsafe {
Secp256k1_init.doit(|| {
Secp256k1_init.call_once(|| {
ffi::secp256k1_start();
});
}
@ -158,7 +160,7 @@ impl Secp256k1 {
pub fn new() -> IoResult<Secp256k1> {
init();
let mut osrng = try!(OsRng::new());
let mut seed = [0, ..2048];
let mut seed = [0; 2048];
osrng.fill_bytes(seed.as_mut_slice());
Ok(Secp256k1 { rng: SeedableRng::from_seed(seed.as_slice()) })
}
@ -170,7 +172,8 @@ impl Secp256k1 {
pub fn generate_keypair(&mut self, compressed: bool)
-> (key::SecretKey, key::PublicKey) {
let sk = key::SecretKey::new(&mut self.rng);
(sk, key::PublicKey::from_secret_key(&sk, compressed))
let pk = key::PublicKey::from_secret_key(&sk, compressed);
(sk, pk)
}
/// Generates a random nonce. Convenience function for `key::Nonce::new`; call
@ -183,30 +186,30 @@ impl Secp256k1 {
/// Constructs a signature for `msg` using the secret key `sk` and nonce `nonce`
pub fn sign(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
-> Result<Signature> {
let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
let mut sig = [0; constants::MAX_SIGNATURE_SIZE];
let mut len = constants::MAX_SIGNATURE_SIZE as c_int;
unsafe {
if ffi::secp256k1_ecdsa_sign(msg.as_ptr(), msg.len() as c_int,
sig.as_mut_slice().as_mut_ptr(), &mut len,
sk.as_ptr(), nonce.as_ptr()) != 1 {
return Err(InvalidNonce);
return Err(Error::InvalidNonce);
}
// This assertation is probably too late :)
assert!(len as uint <= constants::MAX_SIGNATURE_SIZE);
assert!(len as usize <= constants::MAX_SIGNATURE_SIZE);
};
Ok(Signature(len as uint, sig))
Ok(Signature(len as usize, sig))
}
/// Constructs a compact signature for `msg` using the secret key `sk`
pub fn sign_compact(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
-> Result<(Signature, RecoveryId)> {
let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
let mut sig = [0; constants::MAX_SIGNATURE_SIZE];
let mut recid = 0;
unsafe {
if ffi::secp256k1_ecdsa_sign_compact(msg.as_ptr(), msg.len() as c_int,
sig.as_mut_slice().as_mut_ptr(), sk.as_ptr(),
nonce.as_ptr(), &mut recid) != 1 {
return Err(InvalidNonce);
return Err(Error::InvalidNonce);
}
};
Ok((Signature(constants::MAX_COMPACT_SIGNATURE_SIZE, sig), RecoveryId(recid)))
@ -226,9 +229,9 @@ impl Secp256k1 {
sig.as_ptr(), pk.as_mut_ptr(), &mut len,
if compressed {1} else {0},
recid) != 1 {
return Err(InvalidSignature);
return Err(Error::InvalidSignature);
}
assert_eq!(len as uint, pk.len());
assert_eq!(len as usize, pk.len());
};
Ok(pk)
}
@ -256,9 +259,9 @@ impl Secp256k1 {
match res {
1 => Ok(()),
0 => Err(IncorrectSignature),
-1 => Err(InvalidPublicKey),
-2 => Err(InvalidSignature),
0 => Err(Error::IncorrectSignature),
-1 => Err(Error::InvalidPublicKey),
-2 => Err(Error::InvalidSignature),
_ => unreachable!()
}
}
@ -267,6 +270,7 @@ impl Secp256k1 {
#[cfg(test)]
mod tests {
use std::iter::repeat;
use std::rand;
use std::rand::Rng;
@ -274,15 +278,15 @@ mod tests {
use key::{PublicKey, Nonce};
use super::{Secp256k1, Signature};
use super::{InvalidPublicKey, IncorrectSignature, InvalidSignature};
use super::Error::{InvalidPublicKey, IncorrectSignature, InvalidSignature};
#[test]
fn invalid_pubkey() {
let mut msg = Vec::from_elem(32, 0u8);
let sig = Signature::from_slice([0, ..72]).unwrap();
let mut msg: Vec<u8> = repeat(0).take(32).collect();
let sig = Signature::from_slice(&[0; 72]).unwrap();
let pk = PublicKey::new(true);
rand::task_rng().fill_bytes(msg.as_mut_slice());
rand::thread_rng().fill_bytes(msg.as_mut_slice());
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), &sig, &pk), Err(InvalidPublicKey));
}
@ -293,10 +297,10 @@ mod tests {
let (_, pk) = s.generate_keypair(false);
let mut msg = Vec::from_elem(32, 0u8);
let sig = Signature::from_slice([0, ..72]).unwrap();
let mut msg: Vec<u8> = repeat(0).take(32).collect();
let sig = Signature::from_slice(&[0; 72]).unwrap();
rand::task_rng().fill_bytes(msg.as_mut_slice());
rand::thread_rng().fill_bytes(msg.as_mut_slice());
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), &sig, &pk), Err(InvalidSignature));
}
@ -306,10 +310,10 @@ mod tests {
let mut s = Secp256k1::new().unwrap();
let (_, pk) = s.generate_keypair(true);
let mut msg = Vec::from_elem(32, 0u8);
let sig = Signature::from_slice([0, ..72]).unwrap();
let mut msg: Vec<u8> = repeat(0).take(32).collect();
let sig = Signature::from_slice(&[0; 72]).unwrap();
rand::task_rng().fill_bytes(msg.as_mut_slice());
rand::thread_rng().fill_bytes(msg.as_mut_slice());
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), &sig, &pk), Err(InvalidSignature));
}
@ -318,8 +322,8 @@ mod tests {
fn sign() {
let mut s = Secp256k1::new().unwrap();
let mut msg = [0u8, ..32];
rand::task_rng().fill_bytes(msg);
let mut msg = [0u8; 32];
rand::thread_rng().fill_bytes(&mut msg);
let (sk, _) = s.generate_keypair(false);
let nonce = s.generate_nonce();
@ -331,8 +335,8 @@ mod tests {
fn sign_and_verify() {
let mut s = Secp256k1::new().unwrap();
let mut msg = Vec::from_elem(32, 0u8);
rand::task_rng().fill_bytes(msg.as_mut_slice());
let mut msg: Vec<u8> = repeat(0).take(32).collect();
rand::thread_rng().fill_bytes(msg.as_mut_slice());
let (sk, pk) = s.generate_keypair(false);
let nonce = s.generate_nonce();
@ -346,15 +350,15 @@ mod tests {
fn sign_and_verify_fail() {
let mut s = Secp256k1::new().unwrap();
let mut msg = Vec::from_elem(32, 0u8);
rand::task_rng().fill_bytes(msg.as_mut_slice());
let mut msg: Vec<u8> = repeat(0).take(32).collect();
rand::thread_rng().fill_bytes(msg.as_mut_slice());
let (sk, pk) = s.generate_keypair(false);
let nonce = s.generate_nonce();
let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();
rand::task_rng().fill_bytes(msg.as_mut_slice());
rand::thread_rng().fill_bytes(msg.as_mut_slice());
assert_eq!(Secp256k1::verify(msg.as_slice(), &sig, &pk), Err(IncorrectSignature));
}
@ -362,8 +366,8 @@ mod tests {
fn sign_compact_with_recovery() {
let mut s = Secp256k1::new().unwrap();
let mut msg = [0u8, ..32];
rand::task_rng().fill_bytes(msg.as_mut_slice());
let mut msg = [0u8; 32];
rand::thread_rng().fill_bytes(msg.as_mut_slice());
let (sk, pk) = s.generate_keypair(false);
let nonce = s.generate_nonce();
@ -375,12 +379,12 @@ mod tests {
#[test]
fn deterministic_sign() {
let mut msg = [0u8, ..32];
rand::task_rng().fill_bytes(msg.as_mut_slice());
let mut msg = [0u8; 32];
rand::thread_rng().fill_bytes(msg.as_mut_slice());
let mut s = Secp256k1::new().unwrap();
let (sk, pk) = s.generate_keypair(true);
let nonce = Nonce::deterministic(msg, &sk);
let nonce = Nonce::deterministic(&mut msg, &sk);
let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();