Files
aitbc/tests/verification/test_keystore_mac.py
aitbc f4c48ba4e3
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
test: add tests for completed placeholder implementations
- test_keystore_mac.py: Tests HMAC-SHA256 MAC computation for web3 keystore format
  - MAC computation validation
  - Keystore generation with MAC
  - MAC validation for password error detection

- test_agent_signature_verification.py: Tests agent SDK signature verification
  - ed25519 signature generation and verification
  - Wrong public key detection
  - Tampered message detection
  - Public key fetch from coordinator API
  - Receive message with signature verification

- test_agent_integration_service.py: Tests agent integration service features
  - Systemd service file generation
  - Health check response format
  - Metrics collection format
  - Alerting rules configuration
  - Deployment rollback logic
  - Instance removal logic
2026-05-03 23:38:53 +02:00

248 lines
7.1 KiB
Python

#!/usr/bin/env python3
"""
Test MAC computation in keystore scripts
Tests HMAC-SHA256 MAC computation for web3 keystore format
"""
import hashlib
import hmac
import json
import os
import tempfile
from pathlib import Path
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.backends import default_backend
def compute_mac(key: bytes, ciphertext: bytes) -> str:
"""Compute MAC for web3 keystore format (HMAC-SHA256)"""
mac_data = key[16:32] + ciphertext
mac = hmac.new(key[:16], mac_data, hashlib.sha256).hexdigest()
return mac
def test_mac_computation():
"""Test MAC computation matches web3 keystore standard"""
print("Testing MAC Computation")
print("=" * 40)
# Generate test key and ciphertext
password = "test_password_123"
salt = os.urandom(32)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100_000,
backend=default_backend()
)
key = kdf.derive(password.encode('utf-8'))
# Generate test ciphertext
private_key = ed25519.Ed25519PrivateKey.generate()
private_bytes = private_key.private_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PrivateFormat.Raw,
encryption_algorithm=serialization.NoEncryption()
)
aesgcm = AESGCM(key)
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, private_bytes, None)
# Compute MAC
mac = compute_mac(key, ciphertext)
print(f"MAC computed: {mac}")
print(f"MAC length: {len(mac)}")
# Verify MAC is a valid hex string
try:
int(mac, 16)
print("✅ MAC is valid hex string")
except ValueError:
print("❌ MAC is not valid hex string")
return False
# Verify MAC length (64 hex chars = 32 bytes)
if len(mac) == 64:
print("✅ MAC has correct length (64 hex chars)")
else:
print(f"❌ MAC has incorrect length: {len(mac)} (expected 64)")
return False
print("\n✅ MAC computation test passed!")
return True
def test_keystore_with_mac():
"""Test full keystore generation with MAC"""
print("\nTesting Keystore Generation with MAC")
print("=" * 40)
# Create temporary keystore directory
with tempfile.TemporaryDirectory() as temp_dir:
keystore_dir = Path(temp_dir)
# Generate keystore
password = "test_password_123"
name = "test_wallet"
salt = os.urandom(32)
private_key = ed25519.Ed25519PrivateKey.generate()
private_bytes = private_key.private_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PrivateFormat.Raw,
encryption_algorithm=serialization.NoEncryption()
)
# Derive key
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100_000,
backend=default_backend()
)
key = kdf.derive(password.encode('utf-8'))
# Encrypt
aesgcm = AESGCM(key)
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, private_bytes, None)
# Compute MAC
mac = compute_mac(key, ciphertext)
# Build keystore
keystore = {
"crypto": {
"cipher": "aes-256-gcm",
"cipherparams": {"nonce": nonce.hex()},
"ciphertext": ciphertext.hex(),
"kdf": "pbkdf2",
"kdfparams": {
"dklen": 32,
"salt": salt.hex(),
"c": 100_000,
"prf": "hmac-sha256"
},
"mac": mac
},
"address": "test_address",
"keytype": "ed25519",
"version": 1
}
# Write keystore
keystore_file = keystore_dir / f"{name}.json"
with open(keystore_file, 'w') as f:
json.dump(keystore, f, indent=2)
print(f"Keystore written to: {keystore_file}")
# Read back and verify MAC
with open(keystore_file) as f:
loaded = json.load(f)
loaded_mac = loaded["crypto"]["mac"]
if loaded_mac == mac:
print("✅ MAC matches in loaded keystore")
else:
print(f"❌ MAC mismatch: {loaded_mac} != {mac}")
return False
print("\n✅ Keystore with MAC test passed!")
return True
def test_mac_validation():
"""Test MAC validation for password errors"""
print("\nTesting MAC Validation")
print("=" * 40)
password = "correct_password"
wrong_password = "wrong_password"
salt = os.urandom(32)
# Derive key with correct password
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100_000,
backend=default_backend()
)
correct_key = kdf.derive(password.encode('utf-8'))
# Derive key with wrong password
kdf_wrong = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100_000,
backend=default_backend()
)
wrong_key = kdf_wrong.derive(wrong_password.encode('utf-8'))
# Generate test ciphertext
private_key = ed25519.Ed25519PrivateKey.generate()
private_bytes = private_key.private_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PrivateFormat.Raw,
encryption_algorithm=serialization.NoEncryption()
)
aesgcm = AESGCM(correct_key)
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, private_bytes, None)
# Compute MAC with correct key
correct_mac = compute_mac(correct_key, ciphertext)
# Try to compute MAC with wrong key
wrong_mac = compute_mac(wrong_key, ciphertext)
print(f"Correct MAC: {correct_mac}")
print(f"Wrong MAC: {wrong_mac}")
if correct_mac != wrong_mac:
print("✅ MAC validation detects password errors")
else:
print("❌ MAC validation failed to detect password errors")
return False
print("\n✅ MAC validation test passed!")
return True
if __name__ == "__main__":
print("Keystore MAC Computation Tests")
print("=" * 40)
print()
results = []
results.append(("MAC Computation", test_mac_computation()))
results.append(("Keystore with MAC", test_keystore_with_mac()))
results.append(("MAC Validation", test_mac_validation()))
print("\n" + "=" * 40)
print("Test Summary")
print("=" * 40)
for name, passed in results:
status = "✅ PASSED" if passed else "❌ FAILED"
print(f"{name}: {status}")
all_passed = all(result[1] for result in results)
if all_passed:
print("\n🎉 All tests passed!")
else:
print("\n❌ Some tests failed")