SGX Support
This tutorial covers using the Intel SGX (Software Guard Extensions) features of the NeoRust SDK for secure blockchain operations.
Understanding Intel SGX
Intel SGX is a set of security-related instruction codes built into modern Intel CPUs. It allows user-level code to allocate private regions of memory, called enclaves, which are protected from processes running at higher privilege levels. Key benefits include:
- Hardware-Level Security: Protection of sensitive data and code from the operating system, hypervisor, BIOS, and other privileged software
- Secure Computation: Ability to perform computations on sensitive data within the enclave
- Remote Attestation: Verification that code is running in a genuine SGX enclave
- Sealing: Secure storage of sensitive data for later use within an enclave
Prerequisites
Before using the SGX features of NeoRust, you need:
-
Intel SGX-compatible hardware
- CPU with SGX support (check with
cpuidor Intel's processor list) - SGX enabled in BIOS/UEFI
- CPU with SGX support (check with
-
Intel SGX Software Stack
- Intel SGX Driver
- Intel SGX SDK v2.12
- Intel SGX PSW (Platform Software)
-
Rust Toolchain
- Rust nightly-2022-10-22 (required by the Apache Teaclave SGX SDK)
- Install with:
rustup install nightly-2022-10-22 - Set as default for this project:
rustup override set nightly-2022-10-22
For detailed installation instructions, see the SGX Setup Guide.
Enabling SGX Support in NeoRust
To enable SGX support in your project, add the sgx feature to your Cargo.toml:
[dependencies]
neo = { git = "https://github.com/R3E-Network/NeoRust", features = ["sgx"] }
You also need to uncomment the SGX dependencies in the NeoRust Cargo.toml:
# SGX dependencies
sgx_types = { version = "=1.1.1", optional = true }
sgx_urts = { version = "=1.1.1", optional = true }
sgx_tstd = { version = "=1.1.1", optional = true }
sgx_tcrypto = { version = "=1.1.1", optional = true }
[features]
sgx = ["sgx-deps"]
sgx-deps = [
"sgx_types",
"sgx_urts",
"sgx_tstd",
"sgx_tcrypto"
]
Building the SGX Components
Use the provided Makefile for SGX to build the enclave components:
make -f Makefile.sgx
This will build both the trusted enclave components and the untrusted application components.
Creating an SGX Enclave Manager
The first step in using SGX features is to create an enclave manager:
use neo::prelude::*; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; println!("SGX enclave initialized successfully!"); Ok(()) }
Secure Wallet Management with SGX
One of the primary use cases for SGX in blockchain applications is secure wallet management:
use neo::prelude::*; use std::path::Path; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; // Create a wallet with a password let password = "my-secure-password"; let wallet = enclave_manager.create_wallet(password)?; // Get the wallet's public key let public_key = wallet.get_public_key(); println!("Wallet public key: {:?}", public_key); // The private key never leaves the enclave Ok(()) }
Signing Transactions Securely
With SGX, you can sign transactions without exposing private keys:
use neo::prelude::*; use std::path::Path; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; // Create a wallet with a password let password = "my-secure-password"; let wallet = enclave_manager.create_wallet(password)?; // Connect to a Neo N3 TestNet node let provider = Provider::new_http("https://testnet1.neo.coz.io:443"); // Create a transaction let transaction = TransactionBuilder::new() .version(0) .nonce(rand::random::<u32>()) .valid_until_block(provider.get_block_count().await? + 100) .script( ScriptBuilder::new() .contract_call( "d2a4cff31913016155e38e474a2c06d08be276cf".parse::<ScriptHash>()?, "transfer", &[ ContractParameter::hash160(wallet.get_address().script_hash()), ContractParameter::hash160("NZNos2WqTbu5oCgyfss9kUJgBXJqhuYAaj".parse::<Address>()?), ContractParameter::integer(1_00000000), // 1 GAS ContractParameter::any(None), ], ) .to_array() ) .build(); // Sign the transaction securely within the enclave let signed_tx = wallet.sign_transaction(&transaction)?; // Send the transaction let txid = provider.send_raw_transaction(&signed_tx).await?; println!("Transaction sent with ID: {}", txid); Ok(()) }
Secure RPC Client
The SGX module also provides a secure RPC client for blockchain interactions:
use neo::prelude::*; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; // Create a secure RPC client let rpc_url = "https://testnet1.neo.coz.io:443"; let rpc_client = enclave_manager.create_rpc_client(rpc_url)?; // Use the secure RPC client let block_count = rpc_client.get_block_count().await?; println!("Current block height: {}", block_count); // The RPC client encrypts sensitive data and performs secure validation // of responses within the enclave Ok(()) }
Secure Storage
The SGX module provides secure storage for sensitive data:
use neo::prelude::*; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; // Create a secure storage instance let storage = enclave_manager.create_storage()?; // Store sensitive data let key = "api_key"; let value = "my-secret-api-key"; storage.set(key, value)?; // Retrieve sensitive data let retrieved_value = storage.get(key)?; println!("Retrieved value: {}", retrieved_value); // The data is encrypted and stored securely Ok(()) }
Remote Attestation
Remote attestation allows you to verify that your code is running in a genuine SGX enclave:
use neo::prelude::*; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; // Generate a remote attestation quote let quote = enclave_manager.generate_attestation_quote()?; // Send the quote to a remote verifier // (implementation depends on your attestation service) let attestation_service_url = "https://attestation.example.com"; let verification_result = verify_quote_with_service(attestation_service_url, "e).await?; if verification_result.is_valid { println!("Remote attestation successful!"); // Proceed with secure operations } else { println!("Remote attestation failed!"); // Handle the failure } Ok(()) } async fn verify_quote_with_service(url: &str, quote: &[u8]) -> Result<VerificationResult, Box<dyn std::error::Error>> { // Implementation of quote verification with a remote attestation service // This is just a placeholder Ok(VerificationResult { is_valid: true }) } struct VerificationResult { is_valid: bool, }
Simulation Mode
If you don't have SGX hardware, you can still develop and test using simulation mode:
export SGX_MODE=SIM
make -f Makefile.sgx
In your code, you can check if you're running in simulation mode:
use neo::prelude::*; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { // Path to the enclave shared object let enclave_path = "path/to/enclave.so"; // Initialize the SGX enclave let enclave_manager = SgxEnclaveManager::new(enclave_path)?; if enclave_manager.is_simulation_mode() { println!("Running in simulation mode. Security guarantees are not provided."); } else { println!("Running in hardware mode with full SGX protection."); } Ok(()) }
Best Practices
- Minimize Enclave Code: Keep the enclave code small to reduce the attack surface.
- Validate Inputs: Always validate inputs before passing them to the enclave.
- Secure Key Management: Never extract private keys from the enclave.
- Use Remote Attestation: Verify the integrity of the enclave in production environments.
- Regular Updates: Keep the SGX SDK and drivers updated to address security vulnerabilities.
- Error Handling: Implement proper error handling for enclave operations.
- Testing: Test your SGX code in both simulation and hardware modes.
Security Considerations
When using SGX for blockchain applications:
- Side-Channel Attacks: Be aware that SGX is not immune to all side-channel attacks.
- Enclave Interface: The interface between the untrusted application and the enclave is a potential attack vector.
- Data Sealing: Use data sealing to protect sensitive data at rest.
- Memory Limitations: SGX enclaves have memory limitations; design your application accordingly.
- Attestation: Use remote attestation in production to verify enclave integrity.