Skip to content

Commit

Permalink
Extract secretkey code/pubkey serde code in macro
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibo-lg committed Oct 22, 2020
1 parent 157b4ab commit 595850a
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 215 deletions.
217 changes: 2 additions & 215 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,42 +26,7 @@ use Verification;
use constants;
use ffi::{self, CPtr};

/// 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);
impl_pretty_debug!(SecretKey);

impl fmt::LowerHex for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for ch in &self.0[..] {
write!(f, "{:02x}", *ch)?;
}
Ok(())
}
}

impl fmt::Display for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(self, f)
}
}

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
pub const ONE_KEY: SecretKey = SecretKey([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]);
include!("key.rs.in"); // define SecretKey

/// A Secp256k1 public key, used for verification of signatures
#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -101,120 +66,6 @@ impl str::FromStr for PublicKey {
}
}

#[cfg(any(test, feature = "rand"))]
fn random_32_bytes<R: Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
let mut ret = [0u8; 32];
rng.fill_bytes(&mut ret);
ret
}

impl SecretKey {
/// Creates a new random secret key. Requires compilation with the "rand" feature.
#[inline]
#[cfg(any(test, feature = "rand"))]
pub fn new<R: Rng + ?Sized>(rng: &mut R) -> SecretKey {
let mut data = random_32_bytes(rng);
unsafe {
while ffi::secp256k1_ec_seckey_verify(
ffi::secp256k1_context_no_precomp,
data.as_c_ptr(),
) == 0
{
data = random_32_bytes(rng);
}
}
SecretKey(data)
}

/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
#[inline]
pub fn from_slice(data: &[u8])-> Result<SecretKey, Error> {
match data.len() {
constants::SECRET_KEY_SIZE => {
let mut ret = [0; constants::SECRET_KEY_SIZE];
unsafe {
if ffi::secp256k1_ec_seckey_verify(
ffi::secp256k1_context_no_precomp,
data.as_c_ptr(),
) == 0
{
return Err(InvalidSecretKey);
}
}
ret[..].copy_from_slice(data);
Ok(SecretKey(ret))
}
_ => Err(InvalidSecretKey)
}
}

#[inline]
/// Negates one secret key.
pub fn negate_assign(
&mut self
) {
unsafe {
let res = ffi::secp256k1_ec_seckey_negate(
ffi::secp256k1_context_no_precomp,
self.as_mut_c_ptr()
);
debug_assert_eq!(res, 1);
}
}

#[inline]
/// Adds one secret key to another, modulo the curve order. WIll
/// return an error if the resulting key would be invalid or if
/// the tweak was not a 32-byte length slice.
pub fn add_assign(
&mut self,
other: &[u8],
) -> Result<(), Error> {
if other.len() != 32 {
return Err(Error::InvalidTweak);
}
unsafe {
if ffi::secp256k1_ec_seckey_tweak_add(
ffi::secp256k1_context_no_precomp,
self.as_mut_c_ptr(),
other.as_c_ptr(),
) != 1
{
Err(Error::InvalidTweak)
} else {
Ok(())
}
}
}

#[inline]
/// Multiplies one secret key by another, modulo the curve order. Will
/// return an error if the resulting key would be invalid or if
/// the tweak was not a 32-byte length slice.
pub fn mul_assign(
&mut self,
other: &[u8],
) -> Result<(), Error> {
if other.len() != 32 {
return Err(Error::InvalidTweak);
}
unsafe {
if ffi::secp256k1_ec_seckey_tweak_mul(
ffi::secp256k1_context_no_precomp,
self.as_mut_c_ptr(),
other.as_c_ptr(),
) != 1
{
Err(Error::InvalidTweak)
} else {
Ok(())
}
}
}
}

serde_impl!(SecretKey, constants::SECRET_KEY_SIZE);

impl PublicKey {
/// Obtains a raw const pointer suitable for use with FFI functions
#[inline]
Expand Down Expand Up @@ -404,71 +255,7 @@ impl From<ffi::PublicKey> for PublicKey {
}
}

#[cfg(feature = "serde")]
impl ::serde::Serialize for PublicKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
s.serialize_bytes(&self.serialize())
}
}
}

