mirror of
https://github.com/zkemail/zk-email-verify.git
synced 2026-01-10 05:58:08 -05:00
feat: ECDSA Owned Dkim Registry
This commit is contained in:
107
packages/contracts/ECDSAOwnedDKIMRegistry.sol
Normal file
107
packages/contracts/ECDSAOwnedDKIMRegistry.sol
Normal file
@@ -0,0 +1,107 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.12;
|
||||
|
||||
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
|
||||
import "./interfaces/IERC7969.sol";
|
||||
import "./DKIMRegistry.sol";
|
||||
|
||||
/// @title ECDSA Owned DKIM Registry
|
||||
/// @notice This contract allows for the management of DKIM public key hashes through an ECDSA-signed mechanism. It enables the setting and revoking of DKIM public key hashes for domain names, ensuring that only the authorized signer can perform these operations. The contract leverages an underlying DKIMRegistry contract for the actual storage and validation of public key hashes.
|
||||
/// @dev The contract uses OpenZeppelin's ECDSA library for signature recovery and the DKIMRegistry for storing the DKIM public key hashes.
|
||||
contract ECDSAOwnedDKIMRegistry is IDKIMRegistry {
|
||||
using Strings for uint256;
|
||||
using ECDSA for bytes32;
|
||||
|
||||
DKIMRegistry public dkimRegistry;
|
||||
address public signer;
|
||||
|
||||
string public constant SET_PREFIX = "SET:";
|
||||
string public constant REVOKE_PREFIX = "REVOKE:";
|
||||
|
||||
/// @notice Initializes the contract with a predefined signer and deploys a new DKIMRegistry.
|
||||
/// @param _signer The address of the authorized signer who can set or revoke DKIM public key hashes.
|
||||
constructor(address _signer) {
|
||||
// this contract owns the DKIMRegistry and allows signer to set/revoke public key hashes
|
||||
dkimRegistry = new DKIMRegistry(address(this));
|
||||
signer = _signer;
|
||||
}
|
||||
|
||||
/// @notice Checks if a DKIM public key hash is valid for a given domain name.
|
||||
/// @param domainHash The keccak256 hash of the lowercase domain name.
|
||||
/// @param keyHash The keccak256 hash of the DKIM public key.
|
||||
/// @return bool Returns true if the public key hash is valid, false otherwise.
|
||||
function isKeyHashValid(bytes32 domainHash, bytes32 keyHash) public view returns (bool) {
|
||||
return dkimRegistry.isKeyHashValid(domainHash, keyHash);
|
||||
}
|
||||
|
||||
/// @notice Sets a DKIM public key hash for a domain name after validating the provided signature.
|
||||
/// @param selector The selector associated with the DKIM public key.
|
||||
/// @param domainName The domain name to set the DKIM public key hash for.
|
||||
/// @param publicKeyHash The DKIM public key hash to set.
|
||||
/// @param signature The ECDSA signature proving the operation is authorized by the signer.
|
||||
/// @dev This function requires that the public key hash is not already set or revoked.
|
||||
function setDKIMPublicKeyHash(
|
||||
string memory selector,
|
||||
string memory domainName,
|
||||
bytes32 publicKeyHash,
|
||||
bytes memory signature
|
||||
) public {
|
||||
bytes32 domainHash = keccak256(bytes(domainName));
|
||||
require(bytes(selector).length != 0, "Invalid selector");
|
||||
require(bytes(domainName).length != 0, "Invalid domain name");
|
||||
require(publicKeyHash != bytes32(0), "Invalid public key hash");
|
||||
require(!isKeyHashValid(domainHash, publicKeyHash), "publicKeyHash is already set");
|
||||
require(!dkimRegistry.revokedDKIMPublicKeyHashes(publicKeyHash), "publicKeyHash is revoked");
|
||||
|
||||
string memory signedMsg = computeSignedMsg(SET_PREFIX, domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
address recoveredSigner = digest.recover(signature);
|
||||
require(recoveredSigner == signer, "Invalid signature");
|
||||
|
||||
dkimRegistry.setDKIMPublicKeyHash(domainHash, publicKeyHash);
|
||||
}
|
||||
|
||||
/// @notice Revokes a DKIM public key hash for a domain name after validating the provided signature.
|
||||
/// @param selector The selector associated with the DKIM public key.
|
||||
/// @param domainName The domain name to revoke the DKIM public key hash for.
|
||||
/// @param publicKeyHash The DKIM public key hash to revoke.
|
||||
/// @param signature The ECDSA signature proving the operation is authorized by the signer.
|
||||
/// @dev This function requires that the public key hash is currently set and not already revoked.
|
||||
function revokeDKIMPublicKeyHash(
|
||||
string memory selector,
|
||||
string memory domainName,
|
||||
bytes32 publicKeyHash,
|
||||
bytes memory signature
|
||||
) public {
|
||||
bytes32 domainHash = keccak256(bytes(domainName));
|
||||
require(bytes(selector).length != 0, "Invalid selector");
|
||||
require(bytes(domainName).length != 0, "Invalid domain name");
|
||||
require(publicKeyHash != bytes32(0), "Invalid public key hash");
|
||||
require(isKeyHashValid(domainHash, publicKeyHash), "publicKeyHash is not set");
|
||||
require(!dkimRegistry.revokedDKIMPublicKeyHashes(publicKeyHash), "publicKeyHash is already revoked");
|
||||
|
||||
string memory signedMsg = computeSignedMsg(REVOKE_PREFIX, domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
address recoveredSigner = digest.recover(signature);
|
||||
require(recoveredSigner == signer, "Invalid signature");
|
||||
|
||||
dkimRegistry.revokeDKIMPublicKeyHash(publicKeyHash);
|
||||
}
|
||||
|
||||
/// @notice Computes a signed message string for setting or revoking a DKIM public key hash.
|
||||
/// @param prefix The operation prefix (SET: or REVOKE:).
|
||||
/// @param domainName The domain name related to the operation.
|
||||
/// @param publicKeyHash The DKIM public key hash involved in the operation.
|
||||
/// @return string The computed signed message.
|
||||
/// @dev This function is used internally to generate the message that needs to be signed for setting or revoking a public key hash.
|
||||
function computeSignedMsg(string memory prefix, string memory domainName, bytes32 publicKeyHash)
|
||||
public
|
||||
pure
|
||||
returns (string memory)
|
||||
{
|
||||
return
|
||||
string.concat(prefix, "domain=", domainName, ";public_key_hash=", uint256(publicKeyHash).toHexString(), ";");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.12;
|
||||
|
||||
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import "forge-std/Test.sol";
|
||||
import "../../ECDSAOwnedDKIMRegistry.sol";
|
||||
|
||||
contract ECDSAOwnedDKIMRegistryTest_computeSignedMsg is Test {
|
||||
using Strings for uint256;
|
||||
|
||||
ECDSAOwnedDKIMRegistry dkim;
|
||||
|
||||
function setUp() public {
|
||||
address signer = vm.addr(1);
|
||||
dkim = new ECDSAOwnedDKIMRegistry(signer);
|
||||
}
|
||||
|
||||
function test_computeSignedMsg() public view {
|
||||
string memory prefix = "SET:";
|
||||
string memory domainName = "example.com";
|
||||
bytes32 publicKeyHash = bytes32(uint256(1));
|
||||
|
||||
string memory expectedMsg =
|
||||
string.concat(prefix, "domain=", domainName, ";public_key_hash=", uint256(publicKeyHash).toHexString(), ";");
|
||||
|
||||
string memory computedMsg = dkim.computeSignedMsg(prefix, domainName, publicKeyHash);
|
||||
|
||||
assertEq(computedMsg, expectedMsg, "Computed message does not match expected message");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.12;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "../../ECDSAOwnedDKIMRegistry.sol";
|
||||
|
||||
contract ECDSAOwnedDKIMRegistryTest_isDKIMPublicKeyHashValid is Test {
|
||||
ECDSAOwnedDKIMRegistry dkim;
|
||||
|
||||
string public selector = "12345";
|
||||
string public domainName = "example.com";
|
||||
bytes32 public publicKeyHash = bytes32(uint256(1));
|
||||
|
||||
function setUp() public {
|
||||
address signer = vm.addr(1);
|
||||
dkim = new ECDSAOwnedDKIMRegistry(signer);
|
||||
}
|
||||
|
||||
function test_IsKeyHashValid_True() public {
|
||||
// Set a valid public key hash
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Check if the public key hash is valid
|
||||
bool isValid = dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash);
|
||||
require(isValid, "Public key hash should be valid");
|
||||
}
|
||||
|
||||
function test_IsKeyHashValid_False() public view {
|
||||
// Check if a non-set public key hash is invalid
|
||||
bytes32 nonExistentPublicKeyHash = bytes32(uint256(2));
|
||||
bool isValid = dkim.isKeyHashValid(keccak256(bytes(domainName)), nonExistentPublicKeyHash);
|
||||
require(!isValid, "Public key hash should not be valid");
|
||||
}
|
||||
|
||||
function test_IsKeyHashValid_AfterRevoke() public {
|
||||
// Set and then revoke a public key hash
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Revoke the public key hash
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 revokeDigest = MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg));
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, revokeDigest);
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, revokeSig);
|
||||
|
||||
// Check if the public key hash is invalid after revocation
|
||||
bool isValid = dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash);
|
||||
require(!isValid, "Public key hash should not be valid after revocation");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.12;
|
||||
|
||||
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||
import "forge-std/Test.sol";
|
||||
import "forge-std/console.sol";
|
||||
import "../../ECDSAOwnedDKIMRegistry.sol";
|
||||
|
||||
contract ECDSAOwnedDKIMRegistryTest_revokeDKIMPublicKeyHash is Test {
|
||||
ECDSAOwnedDKIMRegistry dkim;
|
||||
|
||||
using console for *;
|
||||
using ECDSA for *;
|
||||
using Strings for *;
|
||||
|
||||
string public selector = "12345";
|
||||
string public domainName = "example.com";
|
||||
// uint public signValidityDuration = 1 days;
|
||||
bytes32 public publicKeyHash = bytes32(uint256(1));
|
||||
|
||||
function setUp() public {
|
||||
address signer = vm.addr(1);
|
||||
{
|
||||
dkim = new ECDSAOwnedDKIMRegistry(signer);
|
||||
}
|
||||
}
|
||||
|
||||
function test_Revert_IfPublicKeyHashNotSet() public {
|
||||
// Attempt to revoke a public key hash that hasn't been set
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
vm.expectRevert("publicKeyHash is not set");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
}
|
||||
|
||||
function test_Revert_IfSignerIsIncorrect() public {
|
||||
// Set a valid public key hash first
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Attempt to revoke with a signature from a different signer
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(2, digest); // Different signer
|
||||
bytes memory invalidSignature = abi.encodePacked(r1, s1, v1);
|
||||
|
||||
vm.expectRevert("Invalid signature");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, invalidSignature);
|
||||
}
|
||||
|
||||
// Test invalid domain name
|
||||
function test_Revert_IfDomainNameIsInvalid() public {
|
||||
// Set a valid public key hash first
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Attempt to revoke with an invalid domain name
|
||||
string memory invalidDomainName = "";
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), invalidDomainName, publicKeyHash);
|
||||
bytes32 revokeDigest = MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg));
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, revokeDigest);
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
|
||||
vm.expectRevert("Invalid domain name");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, invalidDomainName, publicKeyHash, revokeSig);
|
||||
}
|
||||
// Test invalid public key hash
|
||||
|
||||
function test_Revert_IfPublicKeyHashIsInvalid() public {
|
||||
// Set a valid public key hash first
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Attempt to revoke with an invalid public key hash
|
||||
bytes32 invalidPublicKeyHash = bytes32(0);
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, invalidPublicKeyHash);
|
||||
bytes32 revokeDigest = MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg));
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, revokeDigest);
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
|
||||
vm.expectRevert("Invalid public key hash");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, invalidPublicKeyHash, revokeSig);
|
||||
}
|
||||
// Test if publicKeyHash is already revoked
|
||||
|
||||
function test_Revert_IfPublicKeyHashIsAlreadyRevoked() public {
|
||||
// Set a valid public key hash first
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Revoke the public key hash
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 revokeDigest = MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg));
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, revokeDigest);
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, revokeSig);
|
||||
|
||||
// Mock the call to dkimRegistry.isDKIMPublicKeyHashValid to return true
|
||||
vm.mockCall(
|
||||
address(dkim.dkimRegistry()),
|
||||
abi.encodeWithSelector(IDKIMRegistry.isKeyHashValid.selector),
|
||||
abi.encode(true)
|
||||
);
|
||||
// Attempt to revoke the already revoked public key hash
|
||||
vm.expectRevert("publicKeyHash is already revoked");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, revokeSig);
|
||||
}
|
||||
|
||||
function test_Revert_IfSignatureIsInvalid() public {
|
||||
// Set a valid public key hash first
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Attempt to revoke with an invalid signature
|
||||
bytes memory invalidSignature = abi.encodePacked(r, s, v + 1); // Alter the signature
|
||||
vm.expectRevert("Invalid signature");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, invalidSignature);
|
||||
}
|
||||
|
||||
function test_Revert_IfDomainNameIsDifferent() public {
|
||||
// Set a valid public key hash first
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Attempt to revoke with a different domain name
|
||||
string memory differentDomainName = "different.com";
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), differentDomainName, publicKeyHash);
|
||||
bytes32 revokeDigest = MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg));
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, revokeDigest);
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
|
||||
vm.expectRevert("publicKeyHash is not set");
|
||||
dkim.revokeDKIMPublicKeyHash(selector, differentDomainName, publicKeyHash, revokeSig);
|
||||
}
|
||||
|
||||
function test_RevokeDKIMPublicKeyHash() public {
|
||||
// vm.chainId(1);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Revoke
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, publicKeyHash);
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg)));
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, revokeSig);
|
||||
|
||||
require(!dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.12;
|
||||
|
||||
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
||||
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||
import "forge-std/Test.sol";
|
||||
import "forge-std/console.sol";
|
||||
import "../../ECDSAOwnedDKIMRegistry.sol";
|
||||
|
||||
contract ECDSAOwnedDKIMRegistryTest_setDKIMPublicKeyHash is Test {
|
||||
ECDSAOwnedDKIMRegistry dkim;
|
||||
|
||||
using console for *;
|
||||
using ECDSA for *;
|
||||
using Strings for *;
|
||||
|
||||
string public selector = "12345";
|
||||
string public domainName = "example.com";
|
||||
// uint public signValidityDuration = 1 days;
|
||||
bytes32 public publicKeyHash = bytes32(uint256(1));
|
||||
|
||||
function setUp() public {
|
||||
address signer = vm.addr(1);
|
||||
{
|
||||
dkim = new ECDSAOwnedDKIMRegistry(signer);
|
||||
}
|
||||
}
|
||||
|
||||
function test_Revert_IfInvalidSelector() public {
|
||||
string memory invalidSelector = ""; // Example of an invalid selector (empty string)
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
vm.expectRevert("Invalid selector");
|
||||
dkim.setDKIMPublicKeyHash(invalidSelector, domainName, publicKeyHash, signature);
|
||||
}
|
||||
|
||||
function test_Revert_IfInvalidDomainName() public {
|
||||
string memory invalidDomainName = ""; // Example of an invalid domain name (empty string)
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), invalidDomainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
vm.expectRevert("Invalid domain name");
|
||||
dkim.setDKIMPublicKeyHash(selector, invalidDomainName, publicKeyHash, signature);
|
||||
}
|
||||
|
||||
function test_MinLengthSelectorAndDomainName() public {
|
||||
string memory minSelector = "a";
|
||||
string memory minDomainName = "b";
|
||||
bytes32 minPublicKeyHash = bytes32(uint256(1));
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), minDomainName, minPublicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
dkim.setDKIMPublicKeyHash(minSelector, minDomainName, minPublicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(minDomainName)), minPublicKeyHash), "Invalid public key hash");
|
||||
}
|
||||
|
||||
function test_MaxLengthSelectorAndDomainName() public {
|
||||
string memory maxSelector = new string(256);
|
||||
string memory maxDomainName = new string(256);
|
||||
bytes32 aPublicKeyHash = bytes32(uint256(1));
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), maxDomainName, aPublicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
dkim.setDKIMPublicKeyHash(maxSelector, maxDomainName, aPublicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(maxDomainName)), aPublicKeyHash), "Invalid public key hash");
|
||||
}
|
||||
|
||||
function test_Revert_IfInvalidPublicKeyHash() public {
|
||||
bytes32 zeroPublicKeyHash = bytes32(0);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, zeroPublicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
vm.expectRevert("Invalid public key hash");
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, zeroPublicKeyHash, signature);
|
||||
}
|
||||
|
||||
function test_MaxValuePublicKeyHash() public {
|
||||
bytes32 maxPublicKeyHash = bytes32(type(uint256).max);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, maxPublicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, maxPublicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), maxPublicKeyHash), "Invalid public key hash");
|
||||
}
|
||||
|
||||
function test_SetDKIMPublicKeyHash() public {
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash), "Invalid public key hash");
|
||||
}
|
||||
|
||||
function test_SetDKIMPublicKeyHashMultiDomain() public {
|
||||
// vm.chainId(1);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash), "Invalid public key hash");
|
||||
|
||||
selector = "67890";
|
||||
domainName = "example2.com";
|
||||
publicKeyHash = bytes32(uint256(2));
|
||||
signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(v, r, s) = vm.sign(1, digest);
|
||||
signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash), "Invalid public key hash");
|
||||
}
|
||||
|
||||
function test_RevokeDKIMPublicKeyHash() public {
|
||||
// vm.chainId(1);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
|
||||
// Revoke
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, publicKeyHash);
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg)));
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, revokeSig);
|
||||
|
||||
require(!dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash));
|
||||
}
|
||||
|
||||
function test_RevertIfDuplicated() public {
|
||||
// vm.chainId(1);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash), "Invalid public key hash");
|
||||
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, digest);
|
||||
bytes memory signature1 = abi.encodePacked(r1, s1, v1);
|
||||
vm.expectRevert("publicKeyHash is already set");
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature1);
|
||||
}
|
||||
|
||||
function test_Revert_IfRevorked() public {
|
||||
// vm.chainId(1);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash), "Invalid public key hash");
|
||||
|
||||
// Revoke
|
||||
string memory revokeMsg = dkim.computeSignedMsg(dkim.REVOKE_PREFIX(), domainName, publicKeyHash);
|
||||
(uint8 v1, bytes32 r1, bytes32 s1) = vm.sign(1, MessageHashUtils.toEthSignedMessageHash(bytes(revokeMsg)));
|
||||
bytes memory revokeSig = abi.encodePacked(r1, s1, v1);
|
||||
dkim.revokeDKIMPublicKeyHash(selector, domainName, publicKeyHash, revokeSig);
|
||||
require(!dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash));
|
||||
|
||||
signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
(uint8 v2, bytes32 r2, bytes32 s2) = vm.sign(1, digest);
|
||||
bytes memory signature2 = abi.encodePacked(r2, s2, v2);
|
||||
vm.expectRevert("publicKeyHash is revoked");
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature2);
|
||||
}
|
||||
|
||||
function test_Revert_IfSignatureInvalid() public {
|
||||
// vm.chainId(1);
|
||||
string memory signedMsg = dkim.computeSignedMsg(dkim.SET_PREFIX(), domainName, publicKeyHash);
|
||||
bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(signedMsg));
|
||||
(uint8 v, bytes32 r, bytes32 s) = vm.sign(2, digest);
|
||||
bytes memory signature = abi.encodePacked(r, s, v);
|
||||
vm.expectRevert("Invalid signature");
|
||||
dkim.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature);
|
||||
}
|
||||
|
||||
function test_Dfinity_Oracle_Response() public {
|
||||
vm.chainId(1);
|
||||
{
|
||||
dkim = new ECDSAOwnedDKIMRegistry(0x6293A80BF4Bd3fff995a0CAb74CBf281d922dA02);
|
||||
}
|
||||
selector = "20230601";
|
||||
domainName = "gmail.com";
|
||||
publicKeyHash = 0x0ea9c777dc7110e5a9e89b13f0cfc540e3845ba120b2b6dc24024d61488d4788;
|
||||
dkim.setDKIMPublicKeyHash(
|
||||
selector,
|
||||
domainName,
|
||||
publicKeyHash,
|
||||
vm.parseBytes(
|
||||
"0xb491dad31ddd0fd9994e76e0325f29a0f44732c56220b6df0e2672750b87fb2d46e41069e3e93d88ee55e45bb6c712e2b077749c8392908a1a862432e68b104b1b"
|
||||
)
|
||||
);
|
||||
require(dkim.isKeyHashValid(keccak256(bytes(domainName)), publicKeyHash), "Invalid public key hash");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user