remove `without_caps` and every function that used a cap-less context
This commit is contained in:
parent
4653100b7a
commit
93abca5896
|
@ -129,6 +129,8 @@ extern "C" {
|
||||||
|
|
||||||
pub static secp256k1_nonce_function_default: NonceFn;
|
pub static secp256k1_nonce_function_default: NonceFn;
|
||||||
|
|
||||||
|
pub static secp256k1_context_no_precomp: *const Context;
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
pub fn secp256k1_context_create(flags: c_uint) -> *mut Context;
|
pub fn secp256k1_context_create(flags: c_uint) -> *mut Context;
|
||||||
|
|
||||||
|
@ -278,6 +280,7 @@ mod fuzz_dummy {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub static secp256k1_ecdh_hash_function_default: EcdhHashFn;
|
pub static secp256k1_ecdh_hash_function_default: EcdhHashFn;
|
||||||
pub static secp256k1_nonce_function_rfc6979: NonceFn;
|
pub static secp256k1_nonce_function_rfc6979: NonceFn;
|
||||||
|
pub static secp256k1_context_no_precomp: *const Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
|
|
172
src/key.rs
172
src/key.rs
|
@ -87,17 +87,15 @@ impl fmt::Display for PublicKey {
|
||||||
impl str::FromStr for PublicKey {
|
impl str::FromStr for PublicKey {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
fn from_str(s: &str) -> Result<PublicKey, Error> {
|
fn from_str(s: &str) -> Result<PublicKey, Error> {
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let mut res = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
let mut res = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
||||||
match from_hex(s, &mut res) {
|
match from_hex(s, &mut res) {
|
||||||
Ok(constants::PUBLIC_KEY_SIZE) => {
|
Ok(constants::PUBLIC_KEY_SIZE) => {
|
||||||
PublicKey::from_slice(
|
PublicKey::from_slice(
|
||||||
&secp,
|
|
||||||
&res[0..constants::PUBLIC_KEY_SIZE]
|
&res[0..constants::PUBLIC_KEY_SIZE]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Ok(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) => {
|
Ok(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) => {
|
||||||
PublicKey::from_slice(&secp, &res)
|
PublicKey::from_slice(&res)
|
||||||
}
|
}
|
||||||
_ => Err(Error::InvalidPublicKey)
|
_ => Err(Error::InvalidPublicKey)
|
||||||
}
|
}
|
||||||
|
@ -115,10 +113,14 @@ impl SecretKey {
|
||||||
/// Creates a new random secret key. Requires compilation with the "rand" feature.
|
/// Creates a new random secret key. Requires compilation with the "rand" feature.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
pub fn new<R: Rng, C>(secp: &Secp256k1<C>, rng: &mut R) -> SecretKey {
|
pub fn new<R: Rng>(rng: &mut R) -> SecretKey {
|
||||||
let mut data = random_32_bytes(rng);
|
let mut data = random_32_bytes(rng);
|
||||||
unsafe {
|
unsafe {
|
||||||
while ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 {
|
while ffi::secp256k1_ec_seckey_verify(
|
||||||
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
data.as_ptr(),
|
||||||
|
) == 0
|
||||||
|
{
|
||||||
data = random_32_bytes(rng);
|
data = random_32_bytes(rng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,13 +129,16 @@ impl SecretKey {
|
||||||
|
|
||||||
/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
|
/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice<C>(secp: &Secp256k1<C>, data: &[u8])
|
pub fn from_slice(data: &[u8])-> Result<SecretKey, Error> {
|
||||||
-> Result<SecretKey, Error> {
|
|
||||||
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_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 {
|
if ffi::secp256k1_ec_seckey_verify(
|
||||||
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
data.as_ptr(),
|
||||||
|
) == 0
|
||||||
|
{
|
||||||
return Err(InvalidSecretKey);
|
return Err(InvalidSecretKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,10 +151,14 @@ impl SecretKey {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Adds one secret key to another, modulo the curve order
|
/// Adds one secret key to another, modulo the curve order
|
||||||
pub fn add_assign<C>(&mut self, secp: &Secp256k1<C>, other: &SecretKey)
|
pub fn add_assign(&mut self, other: &SecretKey) -> Result<(), Error> {
|
||||||
-> Result<(), Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_privkey_tweak_add(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 {
|
if ffi::secp256k1_ec_privkey_tweak_add(
|
||||||
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
self.as_mut_ptr(),
|
||||||
|
other.as_ptr(),
|
||||||
|
) != 1
|
||||||
|
{
|
||||||
Err(InvalidSecretKey)
|
Err(InvalidSecretKey)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -159,10 +168,14 @@ impl SecretKey {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Multiplies one secret key by another, modulo the curve order
|
/// Multiplies one secret key by another, modulo the curve order
|
||||||
pub fn mul_assign<C>(&mut self, secp: &Secp256k1<C>, other: &SecretKey)
|
pub fn mul_assign(&mut self, other: &SecretKey) -> Result<(), Error> {
|
||||||
-> Result<(), Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_privkey_tweak_mul(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 {
|
if ffi::secp256k1_ec_privkey_tweak_mul(
|
||||||
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
self.as_mut_ptr(),
|
||||||
|
other.as_ptr(),
|
||||||
|
) != 1
|
||||||
|
{
|
||||||
Err(InvalidSecretKey)
|
Err(InvalidSecretKey)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -220,13 +233,16 @@ impl PublicKey {
|
||||||
|
|
||||||
/// Creates a public key directly from a slice
|
/// Creates a public key directly from a slice
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_slice<C>(secp: &Secp256k1<C>, data: &[u8])
|
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
|
||||||
-> Result<PublicKey, Error> {
|
|
||||||
|
|
||||||
let mut pk = unsafe { ffi::PublicKey::blank() };
|
let mut pk = unsafe { ffi::PublicKey::blank() };
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ec_pubkey_parse(secp.ctx, &mut pk, data.as_ptr(),
|
if ffi::secp256k1_ec_pubkey_parse(
|
||||||
data.len() as ::libc::size_t) == 1 {
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut pk,
|
||||||
|
data.as_ptr(),
|
||||||
|
data.len() as ::libc::size_t,
|
||||||
|
) == 1
|
||||||
|
{
|
||||||
Ok(PublicKey(pk))
|
Ok(PublicKey(pk))
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidPublicKey)
|
Err(InvalidPublicKey)
|
||||||
|
@ -239,13 +255,12 @@ impl PublicKey {
|
||||||
/// the y-coordinate is represented by only a single bit, as x determines
|
/// the y-coordinate is represented by only a single bit, as x determines
|
||||||
/// it up to one bit.
|
/// it up to one bit.
|
||||||
pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] {
|
pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] {
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let mut ret = [0; constants::PUBLIC_KEY_SIZE];
|
let mut ret = [0; constants::PUBLIC_KEY_SIZE];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret_len = constants::PUBLIC_KEY_SIZE as ::libc::size_t;
|
let mut ret_len = constants::PUBLIC_KEY_SIZE as ::libc::size_t;
|
||||||
let err = ffi::secp256k1_ec_pubkey_serialize(
|
let err = ffi::secp256k1_ec_pubkey_serialize(
|
||||||
secp.ctx,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_ptr(),
|
ret.as_mut_ptr(),
|
||||||
&mut ret_len,
|
&mut ret_len,
|
||||||
self.as_ptr(),
|
self.as_ptr(),
|
||||||
|
@ -259,13 +274,12 @@ impl PublicKey {
|
||||||
|
|
||||||
/// Serialize the key as a byte-encoded pair of values, in uncompressed form
|
/// Serialize the key as a byte-encoded pair of values, in uncompressed form
|
||||||
pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] {
|
pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] {
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let mut ret = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
let mut ret = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as ::libc::size_t;
|
let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as ::libc::size_t;
|
||||||
let err = ffi::secp256k1_ec_pubkey_serialize(
|
let err = ffi::secp256k1_ec_pubkey_serialize(
|
||||||
secp.ctx,
|
ffi::secp256k1_context_no_precomp,
|
||||||
ret.as_mut_ptr(),
|
ret.as_mut_ptr(),
|
||||||
&mut ret_len,
|
&mut ret_len,
|
||||||
self.as_ptr(),
|
self.as_ptr(),
|
||||||
|
@ -308,11 +322,17 @@ impl PublicKey {
|
||||||
/// Adds a second key to this one, returning the sum. Returns an error if
|
/// Adds a second key to this one, returning the sum. Returns an error if
|
||||||
/// the result would be the point at infinity, i.e. we are adding this point
|
/// the result would be the point at infinity, i.e. we are adding this point
|
||||||
/// to its own negation
|
/// to its own negation
|
||||||
pub fn combine<C>(&self, secp: &Secp256k1<C>, other: &PublicKey) -> Result<PublicKey, Error> {
|
pub fn combine(&self, other: &PublicKey) -> Result<PublicKey, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = mem::uninitialized();
|
let mut ret = mem::uninitialized();
|
||||||
let ptrs = [self.as_ptr(), other.as_ptr()];
|
let ptrs = [self.as_ptr(), other.as_ptr()];
|
||||||
if ffi::secp256k1_ec_pubkey_combine(secp.ctx, &mut ret, ptrs.as_ptr(), 2) == 1 {
|
if ffi::secp256k1_ec_pubkey_combine(
|
||||||
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut ret,
|
||||||
|
ptrs.as_ptr(),
|
||||||
|
2
|
||||||
|
) == 1
|
||||||
|
{
|
||||||
Ok(PublicKey(ret))
|
Ok(PublicKey(ret))
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidPublicKey)
|
Err(InvalidPublicKey)
|
||||||
|
@ -341,9 +361,8 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
|
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
|
||||||
use ::serde::de::Error;
|
use ::serde::de::Error;
|
||||||
|
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
||||||
PublicKey::from_slice(&secp, sl).map_err(D::Error::custom)
|
PublicKey::from_slice(sl).map_err(D::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,24 +388,22 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn skey_from_slice() {
|
fn skey_from_slice() {
|
||||||
let s = Secp256k1::new();
|
let sk = SecretKey::from_slice(&[1; 31]);
|
||||||
let sk = SecretKey::from_slice(&s, &[1; 31]);
|
|
||||||
assert_eq!(sk, Err(InvalidSecretKey));
|
assert_eq!(sk, Err(InvalidSecretKey));
|
||||||
|
|
||||||
let sk = SecretKey::from_slice(&s, &[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() {
|
||||||
let s = Secp256k1::new();
|
assert_eq!(PublicKey::from_slice(&[]), Err(InvalidPublicKey));
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey));
|
assert_eq!(PublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey));
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey));
|
|
||||||
|
|
||||||
let uncompressed = PublicKey::from_slice(&s, &[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());
|
||||||
|
|
||||||
let compressed = PublicKey::from_slice(&s, &[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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,30 +412,31 @@ mod test {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
|
||||||
assert_eq!(SecretKey::from_slice(&s, &sk1[..]), Ok(sk1));
|
assert_eq!(SecretKey::from_slice(&sk1[..]), Ok(sk1));
|
||||||
assert_eq!(PublicKey::from_slice(&s, &pk1.serialize()[..]), Ok(pk1));
|
assert_eq!(PublicKey::from_slice(&pk1.serialize()[..]), Ok(pk1));
|
||||||
assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_uncompressed()[..]), Ok(pk1));
|
assert_eq!(PublicKey::from_slice(&pk1.serialize_uncompressed()[..]), Ok(pk1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn invalid_secret_key() {
|
fn invalid_secret_key() {
|
||||||
let s = Secp256k1::new();
|
|
||||||
// Zero
|
// Zero
|
||||||
assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey));
|
assert_eq!(SecretKey::from_slice(&[0; 32]), Err(InvalidSecretKey));
|
||||||
// -1
|
// -1
|
||||||
assert_eq!(SecretKey::from_slice(&s, &[0xff; 32]), Err(InvalidSecretKey));
|
assert_eq!(SecretKey::from_slice(&[0xff; 32]), Err(InvalidSecretKey));
|
||||||
// Top of range
|
// Top of range
|
||||||
assert!(SecretKey::from_slice(&s,
|
assert!(SecretKey::from_slice(&[
|
||||||
&[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,
|
||||||
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(&s,
|
assert!(SecretKey::from_slice(&[
|
||||||
&[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,
|
||||||
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err());
|
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41,
|
||||||
|
]).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -449,22 +467,33 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pubkey_from_bad_slice() {
|
fn test_pubkey_from_bad_slice() {
|
||||||
let s = Secp256k1::new();
|
|
||||||
// Bad sizes
|
// Bad sizes
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[0; constants::PUBLIC_KEY_SIZE - 1]),
|
assert_eq!(
|
||||||
Err(InvalidPublicKey));
|
PublicKey::from_slice(&[0; constants::PUBLIC_KEY_SIZE - 1]),
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[0; constants::PUBLIC_KEY_SIZE + 1]),
|
Err(InvalidPublicKey)
|
||||||
Err(InvalidPublicKey));
|
);
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]),
|
assert_eq!(
|
||||||
Err(InvalidPublicKey));
|
PublicKey::from_slice(&[0; constants::PUBLIC_KEY_SIZE + 1]),
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]),
|
Err(InvalidPublicKey)
|
||||||
Err(InvalidPublicKey));
|
);
|
||||||
|
assert_eq!(
|
||||||
|
PublicKey::from_slice(&[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]),
|
||||||
|
Err(InvalidPublicKey)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
PublicKey::from_slice(&[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]),
|
||||||
|
Err(InvalidPublicKey)
|
||||||
|
);
|
||||||
|
|
||||||
// Bad parse
|
// Bad parse
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
|
assert_eq!(
|
||||||
Err(InvalidPublicKey));
|
PublicKey::from_slice(&[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
|
||||||
assert_eq!(PublicKey::from_slice(&s, &[0x55; constants::PUBLIC_KEY_SIZE]),
|
Err(InvalidPublicKey)
|
||||||
Err(InvalidPublicKey));
|
);
|
||||||
|
assert_eq!(
|
||||||
|
PublicKey::from_slice(&[0x55; constants::PUBLIC_KEY_SIZE]),
|
||||||
|
Err(InvalidPublicKey)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -494,7 +523,7 @@ mod test {
|
||||||
];
|
];
|
||||||
|
|
||||||
let s = Secp256k1::signing_only();
|
let s = Secp256k1::signing_only();
|
||||||
let sk = SecretKey::from_slice(&s, &SK_BYTES).expect("sk");
|
let sk = SecretKey::from_slice(&SK_BYTES).expect("sk");
|
||||||
let pk = PublicKey::from_secret_key(&s, &sk);
|
let pk = PublicKey::from_secret_key(&s, &sk);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -563,12 +592,12 @@ mod test {
|
||||||
let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng());
|
let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng());
|
||||||
|
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
||||||
assert!(sk1.add_assign(&s, &sk2).is_ok());
|
assert!(sk1.add_assign(&sk2).is_ok());
|
||||||
assert!(pk1.add_exp_assign(&s, &sk2).is_ok());
|
assert!(pk1.add_exp_assign(&s, &sk2).is_ok());
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
||||||
|
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
||||||
assert!(sk2.add_assign(&s, &sk1).is_ok());
|
assert!(sk2.add_assign(&sk1).is_ok());
|
||||||
assert!(pk2.add_exp_assign(&s, &sk1).is_ok());
|
assert!(pk2.add_exp_assign(&s, &sk1).is_ok());
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
||||||
}
|
}
|
||||||
|
@ -581,12 +610,12 @@ mod test {
|
||||||
let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng());
|
let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng());
|
||||||
|
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
||||||
assert!(sk1.mul_assign(&s, &sk2).is_ok());
|
assert!(sk1.mul_assign(&sk2).is_ok());
|
||||||
assert!(pk1.mul_assign(&s, &sk2).is_ok());
|
assert!(pk1.mul_assign(&s, &sk2).is_ok());
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1);
|
||||||
|
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
||||||
assert!(sk2.mul_assign(&s, &sk1).is_ok());
|
assert!(sk2.mul_assign(&sk1).is_ok());
|
||||||
assert!(pk2.mul_assign(&s, &sk1).is_ok());
|
assert!(pk2.mul_assign(&s, &sk1).is_ok());
|
||||||
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
|
||||||
}
|
}
|
||||||
|
@ -617,23 +646,19 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pubkey_combine() {
|
fn pubkey_combine() {
|
||||||
let s = Secp256k1::without_caps();
|
|
||||||
let compressed1 = PublicKey::from_slice(
|
let compressed1 = PublicKey::from_slice(
|
||||||
&s,
|
|
||||||
&hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"),
|
&hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let compressed2 = PublicKey::from_slice(
|
let compressed2 = PublicKey::from_slice(
|
||||||
&s,
|
|
||||||
&hex!("02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"),
|
&hex!("02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let exp_sum = PublicKey::from_slice(
|
let exp_sum = PublicKey::from_slice(
|
||||||
&s,
|
|
||||||
&hex!("0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07"),
|
&hex!("0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07"),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let sum1 = compressed1.combine(&s, &compressed2);
|
let sum1 = compressed1.combine(&compressed2);
|
||||||
assert!(sum1.is_ok());
|
assert!(sum1.is_ok());
|
||||||
let sum2 = compressed2.combine(&s, &compressed1);
|
let sum2 = compressed2.combine(&compressed1);
|
||||||
assert!(sum2.is_ok());
|
assert!(sum2.is_ok());
|
||||||
assert_eq!(sum1, sum2);
|
assert_eq!(sum1, sum2);
|
||||||
assert_eq!(sum1.unwrap(), exp_sum);
|
assert_eq!(sum1.unwrap(), exp_sum);
|
||||||
|
@ -641,14 +666,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pubkey_equal() {
|
fn pubkey_equal() {
|
||||||
let s = Secp256k1::new();
|
|
||||||
let pk1 = PublicKey::from_slice(
|
let pk1 = PublicKey::from_slice(
|
||||||
&s,
|
|
||||||
&hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"),
|
&hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
let pk2 = pk1.clone();
|
let pk2 = pk1.clone();
|
||||||
let pk3 = PublicKey::from_slice(
|
let pk3 = PublicKey::from_slice(
|
||||||
&s,
|
|
||||||
&hex!("02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"),
|
&hex!("02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
|
@ -684,7 +706,7 @@ mod test {
|
||||||
|
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let sk = SecretKey::from_slice(&s, &SK_BYTES).unwrap();
|
let sk = SecretKey::from_slice(&SK_BYTES).unwrap();
|
||||||
let pk = PublicKey::from_secret_key(&s, &sk);
|
let pk = PublicKey::from_secret_key(&s, &sk);
|
||||||
|
|
||||||
assert_tokens(&sk, &[Token::BorrowedBytes(&SK_BYTES[..])]);
|
assert_tokens(&sk, &[Token::BorrowedBytes(&SK_BYTES[..])]);
|
||||||
|
|
206
src/lib.rs
206
src/lib.rs
|
@ -66,7 +66,7 @@
|
||||||
//! use self::secp256k1::{Secp256k1, Message, SecretKey, PublicKey};
|
//! use self::secp256k1::{Secp256k1, Message, SecretKey, PublicKey};
|
||||||
//!
|
//!
|
||||||
//! let secp = Secp256k1::new();
|
//! let secp = Secp256k1::new();
|
||||||
//! let secret_key = SecretKey::from_slice(&secp, &[0xcd; 32]).expect("32 bytes, within curve order");
|
//! let secret_key = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order");
|
||||||
//! let public_key = PublicKey::from_secret_key(&secp, &secret_key);
|
//! let public_key = PublicKey::from_secret_key(&secp, &secret_key);
|
||||||
//! let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
|
//! let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
|
||||||
//!
|
//!
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
//!
|
//!
|
||||||
//! let secp = Secp256k1::verification_only();
|
//! let secp = Secp256k1::verification_only();
|
||||||
//!
|
//!
|
||||||
//! let public_key = PublicKey::from_slice(&secp, &[
|
//! let public_key = PublicKey::from_slice(&[
|
||||||
//! 0x02,
|
//! 0x02,
|
||||||
//! 0xc6, 0x6e, 0x7d, 0x89, 0x66, 0xb5, 0xc5, 0x55,
|
//! 0xc6, 0x6e, 0x7d, 0x89, 0x66, 0xb5, 0xc5, 0x55,
|
||||||
//! 0xaf, 0x58, 0x05, 0x98, 0x9d, 0xa9, 0xfb, 0xf8,
|
//! 0xaf, 0x58, 0x05, 0x98, 0x9d, 0xa9, 0xfb, 0xf8,
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
//! 0xd5, 0x44, 0x53, 0xcf, 0x6e, 0x82, 0xb4, 0x50,
|
//! 0xd5, 0x44, 0x53, 0xcf, 0x6e, 0x82, 0xb4, 0x50,
|
||||||
//! ]).expect("messages must be 32 bytes and are expected to be hashes");
|
//! ]).expect("messages must be 32 bytes and are expected to be hashes");
|
||||||
//!
|
//!
|
||||||
//! let sig = Signature::from_compact(&secp, &[
|
//! let sig = Signature::from_compact(&[
|
||||||
//! 0xdc, 0x4d, 0xc2, 0x64, 0xa9, 0xfe, 0xf1, 0x7a,
|
//! 0xdc, 0x4d, 0xc2, 0x64, 0xa9, 0xfe, 0xf1, 0x7a,
|
||||||
//! 0x3f, 0x25, 0x34, 0x49, 0xcf, 0x8c, 0x39, 0x7a,
|
//! 0x3f, 0x25, 0x34, 0x49, 0xcf, 0x8c, 0x39, 0x7a,
|
||||||
//! 0xb6, 0xf1, 0x6f, 0xb3, 0xd6, 0x3d, 0x86, 0x94,
|
//! 0xb6, 0xf1, 0x6f, 0xb3, 0xd6, 0x3d, 0x86, 0x94,
|
||||||
|
@ -174,10 +174,13 @@ impl fmt::Display for Signature {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let mut v = [0; 72];
|
let mut v = [0; 72];
|
||||||
let mut len = v.len() as size_t;
|
let mut len = v.len() as size_t;
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, v.as_mut_ptr(),
|
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
|
||||||
&mut len, self.as_ptr());
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
v.as_mut_ptr(),
|
||||||
|
&mut len,
|
||||||
|
self.as_ptr()
|
||||||
|
);
|
||||||
debug_assert!(err == 1);
|
debug_assert!(err == 1);
|
||||||
}
|
}
|
||||||
for ch in &v[..] {
|
for ch in &v[..] {
|
||||||
|
@ -190,10 +193,9 @@ impl fmt::Display for Signature {
|
||||||
impl str::FromStr for Signature {
|
impl str::FromStr for Signature {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
fn from_str(s: &str) -> Result<Signature, Error> {
|
fn from_str(s: &str) -> Result<Signature, Error> {
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let mut res = [0; 72];
|
let mut res = [0; 72];
|
||||||
match from_hex(s, &mut res) {
|
match from_hex(s, &mut res) {
|
||||||
Ok(x) => Signature::from_der(&secp, &res[0..x]),
|
Ok(x) => Signature::from_der(&res[0..x]),
|
||||||
_ => Err(Error::InvalidSignature),
|
_ => Err(Error::InvalidSignature),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,12 +225,17 @@ impl RecoveryId {
|
||||||
impl Signature {
|
impl Signature {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Converts a DER-encoded byte slice to a signature
|
/// Converts a DER-encoded byte slice to a signature
|
||||||
pub fn from_der<C>(secp: &Secp256k1<C>, data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
||||||
let mut ret = unsafe { ffi::Signature::blank() };
|
let mut ret = unsafe { ffi::Signature::blank() };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx, &mut ret,
|
if ffi::secp256k1_ecdsa_signature_parse_der(
|
||||||
data.as_ptr(), data.len() as libc::size_t) == 1 {
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut ret,
|
||||||
|
data.as_ptr(),
|
||||||
|
data.len() as libc::size_t,
|
||||||
|
) == 1
|
||||||
|
{
|
||||||
Ok(Signature(ret))
|
Ok(Signature(ret))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidSignature)
|
Err(Error::InvalidSignature)
|
||||||
|
@ -237,15 +244,19 @@ impl Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a 64-byte compact-encoded byte slice to a signature
|
/// Converts a 64-byte compact-encoded byte slice to a signature
|
||||||
pub fn from_compact<C>(secp: &Secp256k1<C>, data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
|
||||||
let mut ret = unsafe { ffi::Signature::blank() };
|
let mut ret = unsafe { ffi::Signature::blank() };
|
||||||
if data.len() != 64 {
|
if data.len() != 64 {
|
||||||
return Err(Error::InvalidSignature)
|
return Err(Error::InvalidSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_signature_parse_compact(secp.ctx, &mut ret,
|
if ffi::secp256k1_ecdsa_signature_parse_compact(
|
||||||
data.as_ptr()) == 1 {
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut ret,
|
||||||
|
data.as_ptr(),
|
||||||
|
) == 1
|
||||||
|
{
|
||||||
Ok(Signature(ret))
|
Ok(Signature(ret))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidSignature)
|
Err(Error::InvalidSignature)
|
||||||
|
@ -257,11 +268,16 @@ impl Signature {
|
||||||
/// only useful for validating signatures in the Bitcoin blockchain from before
|
/// only useful for validating signatures in the Bitcoin blockchain from before
|
||||||
/// 2016. It should never be used in new applications. This library does not
|
/// 2016. It should never be used in new applications. This library does not
|
||||||
/// support serializing to this "format"
|
/// support serializing to this "format"
|
||||||
pub fn from_der_lax<C>(secp: &Secp256k1<C>, data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = ffi::Signature::blank();
|
let mut ret = ffi::Signature::blank();
|
||||||
if ffi::ecdsa_signature_parse_der_lax(secp.ctx, &mut ret,
|
if ffi::ecdsa_signature_parse_der_lax(
|
||||||
data.as_ptr(), data.len() as libc::size_t) == 1 {
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut ret,
|
||||||
|
data.as_ptr(),
|
||||||
|
data.len() as libc::size_t,
|
||||||
|
) == 1
|
||||||
|
{
|
||||||
Ok(Signature(ret))
|
Ok(Signature(ret))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidSignature)
|
Err(Error::InvalidSignature)
|
||||||
|
@ -286,12 +302,15 @@ impl Signature {
|
||||||
/// valid. (For example, parsing the historic Bitcoin blockchain requires
|
/// valid. (For example, parsing the historic Bitcoin blockchain requires
|
||||||
/// this.) For these applications we provide this normalization function,
|
/// this.) For these applications we provide this normalization function,
|
||||||
/// which ensures that the s value lies in the lower half of its range.
|
/// which ensures that the s value lies in the lower half of its range.
|
||||||
pub fn normalize_s<C>(&mut self, secp: &Secp256k1<C>) {
|
pub fn normalize_s(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Ignore return value, which indicates whether the sig
|
// Ignore return value, which indicates whether the sig
|
||||||
// was already normalized. We don't care.
|
// was already normalized. We don't care.
|
||||||
ffi::secp256k1_ecdsa_signature_normalize(secp.ctx, self.as_mut_ptr(),
|
ffi::secp256k1_ecdsa_signature_normalize(
|
||||||
self.as_ptr());
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
self.as_mut_ptr(),
|
||||||
|
self.as_ptr(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,12 +328,16 @@ impl Signature {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Serializes the signature in DER format
|
/// Serializes the signature in DER format
|
||||||
pub fn serialize_der<C>(&self, secp: &Secp256k1<C>) -> Vec<u8> {
|
pub fn serialize_der(&self) -> Vec<u8> {
|
||||||
let mut ret = Vec::with_capacity(72);
|
let mut ret = Vec::with_capacity(72);
|
||||||
let mut len: size_t = ret.capacity() as size_t;
|
let mut len: size_t = ret.capacity() as size_t;
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, ret.as_mut_ptr(),
|
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
|
||||||
&mut len, self.as_ptr());
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
ret.as_mut_ptr(),
|
||||||
|
&mut len,
|
||||||
|
self.as_ptr(),
|
||||||
|
);
|
||||||
debug_assert!(err == 1);
|
debug_assert!(err == 1);
|
||||||
ret.set_len(len as usize);
|
ret.set_len(len as usize);
|
||||||
}
|
}
|
||||||
|
@ -323,11 +346,14 @@ impl Signature {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Serializes the signature in compact format
|
/// Serializes the signature in compact format
|
||||||
pub fn serialize_compact<C>(&self, secp: &Secp256k1<C>) -> [u8; 64] {
|
pub fn serialize_compact(&self) -> [u8; 64] {
|
||||||
let mut ret = [0; 64];
|
let mut ret = [0; 64];
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(secp.ctx, ret.as_mut_ptr(),
|
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(
|
||||||
self.as_ptr());
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
ret.as_mut_ptr(),
|
||||||
|
self.as_ptr(),
|
||||||
|
);
|
||||||
debug_assert!(err == 1);
|
debug_assert!(err == 1);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
@ -348,14 +374,19 @@ impl RecoverableSignature {
|
||||||
/// Converts a compact-encoded byte slice to a signature. This
|
/// Converts a compact-encoded byte slice to a signature. This
|
||||||
/// representation is nonstandard and defined by the libsecp256k1
|
/// representation is nonstandard and defined by the libsecp256k1
|
||||||
/// library.
|
/// library.
|
||||||
pub fn from_compact<C>(secp: &Secp256k1<C>, data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
|
pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
|
||||||
let mut ret = unsafe { ffi::RecoverableSignature::blank() };
|
let mut ret = unsafe { ffi::RecoverableSignature::blank() };
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if data.len() != 64 {
|
if data.len() != 64 {
|
||||||
Err(Error::InvalidSignature)
|
Err(Error::InvalidSignature)
|
||||||
} else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(secp.ctx, &mut ret,
|
} else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(
|
||||||
data.as_ptr(), recid.0) == 1 {
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut ret,
|
||||||
|
data.as_ptr(),
|
||||||
|
recid.0,
|
||||||
|
) == 1
|
||||||
|
{
|
||||||
Ok(RecoverableSignature(ret))
|
Ok(RecoverableSignature(ret))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::InvalidSignature)
|
Err(Error::InvalidSignature)
|
||||||
|
@ -371,12 +402,16 @@ impl RecoverableSignature {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Serializes the recoverable signature in compact format
|
/// Serializes the recoverable signature in compact format
|
||||||
pub fn serialize_compact<C>(&self, secp: &Secp256k1<C>) -> (RecoveryId, [u8; 64]) {
|
pub fn serialize_compact(&self) -> (RecoveryId, [u8; 64]) {
|
||||||
let mut ret = [0u8; 64];
|
let mut ret = [0u8; 64];
|
||||||
let mut recid = 0i32;
|
let mut recid = 0i32;
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact(
|
||||||
secp.ctx, ret.as_mut_ptr(), &mut recid, self.as_ptr());
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
ret.as_mut_ptr(),
|
||||||
|
&mut recid,
|
||||||
|
self.as_ptr(),
|
||||||
|
);
|
||||||
assert!(err == 1);
|
assert!(err == 1);
|
||||||
}
|
}
|
||||||
(RecoveryId(recid), ret)
|
(RecoveryId(recid), ret)
|
||||||
|
@ -385,10 +420,14 @@ impl RecoverableSignature {
|
||||||
/// Converts a recoverable signature to a non-recoverable one (this is needed
|
/// Converts a recoverable signature to a non-recoverable one (this is needed
|
||||||
/// for verification
|
/// for verification
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_standard<C>(&self, secp: &Secp256k1<C>) -> Signature {
|
pub fn to_standard(&self) -> Signature {
|
||||||
let mut ret = unsafe { ffi::Signature::blank() };
|
let mut ret = unsafe { ffi::Signature::blank() };
|
||||||
unsafe {
|
unsafe {
|
||||||
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(secp.ctx, &mut ret, self.as_ptr());
|
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(
|
||||||
|
ffi::secp256k1_context_no_precomp,
|
||||||
|
&mut ret,
|
||||||
|
self.as_ptr(),
|
||||||
|
);
|
||||||
assert!(err == 1);
|
assert!(err == 1);
|
||||||
}
|
}
|
||||||
Signature(ret)
|
Signature(ret)
|
||||||
|
@ -442,8 +481,7 @@ impl ops::Index<ops::RangeFull> for Signature {
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
impl ::serde::Serialize for Signature {
|
impl ::serde::Serialize for Signature {
|
||||||
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||||
let secp = Secp256k1::without_caps();
|
s.serialize_bytes(&self.serialize_der())
|
||||||
s.serialize_bytes(&self.serialize_der(&secp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,9 +490,8 @@ impl<'de> ::serde::Deserialize<'de> for Signature {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Signature, D::Error> {
|
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Signature, D::Error> {
|
||||||
use ::serde::de::Error;
|
use ::serde::de::Error;
|
||||||
|
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
let sl: &[u8] = ::serde::Deserialize::deserialize(d)?;
|
||||||
Signature::from_der(&secp, sl).map_err(D::Error::custom)
|
Signature::from_der(sl).map_err(D::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,9 +568,6 @@ pub trait Signing {}
|
||||||
/// Marker trait for indicating that an instance of `Secp256k1` can be used for verification.
|
/// Marker trait for indicating that an instance of `Secp256k1` can be used for verification.
|
||||||
pub trait Verification {}
|
pub trait Verification {}
|
||||||
|
|
||||||
/// Represents the empty set of capabilities.
|
|
||||||
pub struct None {}
|
|
||||||
|
|
||||||
/// Represents the set of capabilities needed for signing.
|
/// Represents the set of capabilities needed for signing.
|
||||||
pub struct SignOnly {}
|
pub struct SignOnly {}
|
||||||
|
|
||||||
|
@ -581,12 +615,6 @@ impl<C> Drop for Secp256k1<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Secp256k1<None> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "<secp256k1 context {:?}, no capabilities>", self.ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Secp256k1<SignOnly> {
|
impl fmt::Debug for Secp256k1<SignOnly> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "<secp256k1 context {:?}, signing only>", self.ctx)
|
write!(f, "<secp256k1 context {:?}, signing only>", self.ctx)
|
||||||
|
@ -605,13 +633,6 @@ impl fmt::Debug for Secp256k1<All> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Secp256k1<None> {
|
|
||||||
/// Creates a new Secp256k1 context with no capabilities (just de/serialization)
|
|
||||||
pub fn without_caps() -> Secp256k1<None> {
|
|
||||||
Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(ffi::SECP256K1_START_NONE) }, phantom: PhantomData }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Secp256k1<All> {
|
impl Secp256k1<All> {
|
||||||
/// Creates a new Secp256k1 context with all capabilities
|
/// Creates a new Secp256k1 context with all capabilities
|
||||||
pub fn new() -> Secp256k1<All> {
|
pub fn new() -> Secp256k1<All> {
|
||||||
|
@ -686,9 +707,17 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
unsafe {
|
unsafe {
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid signature from a valid `Message` and `SecretKey`
|
// an invalid signature from a valid `Message` and `SecretKey`
|
||||||
assert_eq!(ffi::secp256k1_ecdsa_sign_recoverable(self.ctx, &mut ret, msg.as_ptr(),
|
assert_eq!(
|
||||||
sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
ffi::secp256k1_ecdsa_sign_recoverable(
|
||||||
ptr::null()), 1);
|
self.ctx,
|
||||||
|
&mut ret,
|
||||||
|
msg.as_ptr(),
|
||||||
|
sk.as_ptr(),
|
||||||
|
ffi::secp256k1_nonce_function_rfc6979,
|
||||||
|
ptr::null()
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecoverableSignature::from(ret)
|
RecoverableSignature::from(ret)
|
||||||
|
@ -702,7 +731,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
pub fn generate_keypair<R: Rng>(&self, rng: &mut R)
|
pub fn generate_keypair<R: Rng>(&self, rng: &mut R)
|
||||||
-> (key::SecretKey, key::PublicKey) {
|
-> (key::SecretKey, key::PublicKey) {
|
||||||
let sk = key::SecretKey::new(self, rng);
|
let sk = key::SecretKey::new(rng);
|
||||||
let pk = key::PublicKey::from_secret_key(self, &sk);
|
let pk = key::PublicKey::from_secret_key(self, &sk);
|
||||||
(sk, pk)
|
(sk, pk)
|
||||||
}
|
}
|
||||||
|
@ -792,7 +821,6 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn capabilities() {
|
fn capabilities() {
|
||||||
let none = Secp256k1::without_caps();
|
|
||||||
let sign = Secp256k1::signing_only();
|
let sign = Secp256k1::signing_only();
|
||||||
let vrfy = Secp256k1::verification_only();
|
let vrfy = Secp256k1::verification_only();
|
||||||
let full = Secp256k1::new();
|
let full = Secp256k1::new();
|
||||||
|
@ -824,8 +852,8 @@ mod tests {
|
||||||
|
|
||||||
// Check that we can produce keys from slices with no precomputation
|
// Check that we can produce keys from slices with no precomputation
|
||||||
let (pk_slice, sk_slice) = (&pk.serialize(), &sk[..]);
|
let (pk_slice, sk_slice) = (&pk.serialize(), &sk[..]);
|
||||||
let new_pk = PublicKey::from_slice(&none, pk_slice).unwrap();
|
let new_pk = PublicKey::from_slice(pk_slice).unwrap();
|
||||||
let new_sk = SecretKey::from_slice(&none, sk_slice).unwrap();
|
let new_sk = SecretKey::from_slice(sk_slice).unwrap();
|
||||||
assert_eq!(sk, new_sk);
|
assert_eq!(sk, new_sk);
|
||||||
assert_eq!(pk, new_pk);
|
assert_eq!(pk, new_pk);
|
||||||
}
|
}
|
||||||
|
@ -843,11 +871,11 @@ mod tests {
|
||||||
let one = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
let one = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
|
||||||
|
|
||||||
let sk = SecretKey::from_slice(&s, &one).unwrap();
|
let sk = SecretKey::from_slice(&one).unwrap();
|
||||||
let msg = Message::from_slice(&one).unwrap();
|
let msg = Message::from_slice(&one).unwrap();
|
||||||
|
|
||||||
let sig = s.sign_recoverable(&msg, &sk);
|
let sig = s.sign_recoverable(&msg, &sk);
|
||||||
assert_eq!(Ok(sig), RecoverableSignature::from_compact(&s, &[
|
assert_eq!(Ok(sig), RecoverableSignature::from_compact(&[
|
||||||
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
|
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
|
||||||
0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
|
0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
|
||||||
0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65,
|
0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65,
|
||||||
|
@ -871,29 +899,28 @@ mod tests {
|
||||||
|
|
||||||
let (sk, _) = s.generate_keypair(&mut thread_rng());
|
let (sk, _) = s.generate_keypair(&mut thread_rng());
|
||||||
let sig1 = s.sign(&msg, &sk);
|
let sig1 = s.sign(&msg, &sk);
|
||||||
let der = sig1.serialize_der(&s);
|
let der = sig1.serialize_der();
|
||||||
let sig2 = Signature::from_der(&s, &der[..]).unwrap();
|
let sig2 = Signature::from_der(&der[..]).unwrap();
|
||||||
assert_eq!(sig1, sig2);
|
assert_eq!(sig1, sig2);
|
||||||
|
|
||||||
let compact = sig1.serialize_compact(&s);
|
let compact = sig1.serialize_compact();
|
||||||
let sig2 = Signature::from_compact(&s, &compact[..]).unwrap();
|
let sig2 = Signature::from_compact(&compact[..]).unwrap();
|
||||||
assert_eq!(sig1, sig2);
|
assert_eq!(sig1, sig2);
|
||||||
|
|
||||||
assert!(Signature::from_compact(&s, &der[..]).is_err());
|
assert!(Signature::from_compact(&der[..]).is_err());
|
||||||
assert!(Signature::from_compact(&s, &compact[0..4]).is_err());
|
assert!(Signature::from_compact(&compact[0..4]).is_err());
|
||||||
assert!(Signature::from_der(&s, &compact[..]).is_err());
|
assert!(Signature::from_der(&compact[..]).is_err());
|
||||||
assert!(Signature::from_der(&s, &der[0..4]).is_err());
|
assert!(Signature::from_der(&der[0..4]).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn signature_display() {
|
fn signature_display() {
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let hex_str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45";
|
let hex_str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45";
|
||||||
let byte_str = hex!(hex_str);
|
let byte_str = hex!(hex_str);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Signature::from_der(&secp, &byte_str).expect("byte str decode"),
|
Signature::from_der(&byte_str).expect("byte str decode"),
|
||||||
Signature::from_str(&hex_str).expect("byte str decode")
|
Signature::from_str(&hex_str).expect("byte str decode")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -927,9 +954,8 @@ mod tests {
|
||||||
fn signature_lax_der() {
|
fn signature_lax_der() {
|
||||||
macro_rules! check_lax_sig(
|
macro_rules! check_lax_sig(
|
||||||
($hex:expr) => ({
|
($hex:expr) => ({
|
||||||
let secp = Secp256k1::without_caps();
|
|
||||||
let sig = hex!($hex);
|
let sig = hex!($hex);
|
||||||
assert!(Signature::from_der_lax(&secp, &sig[..]).is_ok());
|
assert!(Signature::from_der_lax(&sig[..]).is_ok());
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -979,7 +1005,7 @@ mod tests {
|
||||||
wild_keys[1][0] -= 1;
|
wild_keys[1][0] -= 1;
|
||||||
wild_msgs[1][0] -= 1;
|
wild_msgs[1][0] -= 1;
|
||||||
|
|
||||||
for key in wild_keys.iter().map(|k| SecretKey::from_slice(&s, &k[..]).unwrap()) {
|
for key in wild_keys.iter().map(|k| SecretKey::from_slice(&k[..]).unwrap()) {
|
||||||
for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) {
|
for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) {
|
||||||
let sig = s.sign(&msg, &key);
|
let sig = s.sign(&msg, &key);
|
||||||
let pk = PublicKey::from_secret_key(&s, &key);
|
let pk = PublicKey::from_secret_key(&s, &key);
|
||||||
|
@ -1000,7 +1026,7 @@ mod tests {
|
||||||
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
let (sk, pk) = s.generate_keypair(&mut thread_rng());
|
||||||
|
|
||||||
let sigr = s.sign_recoverable(&msg, &sk);
|
let sigr = s.sign_recoverable(&msg, &sk);
|
||||||
let sig = sigr.to_standard(&s);
|
let sig = sigr.to_standard();
|
||||||
|
|
||||||
let mut msg = [0u8; 32];
|
let mut msg = [0u8; 32];
|
||||||
thread_rng().fill_bytes(&mut msg);
|
thread_rng().fill_bytes(&mut msg);
|
||||||
|
@ -1035,19 +1061,18 @@ mod tests {
|
||||||
let msg = Message::from_slice(&[0x55; 32]).unwrap();
|
let msg = Message::from_slice(&[0x55; 32]).unwrap();
|
||||||
|
|
||||||
// Zero is not a valid sig
|
// Zero is not a valid sig
|
||||||
let sig = RecoverableSignature::from_compact(&s, &[0; 64], RecoveryId(0)).unwrap();
|
let sig = RecoverableSignature::from_compact(&[0; 64], RecoveryId(0)).unwrap();
|
||||||
assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature));
|
assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature));
|
||||||
// ...but 111..111 is
|
// ...but 111..111 is
|
||||||
let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap();
|
let sig = RecoverableSignature::from_compact(&[1; 64], RecoveryId(0)).unwrap();
|
||||||
assert!(s.recover(&msg, &sig).is_ok());
|
assert!(s.recover(&msg, &sig).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bad_slice() {
|
fn test_bad_slice() {
|
||||||
let s = Secp256k1::new();
|
assert_eq!(Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
|
||||||
assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE + 1]),
|
|
||||||
Err(InvalidSignature));
|
Err(InvalidSignature));
|
||||||
assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE]),
|
assert_eq!(Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]),
|
||||||
Err(InvalidSignature));
|
Err(InvalidSignature));
|
||||||
|
|
||||||
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]),
|
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]),
|
||||||
|
@ -1059,8 +1084,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_debug_output() {
|
fn test_debug_output() {
|
||||||
let s = Secp256k1::new();
|
let sig = RecoverableSignature::from_compact(&[
|
||||||
let sig = RecoverableSignature::from_compact(&s, &[
|
|
||||||
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
|
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
|
||||||
0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
|
0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
|
||||||
0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65,
|
0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65,
|
||||||
|
@ -1081,8 +1105,6 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_recov_sig_serialize_compact() {
|
fn test_recov_sig_serialize_compact() {
|
||||||
let s = Secp256k1::new();
|
|
||||||
|
|
||||||
let recid_in = RecoveryId(1);
|
let recid_in = RecoveryId(1);
|
||||||
let bytes_in = &[
|
let bytes_in = &[
|
||||||
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
|
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
|
||||||
|
@ -1094,8 +1116,10 @@ mod tests {
|
||||||
0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06,
|
0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06,
|
||||||
0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89];
|
0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89];
|
||||||
let sig = RecoverableSignature::from_compact(
|
let sig = RecoverableSignature::from_compact(
|
||||||
&s, bytes_in, recid_in).unwrap();
|
bytes_in,
|
||||||
let (recid_out, bytes_out) = sig.serialize_compact(&s);
|
recid_in,
|
||||||
|
).unwrap();
|
||||||
|
let (recid_out, bytes_out) = sig.serialize_compact();
|
||||||
assert_eq!(recid_in, recid_out);
|
assert_eq!(recid_in, recid_out);
|
||||||
assert_eq!(&bytes_in[..], &bytes_out[..]);
|
assert_eq!(&bytes_in[..], &bytes_out[..]);
|
||||||
}
|
}
|
||||||
|
@ -1124,14 +1148,14 @@ mod tests {
|
||||||
let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
|
let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d");
|
||||||
|
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let mut sig = Signature::from_der(&secp, &sig[..]).unwrap();
|
let mut sig = Signature::from_der(&sig[..]).unwrap();
|
||||||
let pk = PublicKey::from_slice(&secp, &pk[..]).unwrap();
|
let pk = PublicKey::from_slice(&pk[..]).unwrap();
|
||||||
let msg = Message::from_slice(&msg[..]).unwrap();
|
let msg = Message::from_slice(&msg[..]).unwrap();
|
||||||
|
|
||||||
// without normalization we expect this will fail
|
// without normalization we expect this will fail
|
||||||
assert_eq!(secp.verify(&msg, &sig, &pk), Err(IncorrectSignature));
|
assert_eq!(secp.verify(&msg, &sig, &pk), Err(IncorrectSignature));
|
||||||
// after normalization it should pass
|
// after normalization it should pass
|
||||||
sig.normalize_s(&secp);
|
sig.normalize_s();
|
||||||
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
|
assert_eq!(secp.verify(&msg, &sig, &pk), Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,7 +1167,7 @@ mod tests {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
let msg = Message::from_slice(&[1; 32]).unwrap();
|
let msg = Message::from_slice(&[1; 32]).unwrap();
|
||||||
let sk = SecretKey::from_slice(&s, &[2; 32]).unwrap();
|
let sk = SecretKey::from_slice(&[2; 32]).unwrap();
|
||||||
let sig = s.sign(&msg, &sk);
|
let sig = s.sign(&msg, &sk);
|
||||||
static SIG_BYTES: [u8; 71] = [
|
static SIG_BYTES: [u8; 71] = [
|
||||||
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237,
|
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237,
|
||||||
|
|
Loading…
Reference in New Issue