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:
parent
9cab4e023d
commit
d495d9ca06
|
@ -16,25 +16,25 @@
|
||||||
//! Constants
|
//! Constants
|
||||||
|
|
||||||
/// The size (in bytes) of a nonce
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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, 0xff,
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||||
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
|
0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
|
||||||
|
@ -42,7 +42,7 @@ pub static CURVE_ORDER: [u8, ..32] = [
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The X coordinate of the generator
|
/// 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,
|
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
|
||||||
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
|
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
|
||||||
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
|
0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9,
|
||||||
|
@ -50,7 +50,7 @@ pub static GENERATOR_X: [u8, ..32] = [
|
||||||
];
|
];
|
||||||
|
|
||||||
/// The Y coordinate of the generator
|
/// 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,
|
0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65,
|
||||||
0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,
|
0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,
|
||||||
0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
|
0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,
|
||||||
|
|
162
src/key.rs
162
src/key.rs
|
@ -27,17 +27,18 @@ use crypto::hmac::Hmac;
|
||||||
use crypto::mac::Mac;
|
use crypto::mac::Mac;
|
||||||
|
|
||||||
use super::init;
|
use super::init;
|
||||||
use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey, Unknown};
|
use super::Result;
|
||||||
|
use super::Error::{InvalidNonce, InvalidPublicKey, InvalidSecretKey, Unknown};
|
||||||
use constants;
|
use constants;
|
||||||
use ffi;
|
use ffi;
|
||||||
|
|
||||||
/// Secret 256-bit nonce used as `k` in an ECDSA signature
|
/// Secret 256-bit nonce used as `k` in an ECDSA signature
|
||||||
pub struct Nonce([u8, ..constants::NONCE_SIZE]);
|
pub struct Nonce([u8; constants::NONCE_SIZE]);
|
||||||
impl_array_newtype!(Nonce, u8, constants::NONCE_SIZE)
|
impl_array_newtype!(Nonce, u8, constants::NONCE_SIZE);
|
||||||
|
|
||||||
/// Secret 256-bit key used as `x` in an ECDSA signature
|
/// Secret 256-bit key used as `x` in an ECDSA signature
|
||||||
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);
|
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
|
||||||
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE)
|
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
|
||||||
|
|
||||||
/// The number 1 encoded as a secret key
|
/// The number 1 encoded as a secret key
|
||||||
pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
|
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]);
|
0, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
|
||||||
/// Public key
|
/// Public key
|
||||||
#[deriving(Clone, PartialEq, Eq, Show)]
|
#[derive(Clone, PartialEq, Eq, Show)]
|
||||||
pub struct PublicKey(PublicKeyData);
|
pub struct PublicKey(PublicKeyData);
|
||||||
|
impl Copy for PublicKey {}
|
||||||
|
|
||||||
enum PublicKeyData {
|
enum PublicKeyData {
|
||||||
Compressed([u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]),
|
Compressed([u8; constants::COMPRESSED_PUBLIC_KEY_SIZE]),
|
||||||
Uncompressed([u8, ..constants::UNCOMPRESSED_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] {
|
fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8; 32] {
|
||||||
let mut ret = [0u8, ..32];
|
let mut ret = [0u8; 32];
|
||||||
rng.fill_bytes(ret);
|
rng.fill_bytes(&mut ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// As described in RFC 6979
|
/// As described in RFC 6979
|
||||||
fn bits2octets(data: &[u8]) -> [u8, ..32] {
|
fn bits2octets(data: &[u8]) -> [u8; 32] {
|
||||||
let mut ret = [0, ..32];
|
let mut ret = [0; 32];
|
||||||
unsafe {
|
unsafe {
|
||||||
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
||||||
data.as_ptr(),
|
data.as_ptr(),
|
||||||
|
@ -83,7 +86,7 @@ impl Nonce {
|
||||||
pub fn from_slice(data: &[u8]) -> Result<Nonce> {
|
pub fn from_slice(data: &[u8]) -> Result<Nonce> {
|
||||||
match data.len() {
|
match data.len() {
|
||||||
constants::NONCE_SIZE => {
|
constants::NONCE_SIZE => {
|
||||||
let mut ret = [0, ..constants::NONCE_SIZE];
|
let mut ret = [0; constants::NONCE_SIZE];
|
||||||
unsafe {
|
unsafe {
|
||||||
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
||||||
data.as_ptr(),
|
data.as_ptr(),
|
||||||
|
@ -99,54 +102,54 @@ impl Nonce {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(non_snake_case)] // so we can match the names in the RFC
|
#[allow(non_snake_case)] // so we can match the names in the RFC
|
||||||
pub fn deterministic(msg: &[u8], key: &SecretKey) -> Nonce {
|
pub fn deterministic(msg: &[u8], key: &SecretKey) -> Nonce {
|
||||||
static HMAC_SIZE: uint = 64;
|
const HMAC_SIZE: usize = 64;
|
||||||
|
|
||||||
macro_rules! hmac(
|
macro_rules! hmac {
|
||||||
($res:expr <- key $key:expr, data $($data:expr),+) => ({
|
($res:expr; key $key:expr, data $($data:expr),+) => ({
|
||||||
let mut hmacker = Hmac::new(Sha512::new(), $key.as_slice());
|
let mut hmacker = Hmac::new(Sha512::new(), $key.as_slice());
|
||||||
$(hmacker.input($data.as_slice());)+
|
$(hmacker.input($data.as_slice());)+
|
||||||
hmacker.raw_result($res.as_mut_slice());
|
hmacker.raw_result($res.as_mut_slice());
|
||||||
})
|
})
|
||||||
)
|
}
|
||||||
|
|
||||||
// Section 3.2a
|
// Section 3.2a
|
||||||
// Goofy block just to avoid marking `msg_hash` as mutable
|
// Goofy block just to avoid marking `msg_hash` as mutable
|
||||||
let mut hasher = Sha512::new();
|
let mut hasher = Sha512::new();
|
||||||
hasher.input(msg);
|
hasher.input(msg);
|
||||||
let mut x = [0, ..HMAC_SIZE];
|
let mut x = [0; HMAC_SIZE];
|
||||||
hasher.result(x.as_mut_slice());
|
hasher.result(x.as_mut_slice());
|
||||||
let msg_hash = bits2octets(x.as_slice());
|
let msg_hash = bits2octets(x.as_slice());
|
||||||
|
|
||||||
// Section 3.2b
|
// Section 3.2b
|
||||||
let mut V = [0x01u8, ..HMAC_SIZE];
|
let mut V = [0x01u8; HMAC_SIZE];
|
||||||
// Section 3.2c
|
// Section 3.2c
|
||||||
let mut K = [0x00u8, ..HMAC_SIZE];
|
let mut K = [0x00u8; HMAC_SIZE];
|
||||||
|
|
||||||
// Section 3.2d
|
// 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
|
// Section 3.2e
|
||||||
hmac!(V <- key K, data V)
|
hmac!(V; key K, data V);
|
||||||
|
|
||||||
// Section 3.2f
|
// 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
|
// Section 3.2g
|
||||||
hmac!(V <- key K, data V)
|
hmac!(V; key K, data V);
|
||||||
|
|
||||||
// Section 3.2
|
// Section 3.2
|
||||||
let mut k = Err(InvalidSecretKey);
|
let mut k = Err(InvalidSecretKey);
|
||||||
while k.is_err() {
|
while k.is_err() {
|
||||||
// Try to generate the nonce
|
// Try to generate the nonce
|
||||||
let mut T = [0x00u8, ..HMAC_SIZE];
|
let mut T = [0x00u8; HMAC_SIZE];
|
||||||
hmac!(T <- key K, data V)
|
hmac!(T; key K, data V);
|
||||||
|
|
||||||
k = Nonce::from_slice(T.slice_to(constants::NONCE_SIZE));
|
k = Nonce::from_slice(T.slice_to(constants::NONCE_SIZE));
|
||||||
|
|
||||||
// Replace K, V
|
// Replace K, V
|
||||||
if k.is_err() {
|
if k.is_err() {
|
||||||
hmac!(K <- key K, data V, [0x00])
|
hmac!(K; key K, data V, [0x00]);
|
||||||
hmac!(V <- key K, data V)
|
hmac!(V; key K, data V);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +177,7 @@ impl SecretKey {
|
||||||
init();
|
init();
|
||||||
match data.len() {
|
match data.len() {
|
||||||
constants::SECRET_KEY_SIZE => {
|
constants::SECRET_KEY_SIZE => {
|
||||||
let mut ret = [0, ..constants::SECRET_KEY_SIZE];
|
let mut ret = [0; constants::SECRET_KEY_SIZE];
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_seckey_verify(data.as_ptr()) == 0 {
|
if ffi::secp256k1_ecdsa_seckey_verify(data.as_ptr()) == 0 {
|
||||||
return Err(InvalidSecretKey);
|
return Err(InvalidSecretKey);
|
||||||
|
@ -218,8 +221,11 @@ pub struct Sequence {
|
||||||
compressed: bool,
|
compressed: bool,
|
||||||
last_sk: SecretKey,
|
last_sk: SecretKey,
|
||||||
}
|
}
|
||||||
|
impl Copy for Sequence {}
|
||||||
|
|
||||||
|
impl Iterator for Sequence {
|
||||||
|
type Item = (SecretKey, PublicKey);
|
||||||
|
|
||||||
impl<'a> Iterator<(SecretKey, PublicKey)> for Sequence {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<(SecretKey, PublicKey)> {
|
fn next(&mut self) -> Option<(SecretKey, PublicKey)> {
|
||||||
self.last_sk.add_assign(&ONE).unwrap();
|
self.last_sk.add_assign(&ONE).unwrap();
|
||||||
|
@ -232,8 +238,11 @@ impl PublicKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(compressed: bool) -> PublicKey {
|
pub fn new(compressed: bool) -> PublicKey {
|
||||||
PublicKey(
|
PublicKey(
|
||||||
if compressed { Compressed([0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]) }
|
if compressed {
|
||||||
else { Uncompressed([0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) }
|
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,
|
pk.as_mut_ptr(), &mut len,
|
||||||
sk.as_ptr(), compressed), 1);
|
sk.as_ptr(), compressed), 1);
|
||||||
}
|
}
|
||||||
assert_eq!(len as uint, pk.len());
|
assert_eq!(len as usize, pk.len());
|
||||||
pk
|
pk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +270,7 @@ impl PublicKey {
|
||||||
pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
|
pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
|
||||||
match data.len() {
|
match data.len() {
|
||||||
constants::COMPRESSED_PUBLIC_KEY_SIZE => {
|
constants::COMPRESSED_PUBLIC_KEY_SIZE => {
|
||||||
let mut ret = [0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE];
|
let mut ret = [0; constants::COMPRESSED_PUBLIC_KEY_SIZE];
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_pubkey_verify(data.as_ptr(),
|
if ffi::secp256k1_ecdsa_pubkey_verify(data.as_ptr(),
|
||||||
data.len() as ::libc::c_int) == 0 {
|
data.len() as ::libc::c_int) == 0 {
|
||||||
|
@ -271,16 +280,16 @@ impl PublicKey {
|
||||||
data.as_ptr(),
|
data.as_ptr(),
|
||||||
data.len());
|
data.len());
|
||||||
}
|
}
|
||||||
Ok(PublicKey(Compressed(ret)))
|
Ok(PublicKey(PublicKeyData::Compressed(ret)))
|
||||||
}
|
}
|
||||||
constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => {
|
constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => {
|
||||||
let mut ret = [0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
let mut ret = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
||||||
unsafe {
|
unsafe {
|
||||||
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
||||||
data.as_ptr(),
|
data.as_ptr(),
|
||||||
data.len());
|
data.len());
|
||||||
}
|
}
|
||||||
Ok(PublicKey(Uncompressed(ret)))
|
Ok(PublicKey(PublicKeyData::Uncompressed(ret)))
|
||||||
}
|
}
|
||||||
_ => Err(InvalidPublicKey)
|
_ => Err(InvalidPublicKey)
|
||||||
}
|
}
|
||||||
|
@ -291,18 +300,18 @@ impl PublicKey {
|
||||||
pub fn is_compressed(&self) -> bool {
|
pub fn is_compressed(&self) -> bool {
|
||||||
let &PublicKey(ref data) = self;
|
let &PublicKey(ref data) = self;
|
||||||
match *data {
|
match *data {
|
||||||
Compressed(_) => true,
|
PublicKeyData::Compressed(_) => true,
|
||||||
Uncompressed(_) => false
|
PublicKeyData::Uncompressed(_) => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the public key
|
/// Returns the length of the public key
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> uint {
|
pub fn len(&self) -> usize {
|
||||||
let &PublicKey(ref data) = self;
|
let &PublicKey(ref data) = self;
|
||||||
match *data {
|
match *data {
|
||||||
Compressed(ref x) => x.len(),
|
PublicKeyData::Compressed(ref x) => x.len(),
|
||||||
Uncompressed(ref x) => x.len()
|
PublicKeyData::Uncompressed(ref x) => x.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,8 +328,8 @@ impl PublicKey {
|
||||||
pub fn as_ptr(&self) -> *const u8 {
|
pub fn as_ptr(&self) -> *const u8 {
|
||||||
let &PublicKey(ref data) = self;
|
let &PublicKey(ref data) = self;
|
||||||
match *data {
|
match *data {
|
||||||
Compressed(ref x) => x.as_ptr(),
|
PublicKeyData::Compressed(ref x) => x.as_ptr(),
|
||||||
Uncompressed(ref x) => x.as_ptr()
|
PublicKeyData::Uncompressed(ref x) => x.as_ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,10 +337,10 @@ impl PublicKey {
|
||||||
/// with the FFI functions
|
/// with the FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
||||||
let &PublicKey(ref mut data) = self;
|
let &mut PublicKey(ref mut data) = self;
|
||||||
match *data {
|
match *data {
|
||||||
Compressed(ref mut x) => x.as_mut_ptr(),
|
PublicKeyData::Compressed(ref mut x) => x.as_mut_ptr(),
|
||||||
Uncompressed(ref mut x) => x.as_mut_ptr()
|
PublicKeyData::Uncompressed(ref mut x) => x.as_mut_ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +364,8 @@ impl PublicKeyData {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_slice<'a>(&'a self) -> &'a [u8] {
|
fn as_slice<'a>(&'a self) -> &'a [u8] {
|
||||||
match *self {
|
match *self {
|
||||||
Compressed(ref x) => x.as_slice(),
|
PublicKeyData::Compressed(ref x) => x.as_slice(),
|
||||||
Uncompressed(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 {
|
impl Decodable for PublicKey {
|
||||||
fn decode(d: &mut D) -> ::std::prelude::Result<PublicKey, E> {
|
fn decode<D: Decoder>(d: &mut D) -> ::std::result::Result<PublicKey, D::Error> {
|
||||||
d.read_seq(|d, len| {
|
d.read_seq(|d, len| {
|
||||||
if len == constants::UNCOMPRESSED_PUBLIC_KEY_SIZE {
|
if len == constants::UNCOMPRESSED_PUBLIC_KEY_SIZE {
|
||||||
unsafe {
|
unsafe {
|
||||||
use std::mem;
|
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) {
|
for i in range(0, len) {
|
||||||
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
|
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 {
|
} else if len == constants::COMPRESSED_PUBLIC_KEY_SIZE {
|
||||||
unsafe {
|
unsafe {
|
||||||
use std::mem;
|
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) {
|
for i in range(0, len) {
|
||||||
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
|
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
|
||||||
}
|
}
|
||||||
Ok(PublicKey(Compressed(ret)))
|
Ok(PublicKey(PublicKeyData::Compressed(ret)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(d.error("Invalid length"))
|
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 {
|
impl Encodable for PublicKey {
|
||||||
fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> {
|
fn encode<S: Encoder>(&self, s: &mut S) -> ::std::result::Result<(), S::Error> {
|
||||||
self.as_slice().encode(e)
|
self.as_slice().encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,41 +439,42 @@ impl fmt::Show for SecretKey {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
use std::rand::task_rng;
|
use std::rand::thread_rng;
|
||||||
|
|
||||||
use test::Bencher;
|
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};
|
use super::{Nonce, PublicKey, SecretKey};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nonce_from_slice() {
|
fn nonce_from_slice() {
|
||||||
let n = Nonce::from_slice([1, ..31]);
|
let n = Nonce::from_slice(&[1; 31]);
|
||||||
assert_eq!(n, Err(InvalidNonce));
|
assert_eq!(n, Err(InvalidNonce));
|
||||||
|
|
||||||
let n = SecretKey::from_slice([1, ..32]);
|
let n = SecretKey::from_slice(&[1; 32]);
|
||||||
assert!(n.is_ok());
|
assert!(n.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn skey_from_slice() {
|
fn skey_from_slice() {
|
||||||
let sk = SecretKey::from_slice([1, ..31]);
|
let sk = SecretKey::from_slice(&[1; 31]);
|
||||||
assert_eq!(sk, Err(InvalidSecretKey));
|
assert_eq!(sk, Err(InvalidSecretKey));
|
||||||
|
|
||||||
let sk = SecretKey::from_slice([1, ..32]);
|
let sk = SecretKey::from_slice(&[1; 32]);
|
||||||
assert!(sk.is_ok());
|
assert!(sk.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pubkey_from_slice() {
|
fn pubkey_from_slice() {
|
||||||
assert_eq!(PublicKey::from_slice([]), Err(InvalidPublicKey));
|
assert_eq!(PublicKey::from_slice(&[]), Err(InvalidPublicKey));
|
||||||
assert_eq!(PublicKey::from_slice([1, 2, 3]), 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.is_ok());
|
||||||
assert!(!uncompressed.unwrap().is_compressed());
|
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.is_ok());
|
||||||
assert!(compressed.unwrap().is_compressed());
|
assert!(compressed.unwrap().is_compressed());
|
||||||
}
|
}
|
||||||
|
@ -484,7 +494,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nonce_slice_round_trip() {
|
fn nonce_slice_round_trip() {
|
||||||
let mut rng = task_rng();
|
let mut rng = thread_rng();
|
||||||
let nonce = Nonce::new(&mut rng);
|
let nonce = Nonce::new(&mut rng);
|
||||||
assert_eq!(Nonce::from_slice(nonce.as_slice()), Ok(nonce));
|
assert_eq!(Nonce::from_slice(nonce.as_slice()), Ok(nonce));
|
||||||
}
|
}
|
||||||
|
@ -492,16 +502,16 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_secret_key() {
|
fn invalid_secret_key() {
|
||||||
// Zero
|
// Zero
|
||||||
assert_eq!(SecretKey::from_slice([0, ..32]), Err(InvalidSecretKey));
|
assert_eq!(SecretKey::from_slice(&[0; 32]), Err(InvalidSecretKey));
|
||||||
// -1
|
// -1
|
||||||
assert_eq!(SecretKey::from_slice([0xff, ..32]), Err(InvalidSecretKey));
|
assert_eq!(SecretKey::from_slice(&[0xff; 32]), Err(InvalidSecretKey));
|
||||||
// Top of range
|
// Top of range
|
||||||
assert!(SecretKey::from_slice([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
assert!(SecretKey::from_slice(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
||||||
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
||||||
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40]).is_ok());
|
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40]).is_ok());
|
||||||
// One past top of range
|
// One past top of range
|
||||||
assert!(SecretKey::from_slice([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
assert!(SecretKey::from_slice(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
||||||
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
||||||
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err());
|
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err());
|
||||||
|
@ -536,7 +546,7 @@ mod test {
|
||||||
let sk = SecretKey::from_slice(hex_slice!("09e918bbea76205445e9a73eaad2080a135d1e33e9dd1b3ca8a9a1285e7c1f81")).unwrap();
|
let sk = SecretKey::from_slice(hex_slice!("09e918bbea76205445e9a73eaad2080a135d1e33e9dd1b3ca8a9a1285e7c1f81")).unwrap();
|
||||||
|
|
||||||
// "%x" % rfc6979.generate_k(SECP256k1.generator, sk, hashlib.sha512, hashlib.sha512('').digest())
|
// "%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(),
|
assert_eq!(nonce.as_slice(),
|
||||||
hex_slice!("d954eddd184cac2b60edcd0e6be9ec54d93f633b28b366420d38ed9c346ffe27"));
|
hex_slice!("d954eddd184cac2b60edcd0e6be9ec54d93f633b28b366420d38ed9c346ffe27"));
|
||||||
|
|
||||||
|
@ -550,7 +560,7 @@ mod test {
|
||||||
let sk = SecretKey::from_slice(hex_slice!("09e918bbea76205445e9a73eaad2080a135d1e33e9dd1b3ca8a9a1285e7c1f80")).unwrap();
|
let sk = SecretKey::from_slice(hex_slice!("09e918bbea76205445e9a73eaad2080a135d1e33e9dd1b3ca8a9a1285e7c1f80")).unwrap();
|
||||||
|
|
||||||
// "%x" % rfc6979.generate_k(SECP256k1.generator, sk, hashlib.sha512, hashlib.sha512('').digest())
|
// "%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(),
|
assert_eq!(nonce.as_slice(),
|
||||||
hex_slice!("9f45f8d0a28e8956673c8da6db3db86ca4f172f0a2dbd62364fdbf786c7d96df"));
|
hex_slice!("9f45f8d0a28e8956673c8da6db3db86ca4f172f0a2dbd62364fdbf786c7d96df"));
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@
|
||||||
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
//
|
//
|
||||||
|
|
||||||
#![macro_escape]
|
|
||||||
|
|
||||||
// This is a macro that routinely comes in handy
|
// 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) => {
|
($thing:ident, $ty:ty, $len:expr) => {
|
||||||
|
impl Copy for $thing {}
|
||||||
|
|
||||||
impl $thing {
|
impl $thing {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object
|
/// Provides an immutable view into the object
|
||||||
|
@ -28,21 +28,21 @@ macro_rules! impl_array_newtype(
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object from index `s` inclusive to `e` exclusive
|
/// 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;
|
let &$thing(ref dat) = self;
|
||||||
dat.slice(s, e)
|
dat.slice(s, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object, up to index `n` exclusive
|
/// 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;
|
let &$thing(ref dat) = self;
|
||||||
dat.slice_to(n)
|
dat.slice_to(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Provides an immutable view into the object, starting from index `n`
|
/// 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;
|
let &$thing(ref dat) = self;
|
||||||
dat.slice_from(n)
|
dat.slice_from(n)
|
||||||
}
|
}
|
||||||
|
@ -57,13 +57,13 @@ macro_rules! impl_array_newtype(
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Converts the object to a mutable raw pointer for FFI interfacing
|
/// Converts the object to a mutable raw pointer for FFI interfacing
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut $ty {
|
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()
|
dat.as_mut_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Returns the length of the object as an array
|
/// 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 {
|
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 {
|
impl ::serialize::Decodable for $thing {
|
||||||
fn decode(d: &mut D) -> ::std::prelude::Result<$thing, E> {
|
fn decode<D: ::serialize::Decoder>(d: &mut D) -> ::std::result::Result<$thing, D::Error> {
|
||||||
use serialize::Decodable;
|
use serialize::Decodable;
|
||||||
|
|
||||||
::assert_type_is_copy::<$ty>();
|
::assert_type_is_copy::<$ty>();
|
||||||
|
@ -102,7 +102,7 @@ macro_rules! impl_array_newtype(
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
let mut ret: [$ty, ..$len] = mem::uninitialized();
|
let mut ret: [$ty; $len] = mem::uninitialized();
|
||||||
for i in range(0, len) {
|
for i in range(0, len) {
|
||||||
ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d)));
|
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 {
|
impl ::serialize::Encodable for $thing {
|
||||||
fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> {
|
fn encode<S: ::serialize::Encoder>(&self, s: &mut S)
|
||||||
self.as_slice().encode(e)
|
-> ::std::result::Result<(), S::Error> {
|
||||||
|
self.as_slice().encode(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
// for testing
|
// for testing
|
||||||
macro_rules! hex_slice(
|
macro_rules! hex_slice {
|
||||||
($s:expr) => (
|
($s:expr) => (
|
||||||
$s.from_hex().unwrap().as_slice()
|
$s.from_hex().unwrap().as_slice()
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
|
108
src/secp256k1.rs
108
src/secp256k1.rs
|
@ -24,33 +24,32 @@
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![crate_type = "dylib"]
|
#![crate_type = "dylib"]
|
||||||
#![crate_name = "bitcoin-secp256k1-rs"]
|
#![crate_name = "bitcoin-secp256k1-rs"]
|
||||||
#![comment = "Bindings and wrapper functions for bitcoin secp256k1 library."]
|
|
||||||
#![feature(phase)]
|
// Keep this until 1.0 I guess; it's needed for `black_box` at least
|
||||||
#![feature(macro_rules)]
|
#![allow(unstable)]
|
||||||
#![feature(globs)] // for tests only
|
|
||||||
|
|
||||||
// Coding conventions
|
// Coding conventions
|
||||||
#![deny(non_uppercase_statics)]
|
#![deny(non_upper_case_globals)]
|
||||||
#![deny(non_camel_case_types)]
|
#![deny(non_camel_case_types)]
|
||||||
#![deny(non_snake_case)]
|
#![deny(non_snake_case)]
|
||||||
#![deny(unused_mut)]
|
#![deny(unused_mut)]
|
||||||
#![warn(missing_doc)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
extern crate "rust-crypto" as crypto;
|
extern crate crypto;
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
extern crate sync;
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use std::intrinsics::copy_nonoverlapping_memory;
|
use std::intrinsics::copy_nonoverlapping_memory;
|
||||||
use std::io::IoResult;
|
use std::io::IoResult;
|
||||||
use std::rand::{OsRng, Rng, SeedableRng};
|
use std::rand::{OsRng, Rng, SeedableRng};
|
||||||
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use sync::one::{Once, ONCE_INIT};
|
|
||||||
|
|
||||||
use crypto::fortuna::Fortuna;
|
use crypto::fortuna::Fortuna;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
pub mod ffi;
|
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
|
/// A tag used for recovering the public key from a compact signature
|
||||||
pub struct RecoveryId(i32);
|
pub struct RecoveryId(i32);
|
||||||
|
impl Copy for RecoveryId {}
|
||||||
|
|
||||||
/// An ECDSA signature
|
/// 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 {
|
impl Signature {
|
||||||
/// Converts the signature to a raw pointer suitable for use
|
/// Converts the signature to a raw pointer suitable for use
|
||||||
|
@ -78,7 +79,7 @@ impl Signature {
|
||||||
/// with the FFI functions
|
/// with the FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
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()
|
data.as_mut_slice().as_mut_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ impl Signature {
|
||||||
|
|
||||||
/// Returns the length of the signature
|
/// Returns the length of the signature
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> uint {
|
pub fn len(&self) -> usize {
|
||||||
let &Signature(len, _) = self;
|
let &Signature(len, _) = self;
|
||||||
len
|
len
|
||||||
}
|
}
|
||||||
|
@ -100,7 +101,7 @@ impl Signature {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice(data: &[u8]) -> Result<Signature> {
|
pub fn from_slice(data: &[u8]) -> Result<Signature> {
|
||||||
if data.len() <= constants::MAX_SIGNATURE_SIZE {
|
if data.len() <= constants::MAX_SIGNATURE_SIZE {
|
||||||
let mut ret = [0, ..constants::MAX_SIGNATURE_SIZE];
|
let mut ret = [0; constants::MAX_SIGNATURE_SIZE];
|
||||||
unsafe {
|
unsafe {
|
||||||
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
copy_nonoverlapping_memory(ret.as_mut_ptr(),
|
||||||
data.as_ptr(),
|
data.as_ptr(),
|
||||||
|
@ -108,13 +109,13 @@ impl Signature {
|
||||||
}
|
}
|
||||||
Ok(Signature(data.len(), ret))
|
Ok(Signature(data.len(), ret))
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidSignature)
|
Err(Error::InvalidSignature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An ECDSA error
|
/// An ECDSA error
|
||||||
#[deriving(PartialEq, Eq, Clone, Show)]
|
#[derive(PartialEq, Eq, Clone, Show)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Signature failed verification
|
/// Signature failed verification
|
||||||
IncorrectSignature,
|
IncorrectSignature,
|
||||||
|
@ -129,9 +130,10 @@ pub enum Error {
|
||||||
/// Boolean-returning function returned the wrong boolean
|
/// Boolean-returning function returned the wrong boolean
|
||||||
Unknown
|
Unknown
|
||||||
}
|
}
|
||||||
|
impl Copy for Error {}
|
||||||
|
|
||||||
/// Result type
|
/// 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;
|
||||||
|
|
||||||
|
@ -147,7 +149,7 @@ pub struct Secp256k1 {
|
||||||
/// `key::PublicKey::from_secret_key`.
|
/// `key::PublicKey::from_secret_key`.
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
unsafe {
|
unsafe {
|
||||||
Secp256k1_init.doit(|| {
|
Secp256k1_init.call_once(|| {
|
||||||
ffi::secp256k1_start();
|
ffi::secp256k1_start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -158,7 +160,7 @@ impl Secp256k1 {
|
||||||
pub fn new() -> IoResult<Secp256k1> {
|
pub fn new() -> IoResult<Secp256k1> {
|
||||||
init();
|
init();
|
||||||
let mut osrng = try!(OsRng::new());
|
let mut osrng = try!(OsRng::new());
|
||||||
let mut seed = [0, ..2048];
|
let mut seed = [0; 2048];
|
||||||
osrng.fill_bytes(seed.as_mut_slice());
|
osrng.fill_bytes(seed.as_mut_slice());
|
||||||
Ok(Secp256k1 { rng: SeedableRng::from_seed(seed.as_slice()) })
|
Ok(Secp256k1 { rng: SeedableRng::from_seed(seed.as_slice()) })
|
||||||
}
|
}
|
||||||
|
@ -170,7 +172,8 @@ impl Secp256k1 {
|
||||||
pub fn generate_keypair(&mut self, compressed: bool)
|
pub fn generate_keypair(&mut self, compressed: bool)
|
||||||
-> (key::SecretKey, key::PublicKey) {
|
-> (key::SecretKey, key::PublicKey) {
|
||||||
let sk = key::SecretKey::new(&mut self.rng);
|
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
|
/// 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`
|
/// 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)
|
pub fn sign(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
|
||||||
-> Result<Signature> {
|
-> 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;
|
let mut len = constants::MAX_SIGNATURE_SIZE as c_int;
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_sign(msg.as_ptr(), msg.len() as c_int,
|
if ffi::secp256k1_ecdsa_sign(msg.as_ptr(), msg.len() as c_int,
|
||||||
sig.as_mut_slice().as_mut_ptr(), &mut len,
|
sig.as_mut_slice().as_mut_ptr(), &mut len,
|
||||||
sk.as_ptr(), nonce.as_ptr()) != 1 {
|
sk.as_ptr(), nonce.as_ptr()) != 1 {
|
||||||
return Err(InvalidNonce);
|
return Err(Error::InvalidNonce);
|
||||||
}
|
}
|
||||||
// This assertation is probably too late :)
|
// 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`
|
/// Constructs a compact signature for `msg` using the secret key `sk`
|
||||||
pub fn sign_compact(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
|
pub fn sign_compact(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
|
||||||
-> Result<(Signature, RecoveryId)> {
|
-> Result<(Signature, RecoveryId)> {
|
||||||
let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
|
let mut sig = [0; constants::MAX_SIGNATURE_SIZE];
|
||||||
let mut recid = 0;
|
let mut recid = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_sign_compact(msg.as_ptr(), msg.len() as c_int,
|
if ffi::secp256k1_ecdsa_sign_compact(msg.as_ptr(), msg.len() as c_int,
|
||||||
sig.as_mut_slice().as_mut_ptr(), sk.as_ptr(),
|
sig.as_mut_slice().as_mut_ptr(), sk.as_ptr(),
|
||||||
nonce.as_ptr(), &mut recid) != 1 {
|
nonce.as_ptr(), &mut recid) != 1 {
|
||||||
return Err(InvalidNonce);
|
return Err(Error::InvalidNonce);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok((Signature(constants::MAX_COMPACT_SIGNATURE_SIZE, sig), RecoveryId(recid)))
|
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,
|
sig.as_ptr(), pk.as_mut_ptr(), &mut len,
|
||||||
if compressed {1} else {0},
|
if compressed {1} else {0},
|
||||||
recid) != 1 {
|
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)
|
Ok(pk)
|
||||||
}
|
}
|
||||||
|
@ -256,9 +259,9 @@ impl Secp256k1 {
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
1 => Ok(()),
|
1 => Ok(()),
|
||||||
0 => Err(IncorrectSignature),
|
0 => Err(Error::IncorrectSignature),
|
||||||
-1 => Err(InvalidPublicKey),
|
-1 => Err(Error::InvalidPublicKey),
|
||||||
-2 => Err(InvalidSignature),
|
-2 => Err(Error::InvalidSignature),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,6 +270,7 @@ impl Secp256k1 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::iter::repeat;
|
||||||
use std::rand;
|
use std::rand;
|
||||||
use std::rand::Rng;
|
use std::rand::Rng;
|
||||||
|
|
||||||
|
@ -274,15 +278,15 @@ mod tests {
|
||||||
|
|
||||||
use key::{PublicKey, Nonce};
|
use key::{PublicKey, Nonce};
|
||||||
use super::{Secp256k1, Signature};
|
use super::{Secp256k1, Signature};
|
||||||
use super::{InvalidPublicKey, IncorrectSignature, InvalidSignature};
|
use super::Error::{InvalidPublicKey, IncorrectSignature, InvalidSignature};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_pubkey() {
|
fn invalid_pubkey() {
|
||||||
let mut msg = Vec::from_elem(32, 0u8);
|
let mut msg: Vec<u8> = repeat(0).take(32).collect();
|
||||||
let sig = Signature::from_slice([0, ..72]).unwrap();
|
let sig = Signature::from_slice(&[0; 72]).unwrap();
|
||||||
let pk = PublicKey::new(true);
|
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));
|
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 (_, pk) = s.generate_keypair(false);
|
||||||
|
|
||||||
let mut msg = Vec::from_elem(32, 0u8);
|
let mut msg: Vec<u8> = repeat(0).take(32).collect();
|
||||||
let sig = Signature::from_slice([0, ..72]).unwrap();
|
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));
|
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 mut s = Secp256k1::new().unwrap();
|
||||||
|
|
||||||
let (_, pk) = s.generate_keypair(true);
|
let (_, pk) = s.generate_keypair(true);
|
||||||
let mut msg = Vec::from_elem(32, 0u8);
|
let mut msg: Vec<u8> = repeat(0).take(32).collect();
|
||||||
let sig = Signature::from_slice([0, ..72]).unwrap();
|
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));
|
assert_eq!(Secp256k1::verify(msg.as_mut_slice(), &sig, &pk), Err(InvalidSignature));
|
||||||
}
|
}
|
||||||
|
@ -318,8 +322,8 @@ mod tests {
|
||||||
fn sign() {
|
fn sign() {
|
||||||
let mut s = Secp256k1::new().unwrap();
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
|
||||||
let mut msg = [0u8, ..32];
|
let mut msg = [0u8; 32];
|
||||||
rand::task_rng().fill_bytes(msg);
|
rand::thread_rng().fill_bytes(&mut msg);
|
||||||
|
|
||||||
let (sk, _) = s.generate_keypair(false);
|
let (sk, _) = s.generate_keypair(false);
|
||||||
let nonce = s.generate_nonce();
|
let nonce = s.generate_nonce();
|
||||||
|
@ -331,8 +335,8 @@ mod tests {
|
||||||
fn sign_and_verify() {
|
fn sign_and_verify() {
|
||||||
let mut s = Secp256k1::new().unwrap();
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
|
||||||
let mut msg = Vec::from_elem(32, 0u8);
|
let mut msg: Vec<u8> = repeat(0).take(32).collect();
|
||||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
rand::thread_rng().fill_bytes(msg.as_mut_slice());
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(false);
|
let (sk, pk) = s.generate_keypair(false);
|
||||||
let nonce = s.generate_nonce();
|
let nonce = s.generate_nonce();
|
||||||
|
@ -346,15 +350,15 @@ mod tests {
|
||||||
fn sign_and_verify_fail() {
|
fn sign_and_verify_fail() {
|
||||||
let mut s = Secp256k1::new().unwrap();
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
|
||||||
let mut msg = Vec::from_elem(32, 0u8);
|
let mut msg: Vec<u8> = repeat(0).take(32).collect();
|
||||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
rand::thread_rng().fill_bytes(msg.as_mut_slice());
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(false);
|
let (sk, pk) = s.generate_keypair(false);
|
||||||
let nonce = s.generate_nonce();
|
let nonce = s.generate_nonce();
|
||||||
|
|
||||||
let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();
|
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));
|
assert_eq!(Secp256k1::verify(msg.as_slice(), &sig, &pk), Err(IncorrectSignature));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,8 +366,8 @@ mod tests {
|
||||||
fn sign_compact_with_recovery() {
|
fn sign_compact_with_recovery() {
|
||||||
let mut s = Secp256k1::new().unwrap();
|
let mut s = Secp256k1::new().unwrap();
|
||||||
|
|
||||||
let mut msg = [0u8, ..32];
|
let mut msg = [0u8; 32];
|
||||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
rand::thread_rng().fill_bytes(msg.as_mut_slice());
|
||||||
|
|
||||||
let (sk, pk) = s.generate_keypair(false);
|
let (sk, pk) = s.generate_keypair(false);
|
||||||
let nonce = s.generate_nonce();
|
let nonce = s.generate_nonce();
|
||||||
|
@ -375,12 +379,12 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deterministic_sign() {
|
fn deterministic_sign() {
|
||||||
let mut msg = [0u8, ..32];
|
let mut msg = [0u8; 32];
|
||||||
rand::task_rng().fill_bytes(msg.as_mut_slice());
|
rand::thread_rng().fill_bytes(msg.as_mut_slice());
|
||||||
|
|
||||||
let mut s = Secp256k1::new().unwrap();
|
let mut s = Secp256k1::new().unwrap();
|
||||||
let (sk, pk) = s.generate_keypair(true);
|
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();
|
let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue