forked from MystenLabs/sui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crypto: sui-keys crate for keystore and key derivation (MystenLabs#5363)
- Loading branch information
Showing
39 changed files
with
287 additions
and
160 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
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
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
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
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
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
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
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
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
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,26 @@ | ||
[package] | ||
name = "sui-keys" | ||
version = "0.0.0" | ||
authors = ["Mysten Labs <build@mystenlabs.com>"] | ||
license = "Apache-2.0" | ||
publish = false | ||
edition = "2021" | ||
|
||
[dependencies] | ||
anyhow = "1.0.64" | ||
serde = { version = "1.0.144", features = ["derive"] } | ||
serde_json = "1.0.83" | ||
signature = "1.6.0" | ||
rand = "0.8.5" | ||
tiny-bip39 = "1.0.0" | ||
bip32 = "0.4.0" | ||
slip10_ed25519 = "0.1.3" | ||
fastcrypto = { workspace = true, features = ["copy_key"] } | ||
|
||
sui-types = { path = "../sui-types" } | ||
|
||
workspace-hack.workspace = true | ||
|
||
[dev-dependencies] | ||
tempfile = "3.3.0" | ||
sha3 = "0.10.4" |
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,120 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use bip32::{ChildNumber, DerivationPath, XPrv}; | ||
use fastcrypto::ed25519::Ed25519KeyPair; | ||
use fastcrypto::{ | ||
ed25519::Ed25519PrivateKey, | ||
secp256k1::{Secp256k1KeyPair, Secp256k1PrivateKey}, | ||
traits::{KeyPair, ToFromBytes}, | ||
}; | ||
use slip10_ed25519::derive_ed25519_private_key; | ||
use sui_types::{ | ||
base_types::SuiAddress, | ||
crypto::{SignatureScheme, SuiKeyPair}, | ||
error::SuiError, | ||
}; | ||
|
||
pub const DERIVATION_PATH_COIN_TYPE: u32 = 784; | ||
pub const DERVIATION_PATH_PURPOSE_ED25519: u32 = 44; | ||
pub const DERVIATION_PATH_PURPOSE_SECP256K1: u32 = 54; | ||
|
||
/// Ed25519 follows SLIP-0010 using hardened path: m/44'/784'/0'/0'/{index}' | ||
/// Secp256k1 follows BIP-32 using path where the first 3 levels are hardened: m/54'/784'/0'/0/{index} | ||
/// Note that the purpose for Secp256k1 is registered as 54, to differentiate from Ed25519 with purpose 44. | ||
pub fn derive_key_pair_from_path( | ||
seed: &[u8], | ||
derivation_path: Option<DerivationPath>, | ||
key_scheme: &SignatureScheme, | ||
) -> Result<(SuiAddress, SuiKeyPair), SuiError> { | ||
let path = validate_path(key_scheme, derivation_path)?; | ||
match key_scheme { | ||
SignatureScheme::ED25519 => { | ||
let indexes = path.into_iter().map(|i| i.into()).collect::<Vec<_>>(); | ||
let derived = derive_ed25519_private_key(seed, &indexes); | ||
let sk = Ed25519PrivateKey::from_bytes(&derived) | ||
.map_err(|e| SuiError::SignatureKeyGenError(e.to_string()))?; | ||
let kp = Ed25519KeyPair::from(sk); | ||
Ok((kp.public().into(), SuiKeyPair::Ed25519SuiKeyPair(kp))) | ||
} | ||
SignatureScheme::Secp256k1 => { | ||
let child_xprv = XPrv::derive_from_path(seed, &path) | ||
.map_err(|e| SuiError::SignatureKeyGenError(e.to_string()))?; | ||
let kp = Secp256k1KeyPair::from( | ||
Secp256k1PrivateKey::from_bytes(child_xprv.private_key().to_bytes().as_slice()) | ||
.unwrap(), | ||
); | ||
Ok((kp.public().into(), SuiKeyPair::Secp256k1SuiKeyPair(kp))) | ||
} | ||
SignatureScheme::BLS12381 => Err(SuiError::UnsupportedFeatureError { | ||
error: "BLS is not supported for user key derivation".to_string(), | ||
}), | ||
} | ||
} | ||
|
||
pub fn validate_path( | ||
key_scheme: &SignatureScheme, | ||
path: Option<DerivationPath>, | ||
) -> Result<DerivationPath, SuiError> { | ||
match key_scheme { | ||
SignatureScheme::ED25519 => { | ||
match path { | ||
Some(p) => { | ||
// The derivation path must be hardened at all levels with purpose = 44, coin_type = 784 | ||
if let &[purpose, coin_type, account, change, address] = p.as_ref() { | ||
if purpose | ||
== ChildNumber::new(DERVIATION_PATH_PURPOSE_ED25519, true).unwrap() | ||
&& coin_type | ||
== ChildNumber::new(DERIVATION_PATH_COIN_TYPE, true).unwrap() | ||
&& account.is_hardened() | ||
&& change.is_hardened() | ||
&& address.is_hardened() | ||
{ | ||
Ok(p) | ||
} else { | ||
Err(SuiError::SignatureKeyGenError("Invalid path".to_string())) | ||
} | ||
} else { | ||
Err(SuiError::SignatureKeyGenError("Invalid path".to_string())) | ||
} | ||
} | ||
None => Ok(format!( | ||
"m/{DERVIATION_PATH_PURPOSE_ED25519}'/{DERIVATION_PATH_COIN_TYPE}'/0'/0'/0'" | ||
) | ||
.parse() | ||
.unwrap()), | ||
} | ||
} | ||
SignatureScheme::Secp256k1 => { | ||
match path { | ||
Some(p) => { | ||
// The derivation path must be hardened at first 3 levels with purpose = 54, coin_type = 784 | ||
if let &[purpose, coin_type, account, change, address] = p.as_ref() { | ||
if purpose | ||
== ChildNumber::new(DERVIATION_PATH_PURPOSE_SECP256K1, true).unwrap() | ||
&& coin_type | ||
== ChildNumber::new(DERIVATION_PATH_COIN_TYPE, true).unwrap() | ||
&& account.is_hardened() | ||
&& !change.is_hardened() | ||
&& !address.is_hardened() | ||
{ | ||
Ok(p) | ||
} else { | ||
Err(SuiError::SignatureKeyGenError("Invalid path".to_string())) | ||
} | ||
} else { | ||
Err(SuiError::SignatureKeyGenError("Invalid path".to_string())) | ||
} | ||
} | ||
None => Ok(format!( | ||
"m/{DERVIATION_PATH_PURPOSE_SECP256K1}'/{DERIVATION_PATH_COIN_TYPE}'/0'/0/0" | ||
) | ||
.parse() | ||
.unwrap()), | ||
} | ||
} | ||
SignatureScheme::BLS12381 => Err(SuiError::UnsupportedFeatureError { | ||
error: "BLS is not supported for user key derivation".to_string(), | ||
}), | ||
} | ||
} |
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
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,5 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
pub mod key_derive; | ||
pub mod keystore; |
Oops, something went wrong.