#[cfg(feature = "serde")]
impl<'de> ::serde::Deserialize<'de> for PublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
if d.is_human_readable() {
struct HexVisitor;

impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
type Value = PublicKey;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an ASCII hex string")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
if let Ok(hex) = str::from_utf8(v) {
str::FromStr::from_str(hex).map_err(E::custom)
} else {
Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
}
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
str::FromStr::from_str(v).map_err(E::custom)
}
}
d.deserialize_str(HexVisitor)
} else {
struct BytesVisitor;

impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
type Value = PublicKey;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a bytestring")
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
PublicKey::from_slice(v).map_err(E::custom)
}
}

d.deserialize_bytes(BytesVisitor)
}
}
}
serde_impl_from_slice!(PublicKey);

#[cfg(test)]
mod test {
Expand Down
147 changes: 147 additions & 0 deletions src/key.rs.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/// Secret 256-bit key used as `x` in a signature
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);

impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
impl_pretty_debug!(SecretKey);

impl fmt::LowerHex for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for ch in &self.0[..] {
write!(f, "{:02x}", *ch)?;
}
Ok(())
}
}

impl fmt::Display for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(self, f)
}
}

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
pub const ONE_KEY: SecretKey = SecretKey([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]);

#[cfg(any(test, feature = "rand"))]
fn random_32_bytes<R: Rng + ?Sized>(rng: &mut R) -> [u8; 32] {
let mut ret = [0u8; 32];
rng.fill_bytes(&mut ret);
ret
}

impl SecretKey {
/// Creates a new random secret key. Requires compilation with the "rand" feature.
#[inline]
#[cfg(any(test, feature = "rand"))]
pub fn new<R: Rng + ?Sized>(rng: &mut R) -> SecretKey {
let mut data = random_32_bytes(rng);
unsafe {
while ffi::secp256k1_ec_seckey_verify(
ffi::secp256k1_context_no_precomp,
data.as_c_ptr(),
) == 0
{
data = random_32_bytes(rng);
}
}
SecretKey(data)
}
/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
#[inline]
pub fn from_slice(data: &[u8])-> Result<SecretKey, Error> {
match data.len() {
constants::SECRET_KEY_SIZE => {
let mut ret = [0; constants::SECRET_KEY_SIZE];
unsafe {
if ffi::secp256k1_ec_seckey_verify(
ffi::secp256k1_context_no_precomp,
data.as_c_ptr(),
) == 0
{
return Err(InvalidSecretKey);
}
}
ret[..].copy_from_slice(data);
Ok(SecretKey(ret))
}
_ => Err(InvalidSecretKey)
}
}
#[inline]
/// Negates one secret key.
pub fn negate_assign(
&mut self
) {
unsafe {
let res = ffi::secp256k1_ec_seckey_negate(
ffi::secp256k1_context_no_precomp,
self.as_mut_c_ptr()
);
debug_assert_eq!(res, 1);
}
}
#[inline]
/// Adds one secret key to another, modulo the curve order. WIll
/// return an error if the resulting key would be invalid or if
/// the tweak was not a 32-byte length slice.
pub fn add_assign(
&mut self,
other: &[u8],
) -> Result<(), Error> {
if other.len() != 32 {
return Err(Error::InvalidTweak);
}
unsafe {
if ffi::secp256k1_ec_seckey_tweak_add(
ffi::secp256k1_context_no_precomp,
self.as_mut_c_ptr(),
other.as_c_ptr(),
) != 1
{
Err(Error::InvalidTweak)
} else {
Ok(())
}
}
}
#[inline]
/// Multiplies one secret key by another, modulo the curve order. Will
/// return an error if the resulting key would be invalid or if
/// the tweak was not a 32-byte length slice.
pub fn mul_assign(
&mut self,
other: &[u8],
) -> Result<(), Error> {
if other.len() != 32 {
return Err(Error::InvalidTweak);
}
unsafe {
if ffi::secp256k1_ec_seckey_tweak_mul(
ffi::secp256k1_context_no_precomp,
self.as_mut_c_ptr(),
other.as_c_ptr(),
) != 1
{
Err(Error::InvalidTweak)
} else {
Ok(())
}
}
}
}

serde_impl!(SecretKey, constants::SECRET_KEY_SIZE);
Loading

0 comments on commit 595850a

Please sign in to comment.