Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ PointerAlignment: Left
IncludeCategories:
- Regex: '^"\.\./'
Priority: 2
- Regex: '^<(TrustWalletCore|TrezorCrypto)/'
- Regex: '^<(TrustWalletCore)/'
Priority: 3
- Regex: '<.*>'
Priority: 4
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/linux-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ jobs:
CXX: /usr/bin/clang++
- name: Build and test
run: |
ninja -Cbuild tests TrezorCryptoTests
build/trezor-crypto/crypto/tests/TrezorCryptoTests
ninja -Cbuild tests
build/tests/tests --gtest_output=xml
env:
CC: /usr/bin/clang
Expand Down
7 changes: 3 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ target_link_directories(${PROJECT_NAME}_INTERFACE INTERFACE ${PREFIX}/lib)
target_link_directories(${PROJECT_NAME}_INTERFACE INTERFACE ${WALLET_CORE_RS_TARGET_DIR}/release)
set_project_warnings(${PROJECT_NAME}_INTERFACE)

add_subdirectory(trezor-crypto)
set(WALLET_CORE_RS_LIB libwallet_core_rs.a)

set(WALLET_CORE_BINDGEN ${WALLET_CORE_RS_TARGET_DIR}/release/${WALLET_CORE_RS_LIB})
Expand Down Expand Up @@ -72,7 +71,7 @@ if (${ANDROID})
elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "x86_64")
set(WALLET_CORE_BINDGEN ${WALLET_CORE_RS_TARGET_DIR}/x86_64-linux-android/release/${WALLET_CORE_RS_LIB})
endif ()
target_link_libraries(TrustWalletCore PUBLIC ${WALLET_CORE_BINDGEN} ${PROJECT_NAME}_INTERFACE PRIVATE TrezorCrypto protobuf ${log-lib} Boost::boost)
target_link_libraries(TrustWalletCore PUBLIC ${WALLET_CORE_BINDGEN} ${PROJECT_NAME}_INTERFACE PRIVATE protobuf ${log-lib} Boost::boost)
elseif (${TW_COMPILE_JAVA})
message("Configuring for JNI")
file(GLOB_RECURSE core_sources src/*.c src/*.cc src/*.cpp src/*.h jni/cpp/*.cpp jni/cpp/*.h)
Expand All @@ -90,12 +89,12 @@ elseif (${TW_COMPILE_JAVA})
add_library(TrustWalletCore SHARED ${sources} ${PROTO_SRCS} ${PROTO_HDRS})
find_package(JNI REQUIRED)
target_include_directories(TrustWalletCore PRIVATE ${JNI_INCLUDE_DIRS})
target_link_libraries(TrustWalletCore PUBLIC ${WALLET_CORE_BINDGEN} ${PROJECT_NAME}_INTERFACE PRIVATE TrezorCrypto protobuf Boost::boost)
target_link_libraries(TrustWalletCore PUBLIC ${WALLET_CORE_BINDGEN} ${PROJECT_NAME}_INTERFACE PRIVATE protobuf Boost::boost)
else ()
message("Configuring standalone")
file(GLOB_RECURSE sources src/*.c src/*.cc src/*.cpp src/*.h)
add_library(TrustWalletCore STATIC ${sources} ${PROTO_SRCS} ${PROTO_HDRS})
target_link_libraries(TrustWalletCore PUBLIC ${WALLET_CORE_BINDGEN} ${PROJECT_NAME}_INTERFACE PRIVATE TrezorCrypto protobuf Boost::boost)
target_link_libraries(TrustWalletCore PUBLIC ${WALLET_CORE_BINDGEN} ${PROJECT_NAME}_INTERFACE PRIVATE protobuf Boost::boost)
endif ()

if (TW_CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
Expand Down
11 changes: 1 addition & 10 deletions WalletCore.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ Pod::Spec.new do |s|
'swift/Sources/*.{swift,h,m,cpp}',
'swift/Sources/Extensions/*.swift',
'swift/Sources/Generated/*.{swift,h}',
'trezor-crypto/crypto/**/*.{c,h}',
'trezor-crypto/include/**/*.{h}',
"#{protobuf_source_dir}/src/google/protobuf/any.cc",
"#{protobuf_source_dir}/src/google/protobuf/any.pb.cc",
"#{protobuf_source_dir}/src/google/protobuf/any_lite.cc",
Expand Down Expand Up @@ -125,32 +123,25 @@ Pod::Spec.new do |s|
"#{protobuf_source_dir}/src/google/protobuf/wrappers.pb.cc"

ss.exclude_files =
'trezor-crypto/include/TrezorCrypto/base58.h',
'trezor-crypto/crypto/monero',
'trezor-crypto/crypto/tests',
'trezor-crypto/crypto/tools',
'trezor-crypto/crypto/rand.c',
'src/rand.cpp',
'swift/Sources/Generated/WalletCore.h'

ss.public_header_files =
'include/**/*.h',
'swift/Sources/*.h'

ss.preserve_paths =
'trezor-crypto/crypto/*.{table}',
"#{protobuf_source_dir}/src/**/*.{h,inc}",
"#{include_dir}/nlohmann/**/*.hpp",
'src/proto/*.proto'

ss.xcconfig = {
'HEADER_SEARCH_PATHS' => '$(inherited) ' \
'$(SRCROOT)/../../wallet-core ' \
'${SRCROOT}/../../trezor-crypto/crypto ',
'SYSTEM_HEADER_SEARCH_PATHS' => '$(inherited) ' \
'/usr/local/include ' \
'${SRCROOT}/../../include ' \
'${SRCROOT}/../../../build/local/include ' \
"${SRCROOT}/../../trezor-crypto/include " \
"${SRCROOT}/../../protobuf ",
'GCC_WARN_UNUSED_FUNCTION' => 'NO',
'GCC_WARN_64_TO_32_BIT_CONVERSION' => 'NO',
Expand Down
36 changes: 0 additions & 36 deletions include/TrustWalletCore/TWPBKDF2.h

This file was deleted.

13 changes: 12 additions & 1 deletion rust/tw_crypto/src/crypto_pbkdf2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// file LICENSE at the root of the source code distribution tree.

use pbkdf2::pbkdf2_hmac;
use sha2::Sha256;
use sha2::{Sha256, Sha512};

pub fn pbkdf2_hmac_sha256(
password: &[u8],
Expand All @@ -17,3 +17,14 @@ pub fn pbkdf2_hmac_sha256(
pbkdf2_hmac::<Sha256>(password, salt, iterations, &mut output);
output
}

pub fn pbkdf2_hmac_512(
password: &[u8],
salt: &[u8],
iterations: u32,
desired_len: usize,
) -> Vec<u8> {
let mut output = vec![0u8; desired_len];
pbkdf2_hmac::<Sha512>(password, salt, iterations, &mut output);
output
}
38 changes: 32 additions & 6 deletions rust/tw_crypto/src/ffi/crypto_pbkdf2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#![allow(clippy::missing_safety_doc)]

use crate::crypto_pbkdf2::pbkdf2_hmac_sha256;
use crate::crypto_pbkdf2::{pbkdf2_hmac_512, pbkdf2_hmac_sha256};
use tw_macros::tw_ffi;
use tw_memory::ffi::{tw_data::TWData, Nonnull, NullableMut, RawPtrTrait};

Expand All @@ -15,15 +15,15 @@ use tw_memory::ffi::{tw_data::TWData, Nonnull, NullableMut, RawPtrTrait};
/// \param password data.
/// \param salt data.
/// \param iterations PBKDF2 parameter `iterations`.
/// \param desired_len PBKDF2 parameter `desired_len`.
/// \param dk_len PBKDF2 parameter `desired_len`.
/// \return *nullable* data.
#[tw_ffi(ty = static_function, class = TWCrypto, name = PBKDF2)]
#[tw_ffi(ty = static_function, class = TWPBKDF2, name = HmacSha256)]
#[no_mangle]
pub unsafe extern "C" fn crypto_pbkdf2(
pub unsafe extern "C" fn tw_pbkdf2_hmac_sha256(
password: Nonnull<TWData>,
salt: Nonnull<TWData>,
iterations: u32,
desired_len: usize,
dk_len: usize,
) -> NullableMut<TWData> {
let password = TWData::from_ptr_as_ref(password)
.map(|data| data.as_slice())
Expand All @@ -32,6 +32,32 @@ pub unsafe extern "C" fn crypto_pbkdf2(
.map(|data| data.as_slice())
.unwrap_or_default();

let output = pbkdf2_hmac_sha256(password, salt, iterations, desired_len);
let output = pbkdf2_hmac_sha256(password, salt, iterations, dk_len);
TWData::from(output).into_ptr()
}

/// The PBKDF2 key derivation function.
///
/// \param password data.
/// \param salt data.
/// \param iterations PBKDF2 parameter `iterations`.
/// \param dk_len PBKDF2 parameter `desired_len`.
/// \return *nullable* data.
#[tw_ffi(ty = static_function, class = TWPBKDF2, name = HmacSha512)]
#[no_mangle]
pub unsafe extern "C" fn tw_pbkdf2_hmac_sha512(
password: Nonnull<TWData>,
salt: Nonnull<TWData>,
iterations: u32,
dk_len: usize,
) -> NullableMut<TWData> {
let password = TWData::from_ptr_as_ref(password)
.map(|data| data.as_slice())
.unwrap_or_default();
let salt = TWData::from_ptr_as_ref(salt)
.map(|data| data.as_slice())
.unwrap_or_default();

let output = pbkdf2_hmac_512(password, salt, iterations, dk_len);
TWData::from(output).into_ptr()
}
27 changes: 22 additions & 5 deletions rust/tw_crypto/tests/crypto_pbkdf2_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

use tw_crypto::ffi::crypto_pbkdf2::crypto_pbkdf2;
use tw_crypto::ffi::crypto_pbkdf2::{tw_pbkdf2_hmac_sha256, tw_pbkdf2_hmac_sha512};
use tw_encoding::{base64, base64::STANDARD, hex};
use tw_memory::ffi::tw_data::TWData;
use tw_memory::ffi::RawPtrTrait;
use tw_memory::test_utils::tw_data_helper::TWDataHelper;

#[test]
fn test_crypto_pbkdf2_ffi() {
fn test_pbkdf2_hmac_sha256_ffi() {
let password = hex::decode("70617373776f7264").unwrap();
let password = TWDataHelper::create(password);

let salt = hex::decode("73616C74").unwrap();
let salt = TWDataHelper::create(salt);

let res = unsafe { crypto_pbkdf2(password.ptr(), salt.ptr(), 1, 20) };
let res = unsafe { tw_pbkdf2_hmac_sha256(password.ptr(), salt.ptr(), 1, 20) };
let res = unsafe { TWData::from_ptr_as_mut(res).unwrap() };
assert_eq!(
hex::encode(res.to_vec(), false),
"120fb6cffcf8b32c43e7225256c4f837a86548c9"
);

let res = unsafe { crypto_pbkdf2(password.ptr(), salt.ptr(), 4096, 20) };
let res = unsafe { tw_pbkdf2_hmac_sha256(password.ptr(), salt.ptr(), 4096, 20) };
let res = unsafe { TWData::from_ptr_as_mut(res).unwrap() };
assert_eq!(
hex::encode(res.to_vec(), false),
Expand All @@ -35,10 +35,27 @@ fn test_crypto_pbkdf2_ffi() {
let salt2 = base64::decode("kNHS+Mx//slRsmLF9396HQ==", STANDARD).unwrap();
let salt2 = TWDataHelper::create(salt2);

let res = unsafe { crypto_pbkdf2(password.ptr(), salt2.ptr(), 100, 32) };
let res = unsafe { tw_pbkdf2_hmac_sha256(password.ptr(), salt2.ptr(), 100, 32) };
let res = unsafe { TWData::from_ptr_as_mut(res).unwrap() };
assert_eq!(
hex::encode(res.to_vec(), false),
"9cf33ebd3542c691fac6f61609a8d13355a0adf4d15eed77cc9d13f792b77c3a"
);
}

#[test]
fn test_pbkdf2_hmac_sha512_ffi() {
let password = hex::decode("70617373776f7264").unwrap();
let password = TWDataHelper::create(password);

let salt = hex::decode("73616C74").unwrap();
let salt = TWDataHelper::create(salt);

let res = unsafe { tw_pbkdf2_hmac_sha512(password.ptr(), salt.ptr(), 1, 20) };
let res = unsafe { TWData::from_ptr_as_mut(res).unwrap() };

assert_eq!(
hex::encode(res.to_vec(), false),
"867f70cf1ade02cff3752599a3a53dc4af34c7a6"
);
}
21 changes: 19 additions & 2 deletions rust/tw_keypair/src/ecdsa/nist256p1/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ use crate::ecdsa::nist256p1::public::PublicKey;
use crate::ecdsa::nist256p1::Signature;
use crate::traits::{DerivableKeyTrait, SigningKeyTrait};
use crate::{KeyPairError, KeyPairResult};
use p256::ecdsa::SigningKey;
use ecdsa::elliptic_curve::point::AffineCoordinates;
use p256::ecdsa::{SigningKey, VerifyingKey};
use p256::{AffinePoint, ProjectivePoint};
use tw_encoding::hex;
use tw_hash::H256;
use tw_hash::{H256, H512};
use tw_misc::traits::ToBytesZeroizing;
use zeroize::{ZeroizeOnDrop, Zeroizing};

Expand All @@ -25,6 +27,21 @@ impl PrivateKey {
pub fn public(&self) -> PublicKey {
PublicKey::new(*self.secret.verifying_key())
}

// See https://github.com/fioprotocol/fiojs/blob/master/src/ecc/key_private.js
pub fn ecies_shared_key(&self, pubkey: &PublicKey) -> H512 {
let shared_secret = diffie_hellman(&self.secret, &pubkey.public);
let hash = tw_hash::sha2::sha512(shared_secret.x().as_slice());
H512::try_from(hash.as_slice()).expect("Expected 64 byte array sha512 hash")
}
}

/// This method is inspired by [elliptic_curve::ecdh::diffie_hellman](https://github.com/RustCrypto/traits/blob/f0dbe44fea56d4c17e625ababacb580fec842137/elliptic-curve/src/ecdh.rs#L60-L70)
fn diffie_hellman(private: &SigningKey, public: &VerifyingKey) -> AffinePoint {
let public_point = ProjectivePoint::from(*public.as_affine());
let secret_scalar = private.as_nonzero_scalar().as_ref();
// Multiply the secret and public to get a shared secret affine point (x, y).
(public_point * secret_scalar).to_affine()
}

impl SigningKeyTrait for PrivateKey {
Expand Down
22 changes: 22 additions & 0 deletions rust/tw_keypair/src/ecdsa/nist256p1/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
//
// Copyright © 2017 Trust Wallet.

use std::cmp::Ordering;

use crate::ecdsa::nist256p1::{Signature, VerifySignature};
use crate::traits::{DerivableKeyTrait, VerifyingKeyTrait};
use crate::{KeyPairError, KeyPairResult};
use ecdsa::elliptic_curve::group::prime::PrimeCurveAffine;
use ecdsa::elliptic_curve::point::AffineCoordinates;
use p256::ecdsa::signature::hazmat::PrehashVerifier;
use p256::ecdsa::VerifyingKey;
use tw_encoding::hex;
use tw_hash::hasher::{Hasher, StatefulHasher};
use tw_hash::{H256, H264, H520};
use tw_memory::Data;
use tw_misc::traits::ToBytesVec;

/// Represents a `nist256p1` public key.
Expand Down Expand Up @@ -50,6 +55,23 @@ impl PublicKey {
H520::try_from(self.public.to_encoded_point(compressed).as_bytes())
.expect("Expected 65 byte array Public Key")
}

pub fn hash(&self, hasher: Hasher) -> Data {
hasher.hash(self.compressed().as_slice())
}

pub fn compare(&self, other: &PublicKey) -> Ordering {
let self_as_affine = self.public.as_affine();
let other_as_affine = other.public.as_affine();
let result = self_as_affine.x().cmp(&other_as_affine.x());
if result != Ordering::Equal {
return result;
}
self_as_affine
.y_is_odd()
.unwrap_u8()
.cmp(&other_as_affine.y_is_odd().unwrap_u8())
}
}

impl VerifyingKeyTrait for PublicKey {
Expand Down
16 changes: 0 additions & 16 deletions rust/tw_keypair/src/ecdsa/secp256k1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,6 @@ mod tests {
assert!(!private.public().verify(verify_sig, hash_to_sign));
}

#[test]
fn test_shared_key_hash() {
let private = PrivateKey::try_from(
"9cd3b16e10bd574fed3743d8e0de0b7b4e6c69f3245ab5a168ef010d22bfefa0",
)
.unwrap();
let public = PublicKey::try_from(
"02a18a98316b5f52596e75bfa5ca9fa9912edd0c989b86b73d41bb64c9c6adb992",
)
.unwrap();
let actual = private.shared_key_hash(&public);
let expected =
H256::from("ef2cf705af8714b35c0855030f358f2bee356ff3579cea2607b2025d80133c3a");
assert_eq!(actual, expected);
}

#[test]
fn test_public_key_recover() {
let sign_bytes = H520::from("8720a46b5b3963790d94bcc61ad57ca02fd153584315bfa161ed3455e336ba624d68df010ed934b8792c5b6a57ba86c3da31d039f9612b44d1bf054132254de901");
Expand Down
Loading
Loading