mirror of
https://github.com/luxfi/coreth.git
synced 2026-10-30 17:00:51 +00:00
- Fixed post-quantum crypto imports to use luxfi/crypto - Kept go-verkle for Verkle tree support - All crypto operations use unified luxfi/crypto package
227 lines
8.5 KiB
Solidity
227 lines
8.5 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.19;
|
|
|
|
/**
|
|
* @title PostQuantumVerifier
|
|
* @notice Contract for verifying post-quantum signatures using precompiled contracts
|
|
* @dev Uses Lux network's post-quantum precompiles for FALCON and Dilithium verification
|
|
*/
|
|
contract PostQuantumVerifier {
|
|
|
|
// Precompile addresses for post-quantum signatures
|
|
address constant FALCON_VERIFY = 0x0000000000000000000000000000000000000100;
|
|
address constant FALCON_RECOVER = 0x0000000000000000000000000000000000000101;
|
|
address constant DILITHIUM_VERIFY = 0x0000000000000000000000000000000000000102;
|
|
address constant ETH_FALCON_VERIFY = 0x0000000000000000000000000000000000000103;
|
|
address constant ETH_DILITHIUM_VERIFY = 0x0000000000000000000000000000000000000104;
|
|
|
|
// Events
|
|
event FalconVerified(address indexed verifier, bytes32 messageHash, bool valid);
|
|
event DilithiumVerified(address indexed verifier, bytes32 messageHash, bool valid);
|
|
event AddressRecovered(address indexed recovered, bytes32 messageHash);
|
|
|
|
/**
|
|
* @notice Verify a FALCON-512 signature (NIST-compliant)
|
|
* @param signature The FALCON signature
|
|
* @param message The message that was signed
|
|
* @param publicKey The FALCON public key (897 bytes)
|
|
* @return valid True if signature is valid
|
|
*/
|
|
function verifyFalcon(
|
|
bytes memory signature,
|
|
bytes memory message,
|
|
bytes memory publicKey
|
|
) public returns (bool valid) {
|
|
// ABI encode the parameters for the precompile
|
|
bytes memory input = abi.encode(signature, message, publicKey);
|
|
|
|
// Call the FALCON verify precompile
|
|
(bool success, bytes memory result) = FALCON_VERIFY.staticcall(input);
|
|
|
|
if (success && result.length == 32) {
|
|
valid = uint256(bytes32(result)) == 1;
|
|
emit FalconVerified(msg.sender, keccak256(message), valid);
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
* @notice Verify an ETH-optimized FALCON signature (uses Keccak instead of SHAKE)
|
|
* @param messageHash The hash of the message (32 bytes)
|
|
* @param salt The signature salt (40 bytes)
|
|
* @param s2 The s2 component of signature (compacted format)
|
|
* @param ntth The public key in NTT domain (compacted format)
|
|
* @return valid True if signature is valid
|
|
*/
|
|
function verifyETHFalcon(
|
|
bytes32 messageHash,
|
|
bytes memory salt,
|
|
uint256[] memory s2,
|
|
uint256[] memory ntth
|
|
) public returns (bool valid) {
|
|
require(salt.length == 40, "Invalid salt length");
|
|
require(s2.length == 32, "Invalid s2 length");
|
|
require(ntth.length == 32, "Invalid public key length");
|
|
|
|
// Pack the data for ETH-optimized format
|
|
bytes memory input = abi.encodePacked(messageHash, salt);
|
|
|
|
// Add compacted s2
|
|
for (uint i = 0; i < s2.length; i++) {
|
|
input = abi.encodePacked(input, s2[i]);
|
|
}
|
|
|
|
// Add compacted ntth (public key in NTT domain)
|
|
for (uint i = 0; i < ntth.length; i++) {
|
|
input = abi.encodePacked(input, ntth[i]);
|
|
}
|
|
|
|
// Call the ETH-optimized FALCON verify precompile
|
|
(bool success, bytes memory result) = ETH_FALCON_VERIFY.staticcall(input);
|
|
|
|
if (success && result.length == 32) {
|
|
valid = uint256(bytes32(result)) == 1;
|
|
emit FalconVerified(msg.sender, messageHash, valid);
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
* @notice Recover an address from a FALCON signature (EPERVIER variant)
|
|
* @param messageHash The hash of the message
|
|
* @param salt The signature salt (40 bytes)
|
|
* @param signature The FALCON signature with recovery
|
|
* @return recovered The recovered Ethereum address
|
|
*/
|
|
function recoverFalconAddress(
|
|
bytes32 messageHash,
|
|
bytes memory salt,
|
|
bytes memory signature
|
|
) public returns (address recovered) {
|
|
require(salt.length == 40, "Invalid salt length");
|
|
|
|
// Pack the input
|
|
bytes memory input = abi.encodePacked(messageHash, salt, signature);
|
|
|
|
// Call the FALCON recover precompile
|
|
(bool success, bytes memory result) = FALCON_RECOVER.staticcall(input);
|
|
|
|
if (success && result.length == 32) {
|
|
recovered = address(uint160(uint256(bytes32(result))));
|
|
emit AddressRecovered(recovered, messageHash);
|
|
}
|
|
|
|
return recovered;
|
|
}
|
|
|
|
/**
|
|
* @notice Verify a Dilithium3 signature (NIST-compliant)
|
|
* @param signature The Dilithium signature (3293 bytes)
|
|
* @param message The message that was signed
|
|
* @param publicKey The Dilithium public key (1952 bytes)
|
|
* @return valid True if signature is valid
|
|
*/
|
|
function verifyDilithium(
|
|
bytes memory signature,
|
|
bytes memory message,
|
|
bytes memory publicKey
|
|
) public returns (bool valid) {
|
|
require(signature.length == 3293, "Invalid signature length");
|
|
require(publicKey.length == 1952, "Invalid public key length");
|
|
|
|
// ABI encode the parameters for the precompile
|
|
bytes memory input = abi.encode(signature, message, publicKey);
|
|
|
|
// Call the Dilithium verify precompile
|
|
(bool success, bytes memory result) = DILITHIUM_VERIFY.staticcall(input);
|
|
|
|
if (success && result.length == 32) {
|
|
valid = uint256(bytes32(result)) == 1;
|
|
emit DilithiumVerified(msg.sender, keccak256(message), valid);
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
* @notice Verify an ETH-optimized Dilithium signature
|
|
* @param messageHash The hash of the message
|
|
* @param signatureData The packed signature and public key data
|
|
* @return valid True if signature is valid
|
|
*/
|
|
function verifyETHDilithium(
|
|
bytes32 messageHash,
|
|
bytes memory signatureData
|
|
) public returns (bool valid) {
|
|
// Pack the input
|
|
bytes memory input = abi.encodePacked(messageHash, signatureData);
|
|
|
|
// Call the ETH-optimized Dilithium verify precompile
|
|
(bool success, bytes memory result) = ETH_DILITHIUM_VERIFY.staticcall(input);
|
|
|
|
if (success && result.length == 32) {
|
|
valid = uint256(bytes32(result)) == 1;
|
|
emit DilithiumVerified(msg.sender, messageHash, valid);
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
/**
|
|
* @notice Check if an address has been quantum-secured
|
|
* @dev This would integrate with a registry of quantum-secured addresses
|
|
*/
|
|
mapping(address => bool) public quantumSecured;
|
|
mapping(address => bytes) public falconPublicKeys;
|
|
mapping(address => bytes) public dilithiumPublicKeys;
|
|
|
|
/**
|
|
* @notice Register a FALCON public key for an address
|
|
* @param publicKey The FALCON public key to register
|
|
*/
|
|
function registerFalconKey(bytes memory publicKey) public {
|
|
require(publicKey.length == 897, "Invalid FALCON public key length");
|
|
falconPublicKeys[msg.sender] = publicKey;
|
|
quantumSecured[msg.sender] = true;
|
|
}
|
|
|
|
/**
|
|
* @notice Register a Dilithium public key for an address
|
|
* @param publicKey The Dilithium public key to register
|
|
*/
|
|
function registerDilithiumKey(bytes memory publicKey) public {
|
|
require(publicKey.length == 1952, "Invalid Dilithium public key length");
|
|
dilithiumPublicKeys[msg.sender] = publicKey;
|
|
quantumSecured[msg.sender] = true;
|
|
}
|
|
|
|
/**
|
|
* @notice Execute a transaction with FALCON signature verification
|
|
* @param target The target contract
|
|
* @param data The transaction data
|
|
* @param signature The FALCON signature
|
|
* @param signer The address that should have signed
|
|
*/
|
|
function executeWithFalcon(
|
|
address target,
|
|
bytes memory data,
|
|
bytes memory signature,
|
|
address signer
|
|
) public returns (bool success, bytes memory returnData) {
|
|
// Get the registered FALCON public key
|
|
bytes memory publicKey = falconPublicKeys[signer];
|
|
require(publicKey.length > 0, "No FALCON key registered");
|
|
|
|
// Verify the signature
|
|
bytes32 messageHash = keccak256(abi.encodePacked(target, data, block.number));
|
|
bytes memory message = abi.encodePacked(messageHash);
|
|
|
|
bool valid = verifyFalcon(signature, message, publicKey);
|
|
require(valid, "Invalid FALCON signature");
|
|
|
|
// Execute the transaction
|
|
(success, returnData) = target.call(data);
|
|
}
|
|
} |