-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wallet-core: Add basic setup with keys generation
- Loading branch information
Showing
5 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[package] | ||
name = "wallet-core" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
dusk-bytes = "0.1" | ||
bytecheck = { version = "0.6", default-features = false } | ||
execution-core = { version = "0.1", path = "../execution-core/" } | ||
zeroize = { version = "1", default-features = false, features = ["derive"] } | ||
rand_chacha = { version = "0.3", default-features = false } | ||
sha2 = { version = "0.10", default-features = false } | ||
|
||
[dev-dependencies] | ||
|
||
[features] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
all: ## Build the ABI | ||
cargo build | ||
|
||
help: ## Display this help screen | ||
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' | ||
|
||
test: | ||
cargo test --release | ||
|
||
clippy: ## Run clippy | ||
@cargo clippy --release -- -D warnings | ||
@cargo clippy --no-default-features --release -- -D warnings | ||
|
||
doc: ## Run doc gen | ||
@cargo doc --release | ||
|
||
.PHONY: all help test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
//! Utilities to derive keys from the seed. | ||
use rand_chacha::{rand_core::SeedableRng, ChaCha12Rng}; | ||
use sha2::{Digest, Sha256}; | ||
|
||
use execution_core::{ | ||
signatures::bls::SecretKey as BlsSecretKey, | ||
transfer::phoenix::{ | ||
PublicKey as PhoenixPublicKey, SecretKey as PhoenixSecretKey, | ||
ViewKey as PhoenixViewKey, | ||
}, | ||
}; | ||
use zeroize::Zeroize; | ||
|
||
use crate::RNG_SEED; | ||
|
||
/// Generates a [`BlsSecretKey`] from a seed and index that can be used for | ||
/// staking. | ||
/// | ||
/// The randomness is generated using [`rng_with_index`]. | ||
#[must_use] | ||
pub fn derive_stake_sk(seed: &[u8; RNG_SEED], index: u64) -> BlsSecretKey { | ||
// note that if we change the string used for the rng, all previously | ||
// generated keys will become invalid | ||
BlsSecretKey::random(&mut rng_with_index(seed, index, b"SK")) | ||
} | ||
|
||
/// Generates a [`PhoenixSecretKey`] from a seed and index. | ||
/// | ||
/// The randomness is generated using [`rng_with_index`]. | ||
#[must_use] | ||
pub fn derive_phoenix_sk( | ||
seed: &[u8; RNG_SEED], | ||
index: u64, | ||
) -> PhoenixSecretKey { | ||
// note that if we change the string used for the rng, all previously | ||
// generated keys will become invalid | ||
PhoenixSecretKey::random(&mut rng_with_index(seed, index, b"SSK")) | ||
} | ||
|
||
/// Generates a [`PheonixPublicKey`] from its seed and index. | ||
/// | ||
/// First the [`PhoenixSecretKey`] is derived with [`derive_phoenix_sk`], then | ||
/// the public key is generated from it and the secret key is erased from | ||
/// memory. | ||
#[must_use] | ||
pub fn derive_phoenix_pk( | ||
seed: &[u8; RNG_SEED], | ||
index: u64, | ||
) -> PhoenixPublicKey { | ||
let mut sk = derive_phoenix_sk(seed, index); | ||
let pk = PhoenixPublicKey::from(&sk); | ||
sk.zeroize(); | ||
|
||
pk | ||
} | ||
|
||
/// Generates a [`PhoenixViewKey`] from its seed and index. | ||
/// | ||
/// First the [`PhoenixSecretKey`] is derived with [`derive_phoenix_sk`], then | ||
/// the view key is generated from it and the secret key is erased from memory. | ||
#[must_use] | ||
pub fn derive_phoenix_vk(seed: &[u8; RNG_SEED], index: u64) -> PhoenixViewKey { | ||
let mut sk = derive_phoenix_sk(seed, index); | ||
let vk = PhoenixViewKey::from(&sk); | ||
sk.zeroize(); | ||
|
||
vk | ||
} | ||
|
||
/// Creates a secure RNG from a seed with embedded index and termination | ||
/// constant. | ||
/// | ||
/// First the `seed` and then the little-endian representation of the key's | ||
/// `index` are passed through SHA-256. A constant is then mixed in and the | ||
/// resulting hash is then used to seed a `ChaCha12` CSPRNG, which is | ||
/// subsequently used to generate the key. | ||
#[must_use] | ||
pub fn rng_with_index( | ||
seed: &[u8; RNG_SEED], | ||
index: u64, | ||
termination: &[u8], | ||
) -> ChaCha12Rng { | ||
let mut hash = Sha256::new(); | ||
|
||
hash.update(seed); | ||
hash.update(index.to_le_bytes()); | ||
hash.update(termination); | ||
|
||
let hash = hash.finalize().into(); | ||
ChaCha12Rng::from_seed(hash) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
//! Types used for interacting with Dusk's transfer and stake contracts. | ||
#![no_std] | ||
#![deny(missing_docs)] | ||
#![deny(rustdoc::broken_intra_doc_links)] | ||
#![deny(clippy::pedantic)] | ||
|
||
pub mod keys; | ||
|
||
/// Length of the seed of the generated rng. | ||
pub const RNG_SEED: usize = 64; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// This Source Code Form is subject to the terms of the Mozilla Public | ||
// License, v. 2.0. If a copy of the MPL was not distributed with this | ||
// file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// | ||
// Copyright (c) DUSK NETWORK. All rights reserved. | ||
|
||
use dusk_bytes::Serializable; | ||
use wallet_core::keys::{ | ||
derive_phoenix_pk, derive_phoenix_sk, derive_phoenix_vk, derive_stake_sk, | ||
}; | ||
|
||
const SEED: [u8; 64] = [0; 64]; | ||
const INDEX: u64 = 42; | ||
|
||
#[test] | ||
fn test_derive_phoenix_sk() { | ||
// it is important that we always derive the same key from a fixed seed | ||
let sk_bytes = [ | ||
12, 16, 72, 188, 33, 76, 44, 178, 86, 123, 107, 153, 230, 149, 238, | ||
131, 87, 30, 94, 88, 52, 129, 247, 167, 30, 167, 163, 246, 68, 254, 14, | ||
9, 218, 135, 245, 104, 11, 190, 143, 129, 83, 202, 64, 179, 157, 248, | ||
175, 120, 157, 220, 98, 211, 141, 50, 224, 8, 1, 125, 29, 180, 206, | ||
195, 34, 0, | ||
]; | ||
assert_eq!(derive_phoenix_sk(&SEED, INDEX).to_bytes(), sk_bytes); | ||
} | ||
|
||
#[test] | ||
fn test_derive_phoenix_pk() { | ||
// it is important that we always derive the same key from a fixed seed | ||
let pk_bytes = [ | ||
51, 204, 45, 112, 212, 44, 118, 183, 148, 176, 254, 135, 253, 117, 230, | ||
62, 177, 139, 2, 57, 21, 150, 41, 86, 118, 239, 75, 194, 148, 129, 225, | ||
38, 132, 140, 106, 77, 181, 217, 196, 50, 135, 177, 158, 153, 43, 147, | ||
159, 217, 0, 160, 89, 95, 67, 160, 42, 74, 19, 1, 221, 216, 126, 204, | ||
206, 209, | ||
]; | ||
assert_eq!(derive_phoenix_pk(&SEED, INDEX).to_bytes(), pk_bytes); | ||
} | ||
|
||
#[test] | ||
fn test_derive_phoenix_vk() { | ||
// it is important that we always derive the same key from a fixed seed | ||
let vk_bytes = [ | ||
12, 16, 72, 188, 33, 76, 44, 178, 86, 123, 107, 153, 230, 149, 238, | ||
131, 87, 30, 94, 88, 52, 129, 247, 167, 30, 167, 163, 246, 68, 254, 14, | ||
9, 132, 140, 106, 77, 181, 217, 196, 50, 135, 177, 158, 153, 43, 147, | ||
159, 217, 0, 160, 89, 95, 67, 160, 42, 74, 19, 1, 221, 216, 126, 204, | ||
206, 209, | ||
]; | ||
assert_eq!(derive_phoenix_vk(&SEED, INDEX).to_bytes(), vk_bytes); | ||
} | ||
|
||
#[test] | ||
fn test_derive_stake_sk() { | ||
// it is important that we always derive the same key from a fixed seed | ||
let sk_bytes = [ | ||
95, 35, 167, 191, 106, 171, 71, 158, 159, 39, 84, 1, 132, 238, 152, | ||
235, 154, 5, 250, 158, 255, 195, 79, 95, 193, 58, 36, 189, 0, 99, 230, | ||
86, | ||
]; | ||
assert_eq!(derive_stake_sk(&SEED, INDEX).to_bytes(), sk_bytes); | ||
} |