Cryptography
This section is all about the cryptography used in Tusknet
AES Encryption Standard
Advanced Encryption Standard (AES) is a widely used symmetric encryption algorithm. It operates on fixed-size blocks of data (128-bit blocks) and supports key sizes of 128, 192, or 256 bits. AES is highly efficient and secure, making it a popular choice for encrypting sensitive data.
Key Features:
Symmetric Encryption: Both encryption and decryption use the same key.
Block Cipher: AES encrypts data in blocks of 128 bits.
Operating Modes: AES supports several modes like CBC (Cipher Block Chaining), GCM (Galois/Counter Mode), etc., for flexibility in different applications.
Security: AES-256 provides a high level of security due to its large key size.
Your AES Implementation:
The provided code uses AES-256-CBC, where:
Key (256 bits): Used for both encryption and decryption.
Initialization Vector (IV): A random value to ensure unique ciphertexts for identical plaintexts.
Encryption Process:
Input text is converted to bytes.
Encrypted using the cipher initialized with the key and IV.
Outputs the encrypted data and IV as hexadecimal strings.
Decryption Process:
Uses the encrypted data and IV to reconstruct the original plaintext.
AES Code Example:
const crypto = require('crypto');
const algorithm = 'aes-256-cbc';
const key = "mypasswith32chars>>AES_256_bytes"; // Symmetric key
const iv = crypto.randomBytes(16); // Initialization vector
function encrypt(text) {
let cipher = crypto.createCipheriv(algorithm, Buffer.from(key), iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return { iv: iv.toString('hex'), encryptedData: encrypted.toString('hex') };
}
function decrypt(text) {
let iv = Buffer.from(text.iv, 'hex');
let encryptedText = Buffer.from(text.encryptedData, 'hex');
let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, cipher.final()]);
return decrypted;
}
This AES encryption is applied to secure cost functions within your network.
Pedersen Commitments
The Pedersen Commitment scheme is a cryptographic protocol that allows a value to be "committed" while keeping it hidden. It is widely used in privacy-preserving systems due to its binding and hiding properties.
Properties:
Binding: Once committed, the value cannot be changed without invalidating the commitment.
Hiding: The committed value remains hidden until explicitly revealed.
Homomorphic: Commitments can be added together to produce a commitment to the sum of their values.
How It Works:
Setup:
Two large prime numbers ppp and qqq are generated, where q∣(p−1)q \mid (p-1)q∣(p−1).
Two group elements ggg and hhh are chosen such that g,h∈Zq∗g, h \in \mathbb{Z}_q^*g,h∈Zq∗.
Commitment: A value xxx is committed using: C=gx⋅hrmod qC = g^x \cdot h^r \mod qC=gx⋅hrmodq where rrr is a random value.
Verification: To verify, the commitment CCC is checked against the disclosed xxx and rrr.
Your Pedersen Commitment Implementation:
Generates large primes ppp and qqq.
Randomly selects ggg, sss, and computes h=gsmod qh = g^s \mod qh=gsmodq.
Provides functions for committing, verifying, and adding commitments.
Code Implementation:
import os
import sys
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
def generate_large_prime(bit_length):
return rsa.generate_private_key(public_exponent=65537, key_size=bit_length, backend=default_backend()).private_numbers().p
class PedersonCommitment:
def __init__(self, security=1024):
self.p = generate_large_prime(security)
self.q = generate_large_prime(security * 2)
self.g = int.from_bytes(os.urandom(32), 'big') % self.q
self.s = int.from_bytes(os.urandom(32), 'big') % self.q
self.h = pow(self.g, self.s, self.q)
def commit(self, x):
r = int.from_bytes(os.urandom(32), 'big') % self.q
c = (pow(self.g, x, self.q) * pow(self.h, r, self.q)) % self.q
return c, r
def verify(self, c, x, r):
return c == (pow(self.g, x, self.q) * pow(self.h, r, self.q)) % self.q
def add_commitments(self, c1, c2):
return (c1 * c2) % self.q
System Overview
Byzantine Fault Tolerance:
The system employs Pedersen commitments to ensure that all nodes in the network agree on cost functions securely:
Commitments: Each node commits to a cost using Pedersen commitments.
Encryption: Cost values are encrypted using AES before aggregation.
Aggregation: Committed values are aggregated to ensure correctness.
Verification: Results can be verified to ensure Byzantine fault tolerance.
Workflow:
Encrypt Cost:
def encrypt_cost(cost): cost_int = int(cost) c, r = commitment.commit(cost_int) print(f"Salt: {r}") print(f"Encrypted Cost: {c}") return c, r
Aggregate Commitments:
def aggregate_commitments(commitments): result = 1 for c in commitments: result = commitment.add_commitments(result, c) return result
This hybrid approach combines Pedersen commitments and AES encryption to secure cost functions and maintain fault tolerance in a distributed network.
Last updated