From 2d571df7fee92b85b47b49cf14aa3a7641f2f3b9 Mon Sep 17 00:00:00 2001 From: Andronik Ordian Date: Mon, 5 Jul 2021 14:57:56 +0200 Subject: [PATCH] decommission parity-crypto (#566) * decommission parity-crypto * fix CI --- .github/workflows/ci.yml | 6 - Cargo.toml | 1 - parity-crypto/CHANGELOG.md | 42 -- parity-crypto/Cargo.toml | 42 -- parity-crypto/README.md | 8 - parity-crypto/benches/bench.rs | 51 -- parity-crypto/src/aes.rs | 188 ------ parity-crypto/src/digest.rs | 109 ---- parity-crypto/src/error.rs | 142 ----- parity-crypto/src/hmac/mod.rs | 161 ------ parity-crypto/src/hmac/test.rs | 234 -------- parity-crypto/src/lib.rs | 82 --- parity-crypto/src/pbkdf2/mod.rs | 21 - parity-crypto/src/pbkdf2/test.rs | 22 - parity-crypto/src/publickey/ec_math_utils.rs | 149 ----- parity-crypto/src/publickey/ecdh.rs | 45 -- .../src/publickey/ecdsa_signature.rs | 331 ----------- parity-crypto/src/publickey/ecies.rs | 130 ----- parity-crypto/src/publickey/error.rs | 91 --- parity-crypto/src/publickey/extended_keys.rs | 542 ------------------ parity-crypto/src/publickey/keypair.rs | 109 ---- .../src/publickey/keypair_generator.rs | 22 - parity-crypto/src/publickey/mod.rs | 47 -- parity-crypto/src/publickey/secret_key.rs | 307 ---------- parity-crypto/src/scrypt.rs | 56 -- 25 files changed, 2938 deletions(-) delete mode 100644 parity-crypto/CHANGELOG.md delete mode 100644 parity-crypto/Cargo.toml delete mode 100644 parity-crypto/README.md delete mode 100644 parity-crypto/benches/bench.rs delete mode 100644 parity-crypto/src/aes.rs delete mode 100644 parity-crypto/src/digest.rs delete mode 100644 parity-crypto/src/error.rs delete mode 100644 parity-crypto/src/hmac/mod.rs delete mode 100644 parity-crypto/src/hmac/test.rs delete mode 100644 parity-crypto/src/lib.rs delete mode 100644 parity-crypto/src/pbkdf2/mod.rs delete mode 100644 parity-crypto/src/pbkdf2/test.rs delete mode 100644 parity-crypto/src/publickey/ec_math_utils.rs delete mode 100644 parity-crypto/src/publickey/ecdh.rs delete mode 100644 parity-crypto/src/publickey/ecdsa_signature.rs delete mode 100644 parity-crypto/src/publickey/ecies.rs delete mode 100644 parity-crypto/src/publickey/error.rs delete mode 100644 parity-crypto/src/publickey/extended_keys.rs delete mode 100644 parity-crypto/src/publickey/keypair.rs delete mode 100644 parity-crypto/src/publickey/keypair_generator.rs delete mode 100644 parity-crypto/src/publickey/mod.rs delete mode 100644 parity-crypto/src/publickey/secret_key.rs delete mode 100644 parity-crypto/src/scrypt.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 115bec02f..84a12b31c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,12 +98,6 @@ jobs: command: test args: -p ethbloom --all-features - - name: Test parity-crypto all-features - uses: actions-rs/cargo@v1 - with: - command: test - args: -p parity-crypto --all-features - - name: Test uint on bigendian if: runner.os == 'Linux' uses: actions-rs/cargo@v1 diff --git a/Cargo.toml b/Cargo.toml index 91bb0fee1..bb9fac368 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ members = [ "kvdb-rocksdb", "kvdb-shared-tests", "parity-bytes", - "parity-crypto", "rlp", "rlp-derive", "uint", diff --git a/parity-crypto/CHANGELOG.md b/parity-crypto/CHANGELOG.md deleted file mode 100644 index af033f2a0..000000000 --- a/parity-crypto/CHANGELOG.md +++ /dev/null @@ -1,42 +0,0 @@ -# Changelog - -The format is based on [Keep a Changelog]. - -[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ - -## [Unreleased] - -### Breaking -- Updated `ethereum-types` to 0.12. [#556](https://github.com/paritytech/parity-common/pull/556) - -## [0.8.0] - 2021-01-27 -### Breaking -- Updated `ethereum-types` to 0.11. [#510](https://github.com/paritytech/parity-common/pull/510) - -## [0.7.0] - 2021-01-05 -### Breaking -- Bump `rust-secp256k1` to v0.19, always allow zero signatures. [#438](https://github.com/paritytech/parity-common/pull/438) -- Updated `rlp` to 0.5. [#463](https://github.com/paritytech/parity-common/pull/463) -- Updated dependencies. [#483](https://github.com/paritytech/parity-common/pull/483) -- Remove deprecated trait impls `FromStr`/`TryFrom` for `Secret` [#495](https://github.com/paritytech/parity-common/pull/495) - -## [0.6.2] - 2020-06-19 -- Put `Secret` memory on heap. [#400](https://github.com/paritytech/parity-common/pull/400) -- Add `copy_from_str` conversion methods for `Secret`. -- Deprecate `From<&str>` in favor of `copy_from_str`. - -## [0.6.1] - 2020-04-11 -- Add `recover_allowing_all_zero_message()` and `ZeroesAllowedMessage` to accomodate ethereum's `ecrecover` builtin. [#369](https://github.com/paritytech/parity-common/pull/369) - -## [0.6.0] - 2020-03-16 -- License changed from GPL3 to dual MIT/Apache2. [#342](https://github.com/paritytech/parity-common/pull/342) -- Updated dependencies. [#361](https://github.com/paritytech/parity-common/pull/361) - -## [0.5.0] - 2020-02-08 -- Remove `inv()` from `SecretKey` (breaking). [#258](https://github.com/paritytech/parity-common/pull/258) -- `Generate::generate()` does not return error. [#258](https://github.com/paritytech/parity-common/pull/258) -- `Secp256k1` is no longer exported. [#258](https://github.com/paritytech/parity-common/pull/258) -- Remove `public_is_valid()` as it is now impossible to create invalid public keys. [#258](https://github.com/paritytech/parity-common/pull/258) -- 0-valued `Secp::Message`s are disallowed (signatures on them are forgeable for all keys). [#258](https://github.com/paritytech/parity-common/pull/258) -- Switch to upstream `rust-secp256k1` at v0.17.2. [#258](https://github.com/paritytech/parity-common/pull/258) -- make `rustc_hex` dependency optional. [#337](https://github.com/paritytech/parity-common/pull/337) diff --git a/parity-crypto/Cargo.toml b/parity-crypto/Cargo.toml deleted file mode 100644 index 851ad0248..000000000 --- a/parity-crypto/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "parity-crypto" -version = "0.9.0" -authors = ["Parity Technologies "] -repository = "https://github.com/paritytech/parity-common" -description = "Crypto utils used by ethstore and network." -license = "MIT OR Apache-2.0" -autobenches = false -edition = "2018" - -[[bench]] -name = "bench" -harness = false -required-features = ["publickey"] - -[dependencies] -aes = "0.6.0" -aes-ctr = "0.6.0" -block-modes = "0.7.0" -digest = "0.9.0" -ethereum-types = { version = "0.12.0", optional = true, path = "../ethereum-types" } -hmac = "0.10.1" -lazy_static = { version = "1.4.0", optional = true } -pbkdf2 = "0.7.3" -ripemd160 = "0.9.1" -rustc-hex = { version = "2.1.0", default-features = false, optional = true } -scrypt = { version = "0.5.0" } -secp256k1 = { version = "0.20.0", optional = true, features = ["global-context", "recovery", "rand-std"] } -sha2 = "0.9.2" -subtle = "2.4.0" -tiny-keccak = { version = "2.0.2", features = ["keccak"] } -zeroize = { version = "1.2.0", default-features = false } - -[dev-dependencies] -criterion = "0.3.3" -hex-literal = "0.3.1" - -[features] -default = [] -# public key crypto utils -# moved from ethkey module in parity ethereum repository -publickey = ["secp256k1", "lazy_static", "ethereum-types", "rustc-hex"] diff --git a/parity-crypto/README.md b/parity-crypto/README.md deleted file mode 100644 index b7309710c..000000000 --- a/parity-crypto/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# parity-crypto - -General cryptographic utilities for Ethereum. - - -## Changelog - -The 0.4 release removes the dependency on `ring` and replaces it with pure rust alternatives. As a consequence of this, AES GCM support has been removed. `subtle` is used for constant time equality testing and error handling is pared down to the bare minimum required. diff --git a/parity-crypto/benches/bench.rs b/parity-crypto/benches/bench.rs deleted file mode 100644 index 562c50148..000000000 --- a/parity-crypto/benches/bench.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use crate::parity_crypto::publickey::Generator; -use criterion::{criterion_group, criterion_main, Bencher, Criterion}; - -criterion_group!(benches, input_len, ecdh_agree,); - -criterion_main!(benches); - -/// general benches for multiple input size -fn input_len(c: &mut Criterion) { - c.bench_function_over_inputs( - "ripemd", - |b: &mut Bencher, size: &usize| { - let data = vec![0u8; *size]; - b.iter(|| parity_crypto::digest::ripemd160(&data[..])); - }, - vec![100, 500, 1_000, 10_000, 100_000], - ); - - c.bench_function_over_inputs( - "aes_ctr", - |b: &mut Bencher, size: &usize| { - let data = vec![0u8; *size]; - let mut dest = vec![0; *size]; - let k = [0; 16]; - let iv = [0; 16]; - - b.iter(|| { - parity_crypto::aes::encrypt_128_ctr(&k[..], &iv[..], &data[..], &mut dest[..]).unwrap(); - // same as encrypt but add it just in case - parity_crypto::aes::decrypt_128_ctr(&k[..], &iv[..], &data[..], &mut dest[..]).unwrap(); - }); - }, - vec![100, 500, 1_000, 10_000, 100_000], - ); -} - -fn ecdh_agree(c: &mut Criterion) { - let keypair = parity_crypto::publickey::Random.generate().unwrap(); - let public = keypair.public().clone(); - let secret = keypair.secret().clone(); - - c.bench_function("ecdh_agree", move |b| b.iter(|| parity_crypto::publickey::ecdh::agree(&secret, &public))); -} diff --git a/parity-crypto/src/aes.rs b/parity-crypto/src/aes.rs deleted file mode 100644 index c7c860183..000000000 --- a/parity-crypto/src/aes.rs +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use aes::cipher::generic_array::GenericArray; -use aes::{Aes128, Aes256}; -use aes_ctr::cipher::stream::{NewStreamCipher, SyncStreamCipher}; -use block_modes::{ - block_padding::{Pkcs7, ZeroPadding}, - BlockMode, Cbc, Ecb, -}; - -use crate::error::SymmError; - -/// One time encoder/decoder for Ecb mode Aes256 with zero padding -pub struct AesEcb256(Ecb); - -impl AesEcb256 { - /// New encoder/decoder, no iv for ecb - pub fn new(key: &[u8]) -> Result { - Ok(AesEcb256(Ecb::new_var(key, &[])?)) - } - - /// Encrypt data in place without padding. The data length must be a multiple - /// of the block size. - pub fn encrypt(self, content: &mut [u8]) -> Result<(), SymmError> { - let len = content.len(); - self.0.encrypt(content, len)?; - Ok(()) - } - - /// Decrypt data in place without padding. The data length must be a multiple - /// of the block size. - pub fn decrypt(self, content: &mut [u8]) -> Result<(), SymmError> { - self.0.decrypt(content)?; - Ok(()) - } -} - -/// Reusable encoder/decoder for Aes256 in Ctr mode and no padding -pub struct AesCtr256(aes_ctr::Aes256Ctr); - -impl AesCtr256 { - /// New encoder/decoder - pub fn new(key: &[u8], iv: &[u8]) -> Result { - Ok(AesCtr256(aes_ctr::Aes256Ctr::new(GenericArray::from_slice(key), GenericArray::from_slice(iv)))) - } - - /// In place encrypt a content without padding, the content length must be a multiple - /// of the block size. - pub fn encrypt(&mut self, content: &mut [u8]) -> Result<(), SymmError> { - self.0.try_apply_keystream(content)?; - Ok(()) - } - - /// In place decrypt a content without padding, the content length must be a multiple - /// of the block size. - pub fn decrypt(&mut self, content: &mut [u8]) -> Result<(), SymmError> { - self.0.try_apply_keystream(content)?; - Ok(()) - } -} - -/// Encrypt a message (CTR mode). -/// -/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. -/// An error is returned if the input lengths are invalid. -/// If possible prefer `inplace_encrypt_128_ctr` to avoid a slice copy. -pub fn encrypt_128_ctr(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { - let mut encryptor = aes_ctr::Aes128Ctr::new(GenericArray::from_slice(k), GenericArray::from_slice(iv)); - &mut dest[..plain.len()].copy_from_slice(plain); - encryptor.try_apply_keystream(dest)?; - Ok(()) -} - -/// Encrypt a message (CTR mode). -/// -/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. -/// An error is returned if the input lengths are invalid. -pub fn inplace_encrypt_128_ctr(k: &[u8], iv: &[u8], data: &mut [u8]) -> Result<(), SymmError> { - let mut encryptor = aes_ctr::Aes128Ctr::new(GenericArray::from_slice(k), GenericArray::from_slice(iv)); - encryptor.try_apply_keystream(data)?; - Ok(()) -} - -/// Decrypt a message (CTR mode). -/// -/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. -/// An error is returned if the input lengths are invalid. -/// If possible prefer `inplace_decrypt_128_ctr` instead. -pub fn decrypt_128_ctr(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { - let mut encryptor = aes_ctr::Aes128Ctr::new(GenericArray::from_slice(k), GenericArray::from_slice(iv)); - - &mut dest[..encrypted.len()].copy_from_slice(encrypted); - encryptor.try_apply_keystream(dest)?; - Ok(()) -} - -/// Decrypt a message (CTR mode). -/// -/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. -/// An error is returned if the input lengths are invalid. -pub fn inplace_decrypt_128_ctr(k: &[u8], iv: &[u8], data: &mut [u8]) -> Result<(), SymmError> { - let mut encryptor = aes_ctr::Aes128Ctr::new(GenericArray::from_slice(k), GenericArray::from_slice(iv)); - - encryptor.try_apply_keystream(data)?; - Ok(()) -} - -/// Decrypt a message (CBC mode). -/// -/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. -/// An error is returned if the input lengths are invalid. -pub fn decrypt_128_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result { - let encryptor = Cbc::::new_var(k, iv)?; - &mut dest[..encrypted.len()].copy_from_slice(encrypted); - let unpad_length = { encryptor.decrypt(&mut dest[..encrypted.len()])?.len() }; - Ok(unpad_length) -} - -#[cfg(test)] -mod tests { - - use super::*; - - // only use for test could be expose in the future - fn encrypt_128_cbc(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { - let encryptor = Cbc::::new_var(k, iv)?; - &mut dest[..plain.len()].copy_from_slice(plain); - encryptor.encrypt(dest, plain.len())?; - Ok(()) - } - - #[test] - pub fn test_aes_short() -> Result<(), SymmError> { - let key = [ - 97, 110, 121, 99, 111, 110, 116, 101, 110, 116, 116, 111, 114, 101, 97, 99, 104, 49, 50, 56, 98, 105, 116, - 115, 105, 122, 101, 10, - ]; - let salt = [ - 109, 121, 115, 97, 108, 116, 115, 104, 111, 117, 108, 100, 102, 105, 108, 108, 115, 111, 109, 109, 101, 98, - 121, 116, 101, 108, 101, 110, 103, 116, 104, 10, - ]; - let content = [ - 83, 111, 109, 101, 32, 99, 111, 110, 116, 101, 110, 116, 32, 116, 111, 32, 116, 101, 115, 116, 32, 97, 101, - 115, 44, 10, 110, 111, 116, 32, 116, 111, 32, 109, 117, 99, 104, 32, 44, 32, 111, 110, 108, 121, 32, 118, - 101, 114, 121, 32, 98, 97, 115, 105, 99, 32, 116, 101, 115, 116, 32, 116, 111, 32, 97, 118, 111, 105, 100, - 32, 111, 98, 118, 105, 111, 117, 115, 32, 114, 101, 103, 114, 101, 115, 115, 105, 111, 110, 32, 119, 104, - 101, 110, 32, 115, 119, 105, 116, 99, 104, 105, 110, 103, 32, 108, 105, 98, 115, 46, 10, - ]; - let ctr_enc = [ - 65, 55, 246, 75, 24, 117, 30, 233, 218, 139, 91, 251, 251, 179, 171, 69, 60, 244, 249, 44, 238, 60, 10, 66, - 71, 10, 199, 111, 54, 24, 124, 223, 153, 250, 159, 154, 164, 109, 232, 82, 20, 199, 182, 40, 174, 104, 64, - 203, 236, 94, 222, 184, 117, 54, 234, 189, 253, 122, 135, 121, 100, 44, 227, 241, 123, 120, 110, 188, 109, - 148, 112, 160, 131, 205, 116, 104, 232, 8, 22, 170, 80, 231, 155, 246, 255, 115, 101, 5, 234, 104, 220, - 199, 192, 166, 181, 156, 113, 255, 187, 51, 38, 128, 75, 29, 237, 178, 205, 98, 101, 110, - ]; - let cbc_enc = [ - 167, 248, 5, 90, 11, 140, 215, 138, 165, 125, 137, 76, 47, 243, 191, 48, 183, 247, 109, 86, 24, 45, 81, - 215, 0, 51, 221, 185, 131, 97, 234, 189, 244, 255, 107, 210, 70, 60, 41, 221, 43, 137, 185, 166, 42, 65, - 18, 200, 151, 233, 255, 192, 109, 25, 105, 115, 161, 209, 126, 235, 99, 192, 241, 241, 19, 249, 87, 244, - 28, 146, 186, 189, 108, 9, 243, 132, 4, 105, 53, 162, 8, 235, 84, 107, 213, 59, 158, 113, 227, 120, 162, - 50, 237, 123, 70, 187, 83, 73, 146, 13, 44, 191, 53, 4, 125, 207, 176, 45, 8, 153, 175, 198, - ]; - let mut dest = vec![0; 110]; - let mut dest_padded = vec![0; 112]; - let mut dest_padded2 = vec![0; 128]; // TODO RustLib need an extra 16bytes in dest : looks extra buggy but function is not currently use (keep it private for now) - encrypt_128_cbc(&key[..16], &salt[..16], &content, &mut dest_padded2)?; - assert!(&dest_padded2[..112] == &cbc_enc[..]); - encrypt_128_ctr(&key[..16], &salt[..16], &content, &mut dest)?; - assert!(&dest[..] == &ctr_enc[..]); - let mut content_data = content.to_vec(); - inplace_encrypt_128_ctr(&key[..16], &salt[..16], &mut content_data[..])?; - assert!(&content_data[..] == &ctr_enc[..]); - decrypt_128_ctr(&key[..16], &salt[..16], &ctr_enc[..], &mut dest)?; - assert!(&dest[..] == &content[..]); - let mut content_data = ctr_enc.to_vec(); - inplace_decrypt_128_ctr(&key[..16], &salt[..16], &mut content_data[..])?; - assert!(&content_data[..] == &content[..]); - let l = decrypt_128_cbc(&key[..16], &salt[..16], &cbc_enc[..], &mut dest_padded)?; - assert!(&dest_padded[..l] == &content[..]); - Ok(()) - } -} diff --git a/parity-crypto/src/digest.rs b/parity-crypto/src/digest.rs deleted file mode 100644 index 759613f2f..000000000 --- a/parity-crypto/src/digest.rs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::marker::PhantomData; -use std::ops::Deref; - -use digest::generic_array::{ - typenum::{U20, U32, U64}, - GenericArray, -}; -use sha2::Digest as RDigest; - -/// The message digest. -pub struct Digest(InnerDigest, PhantomData); - -enum InnerDigest { - Sha256(GenericArray), - Sha512(GenericArray), - Ripemd160(GenericArray), -} - -impl Deref for Digest { - type Target = [u8]; - fn deref(&self) -> &Self::Target { - match self.0 { - InnerDigest::Sha256(ref d) => &d[..], - InnerDigest::Sha512(ref d) => &d[..], - InnerDigest::Ripemd160(ref d) => &d[..], - } - } -} - -/// Single-step sha256 digest computation. -pub fn sha256(data: &[u8]) -> Digest { - let mut hasher = Hasher::sha256(); - hasher.update(data); - hasher.finish() -} - -/// Single-step sha512 digest computation. -pub fn sha512(data: &[u8]) -> Digest { - let mut hasher = Hasher::sha512(); - hasher.update(data); - hasher.finish() -} - -/// Single-step ripemd160 digest computation. -pub fn ripemd160(data: &[u8]) -> Digest { - let mut hasher = Hasher::ripemd160(); - hasher.update(data); - hasher.finish() -} - -#[derive(Debug)] -pub enum Sha256 {} -#[derive(Debug)] -pub enum Sha512 {} -#[derive(Debug)] -pub enum Ripemd160 {} - -/// Stateful digest computation. -pub struct Hasher(Inner, PhantomData); - -enum Inner { - Sha256(sha2::Sha256), - Sha512(sha2::Sha512), - Ripemd160(ripemd160::Ripemd160), -} - -impl Hasher { - pub fn sha256() -> Hasher { - Hasher(Inner::Sha256(sha2::Sha256::default()), PhantomData) - } -} - -impl Hasher { - pub fn sha512() -> Hasher { - Hasher(Inner::Sha512(sha2::Sha512::default()), PhantomData) - } -} - -impl Hasher { - pub fn ripemd160() -> Hasher { - Hasher(Inner::Ripemd160(ripemd160::Ripemd160::default()), PhantomData) - } -} - -impl Hasher { - pub fn update(&mut self, data: &[u8]) { - match self.0 { - Inner::Sha256(ref mut ctx) => ctx.update(data), - Inner::Sha512(ref mut ctx) => ctx.update(data), - Inner::Ripemd160(ref mut ctx) => ctx.update(data), - } - } - - pub fn finish(self) -> Digest { - match self.0 { - Inner::Sha256(ctx) => Digest(InnerDigest::Sha256(ctx.finalize()), PhantomData), - Inner::Sha512(ctx) => Digest(InnerDigest::Sha512(ctx.finalize()), PhantomData), - Inner::Ripemd160(ctx) => Digest(InnerDigest::Ripemd160(ctx.finalize()), PhantomData), - } - } -} diff --git a/parity-crypto/src/error.rs b/parity-crypto/src/error.rs deleted file mode 100644 index 6f413a247..000000000 --- a/parity-crypto/src/error.rs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::{error::Error as StdError, fmt, result}; - -#[derive(Debug)] -pub enum Error { - Scrypt(ScryptError), - Symm(SymmError), -} - -#[derive(Debug)] -pub enum ScryptError { - // log(N) < r / 16 - InvalidN, - // p <= (2^31-1 * 32)/(128 * r) - InvalidP, - ScryptParam(scrypt::errors::InvalidParams), - ScryptLength(scrypt::errors::InvalidOutputLen), -} - -#[derive(Debug)] -pub struct SymmError(PrivSymmErr); - -#[derive(Debug)] -enum PrivSymmErr { - BlockMode(block_modes::BlockModeError), - KeyStream(aes_ctr::cipher::stream::LoopError), - InvalidKeyLength(block_modes::InvalidKeyIvLength), -} - -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - Error::Scrypt(scrypt_err) => Some(scrypt_err), - Error::Symm(symm_err) => Some(symm_err), - } - } -} - -impl StdError for ScryptError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - ScryptError::ScryptParam(err) => Some(err), - ScryptError::ScryptLength(err) => Some(err), - _ => None, - } - } -} - -impl StdError for SymmError { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match &self.0 { - PrivSymmErr::BlockMode(err) => Some(err), - PrivSymmErr::InvalidKeyLength(err) => Some(err), - _ => None, - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { - match self { - Error::Scrypt(err) => write!(f, "scrypt error: {}", err), - Error::Symm(err) => write!(f, "symm error: {}", err), - } - } -} - -impl fmt::Display for ScryptError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { - match self { - ScryptError::InvalidN => write!(f, "invalid n argument"), - ScryptError::InvalidP => write!(f, "invalid p argument"), - ScryptError::ScryptParam(err) => write!(f, "invalid params: {}", err), - ScryptError::ScryptLength(err) => write!(f, "invalid output length: {}", err), - } - } -} - -impl fmt::Display for SymmError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> { - match self { - SymmError(PrivSymmErr::BlockMode(err)) => write!(f, "block cipher error: {}", err), - SymmError(PrivSymmErr::KeyStream(err)) => write!(f, "ctr key stream ended: {}", err), - SymmError(PrivSymmErr::InvalidKeyLength(err)) => write!(f, "block cipher key length: {}", err), - } - } -} - -impl Into for Error { - fn into(self) -> std::io::Error { - std::io::Error::new(std::io::ErrorKind::Other, format!("Crypto error: {}", self)) - } -} - -impl From for SymmError { - fn from(e: block_modes::BlockModeError) -> SymmError { - SymmError(PrivSymmErr::BlockMode(e)) - } -} - -impl From for SymmError { - fn from(e: block_modes::InvalidKeyIvLength) -> SymmError { - SymmError(PrivSymmErr::InvalidKeyLength(e)) - } -} - -impl From for SymmError { - fn from(e: aes_ctr::cipher::stream::LoopError) -> SymmError { - SymmError(PrivSymmErr::KeyStream(e)) - } -} - -impl From for ScryptError { - fn from(e: scrypt::errors::InvalidParams) -> ScryptError { - ScryptError::ScryptParam(e) - } -} - -impl From for ScryptError { - fn from(e: scrypt::errors::InvalidOutputLen) -> ScryptError { - ScryptError::ScryptLength(e) - } -} - -impl From for Error { - fn from(e: ScryptError) -> Error { - Error::Scrypt(e) - } -} - -impl From for Error { - fn from(e: SymmError) -> Error { - Error::Symm(e) - } -} diff --git a/parity-crypto/src/hmac/mod.rs b/parity-crypto/src/hmac/mod.rs deleted file mode 100644 index ca20ae1c1..000000000 --- a/parity-crypto/src/hmac/mod.rs +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::marker::PhantomData; -use std::ops::Deref; - -use digest::generic_array::{ - typenum::{U32, U64}, - GenericArray, -}; -use hmac::{Hmac, Mac as _, NewMac as _}; -use zeroize::Zeroize; - -use crate::digest::{Sha256, Sha512}; - -/// HMAC signature. -#[derive(Debug)] -pub struct Signature(HashInner, PhantomData); - -#[derive(Debug)] -enum HashInner { - Sha256(GenericArray), - Sha512(GenericArray), -} - -impl Deref for Signature { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - match &self.0 { - HashInner::Sha256(a) => a.as_slice(), - HashInner::Sha512(a) => a.as_slice(), - } - } -} - -/// HMAC signing key. -pub struct SigKey(KeyInner, PhantomData); - -#[derive(PartialEq)] -// Using `Box[u8]` guarantees no reallocation can happen -struct DisposableBox(Box<[u8]>); - -impl std::fmt::Debug for DisposableBox { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", &self.0.as_ref()) - } -} - -impl DisposableBox { - fn from_slice(data: &[u8]) -> Self { - Self(data.to_vec().into_boxed_slice()) - } -} - -impl Drop for DisposableBox { - fn drop(&mut self) { - self.0.zeroize() - } -} - -#[derive(Debug, PartialEq)] -enum KeyInner { - Sha256(DisposableBox), - Sha512(DisposableBox), -} - -impl SigKey { - pub fn sha256(key: &[u8]) -> SigKey { - SigKey(KeyInner::Sha256(DisposableBox::from_slice(key)), PhantomData) - } -} - -impl SigKey { - pub fn sha512(key: &[u8]) -> SigKey { - SigKey(KeyInner::Sha512(DisposableBox::from_slice(key)), PhantomData) - } -} - -/// Compute HMAC signature of `data`. -pub fn sign(k: &SigKey, data: &[u8]) -> Signature { - let mut signer = Signer::with(k); - signer.update(data); - signer.sign() -} - -/// Stateful HMAC computation. -pub struct Signer(SignerInner, PhantomData); - -enum SignerInner { - Sha256(Hmac), - Sha512(Hmac), -} - -impl Signer { - pub fn with(key: &SigKey) -> Signer { - match &key.0 { - KeyInner::Sha256(key_bytes) => Signer( - SignerInner::Sha256(Hmac::::new_varkey(&key_bytes.0).expect("always returns Ok; qed")), - PhantomData, - ), - KeyInner::Sha512(key_bytes) => Signer( - SignerInner::Sha512(Hmac::::new_varkey(&key_bytes.0).expect("always returns Ok; qed")), - PhantomData, - ), - } - } - - pub fn update(&mut self, data: &[u8]) { - match &mut self.0 { - SignerInner::Sha256(hmac) => hmac.update(data), - SignerInner::Sha512(hmac) => hmac.update(data), - } - } - - pub fn sign(self) -> Signature { - match self.0 { - SignerInner::Sha256(hmac) => Signature(HashInner::Sha256(hmac.finalize().into_bytes()), PhantomData), - SignerInner::Sha512(hmac) => Signature(HashInner::Sha512(hmac.finalize().into_bytes()), PhantomData), - } - } -} - -/// HMAC signature verification key. -pub struct VerifyKey(KeyInner, PhantomData); - -impl VerifyKey { - pub fn sha256(key: &[u8]) -> VerifyKey { - VerifyKey(KeyInner::Sha256(DisposableBox::from_slice(key)), PhantomData) - } -} - -impl VerifyKey { - pub fn sha512(key: &[u8]) -> VerifyKey { - VerifyKey(KeyInner::Sha512(DisposableBox::from_slice(key)), PhantomData) - } -} - -/// Verify HMAC signature of `data`. -pub fn verify(key: &VerifyKey, data: &[u8], sig: &[u8]) -> bool { - match &key.0 { - KeyInner::Sha256(key_bytes) => { - let mut ctx = Hmac::::new_varkey(&key_bytes.0).expect("always returns Ok; qed"); - ctx.update(data); - ctx.verify(sig).is_ok() - } - KeyInner::Sha512(key_bytes) => { - let mut ctx = Hmac::::new_varkey(&key_bytes.0).expect("always returns Ok; qed"); - ctx.update(data); - ctx.verify(sig).is_ok() - } - } -} - -#[cfg(test)] -mod test; diff --git a/parity-crypto/src/hmac/test.rs b/parity-crypto/src/hmac/test.rs deleted file mode 100644 index 8f71bd4a9..000000000 --- a/parity-crypto/src/hmac/test.rs +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::*; -use hex_literal::hex; - -#[test] -fn simple_mac_and_verify() { - let input = b"Some bytes"; - let big_input = vec![7u8; 2000]; - - let key1 = vec![3u8; 64]; - let key2 = vec![4u8; 128]; - - let sig_key1 = SigKey::sha256(&key1[..]); - let sig_key2 = SigKey::sha512(&key2[..]); - - let mut signer1 = Signer::with(&sig_key1); - let mut signer2 = Signer::with(&sig_key2); - - signer1.update(&input[..]); - for i in 0..big_input.len() / 33 { - signer2.update(&big_input[i * 33..(i + 1) * 33]); - } - signer2.update(&big_input[(big_input.len() / 33) * 33..]); - let sig1 = signer1.sign(); - assert_eq!( - &sig1[..], - [ - 223, 208, 90, 69, 144, 95, 145, 180, 56, 155, 78, 40, 86, 238, 205, 81, 160, 245, 88, 145, 164, 67, 254, - 180, 202, 107, 93, 249, 64, 196, 86, 225 - ] - ); - let sig2 = signer2.sign(); - assert_eq!( - &sig2[..], - &[ - 29, 63, 46, 122, 27, 5, 241, 38, 86, 197, 91, 79, 33, 107, 152, 195, 118, 221, 117, 119, 84, 114, 46, 65, - 243, 157, 105, 12, 147, 176, 190, 37, 210, 164, 152, 8, 58, 243, 59, 206, 80, 10, 230, 197, 255, 110, 191, - 180, 93, 22, 255, 0, 99, 79, 237, 229, 209, 199, 125, 83, 15, 179, 134, 89 - ][..] - ); - assert_eq!(&sig1[..], &sign(&sig_key1, &input[..])[..]); - assert_eq!(&sig2[..], &sign(&sig_key2, &big_input[..])[..]); - let verif_key1 = VerifyKey::sha256(&key1[..]); - let verif_key2 = VerifyKey::sha512(&key2[..]); - assert!(verify(&verif_key1, &input[..], &sig1[..])); - assert!(verify(&verif_key2, &big_input[..], &sig2[..])); -} - -fn check_test_vector(key: &[u8], data: &[u8], expected_256: &[u8], expected_512: &[u8]) { - // Sha-256 - let sig_key = SigKey::sha256(&key); - let mut signer = Signer::with(&sig_key); - signer.update(&data); - let signature = signer.sign(); - assert_eq!(&signature[..], expected_256); - assert_eq!(&signature[..], &sign(&sig_key, data)[..]); - let ver_key = VerifyKey::sha256(&key); - assert!(verify(&ver_key, data, &signature)); - - // Sha-512 - let sig_key = SigKey::sha512(&key); - let mut signer = Signer::with(&sig_key); - signer.update(&data); - let signature = signer.sign(); - assert_eq!(&signature[..], expected_512); - assert_eq!(&signature[..], &sign(&sig_key, data)[..]); - let ver_key = VerifyKey::sha512(&key); - assert!(verify(&ver_key, data, &signature)); -} - -#[test] -fn ietf_test_vectors() { - // Test vectors from https://tools.ietf.org/html/rfc4231.html#section-4 - - // Test Case 1 - check_test_vector( - &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), - &hex!("4869205468657265"), - &hex!( - " - b0344c61d8db38535ca8afceaf0bf12b - 881dc200c9833da726e9376c2e32cff7" - ), - &hex!( - " - 87aa7cdea5ef619d4ff0b4241a1d6cb0 - 2379f4e2ce4ec2787ad0b30545e17cde - daa833b7d6b8a702038b274eaea3f4e4 - be9d914eeb61f1702e696c203a126854" - ), - ); - - // Test Case 2 - check_test_vector( - &hex!("4a656665"), - &hex!("7768617420646f2079612077616e7420666f72206e6f7468696e673f"), - &hex!( - " - 5bdcc146bf60754e6a042426089575c7 - 5a003f089d2739839dec58b964ec3843" - ), - &hex!( - " - 164b7a7bfcf819e2e395fbe73b56e0a3 - 87bd64222e831fd610270cd7ea250554 - 9758bf75c05a994a6d034f65f8f0e6fd - caeab1a34d4a6b4b636e070a38bce737" - ), - ); - // Test Case 3 - check_test_vector( - &hex!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), - &hex!("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"), - &hex!( - " - 773ea91e36800e46854db8ebd09181a7 - 2959098b3ef8c122d9635514ced565fe" - ), - &hex!( - " - fa73b0089d56a284efb0f0756c890be9 - b1b5dbdd8ee81a3655f83e33b2279d39 - bf3e848279a722c806b485a47e67c807 - b946a337bee8942674278859e13292fb" - ), - ); - - // Test Case 4 - check_test_vector( - &hex!("0102030405060708090a0b0c0d0e0f10111213141516171819"), - &hex!( - " - cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd - cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd - cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd - cdcd" - ), - &hex!( - " - 82558a389a443c0ea4cc819899f2083a - 85f0faa3e578f8077a2e3ff46729665b" - ), - &hex!( - " - b0ba465637458c6990e5a8c5f61d4af7 - e576d97ff94b872de76f8050361ee3db - a91ca5c11aa25eb4d679275cc5788063 - a5f19741120c4f2de2adebeb10a298dd" - ), - ); - - // Test Case 6 - check_test_vector( - &hex!( - " - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaa" - ), - &hex!( - " - 54657374205573696e67204c61726765 - 72205468616e20426c6f636b2d53697a - 65204b6579202d2048617368204b6579 - 204669727374" - ), - &hex!( - " - 60e431591ee0b67f0d8a26aacbf5b77f - 8e0bc6213728c5140546040f0ee37f54" - ), - &hex!( - " - 80b24263c7c1a3ebb71493c1dd7be8b4 - 9b46d1f41b4aeec1121b013783f8f352 - 6b56d037e05f2598bd0fd2215d6a1e52 - 95e64f73f63f0aec8b915a985d786598" - ), - ); - - // Test Case 7 - check_test_vector( - &hex!( - " - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaa" - ), - &hex!( - " - 54686973206973206120746573742075 - 73696e672061206c6172676572207468 - 616e20626c6f636b2d73697a65206b65 - 7920616e642061206c61726765722074 - 68616e20626c6f636b2d73697a652064 - 6174612e20546865206b6579206e6565 - 647320746f2062652068617368656420 - 6265666f7265206265696e6720757365 - 642062792074686520484d414320616c - 676f726974686d2e" - ), - &hex!( - " - 9b09ffa71b942fcb27635fbcd5b0e944 - bfdc63644f0713938a7f51535c3a35e2" - ), - &hex!( - " - e37b6a775dc87dbaa4dfa9f96e5e3ffd - debd71f8867289865df5a32d20cdc944 - b6022cac3c4982b10d5eeb55c3e4de15 - 134676fb6de0446065c97440fa8c6a58" - ), - ); -} diff --git a/parity-crypto/src/lib.rs b/parity-crypto/src/lib.rs deleted file mode 100644 index c3049716c..000000000 --- a/parity-crypto/src/lib.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Crypto utils used by ethstore and network. - -pub mod aes; -pub mod digest; -pub mod error; -pub mod hmac; -pub mod pbkdf2; -#[cfg(feature = "publickey")] -pub mod publickey; -pub mod scrypt; - -pub use crate::error::Error; - -use subtle::ConstantTimeEq; -use tiny_keccak::{Hasher, Keccak}; - -pub const KEY_LENGTH: usize = 32; -pub const KEY_ITERATIONS: usize = 10240; -pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2; - -/// Default authenticated data to use (in RPC). -pub const DEFAULT_MAC: [u8; 2] = [0, 0]; - -pub trait Keccak256 { - fn keccak256(&self) -> T - where - T: Sized; -} - -impl Keccak256<[u8; 32]> for T -where - T: AsRef<[u8]>, -{ - fn keccak256(&self) -> [u8; 32] { - let mut keccak = Keccak::v256(); - let mut result = [0u8; 32]; - keccak.update(self.as_ref()); - keccak.finalize(&mut result); - result - } -} - -pub fn derive_key_iterations(password: &[u8], salt: &[u8], c: u32) -> (Vec, Vec) { - let mut derived_key = [0u8; KEY_LENGTH]; - pbkdf2::sha256(c, pbkdf2::Salt(salt), pbkdf2::Secret(password), &mut derived_key); - let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; - let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; - (derived_right_bits.to_vec(), derived_left_bits.to_vec()) -} - -pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec { - let mut mac = vec![0u8; KEY_LENGTH_AES + cipher_text.len()]; - mac[0..KEY_LENGTH_AES].copy_from_slice(derived_left_bits); - mac[KEY_LENGTH_AES..cipher_text.len() + KEY_LENGTH_AES].copy_from_slice(cipher_text); - mac -} - -pub fn is_equal(a: &[u8], b: &[u8]) -> bool { - a.ct_eq(b).into() -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn can_test_for_equality() { - let a = b"abc"; - let b = b"abc"; - let c = b"efg"; - assert!(is_equal(a, b)); - assert!(!is_equal(a, c)); - } -} diff --git a/parity-crypto/src/pbkdf2/mod.rs b/parity-crypto/src/pbkdf2/mod.rs deleted file mode 100644 index c9f1bd565..000000000 --- a/parity-crypto/src/pbkdf2/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub struct Salt<'a>(pub &'a [u8]); -pub struct Secret<'a>(pub &'a [u8]); - -pub fn sha256(iter: u32, salt: Salt<'_>, sec: Secret<'_>, out: &mut [u8; 32]) { - pbkdf2::pbkdf2::>(sec.0, salt.0, iter, out) -} - -pub fn sha512(iter: u32, salt: Salt<'_>, sec: Secret<'_>, out: &mut [u8; 64]) { - pbkdf2::pbkdf2::>(sec.0, salt.0, iter, out) -} - -#[cfg(test)] -mod test; diff --git a/parity-crypto/src/pbkdf2/test.rs b/parity-crypto/src/pbkdf2/test.rs deleted file mode 100644 index b0bed84ad..000000000 --- a/parity-crypto/src/pbkdf2/test.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::*; - -#[test] -fn basic_test() { - let mut dest = [0; 32]; - let salt = [5; 32]; - let secret = [7; 32]; - sha256(3, Salt(&salt[..]), Secret(&secret[..]), &mut dest); - let res = [ - 242, 33, 31, 124, 36, 223, 179, 185, 206, 175, 190, 253, 85, 33, 23, 126, 141, 29, 23, 97, 66, 63, 51, 196, 27, - 255, 135, 206, 74, 137, 172, 87, - ]; - assert_eq!(res, dest); -} diff --git a/parity-crypto/src/publickey/ec_math_utils.rs b/parity-crypto/src/publickey/ec_math_utils.rs deleted file mode 100644 index af2e2bf96..000000000 --- a/parity-crypto/src/publickey/ec_math_utils.rs +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Multiple primitives for work with public and secret keys and with secp256k1 curve points - -use super::{Error, Public, Secret}; -use ethereum_types::{BigEndianHash as _, H256, U256}; -use lazy_static::lazy_static; -use secp256k1::constants::CURVE_ORDER as SECP256K1_CURVE_ORDER; -use secp256k1::key; -use secp256k1::SECP256K1; - -/// Generation point array combined from X and Y coordinates -/// Equivalent to uncompressed form, see https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html#rfc.section.3 -pub const BASE_POINT_BYTES: [u8; 65] = [ - 0x4, // The X coordinate of the generator - 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, - 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, - // The Y coordinate of the generator - 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, - 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, -]; - -lazy_static! { - pub static ref CURVE_ORDER: U256 = H256::from_slice(&SECP256K1_CURVE_ORDER).into_uint(); -} - -/// In-place 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(()) -} - -/// In-place add one public key to another (EC point + EC point) -pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> { - let key_public = to_secp256k1_public(public)?; - let other_public = to_secp256k1_public(other)?; - let key_public = key_public.combine(&other_public)?; - set_public(public, &key_public); - Ok(()) -} - -/// In-place sub one public key from another (EC point - EC point) -pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> { - let mut key_neg_other = to_secp256k1_public(other)?; - key_neg_other.mul_assign(&SECP256K1, super::MINUS_ONE_KEY)?; - - let mut key_public = to_secp256k1_public(public)?; - key_public = key_public.combine(&key_neg_other)?; - set_public(public, &key_public); - Ok(()) -} - -/// Replace a public key with its additive inverse (EC point = - EC point) -pub fn public_negate(public: &mut Public) -> Result<(), Error> { - let mut key_public = to_secp256k1_public(public)?; - key_public.mul_assign(&SECP256K1, super::MINUS_ONE_KEY)?; - set_public(public, &key_public); - Ok(()) -} - -/// Return the generation point (aka base point) of secp256k1 -pub fn generation_point() -> Public { - let public_key = key::PublicKey::from_slice(&BASE_POINT_BYTES).expect("constructed using 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(&public_data)?) -} - -fn set_public(public: &mut Public, key_public: &key::PublicKey) { - let key_public_serialized = key_public.serialize_uncompressed(); - public.as_bytes_mut().copy_from_slice(&key_public_serialized[1..65]); -} - -#[cfg(test)] -mod tests { - use super::super::{Generator, Random, Secret}; - use super::{generation_point, public_add, public_mul_secret, public_negate, public_sub}; - - #[test] - fn public_addition_is_commutative() { - let public1 = Random.generate().public().clone(); - let public2 = Random.generate().public().clone(); - - let mut left = public1.clone(); - public_add(&mut left, &public2).unwrap(); - - let mut right = public2.clone(); - public_add(&mut right, &public1).unwrap(); - - assert_eq!(left, right); - } - - #[test] - fn public_addition_is_reversible_with_subtraction() { - let public1 = Random.generate().public().clone(); - let public2 = Random.generate().public().clone(); - - let mut sum = public1.clone(); - public_add(&mut sum, &public2).unwrap(); - public_sub(&mut sum, &public2).unwrap(); - - assert_eq!(sum, public1); - } - - #[test] - fn public_negation_is_involutory() { - let public = Random.generate().public().clone(); - let mut negation = public.clone(); - public_negate(&mut negation).unwrap(); - public_negate(&mut negation).unwrap(); - - assert_eq!(negation, public); - } - - #[test] - fn generation_point_expected() { - let point = generation_point(); - // Check the returned value equal to uncompressed form for sec2561k1 - assert_eq!(format!("{:x}", point), "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"); - } - - #[test] - fn public_multiplication_verification() { - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let mut public = generation_point(); - public_mul_secret(&mut public, &secret).unwrap(); - assert_eq!(format!("{:x}", public), "8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4"); - } -} diff --git a/parity-crypto/src/publickey/ecdh.rs b/parity-crypto/src/publickey/ecdh.rs deleted file mode 100644 index a44eaabd3..000000000 --- a/parity-crypto/src/publickey/ecdh.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! ECDH key agreement scheme implemented as a free function. - -use super::{Error, Public, Secret}; -use secp256k1::{self, ecdh, key}; - -/// Agree on a shared secret -pub fn agree(secret: &Secret, public: &Public) -> Result { - let pdata = { - let mut temp = [4u8; 65]; - (&mut temp[1..65]).copy_from_slice(&public[0..64]); - temp - }; - - let publ = key::PublicKey::from_slice(&pdata)?; - let sec = key::SecretKey::from_slice(secret.as_bytes())?; - let shared = ecdh::SharedSecret::new_with_hash(&publ, &sec, |x, _| x.into()); - - Secret::import_key(&shared[0..32]).map_err(|_| Error::Secp(secp256k1::Error::InvalidSecretKey)) -} - -#[cfg(test)] -mod tests { - use super::{agree, Public, Secret}; - use std::str::FromStr; - - #[test] - fn test_agree() { - // Just some random values for secret/public to check we agree with previous implementation. - let secret = - Secret::copy_from_str(&"01a400760945613ff6a46383b250bf27493bfe679f05274916182776f09b28f1").unwrap(); - let public= Public::from_str("e37f3cbb0d0601dc930b8d8aa56910dd5629f2a0979cc742418960573efc5c0ff96bc87f104337d8c6ab37e597d4f9ffbd57302bc98a825519f691b378ce13f5").unwrap(); - let shared = agree(&secret, &public); - - assert!(shared.is_ok()); - assert_eq!(shared.unwrap().to_hex(), "28ab6fad6afd854ff27162e0006c3f6bd2daafc0816c85b5dfb05dbb865fa6ac",); - } -} diff --git a/parity-crypto/src/publickey/ecdsa_signature.rs b/parity-crypto/src/publickey/ecdsa_signature.rs deleted file mode 100644 index b7d924c6c..000000000 --- a/parity-crypto/src/publickey/ecdsa_signature.rs +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Signature based on ECDSA, algorithm's description: https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm - -use super::{public_to_address, Address, Error, Message, Public, Secret}; -use ethereum_types::{H256, H520}; -use rustc_hex::{FromHex, ToHex}; -use secp256k1::{ - key::{PublicKey, SecretKey}, - recovery::{RecoverableSignature, RecoveryId}, - Error as SecpError, Message as SecpMessage, SECP256K1, -}; -use std::{ - cmp::PartialEq, - fmt, - hash::{Hash, Hasher}, - ops::{Deref, DerefMut}, - str::FromStr, -}; - -/// Signature encoded as RSV components -#[repr(C)] -pub struct Signature([u8; 65]); - -impl Signature { - /// Get a slice into the 'r' portion of the data. - pub fn r(&self) -> &[u8] { - &self.0[0..32] - } - - /// Get a slice into the 's' portion of the data. - pub fn s(&self) -> &[u8] { - &self.0[32..64] - } - - /// Get the recovery byte. - pub fn v(&self) -> u8 { - self.0[64] - } - - /// Encode the signature into RSV array (V altered to be in "Electrum" notation). - pub fn into_electrum(mut self) -> [u8; 65] { - self.0[64] += 27; - self.0 - } - - /// Parse bytes as a signature encoded as RSV (V in "Electrum" notation). - /// May return empty (invalid) signature if given data has invalid length. - pub fn from_electrum(data: &[u8]) -> Self { - if data.len() != 65 || data[64] < 27 { - // fallback to empty (invalid) signature - return Signature::default(); - } - - let mut sig = [0u8; 65]; - sig.copy_from_slice(data); - sig[64] -= 27; - Signature(sig) - } - - /// Create a signature object from the RSV triple. - pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Self { - let mut sig = [0u8; 65]; - sig[0..32].copy_from_slice(r.as_ref()); - sig[32..64].copy_from_slice(s.as_ref()); - sig[64] = v; - Signature(sig) - } - - /// Check if this is a "low" signature (that s part of the signature is in range - /// 0x1 and 0x7FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 5D576E73 57A4501D DFE92F46 681B20A0 (inclusive)). - /// This condition may be required by some verification algorithms - pub fn is_low_s(&self) -> bool { - const LOW_SIG_THRESHOLD: H256 = H256([ - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x57, - 0x6E, 0x73, 0x57, 0xA4, 0x50, 0x1D, 0xDF, 0xE9, 0x2F, 0x46, 0x68, 0x1B, 0x20, 0xA0, - ]); - H256::from_slice(self.s()) <= LOW_SIG_THRESHOLD - } - - /// Check if each component of the signature is in valid range. - /// r is in range 0x1 and 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 (inclusive) - /// s is in range 0x1 and fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 (inclusive) - /// v is 0 or 1 - /// Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1; - /// used here as the upper bound for a valid (r, s, v) tuple - pub fn is_valid(&self) -> bool { - const UPPER_BOUND: H256 = H256([ - 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, - ]); - const ONE: H256 = H256([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - ]); - let r = H256::from_slice(self.r()); - let s = H256::from_slice(self.s()); - self.v() <= 1 && r < UPPER_BOUND && r >= ONE && s < UPPER_BOUND && s >= ONE - } -} - -// manual implementation large arrays don't have trait impls by default. -// TODO[grbIzl] remove when integer generics exist -impl PartialEq for Signature { - fn eq(&self, other: &Self) -> bool { - &self.0[..] == &other.0[..] - } -} - -// manual implementation required in Rust 1.13+, see `std::cmp::AssertParamIsEq`. -impl Eq for Signature {} - -// also manual for the same reason, but the pretty printing might be useful. -impl fmt::Debug for Signature { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.debug_struct("Signature") - .field("r", &self.0[0..32].to_hex::()) - .field("s", &self.0[32..64].to_hex::()) - .field("v", &self.0[64..65].to_hex::()) - .finish() - } -} - -impl fmt::Display for Signature { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{}", self.to_hex::()) - } -} - -impl FromStr for Signature { - type Err = Error; - - fn from_str(s: &str) -> Result { - match s.from_hex::>() { - Ok(ref hex) if hex.len() == 65 => { - let mut data = [0; 65]; - data.copy_from_slice(&hex[0..65]); - Ok(Signature(data)) - } - _ => Err(Error::InvalidSignature), - } - } -} - -impl Default for Signature { - fn default() -> Self { - Signature([0; 65]) - } -} - -impl Hash for Signature { - fn hash(&self, state: &mut H) { - H520::from(self.0).hash(state); - } -} - -impl Clone for Signature { - fn clone(&self) -> Self { - Signature(self.0.clone()) - } -} - -impl From<[u8; 65]> for Signature { - fn from(s: [u8; 65]) -> Self { - Signature(s) - } -} - -impl Into<[u8; 65]> for Signature { - fn into(self) -> [u8; 65] { - self.0 - } -} - -impl From for H520 { - fn from(s: Signature) -> Self { - H520::from(s.0) - } -} - -impl From for Signature { - fn from(bytes: H520) -> Self { - Signature(bytes.into()) - } -} - -impl Deref for Signature { - type Target = [u8; 65]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Signature { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -/// Signs message with the given secret key. -/// Returns the corresponding signature. -pub fn sign(secret: &Secret, message: &Message) -> Result { - let context = &SECP256K1; - let sec = SecretKey::from_slice(secret.as_ref())?; - let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec); - let (rec_id, data) = s.serialize_compact(); - let mut data_arr = [0; 65]; - - // no need to check if s is low, it always is - data_arr[0..64].copy_from_slice(&data[0..64]); - data_arr[64] = rec_id.to_i32() as u8; - Ok(Signature(data_arr)) -} - -/// Performs verification of the signature for the given message with corresponding public key -pub fn verify_public(public: &Public, signature: &Signature, message: &Message) -> Result { - let context = &SECP256K1; - let rsig = RecoverableSignature::from_compact(&signature[0..64], RecoveryId::from_i32(signature[64] as i32)?)?; - let sig = rsig.to_standard(); - - let pdata: [u8; 65] = { - let mut temp = [4u8; 65]; - temp[1..65].copy_from_slice(public.as_bytes()); - temp - }; - - let publ = PublicKey::from_slice(&pdata)?; - match context.verify(&SecpMessage::from_slice(&message[..])?, &sig, &publ) { - Ok(_) => Ok(true), - Err(SecpError::IncorrectSignature) => Ok(false), - Err(x) => Err(Error::from(x)), - } -} - -/// Checks if the address corresponds to the public key from the signature for the message -pub fn verify_address(address: &Address, signature: &Signature, message: &Message) -> Result { - let public = recover(signature, message)?; - let recovered_address = public_to_address(&public); - Ok(address == &recovered_address) -} - -/// Recovers the public key from the signature for the message -pub fn recover(signature: &Signature, message: &Message) -> Result { - let rsig = RecoverableSignature::from_compact(&signature[0..64], RecoveryId::from_i32(signature[64] as i32)?)?; - let pubkey = &SECP256K1.recover(&SecpMessage::from_slice(&message[..])?, &rsig)?; - let serialized = pubkey.serialize_uncompressed(); - let mut public = Public::default(); - public.as_bytes_mut().copy_from_slice(&serialized[1..65]); - Ok(public) -} - -#[cfg(test)] -mod tests { - use super::{ - super::{Generator, Message, Random}, - recover, sign, verify_address, verify_public, Signature, - }; - use std::str::FromStr; - - #[test] - fn vrs_conversion() { - // given - let keypair = Random.generate(); - let message = Message::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let signature = sign(keypair.secret(), &message).expect("can sign a non-zero message"); - - // when - let vrs = signature.clone().into_electrum(); - let from_vrs = Signature::from_electrum(&vrs); - - // then - assert_eq!(signature, from_vrs); - } - - #[test] - fn signature_to_and_from_str() { - let keypair = Random.generate(); - let message = Message::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let signature = sign(keypair.secret(), &message).expect("can sign a non-zero message"); - let string = format!("{}", signature); - let deserialized = Signature::from_str(&string).unwrap(); - assert_eq!(signature, deserialized); - } - - #[test] - fn sign_and_recover_public() { - let keypair = Random.generate(); - let message = Message::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let signature = sign(keypair.secret(), &message).unwrap(); - assert_eq!(keypair.public(), &recover(&signature, &message).unwrap()); - } - - #[test] - fn sign_and_recover_public_works_with_zeroed_messages() { - let keypair = Random.generate(); - let signature = sign(keypair.secret(), &Message::zero()).unwrap(); - let zero_message = Message::zero(); - assert_eq!(keypair.public(), &recover(&signature, &zero_message).unwrap()); - } - - #[test] - fn recover_allowing_all_zero_message_can_recover_from_all_zero_messages() { - let keypair = Random.generate(); - let signature = sign(keypair.secret(), &Message::zero()).unwrap(); - let zero_message = Message::zero(); - assert_eq!(keypair.public(), &recover(&signature, &zero_message).unwrap()) - } - - #[test] - fn sign_and_verify_public() { - let keypair = Random.generate(); - let message = Message::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let signature = sign(keypair.secret(), &message).expect("can sign a non-zero message"); - assert!(verify_public(keypair.public(), &signature, &message).unwrap()); - } - - #[test] - fn sign_and_verify_address() { - let keypair = Random.generate(); - let message = Message::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let signature = sign(keypair.secret(), &message).expect("can sign a non-zero message"); - assert!(verify_address(&keypair.address(), &signature, &message).unwrap()); - } -} diff --git a/parity-crypto/src/publickey/ecies.rs b/parity-crypto/src/publickey/ecies.rs deleted file mode 100644 index 3332f8a94..000000000 --- a/parity-crypto/src/publickey/ecies.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Functions for ECIES scheme encryption and decryption - -use super::{ecdh, Error, Generator, Public, Random, Secret}; -use crate::{aes, digest, hmac, is_equal}; -use ethereum_types::H128; - -const ENC_VERSION: u8 = 0x04; - -/// Encrypt a message with a public key, writing an HMAC covering both -/// the plaintext and authenticated data. -/// -/// Authenticated data may be empty. -pub fn encrypt(public: &Public, auth_data: &[u8], plain: &[u8]) -> Result, Error> { - let r = Random.generate(); - let z = ecdh::agree(r.secret(), public)?; - let mut key = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - - let ekey = &key[0..16]; - let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32])); - - let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32]; - msg[0] = ENC_VERSION; - { - let result_msg = &mut msg[1..]; - result_msg[0..64].copy_from_slice(r.public().as_bytes()); - let iv = H128::random(); - result_msg[64..80].copy_from_slice(iv.as_bytes()); - { - let cipher = &mut result_msg[(64 + 16)..(64 + 16 + plain.len())]; - aes::encrypt_128_ctr(ekey, iv.as_bytes(), plain, cipher)?; - } - let mut hmac = hmac::Signer::with(&mkey); - { - let cipher_iv = &result_msg[64..(64 + 16 + plain.len())]; - hmac.update(cipher_iv); - } - hmac.update(auth_data); - let sig = hmac.sign(); - result_msg[(64 + 16 + plain.len())..].copy_from_slice(&sig); - } - Ok(msg) -} - -/// Decrypt a message with a secret key, checking HMAC for ciphertext -/// and authenticated data validity. -pub fn decrypt(secret: &Secret, auth_data: &[u8], encrypted: &[u8]) -> Result, Error> { - const META_LEN: usize = 1 + 64 + 16 + 32; - let enc_version = encrypted[0]; - if encrypted.len() < META_LEN || enc_version < 2 || enc_version > 4 { - return Err(Error::InvalidMessage); - } - - let e = &encrypted[1..]; - let p = Public::from_slice(&e[0..64]); - let z = ecdh::agree(secret, &p)?; - let mut key = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - - let ekey = &key[0..16]; - let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32])); - - let cipher_text_len = encrypted.len() - META_LEN; - let cipher_with_iv = &e[64..(64 + 16 + cipher_text_len)]; - let cipher_iv = &cipher_with_iv[0..16]; - let cipher_no_iv = &cipher_with_iv[16..]; - let msg_mac = &e[(64 + 16 + cipher_text_len)..]; - - // Verify tag - let mut hmac = hmac::Signer::with(&mkey); - hmac.update(cipher_with_iv); - hmac.update(auth_data); - let mac = hmac.sign(); - - if !is_equal(&mac.as_ref()[..], msg_mac) { - return Err(Error::InvalidMessage); - } - - let mut msg = vec![0u8; cipher_text_len]; - aes::decrypt_128_ctr(ekey, cipher_iv, cipher_no_iv, &mut msg[..])?; - Ok(msg) -} - -fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) { - // SEC/ISO/Shoup specify counter size SHOULD be equivalent - // to size of hash output, however, it also notes that - // the 4 bytes is okay. NIST specifies 4 bytes. - let mut ctr = 1u32; - let mut written = 0usize; - while written < dest.len() { - let mut hasher = digest::Hasher::sha256(); - let ctrs = [(ctr >> 24) as u8, (ctr >> 16) as u8, (ctr >> 8) as u8, ctr as u8]; - hasher.update(&ctrs); - hasher.update(secret.as_bytes()); - hasher.update(s1); - let d = hasher.finish(); - &mut dest[written..(written + 32)].copy_from_slice(&d); - written += 32; - ctr += 1; - } -} - -#[cfg(test)] -mod tests { - use super::super::{ecies, Generator, Random}; - - #[test] - fn ecies_shared() { - let kp = Random.generate(); - let message = b"So many books, so little time"; - - let shared = b"shared"; - let wrong_shared = b"incorrect"; - let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap(); - assert!(encrypted[..] != message[..]); - assert_eq!(encrypted[0], 0x04); - - assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err()); - let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap(); - assert_eq!(decrypted[..message.len()], message[..]); - } -} diff --git a/parity-crypto/src/publickey/error.rs b/parity-crypto/src/publickey/error.rs deleted file mode 100644 index 5ea8ce391..000000000 --- a/parity-crypto/src/publickey/error.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Module specific errors. - -use crate::error::SymmError; -use std::{error::Error as StdError, fmt, result}; - -/// Module specific errors -#[derive(Debug)] -pub enum Error { - /// secp256k1 enc error - Secp(secp256k1::Error), - /// Invalid secret key - InvalidSecretKey, - /// Invalid public key - InvalidPublicKey, - /// Invalid address - InvalidAddress, - /// Invalid EC signature - InvalidSignature, - /// Invalid AES message - InvalidMessage, - /// IO Error - Io(std::io::Error), - /// Symmetric encryption error - Symm(SymmError), - /// Custom - Custom(String), -} - -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - match self { - Error::Secp(secp_err) => Some(secp_err), - Error::Io(err) => Some(err), - Error::Symm(symm_err) => Some(symm_err), - _ => None, - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { - match self { - Error::Secp(err) => write!(f, "secp error: {}", err), - Error::InvalidSecretKey => write!(f, "invalid secret key"), - Error::InvalidPublicKey => write!(f, "invalid public key"), - Error::InvalidAddress => write!(f, "invalid address"), - Error::InvalidSignature => write!(f, "invalid EC signature"), - Error::InvalidMessage => write!(f, "invalid AES message"), - Error::Io(err) => write!(f, "I/O error: {}", err), - Error::Symm(err) => write!(f, "symmetric encryption error: {}", err), - Error::Custom(err) => write!(f, "custom crypto error: {}", err), - } - } -} - -impl Into for Error { - fn into(self) -> String { - format!("{}", self) - } -} - -impl From for Error { - fn from(err: std::io::Error) -> Error { - Error::Io(err) - } -} - -impl From for Error { - fn from(err: SymmError) -> Error { - Error::Symm(err) - } -} - -impl From for Error { - fn from(e: secp256k1::Error) -> Error { - match e { - secp256k1::Error::InvalidMessage => Error::InvalidMessage, - secp256k1::Error::InvalidPublicKey => Error::InvalidPublicKey, - secp256k1::Error::InvalidSecretKey => Error::InvalidSecretKey, - _ => Error::InvalidSignature, - } - } -} diff --git a/parity-crypto/src/publickey/extended_keys.rs b/parity-crypto/src/publickey/extended_keys.rs deleted file mode 100644 index adc4f3862..000000000 --- a/parity-crypto/src/publickey/extended_keys.rs +++ /dev/null @@ -1,542 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Secret, public keys extended with the entropy (aka chain code), that allows further key derivation -//! Each extended key has 2^31 normal child keys, and 2^31 hardened child keys. -//! Each of these child keys has an index. The normal child keys use indices 0 through 2^31 - 1. -//! The hardened child keys use indices 2^31 through 2^32 - 1. -//! See more details about derivation in https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki - -pub use self::derivation::Error as DerivationError; -use super::{Public, Secret}; -use ethereum_types::H256; -use zeroize::Zeroize; - -/// Represents label that can be stored as a part of key derivation -pub trait Label { - /// Length of the data that label occupies - fn len() -> usize; - - /// Store label data to the key derivation sequence - /// Must not use more than `len()` bytes from slice - fn store(&self, target: &mut [u8]); -} - -impl Label for u32 { - fn len() -> usize { - 4 - } - - fn store(&self, target: &mut [u8]) { - let bytes = self.to_be_bytes(); - target[0..4].copy_from_slice(&bytes); - } -} - -/// Key derivation over generic label `T` -pub enum Derivation { - /// Soft key derivation (allow proof of parent) - Soft(T), - /// Hard key derivation (does not allow proof of parent) - Hard(T), -} - -impl From for Derivation { - fn from(index: u32) -> Self { - // Type of the derived key is defined by it index - // See module's documentation for more details - if index < (2 << 30) { - Derivation::Soft(index) - } else { - Derivation::Hard(index) - } - } -} - -impl Label for H256 { - fn len() -> usize { - 32 - } - - fn store(&self, target: &mut [u8]) { - (&mut target[0..32]).copy_from_slice(self.as_bytes()); - } -} - -/// Extended secret key, allows deterministic derivation of subsequent keys. -pub struct ExtendedSecret { - secret: Secret, - chain_code: H256, -} - -impl ExtendedSecret { - /// New extended key from given secret and chain code. - pub fn with_code(secret: Secret, chain_code: H256) -> ExtendedSecret { - ExtendedSecret { secret, chain_code } - } - - /// New extended key from given secret with the random chain code. - pub fn new_random(secret: Secret) -> ExtendedSecret { - ExtendedSecret::with_code(secret, H256::random()) - } - - /// New extended key from given secret. - /// Chain code will be derived from the secret itself (deterministically). - pub fn new(secret: Secret) -> ExtendedSecret { - let chain_code = derivation::chain_code(*secret); - ExtendedSecret::with_code(secret, chain_code) - } - - /// Derive new private key - pub fn derive(&self, index: Derivation) -> ExtendedSecret - where - T: Label, - { - let (mut derived_key, next_chain_code) = derivation::private(*self.secret, self.chain_code, index); - - let new_derived_secret = Secret::from(derived_key.0); - - derived_key.0.zeroize(); - - ExtendedSecret::with_code(new_derived_secret, next_chain_code) - } - - /// Private key component of the extended key. - pub fn as_raw(&self) -> &Secret { - &self.secret - } -} - -/// Extended public key, allows deterministic derivation of subsequent keys. -pub struct ExtendedPublic { - public: Public, - chain_code: H256, -} - -impl ExtendedPublic { - /// New extended public key from known parent and chain code - pub fn new(public: Public, chain_code: H256) -> Self { - ExtendedPublic { public: public, chain_code: chain_code } - } - - /// Create new extended public key from known secret - pub fn from_secret(secret: &ExtendedSecret) -> Result { - Ok(ExtendedPublic::new(derivation::point(**secret.as_raw())?, secret.chain_code.clone())) - } - - /// Derive new public key - /// Operation is defined only for index belongs [0..2^31) - pub fn derive(&self, index: Derivation) -> Result - where - T: Label, - { - let (derived_key, next_chain_code) = derivation::public(self.public, self.chain_code, index)?; - Ok(ExtendedPublic::new(derived_key, next_chain_code)) - } - - pub fn public(&self) -> &Public { - &self.public - } -} - -pub struct ExtendedKeyPair { - secret: ExtendedSecret, - public: ExtendedPublic, -} - -impl ExtendedKeyPair { - pub fn new(secret: Secret) -> Self { - let extended_secret = ExtendedSecret::new(secret); - let extended_public = - ExtendedPublic::from_secret(&extended_secret).expect("Valid `Secret` always produces valid public; qed"); - ExtendedKeyPair { secret: extended_secret, public: extended_public } - } - - pub fn with_code(secret: Secret, public: Public, chain_code: H256) -> Self { - ExtendedKeyPair { - secret: ExtendedSecret::with_code(secret, chain_code.clone()), - public: ExtendedPublic::new(public, chain_code), - } - } - - pub fn with_secret(secret: Secret, chain_code: H256) -> Self { - let extended_secret = ExtendedSecret::with_code(secret, chain_code); - let extended_public = - ExtendedPublic::from_secret(&extended_secret).expect("Valid `Secret` always produces valid public; qed"); - ExtendedKeyPair { secret: extended_secret, public: extended_public } - } - - pub fn with_seed(seed: &[u8]) -> Result { - let (master_key, chain_code) = derivation::seed_pair(seed); - Ok(ExtendedKeyPair::with_secret( - Secret::import_key(master_key.as_bytes()).map_err(|_| DerivationError::InvalidSeed)?, - chain_code, - )) - } - - pub fn secret(&self) -> &ExtendedSecret { - &self.secret - } - - pub fn public(&self) -> &ExtendedPublic { - &self.public - } - - pub fn derive(&self, index: Derivation) -> Result - where - T: Label, - { - let derived = self.secret.derive(index); - - Ok(ExtendedKeyPair { public: ExtendedPublic::from_secret(&derived)?, secret: derived }) - } -} - -// Derivation functions for private and public keys -// Work is based on BIP0032 -// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -mod derivation { - use super::super::ec_math_utils::CURVE_ORDER; - use super::{Derivation, Label}; - use crate::{hmac, Keccak256}; - use ethereum_types::{BigEndianHash, H256, H512, U256, U512}; - use secp256k1::{ - key::{PublicKey, SecretKey}, - SECP256K1, - }; - use std::convert::TryInto; - - #[derive(Debug)] - pub enum Error { - InvalidHardenedUse, - InvalidPoint, - MissingIndex, - InvalidSeed, - } - - // Deterministic derivation of the key using secp256k1 elliptic curve. - // Derivation can be either hardened or not. - // For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum - // - // Can panic if passed `private_key` is not a valid secp256k1 private key - // (outside of (0..curve_order()]) field - pub fn private(private_key: H256, chain_code: H256, index: Derivation) -> (H256, H256) - where - T: Label, - { - match index { - Derivation::Soft(index) => private_soft(private_key, chain_code, index), - Derivation::Hard(index) => private_hard(private_key, chain_code, index), - } - } - - fn hmac_pair(data: &[u8], private_key: H256, chain_code: H256) -> (H256, H256) { - let private: U256 = private_key.into_uint(); - - // produces 512-bit derived hmac (I) - let skey = hmac::SigKey::sha512(chain_code.as_bytes()); - let i_512 = hmac::sign(&skey, &data[..]); - - // left most 256 bits are later added to original private key - let hmac_key: U256 = H256::from_slice(&i_512[0..32]).into_uint(); - // right most 256 bits are new chain code for later derivations - let next_chain_code = H256::from_slice(&i_512[32..64]); - - let child_key = BigEndianHash::from_uint(&private_add(hmac_key, private)); - (child_key, next_chain_code) - } - - // Can panic if passed `private_key` is not a valid secp256k1 private key - // (outside of (0..curve_order()]) field - fn private_soft(private_key: H256, chain_code: H256, index: T) -> (H256, H256) - where - T: Label, - { - let mut data = vec![0u8; 33 + T::len()]; - - let sec_private = - SecretKey::from_slice(private_key.as_bytes()).expect("Caller should provide valid private key"); - let sec_public = PublicKey::from_secret_key(&SECP256K1, &sec_private); - let public_serialized = sec_public.serialize(); - - // curve point (compressed public key) -- index - // 0.33 -- 33..end - data[0..33].copy_from_slice(&public_serialized); - index.store(&mut data[33..]); - - hmac_pair(&data, private_key, chain_code) - } - - // Deterministic derivation of the key using secp256k1 elliptic curve - // This is hardened derivation and does not allow to associate - // corresponding public keys of the original and derived private keys - fn private_hard(private_key: H256, chain_code: H256, index: T) -> (H256, H256) - where - T: Label, - { - let mut data: Vec = vec![0u8; 33 + T::len()]; - let private: U256 = private_key.into_uint(); - - // 0x00 (padding) -- private_key -- index - // 0 -- 1..33 -- 33..end - private.to_big_endian(&mut data[1..33]); - index.store(&mut data[33..(33 + T::len())]); - - hmac_pair(&data, private_key, chain_code) - } - - fn private_add(k1: U256, k2: U256) -> U256 { - let sum = U512::from(k1) + U512::from(k2); - modulo(sum, *CURVE_ORDER) - } - - // todo: surely can be optimized - fn modulo(u1: U512, u2: U256) -> U256 { - let m = u1 % U512::from(u2); - m.try_into().expect("U512 modulo U256 should fit into U256; qed") - } - - pub fn public(public_key: H512, chain_code: H256, derivation: Derivation) -> Result<(H512, H256), Error> - where - T: Label, - { - let index = match derivation { - Derivation::Soft(index) => index, - Derivation::Hard(_) => { - return Err(Error::InvalidHardenedUse); - } - }; - - let mut public_sec_raw = [0u8; 65]; - public_sec_raw[0] = 4; - public_sec_raw[1..65].copy_from_slice(public_key.as_bytes()); - let public_sec = PublicKey::from_slice(&public_sec_raw).map_err(|_| Error::InvalidPoint)?; - let public_serialized = public_sec.serialize(); - - let mut data = vec![0u8; 33 + T::len()]; - // curve point (compressed public key) -- index - // 0.33 -- 33..end - data[0..33].copy_from_slice(&public_serialized); - index.store(&mut data[33..(33 + T::len())]); - - // HMAC512SHA produces [derived private(256); new chain code(256)] - let skey = hmac::SigKey::sha512(chain_code.as_bytes()); - let i_512 = hmac::sign(&skey, &data[..]); - - let new_private = H256::from_slice(&i_512[0..32]); - let new_chain_code = H256::from_slice(&i_512[32..64]); - - // Generated private key can (extremely rarely) be out of secp256k1 key field - if *CURVE_ORDER <= new_private.into_uint() { - return Err(Error::MissingIndex); - } - let new_private_sec = SecretKey::from_slice(new_private.as_bytes()).expect( - "Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed", - ); - let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec); - - // Adding two points on the elliptic curves (combining two public keys) - new_public = new_public.combine(&public_sec).expect("Addition of two valid points produce valid point"); - - let serialized = new_public.serialize_uncompressed(); - - Ok((H512::from_slice(&serialized[1..65]), new_chain_code)) - } - - fn sha3(slc: &[u8]) -> H256 { - slc.keccak256().into() - } - - pub fn chain_code(secret: H256) -> H256 { - // 10,000 rounds of sha3 - let mut running_sha3 = sha3(secret.as_bytes()); - for _ in 0..99999 { - running_sha3 = sha3(running_sha3.as_bytes()); - } - running_sha3 - } - - pub fn point(secret: H256) -> Result { - let sec = SecretKey::from_slice(secret.as_bytes()).map_err(|_| Error::InvalidPoint)?; - let public_sec = PublicKey::from_secret_key(&SECP256K1, &sec); - let serialized = public_sec.serialize_uncompressed(); - Ok(H512::from_slice(&serialized[1..65])) - } - - pub fn seed_pair(seed: &[u8]) -> (H256, H256) { - let skey = hmac::SigKey::sha512(b"Bitcoin seed"); - let i_512 = hmac::sign(&skey, seed); - - let master_key = H256::from_slice(&i_512[0..32]); - let chain_code = H256::from_slice(&i_512[32..64]); - - (master_key, chain_code) - } -} - -#[cfg(test)] -mod tests { - use super::super::Secret; - use super::{derivation, Derivation}; - use super::{ExtendedKeyPair, ExtendedPublic, ExtendedSecret}; - use ethereum_types::{H128, H256, H512}; - use std::str::FromStr; - - fn master_chain_basic() -> (H256, H256) { - let seed = - H128::from_str("000102030405060708090a0b0c0d0e0f").expect("Seed should be valid H128").as_bytes().to_vec(); - - derivation::seed_pair(&*seed) - } - - fn test_extended(f: F, test_private: H256) - where - F: Fn(ExtendedSecret) -> ExtendedSecret, - { - let (private_seed, chain_code) = master_chain_basic(); - let extended_secret = ExtendedSecret::with_code(Secret::from(private_seed.0), chain_code); - let derived = f(extended_secret); - assert_eq!(**derived.as_raw(), test_private); - } - - #[test] - fn smoky() { - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let extended_secret = ExtendedSecret::with_code(secret.clone(), H256::zero()); - - // hardened - assert_eq!(&**extended_secret.as_raw(), &*secret); - assert_eq!( - **extended_secret.derive(2147483648.into()).as_raw(), - H256::from_str("0927453daed47839608e414a3738dfad10aed17c459bbd9ab53f89b026c834b6").unwrap(), - ); - assert_eq!( - **extended_secret.derive(2147483649.into()).as_raw(), - H256::from_str("44238b6a29c6dcbe9b401364141ba11e2198c289a5fed243a1c11af35c19dc0f").unwrap(), - ); - - // normal - assert_eq!( - **extended_secret.derive(0.into()).as_raw(), - H256::from_str("bf6a74e3f7b36fc4c96a1e12f31abc817f9f5904f5a8fc27713163d1f0b713f6").unwrap() - ); - assert_eq!( - **extended_secret.derive(1.into()).as_raw(), - H256::from_str("bd4fca9eb1f9c201e9448c1eecd66e302d68d4d313ce895b8c134f512205c1bc").unwrap() - ); - assert_eq!( - **extended_secret.derive(2.into()).as_raw(), - H256::from_str("86932b542d6cab4d9c65490c7ef502d89ecc0e2a5f4852157649e3251e2a3268").unwrap() - ); - - let extended_public = ExtendedPublic::from_secret(&extended_secret).expect("Extended public should be created"); - let derived_public = extended_public.derive(0.into()).expect("First derivation of public should succeed"); - assert_eq!( - *derived_public.public(), - H512::from_str("f7b3244c96688f92372bfd4def26dc4151529747bab9f188a4ad34e141d47bd66522ff048bc6f19a0a4429b04318b1a8796c000265b4fa200dae5f6dda92dd94").unwrap(), - ); - - let keypair = ExtendedKeyPair::with_secret( - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(), - H256::from_low_u64_be(64), - ); - assert_eq!( - **keypair.derive(2147483648u32.into()).expect("Derivation of keypair should succeed").secret().as_raw(), - H256::from_str("edef54414c03196557cf73774bc97a645c9a1df2164ed34f0c2a78d1375a930c").unwrap(), - ); - } - - #[test] - fn h256_soft_match() { - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let derivation_secret = - H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015").unwrap(); - - let extended_secret = ExtendedSecret::with_code(secret.clone(), H256::zero()); - let extended_public = ExtendedPublic::from_secret(&extended_secret).expect("Extended public should be created"); - - let derived_secret0 = extended_secret.derive(Derivation::Soft(derivation_secret)); - let derived_public0 = extended_public - .derive(Derivation::Soft(derivation_secret)) - .expect("First derivation of public should succeed"); - - let public_from_secret0 = - ExtendedPublic::from_secret(&derived_secret0).expect("Extended public should be created"); - - assert_eq!(public_from_secret0.public(), derived_public0.public()); - } - - #[test] - fn h256_hard() { - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let derivation_secret = - H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015").unwrap(); - let extended_secret = ExtendedSecret::with_code(secret.clone(), H256::from_low_u64_be(1)); - - assert_eq!( - **extended_secret.derive(Derivation::Hard(derivation_secret)).as_raw(), - H256::from_str("2bc2d696fb744d77ff813b4a1ef0ad64e1e5188b622c54ba917acc5ebc7c5486").unwrap(), - ); - } - - #[test] - fn test_key_derivation() { - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let extended_secret = ExtendedSecret::with_code(secret.clone(), H256::from_low_u64_be(1)); - let extended_public = ExtendedPublic::from_secret(&extended_secret).expect("Extended public should be created"); - - let derived_secret0 = extended_secret.derive(0.into()); - let derived_public0 = extended_public.derive(0.into()).expect("First derivation of public should succeed"); - - let public_from_secret0 = - ExtendedPublic::from_secret(&derived_secret0).expect("Extended public should be created"); - - assert_eq!(public_from_secret0.public(), derived_public0.public()); - } - - #[test] - fn test_seeds() { - let seed = - H128::from_str("000102030405060708090a0b0c0d0e0f").expect("Seed should be valid H128").as_bytes().to_vec(); - - // private key from bitcoin test vector - // xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs - let test_private = H256::from_str("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35") - .expect("Private should be decoded ok"); - - let (private_seed, _) = derivation::seed_pair(&*seed); - - assert_eq!(private_seed, test_private); - } - - #[test] - fn test_vector_1() { - // xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 - // H(0) - test_extended( - |secret| secret.derive(2147483648.into()), - H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea") - .expect("Private should be decoded ok"), - ); - } - - #[test] - fn test_vector_2() { - // xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs - // H(0)/1 - test_extended( - |secret| secret.derive(2147483648.into()).derive(1.into()), - H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368") - .expect("Private should be decoded ok"), - ); - } -} diff --git a/parity-crypto/src/publickey/keypair.rs b/parity-crypto/src/publickey/keypair.rs deleted file mode 100644 index dbbf637dc..000000000 --- a/parity-crypto/src/publickey/keypair.rs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Key pair (public + secret) description. - -use super::{Address, Error, Public, Secret}; -use crate::Keccak256; -use secp256k1::{key, SECP256K1}; -use std::fmt; - -/// Convert public key into the address -pub fn public_to_address(public: &Public) -> Address { - let hash = public.keccak256(); - let mut result = Address::zero(); - result.as_bytes_mut().copy_from_slice(&hash[12..]); - result -} - -#[derive(Debug, Clone, PartialEq)] -/// secp256k1 key pair -pub struct KeyPair { - secret: Secret, - public: Public, -} - -impl fmt::Display for KeyPair { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - writeln!(f, "secret: {:x}", self.secret)?; - writeln!(f, "public: {:x}", self.public)?; - write!(f, "address: {:x}", self.address()) - } -} - -impl KeyPair { - /// Create a pair from secret key - pub fn from_secret(secret: Secret) -> Result { - let context = &SECP256K1; - let s: key::SecretKey = key::SecretKey::from_slice(&secret[..])?; - let pub_key = key::PublicKey::from_secret_key(context, &s); - let serialized = pub_key.serialize_uncompressed(); - - let mut public = Public::default(); - public.as_bytes_mut().copy_from_slice(&serialized[1..65]); - - let keypair = KeyPair { secret, public }; - - Ok(keypair) - } - - /// Create a pair from the slice, which imported and verified as secret key - pub fn from_secret_slice(slice: &[u8]) -> Result { - Self::from_secret(Secret::import_key(slice)?) - } - - /// Copies a pair from another one - #[inline(always)] - pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self { - let serialized = publ.serialize_uncompressed(); - let secret = Secret::from(sec); - let mut public = Public::default(); - public.as_bytes_mut().copy_from_slice(&serialized[1..65]); - - KeyPair { secret, public } - } - - /// Returns secret part of the keypair - pub fn secret(&self) -> &Secret { - &self.secret - } - - /// Returns public part of the keypair - pub fn public(&self) -> &Public { - &self.public - } - - /// Returns public part of the keypair converted into Address - pub fn address(&self) -> Address { - public_to_address(&self.public) - } -} - -#[cfg(test)] -mod tests { - use super::{KeyPair, Secret}; - - #[test] - fn from_secret() { - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let _ = KeyPair::from_secret(secret).unwrap(); - } - - #[test] - fn keypair_display() { - let expected = -"secret: a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65 -public: 8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4 -address: 5b073e9233944b5e729e46d618f0d8edf3d9c34a".to_owned(); - let secret = - Secret::copy_from_str(&"a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); - let kp = KeyPair::from_secret(secret).unwrap(); - assert_eq!(format!("{}", kp), expected); - } -} diff --git a/parity-crypto/src/publickey/keypair_generator.rs b/parity-crypto/src/publickey/keypair_generator.rs deleted file mode 100644 index 6ebef0985..000000000 --- a/parity-crypto/src/publickey/keypair_generator.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Random key pair generator. Relies on the secp256k1 C-library to generate random data. - -use super::{Generator, KeyPair}; -use secp256k1::SECP256K1; - -/// Randomly generates new keypair, instantiating the RNG each time. -pub struct Random; - -impl Generator for Random { - fn generate(&mut self) -> KeyPair { - let (sec, publ) = SECP256K1.generate_keypair(&mut secp256k1::rand::thread_rng()); - KeyPair::from_keypair(sec, publ) - } -} diff --git a/parity-crypto/src/publickey/mod.rs b/parity-crypto/src/publickey/mod.rs deleted file mode 100644 index c7981515c..000000000 --- a/parity-crypto/src/publickey/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Submodule of crypto utils for working with public key crypto primitives -//! If you are looking for git history please refer to the `ethkey` crate in the `parity-ethereum` repository. - -mod ecdsa_signature; -mod extended_keys; -mod keypair; -mod keypair_generator; -mod secret_key; - -pub mod ec_math_utils; -pub mod ecdh; -pub mod ecies; -pub mod error; - -pub use self::{ - ecdsa_signature::{recover, sign, verify_address, verify_public, Signature}, - error::Error, - extended_keys::{Derivation, DerivationError, ExtendedKeyPair, ExtendedPublic, ExtendedSecret}, - keypair::{public_to_address, KeyPair}, - keypair_generator::Random, - secret_key::{Secret, ZeroizeSecretKey}, -}; - -use ethereum_types::H256; - -pub use ethereum_types::{Address, Public}; -pub type Message = H256; - -/// The number -1 encoded as a secret key -const MINUS_ONE_KEY: &'static [u8] = &[ - 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, -]; - -/// Generates new keypair. -pub trait Generator { - /// Should be called to generate new keypair. - fn generate(&mut self) -> KeyPair; -} diff --git a/parity-crypto/src/publickey/secret_key.rs b/parity-crypto/src/publickey/secret_key.rs deleted file mode 100644 index 7f5692f1d..000000000 --- a/parity-crypto/src/publickey/secret_key.rs +++ /dev/null @@ -1,307 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Secret key implementation. - -use std::fmt; -use std::ops::Deref; -use std::str::FromStr; - -use ethereum_types::H256; -use secp256k1::constants::SECRET_KEY_SIZE as SECP256K1_SECRET_KEY_SIZE; -use secp256k1::key; -use zeroize::Zeroize; - -use crate::publickey::Error; - -/// Represents secret key -#[derive(Clone, PartialEq, Eq)] -pub struct Secret { - inner: Box, -} - -impl Drop for Secret { - fn drop(&mut self) { - self.inner.0.zeroize() - } -} - -impl fmt::LowerHex for Secret { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(fmt) - } -} - -impl fmt::Debug for Secret { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(fmt) - } -} - -impl fmt::Display for Secret { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "Secret: 0x{:x}{:x}..{:x}{:x}", self.inner[0], self.inner[1], self.inner[30], self.inner[31]) - } -} - -impl Secret { - /// Creates a `Secret` from the given slice, returning `None` if the slice length != 32. - /// Caller is responsible to zeroize input slice. - pub fn copy_from_slice(key: &[u8]) -> Option { - if key.len() != 32 { - return None; - } - let mut h = H256::zero(); - h.as_bytes_mut().copy_from_slice(&key[0..32]); - Some(Secret { inner: Box::new(h) }) - } - - /// Creates a `Secret` from the given `str` representation, - /// returning an error for hex big endian representation of - /// the secret. - /// Caller is responsible to zeroize input slice. - pub fn copy_from_str(s: &str) -> Result { - let h = H256::from_str(s).map_err(|e| Error::Custom(format!("{:?}", e)))?; - Ok(Secret { inner: Box::new(h) }) - } - - /// Creates zero key, which is invalid for crypto operations, but valid for math operation. - pub fn zero() -> Self { - Secret { inner: Box::new(H256::zero()) } - } - - /// Imports and validates the key. - /// Caller is responsible to zeroize input slice. - pub fn import_key(key: &[u8]) -> Result { - let secret = key::SecretKey::from_slice(key)?; - Ok(secret.into()) - } - - /// Checks validity of this key. - pub fn check_validity(&self) -> Result<(), Error> { - self.to_secp256k1_secret().map(|_| ()) - } - - /// Wrapper over hex conversion - pub fn to_hex(&self) -> String { - format!("{:x}", self.inner.deref()) - } - - /// Inplace add one secret key to another (scalar + scalar) - pub fn add(&mut self, other: &Secret) -> Result<(), Error> { - match (self.is_zero(), other.is_zero()) { - (true, true) | (false, true) => Ok(()), - (true, false) => { - *self = other.clone(); - Ok(()) - } - (false, false) => { - let mut key_secret = self.to_secp256k1_secret()?; - let other_secret = other.to_secp256k1_secret()?; - key_secret.add_assign(&other_secret[..])?; - *self = key_secret.into(); - ZeroizeSecretKey(other_secret).zeroize(); - - Ok(()) - } - } - } - - /// Inplace subtract one secret key from another (scalar - scalar) - pub fn sub(&mut self, other: &Secret) -> Result<(), Error> { - match (self.is_zero(), other.is_zero()) { - (true, true) | (false, true) => Ok(()), - (true, false) => { - *self = other.clone(); - self.neg() - } - (false, false) => { - let mut key_secret = self.to_secp256k1_secret()?; - let mut other_secret = other.to_secp256k1_secret()?; - other_secret.mul_assign(super::MINUS_ONE_KEY)?; - key_secret.add_assign(&other_secret[..])?; - - *self = key_secret.into(); - ZeroizeSecretKey(other_secret).zeroize(); - Ok(()) - } - } - } - - /// Inplace decrease secret key (scalar - 1) - pub fn dec(&mut self) -> Result<(), Error> { - match self.is_zero() { - true => { - *self = Self::copy_from_slice(&super::MINUS_ONE_KEY) - .expect("Constructing a secret key from a known-good constant works; qed."); - Ok(()) - } - false => { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.add_assign(super::MINUS_ONE_KEY)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Inplace multiply one secret key to another (scalar * scalar) - pub fn mul(&mut self, other: &Secret) -> Result<(), Error> { - match (self.is_zero(), other.is_zero()) { - (true, true) | (true, false) => Ok(()), - (false, true) => { - *self = Self::zero(); - Ok(()) - } - (false, false) => { - let mut key_secret = self.to_secp256k1_secret()?; - let other_secret = other.to_secp256k1_secret()?; - key_secret.mul_assign(&other_secret[..])?; - - *self = key_secret.into(); - ZeroizeSecretKey(other_secret).zeroize(); - Ok(()) - } - } - } - - /// Inplace negate secret key (-scalar) - pub fn neg(&mut self) -> Result<(), Error> { - match self.is_zero() { - true => Ok(()), - false => { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.mul_assign(super::MINUS_ONE_KEY)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Compute power of secret key inplace (secret ^ pow). - pub fn pow(&mut self, pow: usize) -> Result<(), Error> { - if self.is_zero() { - return Ok(()); - } - - match pow { - 0 => *self = key::ONE_KEY.into(), - 1 => (), - _ => { - let c = self.clone(); - for _ in 1..pow { - self.mul(&c)?; - } - } - } - - Ok(()) - } - - /// Create a `secp256k1::key::SecretKey` based on this secret. - /// Warning the resulting secret key need to be zeroized manually. - pub fn to_secp256k1_secret(&self) -> Result { - key::SecretKey::from_slice(&self[..]).map_err(Into::into) - } -} - -impl From<[u8; 32]> for Secret { - #[inline(always)] - fn from(mut k: [u8; 32]) -> Self { - let result = Secret { inner: Box::new(H256(k)) }; - k.zeroize(); - result - } -} - -impl From for Secret { - #[inline(always)] - fn from(mut s: H256) -> Self { - let result = s.0.into(); - s.0.zeroize(); - result - } -} - -impl From for Secret { - #[inline(always)] - fn from(key: key::SecretKey) -> Self { - let mut a = [0; SECP256K1_SECRET_KEY_SIZE]; - a.copy_from_slice(&key[0..SECP256K1_SECRET_KEY_SIZE]); - ZeroizeSecretKey(key).zeroize(); - a.into() - } -} - -impl Deref for Secret { - type Target = H256; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -/// A wrapper type around `SecretKey` to prevent leaking secret key data. This -/// type will properly zeroize the secret key to `ONE_KEY` in a way that will -/// not get optimized away by the compiler nor be prone to leaks that take -/// advantage of access reordering. -#[derive(Clone, Copy)] -pub struct ZeroizeSecretKey(pub secp256k1::SecretKey); - -impl Default for ZeroizeSecretKey { - fn default() -> Self { - ZeroizeSecretKey(secp256k1::key::ONE_KEY) - } -} - -impl std::ops::Deref for ZeroizeSecretKey { - type Target = secp256k1::SecretKey; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl zeroize::DefaultIsZeroes for ZeroizeSecretKey {} - -#[cfg(test)] -mod tests { - use super::super::{Generator, Random}; - use super::Secret; - - #[test] - fn secret_pow() { - let secret = Random.generate().secret().clone(); - - let mut pow0 = secret.clone(); - pow0.pow(0).unwrap(); - assert_eq!( - pow0, - Secret::copy_from_str(&"0000000000000000000000000000000000000000000000000000000000000001").unwrap() - ); - - let mut pow1 = secret.clone(); - pow1.pow(1).unwrap(); - assert_eq!(pow1, secret); - - let mut pow2 = secret.clone(); - pow2.pow(2).unwrap(); - let mut pow2_expected = secret.clone(); - pow2_expected.mul(&secret).unwrap(); - assert_eq!(pow2, pow2_expected); - - let mut pow3 = secret.clone(); - pow3.pow(3).unwrap(); - let mut pow3_expected = secret.clone(); - pow3_expected.mul(&secret).unwrap(); - pow3_expected.mul(&secret).unwrap(); - assert_eq!(pow3, pow3_expected); - } -} diff --git a/parity-crypto/src/scrypt.rs b/parity-crypto/src/scrypt.rs deleted file mode 100644 index 15b7e14e1..000000000 --- a/parity-crypto/src/scrypt.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::{KEY_LENGTH, KEY_LENGTH_AES}; -use crate::error::ScryptError; -use scrypt::{scrypt, ScryptParams}; - -#[cfg(test)] -use std::io::Error; - -pub fn derive_key(pass: &[u8], salt: &[u8], n: u32, p: u32, r: u32) -> Result<(Vec, Vec), ScryptError> { - // sanity checks - let log_n = (32 - n.leading_zeros() - 1) as u8; - if log_n as u32 >= r * 16 { - return Err(ScryptError::InvalidN); - } - - if p as u64 > ((u32::max_value() as u64 - 1) * 32) / (128 * (r as u64)) { - return Err(ScryptError::InvalidP); - } - - let mut derived_key = vec![0u8; KEY_LENGTH]; - let scrypt_params = ScryptParams::new(log_n, r, p)?; - scrypt(pass, salt, &scrypt_params, &mut derived_key)?; - let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; - let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; - Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec())) -} - -// test is build from previous crypto lib behaviour, values may be incorrect -// if previous crypto lib got a bug. -#[test] -pub fn test_derive() -> Result<(), Error> { - let pass = [109, 121, 112, 97, 115, 115, 10]; - let salt = [ - 109, 121, 115, 97, 108, 116, 115, 104, 111, 117, 108, 100, 102, 105, 108, 108, 115, 111, 109, 109, 101, 98, - 121, 116, 101, 108, 101, 110, 103, 116, 104, 10, - ]; - let r1 = [93, 134, 79, 68, 223, 27, 44, 174, 236, 184, 179, 203, 74, 139, 73, 66]; - let r2 = [2, 24, 239, 131, 172, 164, 18, 171, 132, 207, 22, 217, 150, 20, 203, 37]; - let l1 = [6, 90, 119, 45, 67, 2, 99, 151, 81, 88, 166, 210, 244, 19, 123, 208]; - let l2 = [253, 123, 132, 12, 188, 89, 196, 2, 107, 224, 239, 231, 135, 177, 125, 62]; - - let (l, r) = derive_key(&pass[..], &salt, 262, 1, 8).unwrap(); - assert!(l == r1); - assert!(r == l1); - let (l, r) = derive_key(&pass[..], &salt, 144, 4, 4).unwrap(); - assert!(l == r2); - assert!(r == l2); - Ok(()) -}