add `FromStr` implementation for key types
This commit is contained in:
parent
dc2cd97196
commit
572adb2873
95
src/key.rs
95
src/key.rs
|
@ -17,9 +17,9 @@
|
|||
|
||||
#[cfg(any(test, feature = "rand"))] use rand::Rng;
|
||||
|
||||
use std::{fmt, mem};
|
||||
use std::{fmt, mem, str};
|
||||
|
||||
use super::{Secp256k1};
|
||||
use super::{from_hex, Secp256k1};
|
||||
use super::Error::{self, InvalidPublicKey, InvalidSecretKey};
|
||||
use Signing;
|
||||
use Verification;
|
||||
|
@ -40,6 +40,17 @@ impl fmt::Display for SecretKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for SecretKey {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<SecretKey, Error> {
|
||||
let mut res = [0; constants::SECRET_KEY_SIZE];
|
||||
match from_hex(s, &mut res) {
|
||||
Ok(constants::SECRET_KEY_SIZE) => Ok(SecretKey(res)),
|
||||
_ => Err(Error::InvalidSecretKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The number 1 encoded as a secret key
|
||||
/// Deprecated; `static` is not what I want; use `ONE_KEY` instead
|
||||
pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -73,6 +84,26 @@ impl fmt::Display for PublicKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for PublicKey {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<PublicKey, Error> {
|
||||
let secp = Secp256k1::without_caps();
|
||||
let mut res = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
|
||||
match from_hex(s, &mut res) {
|
||||
Ok(constants::PUBLIC_KEY_SIZE) => {
|
||||
PublicKey::from_slice(
|
||||
&secp,
|
||||
&res[0..constants::PUBLIC_KEY_SIZE]
|
||||
)
|
||||
}
|
||||
Ok(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) => {
|
||||
PublicKey::from_slice(&secp, &res)
|
||||
}
|
||||
_ => Err(Error::InvalidPublicKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "rand"))]
|
||||
fn random_32_bytes<R: Rng>(rng: &mut R) -> [u8; 32] {
|
||||
let mut ret = [0u8; 32];
|
||||
|
@ -318,34 +349,22 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::{Secp256k1};
|
||||
use Secp256k1;
|
||||
use from_hex;
|
||||
use super::super::Error::{InvalidPublicKey, InvalidSecretKey};
|
||||
use super::{PublicKey, SecretKey};
|
||||
use super::super::constants;
|
||||
|
||||
use rand::{Rng, thread_rng};
|
||||
use std::iter;
|
||||
use std::str::FromStr;
|
||||
|
||||
macro_rules! hex {
|
||||
($hex:expr) => {
|
||||
{
|
||||
let mut vec = Vec::new();
|
||||
let mut b = 0;
|
||||
for (idx, c) in $hex.as_bytes().iter().enumerate() {
|
||||
b <<= 4;
|
||||
match *c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => panic!("Bad hex"),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
vec.push(b);
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
vec
|
||||
}
|
||||
}
|
||||
($hex:expr) => ({
|
||||
let mut result = vec![0; $hex.len() / 2];
|
||||
from_hex($hex, &mut result).expect("valid hex string");
|
||||
result
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -482,10 +501,40 @@ mod test {
|
|||
sk.to_string(),
|
||||
"01010101010101010001020304050607ffff0000ffff00006363636363636363"
|
||||
);
|
||||
assert_eq!(
|
||||
SecretKey::from_str("01010101010101010001020304050607ffff0000ffff00006363636363636363").unwrap(),
|
||||
sk
|
||||
);
|
||||
assert_eq!(
|
||||
pk.to_string(),
|
||||
"0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
|
||||
);
|
||||
assert_eq!(
|
||||
PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166").unwrap(),
|
||||
pk
|
||||
);
|
||||
assert_eq!(
|
||||
PublicKey::from_str("04\
|
||||
18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166\
|
||||
84B84DB303A340CD7D6823EE88174747D12A67D2F8F2F9BA40846EE5EE7A44F6"
|
||||
).unwrap(),
|
||||
pk
|
||||
);
|
||||
|
||||
assert!(SecretKey::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").is_err());
|
||||
assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff0000636363636363636363").is_err());
|
||||
assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff0000636363636363636").is_err());
|
||||
assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff000063636363636363").is_err());
|
||||
assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff000063636363636363xx").is_err());
|
||||
assert!(PublicKey::from_str("0300000000000000000000000000000000000000000000000000000000000000000").is_err());
|
||||
assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16601").is_err());
|
||||
assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16").is_err());
|
||||
assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err());
|
||||
assert!(PublicKey::from_str("xx0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err());
|
||||
|
||||
let long_str: String = iter::repeat('a').take(1024 * 1024).collect();
|
||||
assert!(SecretKey::from_str(&long_str).is_err());
|
||||
assert!(PublicKey::from_str(&long_str).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
54
src/lib.rs
54
src/lib.rs
|
@ -708,36 +708,50 @@ impl<C: Verification> Secp256k1<C> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Utility function used to parse hex into a target u8 buffer. Returns
|
||||
/// the number of bytes converted or an error if it encounters an invalid
|
||||
/// character or unexpected end of string.
|
||||
fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
|
||||
if hex.len() % 2 == 1 || hex.len() > target.len() * 2 {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut b = 0;
|
||||
let mut idx = 0;
|
||||
for c in hex.bytes() {
|
||||
b <<= 4;
|
||||
match c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => return Err(()),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
target[idx / 2] = b;
|
||||
b = 0;
|
||||
}
|
||||
idx += 1;
|
||||
}
|
||||
Ok(idx / 2)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rand::{Rng, thread_rng};
|
||||
|
||||
use key::{SecretKey, PublicKey};
|
||||
use super::from_hex;
|
||||
use super::constants;
|
||||
use super::{Secp256k1, Signature, RecoverableSignature, Message, RecoveryId};
|
||||
use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature};
|
||||
|
||||
macro_rules! hex {
|
||||
($hex:expr) => {
|
||||
{
|
||||
let mut vec = Vec::new();
|
||||
let mut b = 0;
|
||||
for (idx, c) in $hex.as_bytes().iter().enumerate() {
|
||||
b <<= 4;
|
||||
match *c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => panic!("Bad hex"),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
vec.push(b);
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
vec
|
||||
}
|
||||
}
|
||||
($hex:expr) => ({
|
||||
let mut result = vec![0; $hex.len() / 2];
|
||||
from_hex($hex, &mut result).expect("valid hex string");
|
||||
result
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue