Skip to content

Commit

Permalink
Ethereum and Bitcoin key repository (#2454)
Browse files Browse the repository at this point in the history
* init eth and btc wallet

* fmt

---------

Co-authored-by: Kai <7630809+Kailai-Wang@users.noreply.github.com>
  • Loading branch information
kziemianek and Kailai-Wang committed Feb 1, 2024
1 parent 4276678 commit 81e8402
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 4 deletions.
1 change: 1 addition & 0 deletions bitacross-worker/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bitacross-worker/core-primitives/sgx/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ edition = "2021"
aes = { version = "0.6.0" }
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
derive_more = { version = "0.99.5" }
libsecp256k1 = { version = "0.7.1", default-features = false }
log = { version = "0.4", default-features = false }
ofb = { version = "0.4.0" }
serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true }
Expand Down
1 change: 1 addition & 0 deletions bitacross-worker/core-primitives/sgx/crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub mod ed25519_derivation;
pub mod error;
pub mod key_repository;
pub mod rsa3072;
pub mod secp256k1;
pub mod traits;

pub use self::{aes::*, ed25519::*, rsa3072::*};
Expand Down
168 changes: 168 additions & 0 deletions bitacross-worker/core-primitives/sgx/crypto/src/secp256k1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright 2020-2024 Trust Computing GmbH.
// This file is part of Litentry.
//
// Litentry 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.
//
// Litentry 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 Litentry. If not, see <https://www.gnu.org/licenses/>.
#[cfg(feature = "sgx")]
pub use sgx::*;

pub use libsecp256k1;

use libsecp256k1::{PublicKey, SecretKey};

/// File name of the sealed seed file.
pub const SEALED_SIGNER_SEED_FILE: &str = "secp256k1_key_sealed.bin";

#[derive(Clone, PartialEq)]
pub struct Pair {
pub public: PublicKey,
pub secret: SecretKey,
}

#[cfg(feature = "sgx")]
pub mod sgx {
use super::SEALED_SIGNER_SEED_FILE;
use crate::{
error::{Error, Result},
key_repository::KeyRepository,
secp256k1::Pair,
std::string::ToString,
};
use itp_sgx_io::{seal, unseal, SealedIO};
use libsecp256k1::{PublicKey, SecretKey};
use log::*;
use sgx_rand::{Rng, StdRng};
use std::{path::PathBuf, string::String};

/// Creates a repository for an secp256k1 keypair and initializes
/// a fresh private key if it doesn't exist at `path`.
pub fn create_secp256k1_repository(
path: PathBuf,
key_file_prefix: &str,
) -> Result<KeyRepository<Pair, Seal>> {
let seal = Seal::new(path, key_file_prefix.to_string());
Ok(KeyRepository::new(seal.init()?, seal.into()))
}

#[derive(Clone, Debug)]
pub struct Seal {
base_path: PathBuf,
key_file_prefix: String,
}

impl Seal {
pub fn new(base_path: PathBuf, key_file_prefix: String) -> Self {
Self { base_path, key_file_prefix }
}

pub fn path(&self) -> PathBuf {
self.base_path
.join(self.key_file_prefix.clone() + "_" + SEALED_SIGNER_SEED_FILE)
}
}

impl Seal {
fn unseal_pair(&self) -> Result<Pair> {
self.unseal()
}

fn exists(&self) -> bool {
self.path().exists()
}

fn init(&self) -> Result<Pair> {
if !self.exists() {
info!("Keyfile not found, creating new! {}", self.path().display());
let mut seed = [0u8; 32];
let mut rand = StdRng::new()?;
rand.fill_bytes(&mut seed);
seal(&seed, self.path())?;
}
self.unseal_pair()
}
}

impl SealedIO for Seal {
type Error = Error;
type Unsealed = Pair;

fn unseal(&self) -> Result<Self::Unsealed> {
let raw = unseal(self.path())?;

let secret = SecretKey::parse_slice(&raw)
.map_err(|e| Error::Other(format!("{:?}", e).into()))?;
let public = PublicKey::from_secret_key(&secret);

Ok(Pair { public, secret })
}

fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> {
let raw = unsealed.secret.serialize();
seal(&raw, self.path()).map_err(|e| e.into())
}
}
}

#[cfg(feature = "test")]
pub mod sgx_tests {
use super::sgx::*;
use crate::{key_repository::AccessKey, secp256k1::Pair, std::string::ToString, ToPubkey};
use itp_sgx_temp_dir::TempDir;
use std::path::{Path, PathBuf};

#[test]
pub fn creating_repository_with_same_path_and_prefix_results_in_same_key() {
let key_file_prefix = "test";
fn get_key_from_repo(path: PathBuf, prefix: &str) -> Pair {
create_secp256k1_repository(path, prefix).unwrap().retrieve_key().unwrap()
}
let temp_dir = TempDir::with_prefix(
"creating_repository_with_same_path_and_prefix_results_in_same_key",
)
.unwrap();
let temp_path = temp_dir.path().to_path_buf();
assert_eq!(
get_key_from_repo(temp_path.clone(), key_file_prefix),
get_key_from_repo(temp_path.clone(), key_file_prefix)
);
}

#[test]
pub fn seal_init_should_create_new_key_if_not_present() {
//given
let temp_dir =
TempDir::with_prefix("seal_init_should_create_new_key_if_not_present").unwrap();
let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string());
assert!(!seal.exists());

//when
seal.init().unwrap();

//then
assert!(seal.exists());
}

#[test]
pub fn seal_init_should_not_change_key_if_exists() {
//given
let temp_dir = TempDir::with_prefix("seal_init_should_not_change_key_if_exists").unwrap();
let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string());
let pair = seal.init().unwrap();

//when
let new_pair = seal.init().unwrap();

//then
assert!(pair, new_pair);
}
}
1 change: 1 addition & 0 deletions bitacross-worker/enclave-runtime/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions bitacross-worker/enclave-runtime/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

######## Worker Feature Settings ########
# Set sidechain as default feature mode
WORKER_MODE ?= sidechain
# Set offchain-worker as default feature mode
WORKER_MODE ?= offchain-worker

Rust_Enclave_Name := libenclave.a
Rust_Enclave_Files := $(wildcard src/*.rs) $(wildcard ../stf/src/*.rs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ use itp_node_api::{
metadata::{provider::NodeMetadataRepository, NodeMetadata},
};
use itp_nonce_cache::NonceCache;
use itp_sgx_crypto::{key_repository::KeyRepository, Aes, AesSeal, Ed25519Seal, Rsa3072Seal};
use itp_sgx_crypto::{
key_repository::KeyRepository,
secp256k1::{Pair as Secp256k1Pair, Seal as Secp256k1Seal},
Aes, AesSeal, Ed25519Seal, Rsa3072Seal,
};
use itp_stf_executor::{
enclave_signer::StfEnclaveSigner, executor::StfExecutor, getter_executor::GetterExecutor,
state_getter::StfStateGetter,
Expand Down Expand Up @@ -106,6 +110,8 @@ pub type EnclaveStf = Stf<EnclaveTrustedCallSigned, EnclaveGetter, StfState, Run
pub type EnclaveStateKeyRepository = KeyRepository<Aes, AesSeal>;
pub type EnclaveShieldingKeyRepository = KeyRepository<Rsa3072KeyPair, Rsa3072Seal>;
pub type EnclaveSigningKeyRepository = KeyRepository<ed25519::Pair, Ed25519Seal>;
pub type EnclaveBitcoinKeyRepository = KeyRepository<Secp256k1Pair, Secp256k1Seal>;
pub type EnclaveEthereumKeyRepository = KeyRepository<Secp256k1Pair, Secp256k1Seal>;
pub type EnclaveStateFileIo = SgxStateFileIo<EnclaveStateKeyRepository, StfState>;
pub type EnclaveStateSnapshotRepository = StateSnapshotRepository<EnclaveStateFileIo>;
pub type EnclaveStateObserver = StateObserver<StfState>;
Expand Down Expand Up @@ -381,6 +387,16 @@ pub static GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT: ComponentContainer<
EnclaveSigningKeyRepository,
> = ComponentContainer::new("Signing key repository");

/// Bitcoin key repository
pub static GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT: ComponentContainer<
EnclaveBitcoinKeyRepository,
> = ComponentContainer::new("Bitcoin key repository");

/// Ethereum key repository
pub static GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT: ComponentContainer<
EnclaveEthereumKeyRepository,
> = ComponentContainer::new("Ethereum key repository");

/// Light client db seal for the Integritee parentchain
pub static GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer<
EnclaveLightClientSeal,
Expand Down
16 changes: 15 additions & 1 deletion bitacross-worker/enclave-runtime/src/initialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ use crate::{
EnclaveStateHandler, EnclaveStateInitializer, EnclaveStateObserver,
EnclaveStateSnapshotRepository, EnclaveStfEnclaveSigner, EnclaveTopPool,
EnclaveTopPoolAuthor, DIRECT_RPC_REQUEST_SINK_COMPONENT,
GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT,
GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT,
GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT,
GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_OCALL_API_COMPONENT,
GLOBAL_RPC_WS_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT,
GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT,
Expand Down Expand Up @@ -70,6 +71,7 @@ use itp_settings::files::{
};
use itp_sgx_crypto::{
get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey,
secp256k1::create_secp256k1_repository,
};
use itp_stf_state_handler::{
file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState,
Expand Down Expand Up @@ -99,6 +101,18 @@ pub(crate) fn init_enclave(
let signer = signing_key_repository.retrieve_key()?;
info!("[Enclave initialized] Ed25519 prim raw : {:?}", signer.public().0);

let bitcoin_key_repository =
Arc::new(create_secp256k1_repository(base_dir.clone(), "bitcoin")?);
GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.initialize(bitcoin_key_repository.clone());
let bitcoin_key = bitcoin_key_repository.retrieve_key()?;
info!("[Enclave initialized] Bitcoin public key raw : {:?}", bitcoin_key.public.serialize());

let ethereum_key_repository =
Arc::new(create_secp256k1_repository(base_dir.clone(), "ethereum")?);
GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.initialize(ethereum_key_repository.clone());
let ethereum_key = ethereum_key_repository.retrieve_key()?;
info!("[Enclave initialized] Ethereum public key raw : {:?}", ethereum_key.public.serialize());

let shielding_key_repository = Arc::new(get_rsa3072_repository(base_dir.clone())?);
GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.initialize(shielding_key_repository.clone());

Expand Down

0 comments on commit 81e8402

Please sign in to comment.