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
|
||||
|
||||
/// 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,
|
||||
|
|
162
src/key.rs
162
src/key.rs
|
@ -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,16 +502,16 @@ 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,
|
||||
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,
|
||||
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());
|
||||
|
@ -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"));
|
||||
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
110
src/secp256k1.rs
110
src/secp256k1.rs
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue