Documentation Index
Fetch the complete documentation index at: https://mintlify.com/stellar/rs-soroban-sdk/llms.txt
Use this file to discover all available pages before exploring further.
The Soroban SDK provides comprehensive cryptographic primitives through the Crypto module, including support for elliptic curve operations on BLS12-381 and BN254 curves.
Accessing Crypto Functions
Access cryptographic functions through the environment:
use soroban_sdk::{Env, Bytes};
let env = Env::default();
let crypto = env.crypto();
Hash Functions
SHA-256
Compute SHA-256 hash of data:
let data = Bytes::from_slice(&env, b"hello world");
let hash = crypto.sha256(&data);
// Returns Hash<32> - a cryptographically secure hash
Keccak-256
Compute Keccak-256 hash (used in Ethereum):
let data = Bytes::from_slice(&env, b"hello world");
let hash = crypto.keccak256(&data);
// Returns Hash<32>
Digital Signatures
ED25519
Verify ED25519 signatures:
use soroban_sdk::BytesN;
let public_key: BytesN<32> = /* ... */;
let message = Bytes::from_slice(&env, b"message");
let signature: BytesN<64> = /* ... */;
crypto.ed25519_verify(&public_key, &message, &signature);
// Panics if verification fails
ECDSA secp256k1
Recover public key from signature:
let message_digest = crypto.sha256(&message);
let signature: BytesN<64> = /* ... */;
let recovery_id: u32 = 0;
let public_key = crypto.secp256k1_recover(&message_digest, &signature, recovery_id);
// Returns BytesN<65> - SEC-1-encoded public key
ECDSA secp256r1
Verify secp256r1 signatures:
let public_key: BytesN<65> = /* ... */;
let message_digest = crypto.sha256(&message);
let signature: BytesN<64> = /* ... */;
crypto.secp256r1_verify(&public_key, &message_digest, &signature);
BLS12-381 Curve Operations
The BLS12-381 curve is used for pairing-based cryptography and BLS signatures.
Accessing BLS12-381
use soroban_sdk::crypto::bls12_381::{Bls12_381, G1Affine, G2Affine, Fr};
let bls = env.crypto().bls12_381();
Field Elements
use soroban_sdk::{bytesn, crypto::bls12_381::Fp};
// Create a field element
let fp = Fp::from_array(&env, &[0u8; 48]);
// Field arithmetic
let neg_fp = -fp;
G1 Point Operations
use soroban_sdk::bytesn;
// Generator point in G1
let g1_generator = G1Affine::from_bytes(bytesn!(&env,
0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1
));
// Point addition
let result = bls.g1_add(&point1, &point2);
// Scalar multiplication
let scalar = Fr::from_u256(U256::from_u32(&env, 5));
let result = bls.g1_mul(&point1, &scalar);
// Check if point is in correct subgroup
let is_valid = bls.g1_is_in_subgroup(&point1);
// Multi-scalar multiplication (MSM)
let points = vec![&env, point1, point2];
let scalars = vec![&env, scalar1, scalar2];
let result = bls.g1_msm(points, scalars);
G2 Point Operations
// G2 operations are similar to G1
let result = bls.g2_add(&p1, &p2);
let result = bls.g2_mul(&p1, &scalar);
let is_valid = bls.g2_is_in_subgroup(&p1);
Hash to Curve
Map arbitrary data to curve points:
// Hash to G1
let msg = Bytes::from_slice(&env, b"message");
let dst = Bytes::from_slice(&env, b"DOMAIN_SEPARATION_TAG");
let point = bls.hash_to_g1(&msg, &dst);
// Hash to G2
let point = bls.hash_to_g2(&msg, &dst);
Pairing Operations
Perform pairing checks for signature verification:
use soroban_sdk::Vec;
// Pairing check: e(P1, Q1) * e(P2, Q2) == 1
let g1_points = vec![&env, p1, p2];
let g2_points = vec![&env, q1, q2];
let is_valid = bls.pairing_check(g1_points, g2_points);
Scalar Field Arithmetic
// Fr represents elements in the scalar field
let a = Fr::from_u256(U256::from_u32(&env, 10));
let b = Fr::from_u256(U256::from_u32(&env, 5));
// Arithmetic operations
let sum = bls.fr_add(&a, &b);
let diff = bls.fr_sub(&a, &b);
let product = bls.fr_mul(&a, &b);
let power = bls.fr_pow(&a, 3);
let inverse = bls.fr_inv(&a);
BN254 Curve Operations
BN254 (alt_bn128) is Ethereum-compatible and commonly used in zkSNARKs.
Accessing BN254
use soroban_sdk::crypto::bn254::{Bn254, Bn254G1Affine, Bn254G2Affine};
let bn254 = env.crypto().bn254();
G1 Operations
// Point addition
let result = bn254.g1_add(&point1, &point2);
// Scalar multiplication
let scalar = bn254::Fr::from_u256(U256::from_u32(&env, 5));
let result = bn254.g1_mul(&point1, &scalar);
Pairing Check (Ethereum-compatible)
use soroban_sdk::Vec;
// BN254 pairing for zkSNARK verification
let g1_points = vec![&env, p1, p2];
let g2_points = vec![&env, q1, q2];
let is_valid = bn254.pairing_check(g1_points, g2_points);
Best Practices
Use Checked Operations for Subgroup Safety
When aggregating multiple points, use checked operations on the final result:
// Use unchecked operations for intermediate additions
let temp1 = bls.g1_add(&p0, &p1);
let temp2 = bls.g1_add(&temp1, &p2);
// Use checked operation for final result to ensure correctness
let final_result = bls.g1_checked_add(&temp2, &p3);
match final_result {
Some(point) => {
// Point is in correct subgroup
},
None => {
// Point is not in correct subgroup
}
}
Hash Type Safety
The Hash<N> type ensures values come from cryptographic hash functions:
use soroban_sdk::crypto::Hash;
// Hash<32> can only be created from secure hash functions
let hash: Hash<32> = crypto.sha256(&data);
// Convert to bytes when needed
let bytes = hash.to_bytes();
let array = hash.to_array();
Hazmat Crypto
Low-level operations are available but should be used with caution:
// ⚠️ Warning: These operations can be insecure if misused
// Only use if you understand the security implications
- MSM operations are optimized for multiple scalar multiplications
- Subgroup checks are expensive; minimize their use in loops
- Pairing operations are the most expensive; batch verifications when possible
- BLS12-381 operations are generally slower but more secure than BN254
- BN254 operations are faster and Ethereum-compatible