Skip to main content

Cryptography Specification

Complete specification of all cryptographic primitives used in the Savitri Network.

Signature Scheme

PropertyValue
AlgorithmEd25519
Libraryed25519-dalek
Private key32 bytes
Public key32 bytes (compressed Edwards point)
Signature64 bytes
AddressHex-encoded public key (64 hex characters)

Transaction Signing

message = from_hex_bytes || to_hex_bytes || amount_le_u64 || nonce_le_u64 || fee_le_u128
hash = SHA-256(message)
sig = Ed25519_sign(signing_key, hash)

Block Signing

Blocks are signed by the proposer using Ed25519 over the block header hash (SHA-512).

Peer Identity

libp2p peers use Ed25519 for their peer identity keys (separate from account keys).

Hash Functions

SHA-256

UsageInputOutput
Transaction signing messageCanonical TX bytes32 bytes
Monolith commitmentHeader fields32 bytes
ZKP statement hashStatement fields32 bytes
AES key derivationPassword32 bytes

SHA-512

UsageInputOutput
Block hash"BLK" + version byte + header bytes64 bytes
Headers commitBinary tree of block headers64 bytes

BLAKE3

UsageInputOutput
Fast hashingGeneral purposeVariable
State computationState data32 bytes

Keccak256

UsageInputOutput
Contract storage slotsaddress || base_slot8 bytes (u64)
Nested mappingskey || inner_hash8 bytes (u64)

Domain Separation

All hash computations include domain tags to prevent cross-domain collisions:

DomainTagHashOutput
Block"BLK" + version: u8SHA-51264 bytes
TX root"TXv1" leaf tagRolling accumulator32 bytes
State root"STATEv1-LE" seed + "STATE" leafLexicographic snapshot32 bytes

Transaction Root

Computed as a rolling accumulator over canonical bincode of transactions:

accumulator = H("TXv1")
for tx in transactions:
leaf = bincode::serialize(tx)
accumulator = H(accumulator || leaf)
tx_root = accumulator

State Root

Computed from a lexicographic database snapshot:

seed = H("STATEv1-LE")
for (key, value) in storage.iter_sorted():
leaf = H("STATE" || key || value)
seed = H(seed || leaf)
state_root = seed

Encryption

AES-256-GCM (At Rest)

Used for:

  • Private key encryption in the SDK
  • Mobile database column encryption
  • Device data encryption in IoT connector
PropertyValue
AlgorithmAES-256-GCM
Key size256 bits
Nonce size96 bits (12 bytes)
Tag size128 bits (16 bytes)
Key derivationPassword-based

P2P Encryption

PropertyValue
ProtocolNoise (XX handshake pattern)
Key exchangeX25519
CipherChaChaPoly
MultiplexingYamux

Key Derivation (Mobile)

BIP-39

  • Wordlist: English (2048 words)
  • Entropy: 128 bits (12 words) or 256 bits (24 words)
  • Mnemonic → Seed: PBKDF2-HMAC-SHA512 (2048 rounds)

BIP-44

  • Path: m/44'/1337'/0'/0/0
  • Coin type: 1337 (Savitri)
  • Account: 0
  • Change: 0 (external)
  • Index: 0

Key Hierarchy

mnemonic → seed (512 bits)
→ master_key (via HMAC-SHA512)
→ m/44' → m/44'/1337' → m/44'/1337'/0'
→ m/44'/1337'/0'/0 → m/44'/1337'/0'/0/0
→ ed25519_private_key (32 bytes)
→ ed25519_public_key (32 bytes)
→ address (hex-encoded, 64 chars)

Zero-Knowledge Proofs

See ZKP Architecture for details.

BackendCurveProof SystemUse Case
MockN/AAlways-validTesting
ArkworksBN254Groth16Production
PLONKBN254PLONKGeneral-purpose

Security Properties

Constant-Time Operations

All signature verification uses constant-time comparison (via subtle crate) to prevent timing side-channel attacks.

Key Zeroization

Private keys are zeroized on drop using the zeroize crate in both the SDK and mobile app.

Replay Protection

  • Transactions: Nonce-based (monotonically increasing per account)
  • FL updates: Per-round nonce per trainer
  • Oracle feeds: Sequence number tracking
  • P2P messages: Gossipsub deduplication