Unverified Commit 90b6cdd4 authored by Maciej Hirsz's avatar Maciej Hirsz Committed by GitHub
Browse files

Fixed Rust dependencies + BIP39 support (#232)

* feat: Fixed Rust dependencies + BIP39 support

* feat: Reintroduce checking for extra whitespace

* fix: Update headers for iOS

* fix: Restore iOS simulator build pipeline (fixes #176)
parent 86c57c56
......@@ -40,14 +40,14 @@ Parity Signer was built to be used offline. The mobile device used to run the ap
- `rustup` (tested on `rustup 1.16.0`)
- `rustc` (tested on `rustc 1.32.0 (9fda7c223 2019-01-16)`)
- `cargo` (tested on `cargo 1.32.0 (8610973aa 2019-01-02)`)
- `android_ndk` (tested on `r13b`)
- `android_ndk` (tested on `r19`)
- `Android Studio` (only for Android, tested on `Version 3.3`)
- `Xcode` (only for iOS, tested on `Version 9.4.1 (9F2000)`)
- `$NDK_HOME` envarionment variable set to ndk home directory (eg. `/usr/local/opt/android-ndk`)
- `$JAVA_HOME` envarionment variable set to java home directory (eg. `/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home`)
- `$ANDROID_HOME` environment variable set to Android SDK directory (eg. `/home/your_username/Android/Sdk`)*.
\* It's recommended to install **Android Studio** and use that to install the necessary build tools and SDKs for the Android version you want to test on. It's also the best way to test in the emulator. **DO NOT INSTALL NDK VIA ANDROID STUDIO** as that will install the latest version instead of `r13b`.
\* It's recommended to install **Android Studio** and use that to install the necessary build tools and SDKs for the Android version you want to test on. It's also the best way to test in the emulator. **DO NOT INSTALL NDK VIA ANDROID STUDIO** as that will install the latest version. Make sure to get `r19` instead.
### Setup
......@@ -124,3 +124,11 @@ adb shell input keyevent 82
(You can find `adb` binary in your local Android SDK folder under `platform-tools`, eg. `/home/your_username/Android/Sdk/platform-tools`)
This should open a menu on the device. In that menu go to `Dev Settings` > `Debug server host & port for device`, and enter your local IP address with port 8081 (eg. `192.168.1.42:8081`). Restart the app, the error should disappear.
#### Upgrading NDK from `r13b` to `r19`
1. [Download NDK `r19`](https://developer.android.com/ndk/downloads/), unpack it in a convenient location.
1. Update your `NDK_HOME` env variable to the absolute path of the NDK directory.
1. Edit `./android/local.properties` so that `ndk.dir` points to the absolute path to the NDK directory.
1. Remove old NDK build with `rm -rf ./NDK`.
1. Build the new NDK with `./create-ndk-standalone.sh`.
......@@ -44,11 +44,6 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
promise.resolve(ethkeyBrainwalletAddress(seed));
}
@ReactMethod
public void brainWalletSecret(String seed, Promise promise) {
promise.resolve(ethkeyBrainwalletSecret(seed));
}
@ReactMethod
public void brainWalletSign(String seed, String message, Promise promise) {
promise.resolve(ethkeyBrainwalletSign(seed, message));
......@@ -80,8 +75,8 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
}
@ReactMethod
public void randomPhrase(int words, Promise promise) {
promise.resolve(ethkeyRandomPhrase(words));
public void randomPhrase(Promise promise) {
promise.resolve(ethkeyRandomPhrase());
}
@ReactMethod
......@@ -99,13 +94,12 @@ public class EthkeyBridge extends ReactContextBaseJavaModule {
}
private static native String ethkeyBrainwalletAddress(String seed);
private static native String ethkeyBrainwalletSecret(String seed);
private static native String ethkeyBrainwalletSign(String seed, String message);
private static native String ethkeyRlpItem(String data, int position);
private static native String ethkeyKeccak(String data);
private static native String ethkeyEthSign(String data);
private static native String ethkeyBlockiesIcon(String seed);
private static native String ethkeyRandomPhrase(int words);
private static native String ethkeyRandomPhrase();
private static native String ethkeyEncryptData(String data, String password);
private static native String ethkeyDecryptData(String data, String password);
}
......@@ -21,7 +21,7 @@ class EthkeyBridge: NSObject {
ethkey_keypair_destroy(keypair_ptr)
resolve(address)
}
@objc func brainWalletSecret(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var seed_ptr = seed.asPtr()
let keypair_ptr = ethkey_keypair_brainwallet(&seed_ptr)
......@@ -33,7 +33,7 @@ class EthkeyBridge: NSObject {
ethkey_keypair_destroy(keypair_ptr)
resolve(secret)
}
@objc func brainWalletSign(_ seed: String, message: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
print(seed, " + ", message)
var seed_ptr = seed.asPtr()
......@@ -47,7 +47,7 @@ class EthkeyBridge: NSObject {
ethkey_keypair_destroy(keypair_ptr)
resolve(signature)
}
@objc func rlpItem(_ rlp: String, position: UInt32, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var rlp_ptr = rlp.asPtr()
var error: UInt32 = 0
......@@ -62,7 +62,7 @@ class EthkeyBridge: NSObject {
reject("invalid rlp", nil, nil)
}
}
@objc func keccak(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
let hash_rust_str = keccak256(&data_ptr)
......@@ -72,7 +72,7 @@ class EthkeyBridge: NSObject {
rust_string_destroy(hash_rust_str)
resolve(hash)
}
@objc func ethSign(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
let hash_rust_str = eth_sign(&data_ptr)
......@@ -82,7 +82,7 @@ class EthkeyBridge: NSObject {
rust_string_destroy(hash_rust_str)
resolve(hash)
}
@objc func blockiesIcon(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var seed_ptr = seed.asPtr()
let icon_rust_str = blockies_icon(&seed_ptr)
......@@ -92,16 +92,16 @@ class EthkeyBridge: NSObject {
rust_string_destroy(icon_rust_str)
resolve(icon)
}
@objc func randomPhrase(_ words: UInt32, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
let words_rust_str = random_phrase(words)
@objc func randomPhrase(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
let words_rust_str = random_phrase()
let words_rust_str_ptr = rust_string_ptr(words_rust_str)
let words = String.fromStringPtr(ptr: words_rust_str_ptr!.pointee)
rust_string_ptr_destroy(words_rust_str_ptr)
rust_string_destroy(words_rust_str)
resolve(words)
}
@objc func encryptData(_ data: String, password: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
var password_ptr = password.asPtr()
......@@ -112,7 +112,7 @@ class EthkeyBridge: NSObject {
rust_string_destroy(encrypted_data_rust_str)
resolve(encrypted_data)
}
@objc func decryptData(_ data: String, password: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
var password_ptr = password.asPtr()
......
......@@ -10,11 +10,11 @@ import Foundation
@objc(EthkeyBridge)
class EthkeyBridge: NSObject {
open static func requiresMainQueueSetup() -> Bool {
return true;
}
@objc func brainWalletAddress(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var seed_ptr = seed.asPtr()
let keypair_ptr = ethkey_keypair_brainwallet(&seed_ptr)
......@@ -26,19 +26,7 @@ class EthkeyBridge: NSObject {
ethkey_keypair_destroy(keypair_ptr)
resolve(address)
}
@objc func brainWalletSecret(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var seed_ptr = seed.asPtr()
let keypair_ptr = ethkey_keypair_brainwallet(&seed_ptr)
let secret_rust_str = ethkey_keypair_secret(keypair_ptr)
let secret_rust_str_ptr = rust_string_ptr(secret_rust_str)
let secret = String.fromStringPtr(ptr: secret_rust_str_ptr!.pointee)
rust_string_ptr_destroy(secret_rust_str_ptr)
rust_string_destroy(secret_rust_str)
ethkey_keypair_destroy(keypair_ptr)
resolve(secret)
}
@objc func brainWalletSign(_ seed: String, message: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
print(seed, " + ", message)
var seed_ptr = seed.asPtr()
......@@ -52,7 +40,7 @@ class EthkeyBridge: NSObject {
ethkey_keypair_destroy(keypair_ptr)
resolve(signature)
}
@objc func rlpItem(_ rlp: String, position: UInt32, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var rlp_ptr = rlp.asPtr()
var error: UInt32 = 0
......@@ -67,7 +55,7 @@ class EthkeyBridge: NSObject {
reject("invalid rlp", nil, nil)
}
}
@objc func keccak(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
let hash_rust_str = keccak256(&data_ptr)
......@@ -77,7 +65,7 @@ class EthkeyBridge: NSObject {
rust_string_destroy(hash_rust_str)
resolve(hash)
}
@objc func ethSign(_ data: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
let hash_rust_str = eth_sign(&data_ptr)
......@@ -87,7 +75,7 @@ class EthkeyBridge: NSObject {
rust_string_destroy(hash_rust_str)
resolve(hash)
}
@objc func blockiesIcon(_ seed: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var seed_ptr = seed.asPtr()
let icon_rust_str = blockies_icon(&seed_ptr)
......@@ -97,16 +85,16 @@ class EthkeyBridge: NSObject {
rust_string_destroy(icon_rust_str)
resolve(icon)
}
@objc func randomPhrase(_ words: UInt32, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
let words_rust_str = random_phrase(words)
@objc func randomPhrase(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
let words_rust_str = random_phrase()
let words_rust_str_ptr = rust_string_ptr(words_rust_str)
let words = String.fromStringPtr(ptr: words_rust_str_ptr!.pointee)
rust_string_ptr_destroy(words_rust_str_ptr)
rust_string_destroy(words_rust_str)
resolve(words)
}
@objc func encryptData(_ data: String, password: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
var password_ptr = password.asPtr()
......@@ -117,7 +105,7 @@ class EthkeyBridge: NSObject {
rust_string_destroy(encrypted_data_rust_str)
resolve(encrypted_data)
}
@objc func decryptData(_ data: String, password: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
var data_ptr = data.asPtr()
var password_ptr = password.asPtr()
......
This diff is collapsed.
......@@ -3,17 +3,23 @@ name = "signer"
version = "0.1.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
build = "build.rs"
edition = "2018"
[dependencies]
base64 = "0.10.1"
blockies = "0.2"
ethsign = { version = "0.6.1", default-features = false, features = ["pure-rust"] }
jni = { version = "0.10.2", default-features = false, optional = true }
libc = "0.2"
rustc-serialize = "0.3"
ethkey = { git = "https://github.com/paritytech/parity-ethereum" }
ethstore = { git = "https://github.com/paritytech/parity-ethereum" }
rlp = { version = "0.3.0", features = ["ethereum"] }
tiny-keccak = "1.1"
blockies = "0.2"
parity-wordlist = { git = "https://github.com/paritytech/wordlist" }
jni = { git = "https://github.com/prevoty/jni-rs", default-features = false, optional = true }
rustc-hex = "2.0.1"
schnorrkel = "0.0.0"
serde = "1.0"
serde_json = "1.0"
sha2 = "0.8"
tiny-bip39 = { version = "0.6.1", default-features = false }
tiny-hderive = "0.1"
tiny-keccak = "1.4"
[lib]
name = "signer"
......@@ -21,7 +27,3 @@ crate-type = ["staticlib", "cdylib"]
[features]
default = ["jni"]
# https://github.com/DaGenix/rust-crypto/issues/383
[replace]
"rust-crypto:0.2.36" = { git = "https://github.com/debris/rust-crypto" }
NDK_STANDALONE = $(shell pwd)/../../NDK
ARCHS_IOS = armv7-apple-ios armv7s-apple-ios aarch64-apple-ios
ARCHS_IOS = i386-apple-ios x86_64-apple-ios armv7-apple-ios armv7s-apple-ios aarch64-apple-ios
ARCHS_ANDROID = aarch64-linux-android armv7-linux-androideabi i686-linux-android
LIB=libsigner.a
......
......@@ -49,9 +49,6 @@ void ethkey_keypair_destroy(struct keypair_ptr* keypair);
// creates new brainwallet keypair from seed
struct keypair_ptr* ethkey_keypair_brainwallet(const struct rust_string_ptr* seed);
// returns keypair secret
struct rust_string* ethkey_keypair_secret(const struct keypair_ptr* keypair);
// return keypair address
struct rust_string* ethkey_keypair_address(const struct keypair_ptr* keypair);
......@@ -75,7 +72,7 @@ struct rust_string* blockies_icon(const struct rust_string_ptr* blockies_seed);
// random phrase ffi
struct rust_string* random_phrase(const uint32_t words);
struct rust_string* random_phrase();
// data encryption ffi
......
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Ethereum key utils
use bip39::{Mnemonic, Seed, Language};
use ethsign::{SecretKey, PublicKey, Error};
use tiny_hderive::bip32::ExtendedPrivKey;
use tiny_keccak::keccak256;
pub struct KeyPair {
secret: SecretKey,
public: PublicKey,
}
impl KeyPair {
pub fn from_secret(secret: SecretKey) -> KeyPair {
let public = secret.public();
KeyPair {
secret,
public,
}
}
pub fn from_parity_phrase(phrase: &str) -> KeyPair {
let mut secret = keccak256(phrase.as_bytes());
let mut i = 0;
loop {
secret = keccak256(&secret);
match i > 16384 {
false => i += 1,
true => {
if let Ok(pair) = SecretKey::from_raw(&secret).map(KeyPair::from_secret) {
if pair.public().address()[0] == 0 {
return pair
}
}
},
}
}
}
pub fn from_bip39_phrase(phrase: &str) -> Option<KeyPair> {
let mnemonic = Mnemonic::from_phrase(phrase, Language::English).ok()?;
let seed = Seed::new(&mnemonic, "");
let epriv = ExtendedPrivKey::derive(seed.as_bytes(), "m/44'/60'/0'/0/0").ok()?;
SecretKey::from_raw(&epriv.secret()).map(KeyPair::from_secret).ok()
}
pub fn from_auto_phrase(phrase: &str) -> KeyPair {
Self::from_bip39_phrase(phrase)
.unwrap_or_else(|| Self::from_parity_phrase(phrase))
}
pub fn secret(&self) -> &SecretKey {
&self.secret
}
pub fn public(&self) -> &PublicKey {
&self.public
}
pub fn address(&self) -> &[u8; 20] {
self.public().address()
}
pub fn sign(&self, message: &[u8]) -> Result<[u8; 65], Error> {
let signature = self.secret().sign(message)?;
let mut data: [u8; 65] = [0; 65];
data[0..32].copy_from_slice(&signature.r);
data[32..64].copy_from_slice(&signature.s);
data[64] = signature.v;
Ok(data)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bip39_phrase() {
let phrase = "panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside";
let expected_address = b"\x63\xF9\xA9\x2D\x8D\x61\xb4\x8a\x9f\xFF\x8d\x58\x08\x04\x25\xA3\x01\x2d\x05\xC8";
let keypair = KeyPair::from_bip39_phrase(phrase).unwrap();
assert_eq!(keypair.address(), expected_address);
}
#[test]
fn test_parity_phrase() {
let phrase = "this is sparta";
let expected_address = b"\x00\x6E\x27\xB6\xA7\x2E\x1f\x34\xC6\x26\x76\x2F\x3C\x47\x61\x54\x7A\xff\x14\x21";
let keypair = KeyPair::from_parity_phrase(phrase);
assert_eq!(keypair.address(), expected_address);
}
#[test]
fn test_parity_empty_phrase() {
let phrase = "";
let expected_address = b"\x00\xa3\x29\xc0\x64\x87\x69\xA7\x3a\xfA\xc7\xF9\x38\x1E\x08\xFB\x43\xdB\xEA\x72";
let keypair = KeyPair::from_parity_phrase(phrase);
assert_eq!(keypair.address(), expected_address);
}
#[test]
fn test_auto_bip39_phrase() {
let phrase = "panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside";
let expected_address = b"\x63\xF9\xA9\x2D\x8D\x61\xb4\x8a\x9f\xFF\x8d\x58\x08\x04\x25\xA3\x01\x2d\x05\xC8";
let keypair = KeyPair::from_auto_phrase(phrase);
assert_eq!(keypair.address(), expected_address);
}
#[test]
fn test_auto_parity_phrase() {
let phrase = "this is sparta";
let expected_address = b"\x00\x6E\x27\xB6\xA7\x2E\x1f\x34\xC6\x26\x76\x2F\x3C\x47\x61\x54\x7A\xff\x14\x21";
let keypair = KeyPair::from_auto_phrase(phrase);
assert_eq!(keypair.address(), expected_address);
}
}
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
......@@ -14,26 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate libc;
extern crate rustc_serialize;
extern crate tiny_keccak;
extern crate parity_wordlist as wordlist;
extern crate ethkey;
extern crate ethstore;
extern crate rlp;
extern crate blockies;
mod eth;
mod util;
mod string;
use util::StringPtr;
use eth::KeyPair;
use rustc_serialize::hex::{ToHex, FromHex};
use rustc_serialize::base64::{self, ToBase64};
use tiny_keccak::Keccak;
use ethkey::{KeyPair, Generator, Brain, Message, Password, sign};
use ethstore::Crypto;
use rlp::decode_list;
use blockies::{Blockies, create_icon, ethereum};
use ethsign::{Protected, keyfile::Crypto};
use rlp::decode_list;
use rustc_hex::{ToHex, FromHex};
use tiny_keccak::Keccak;
use tiny_keccak::keccak256 as keccak;
use std::num::NonZeroU32;
use string::StringPtr;
// 10240 is always non-zero, ergo this is safe
const CRYPTO_ITERATIONS: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(10240) };
fn blockies_icon_in_base64(seed: Vec<u8>) -> String {
let mut result = Vec::new();
......@@ -47,12 +44,8 @@ fn blockies_icon_in_base64(seed: Vec<u8>) -> String {
};
create_icon(&mut result, Blockies::Ethereum(options)).unwrap();
result.to_base64(base64::Config {
char_set: base64::CharacterSet::Standard,
newline: base64::Newline::LF,
pad: true,
line_length: None,
})
base64::encode(&result)
}
// string ffi
......@@ -81,32 +74,26 @@ pub unsafe extern fn ethkey_keypair_destroy(keypair: *mut KeyPair) {
#[no_mangle]
pub unsafe extern fn ethkey_keypair_brainwallet(seed: *mut StringPtr) -> *mut KeyPair {
let mut generator = Brain::new((*seed).as_str().to_owned());
Box::into_raw(Box::new(generator.generate().unwrap()))
}
#[no_mangle]
pub unsafe extern fn ethkey_keypair_secret(keypair: *mut KeyPair) -> *mut String {
let secret = format!("{:?}", (*keypair).secret());
Box::into_raw(Box::new(secret))
let keypair = KeyPair::from_auto_phrase(&**seed);
Box::into_raw(Box::new(keypair))
}
#[no_mangle]
pub unsafe extern fn ethkey_keypair_address(keypair: *mut KeyPair) -> *mut String {
let address = format!("{:?}", (*keypair).address());
let address: String = (*keypair).address().to_hex();
Box::into_raw(Box::new(address))
}
#[no_mangle]
pub unsafe extern fn ethkey_keypair_sign(keypair: *mut KeyPair, message: *mut StringPtr) -> *mut String {
let secret = (*keypair).secret();
let message: Message = (*message).as_str().parse().unwrap();
let signature = format!("{}", sign(secret, &message).unwrap());
let keypair = &*keypair;
let message: Vec<u8> = (*message).as_str().from_hex().unwrap();
let signature = keypair.sign(&message).unwrap().to_hex();
Box::into_raw(Box::new(signature))
}
fn safe_rlp_item(rlp: &str, position: u32) -> Result<String, String> {
let hex = rlp.from_hex().map_err(| e | e.to_string())?;
let hex: Vec<u8> = rlp.from_hex().map_err(| e | e.to_string())?;
let rlp = decode_list::<Vec<u8>>(&hex);
let data = rlp.get(position as usize).ok_or_else(|| "Invalid RLP position".to_string())?;
Ok(data.to_hex())
......@@ -126,19 +113,15 @@ pub unsafe extern fn rlp_item(rlp: *mut StringPtr, position: u32, error: *mut u3
#[no_mangle]
pub unsafe extern fn keccak256(data: *mut StringPtr) -> *mut String {
let data = (*data).as_str();
let hex = data.from_hex().unwrap();
let mut res: [u8; 32] = [0; 32];
let mut keccak = Keccak::new_keccak256();
keccak.update(&hex);
keccak.finalize(&mut res);
let data: Vec<u8> = (*data).as_str().from_hex().unwrap();
let res = keccak(&data);
Box::into_raw(Box::new(res.to_hex()))
}
#[no_mangle]
pub unsafe extern fn eth_sign(data: *mut StringPtr) -> *mut String {
let data = (*data).as_str();
let hex = data.from_hex().unwrap();
let hex: Vec<u8> = data.from_hex().unwrap();
let message = format!("\x19Ethereum Signed Message:\n{}", hex.len()).into_bytes();
let mut res: [u8; 32] = [0; 32];
let mut keccak = Keccak::new_keccak256();
......@@ -159,9 +142,10 @@ pub unsafe extern fn blockies_icon(blockies_seed: *mut StringPtr) -> *mut String
// random phrase ffi
#[no_mangle]
pub unsafe extern fn random_phrase(words: u32) -> *mut String {
let words = wordlist::random_phrase(words as usize);
Box::into_raw(Box::new(words))
pub unsafe extern fn random_phrase() -> *mut String {
use bip39::{Mnemonic, MnemonicType, Language};
let mnemonic = Mnemonic::new(MnemonicType::Words24, Language::English);
Box::into_raw(Box::new(mnemonic.into_phrase()))
}
// data encryption ffi
......@@ -169,22 +153,24 @@ pub unsafe extern fn random_phrase(words: u32) -> *mut String {
#[no_mangle]
pub unsafe extern fn encrypt_data(data: *mut StringPtr, password: *mut StringPtr) -> *mut String {
let data = (*data).as_str();