diff --git a/Cargo.lock b/Cargo.lock index 5cb5a12f6..479cd0068 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -344,7 +344,7 @@ dependencies = [ [[package]] name = "eth-secp256k1" version = "0.5.6" -source = "git+https://github.com/ethcore/rust-secp256k1#edab95f5569e4fb97579dc8947be96e7ac789c16" +source = "git+https://github.com/ethcore/rust-secp256k1#98ad9b9ecae44a563efdd64273bcebc6b4ed81c6" dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs index 9c0c7907d..60039b671 100644 --- a/ethkey/src/lib.rs +++ b/ethkey/src/lib.rs @@ -44,6 +44,8 @@ pub trait Generator { fn generate(self) -> Result; } +pub mod math; + pub use self::brain::Brain; pub use self::error::Error; pub use self::keypair::{KeyPair, public_to_address}; diff --git a/ethkey/src/math.rs b/ethkey/src/math.rs new file mode 100644 index 000000000..45e5d04e6 --- /dev/null +++ b/ethkey/src/math.rs @@ -0,0 +1,66 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use super::{SECP256K1, Public, Secret, Error}; +use secp256k1::key; +use secp256k1::constants::{GENERATOR_X, GENERATOR_Y}; + +/// Inplace multiply public key by secret key (EC point * scalar) +pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> { + let key_secret = secret.to_secp256k1_secret()?; + let mut key_public = to_secp256k1_public(public)?; + key_public.mul_assign(&SECP256K1, &key_secret)?; + set_public(public, &key_public); + Ok(()) +} + +/// Inplace add one public key to another (EC point + EC point) +pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> { + let mut key_public = to_secp256k1_public(public)?; + let other_public = to_secp256k1_public(other)?; + key_public.add_assign(&SECP256K1, &other_public)?; + set_public(public, &key_public); + Ok(()) +} + +/// Return base point of secp256k1 +pub fn generation_point() -> Public { + let mut public_sec_raw = [0u8; 65]; + public_sec_raw[0] = 4; + public_sec_raw[1..33].copy_from_slice(&GENERATOR_X); + public_sec_raw[33..65].copy_from_slice(&GENERATOR_Y); + + let public_key = key::PublicKey::from_slice(&SECP256K1, &public_sec_raw) + .expect("constructing using predefined constants; qed"); + let mut public = Public::default(); + set_public(&mut public, &public_key); + public +} + +fn to_secp256k1_public(public: &Public) -> Result { + let public_data = { + let mut temp = [4u8; 65]; + (&mut temp[1..65]).copy_from_slice(&public[0..64]); + temp + }; + + Ok(key::PublicKey::from_slice(&SECP256K1, &public_data)?) +} + +fn set_public(public: &mut Public, key_public: &key::PublicKey) { + let key_public_serialized = key_public.serialize_vec(&SECP256K1, false); + public.copy_from_slice(&key_public_serialized[1..65]); +} diff --git a/ethkey/src/secret.rs b/ethkey/src/secret.rs index 61f4cd184..d8696ef73 100644 --- a/ethkey/src/secret.rs +++ b/ethkey/src/secret.rs @@ -19,7 +19,7 @@ use std::ops::Deref; use std::str::FromStr; use secp256k1::key; use bigint::hash::H256; -use {Error}; +use {Error, SECP256K1}; #[derive(Clone, PartialEq, Eq)] pub struct Secret { @@ -45,6 +45,68 @@ impl Secret { let secret = key::SecretKey::from_slice(&super::SECP256K1, key)?; Ok(secret.into()) } + + /// Inplace add one secret key to another (scalar + scalar) + pub fn add(&mut self, other: &Secret) -> Result<(), Error> { + let mut key_secret = self.to_secp256k1_secret()?; + let other_secret = other.to_secp256k1_secret()?; + key_secret.add_assign(&SECP256K1, &other_secret)?; + + *self = key_secret.into(); + Ok(()) + } + + /// Inplace subtract one secret key from another (scalar - scalar) + pub fn sub(&mut self, other: &Secret) -> Result<(), Error> { + let mut key_secret = self.to_secp256k1_secret()?; + let mut other_secret = other.to_secp256k1_secret()?; + other_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + key_secret.add_assign(&SECP256K1, &other_secret)?; + + *self = key_secret.into(); + Ok(()) + } + + /// Inplace multiply one secret key to another (scalar * scalar) + pub fn mul(&mut self, other: &Secret) -> Result<(), Error> { + let mut key_secret = self.to_secp256k1_secret()?; + let other_secret = other.to_secp256k1_secret()?; + key_secret.mul_assign(&SECP256K1, &other_secret)?; + + *self = key_secret.into(); + Ok(()) + } + + /// Inplace inverse secret key (1 / scalar) + pub fn inv(&mut self) -> Result<(), Error> { + let mut key_secret = self.to_secp256k1_secret()?; + key_secret.inv_assign(&SECP256K1)?; + + *self = key_secret.into(); + Ok(()) + } + + /// Compute power of secret key inplace (secret ^ pow). + /// This function is not intended to be used with large powers. + pub fn pow(&mut self, pow: usize) -> Result<(), Error> { + match pow { + 0 => *self = key::ONE_KEY.into(), + 1 => (), + _ => { + let c = self.clone(); + for _ in 1..pow { + self.mul(&c)?; + } + }, + } + + Ok(()) + } + + /// Create `secp256k1::key::SecretKey` based on this secret + pub fn to_secp256k1_secret(&self) -> Result { + Ok(key::SecretKey::from_slice(&SECP256K1, &self[..])?) + } } impl FromStr for Secret {