Skip to content

Commit

Permalink
fixed and added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Arvolear committed Apr 10, 2024
1 parent a2d3d99 commit fe4d047
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 104 deletions.
64 changes: 32 additions & 32 deletions contracts/authenticators/RSASHA1Authenticator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,42 @@ pragma solidity 0.8.16;

import {SHA1} from "../utils/SHA1.sol";

library RSASHA1Authenticator {
contract RSASHA1Authenticator {
using SHA1 for bytes;

uint256 constant HASH_LEN = 20;

function decrypt(
function authenticate(
bytes memory challenge_,
bytes memory s_,
bytes memory e_,
bytes memory n_
) external view returns (bool) {
if (s_.length == 0 || e_.length == 0 || n_.length == 0) {
return false;
}

bytes memory decipher_ = _decrypt(s_, e_, n_);

assembly {
mstore(decipher_, sub(mload(decipher_), 1))
}

bytes memory prepared_ = new bytes(decipher_.length - HASH_LEN - 1);
bytes memory digest_ = new bytes(HASH_LEN);

for (uint256 i = 0; i < prepared_.length; ++i) {
prepared_[i] = decipher_[i + 1];
}

for (uint256 i = 0; i < digest_.length; ++i) {
digest_[i] = decipher_[decipher_.length - HASH_LEN + i];
}

return bytes20(digest_) == abi.encodePacked(prepared_, challenge_).sha1();
}

function _decrypt(
bytes memory s_,
bytes memory e_,
bytes memory n_
Expand Down Expand Up @@ -39,34 +69,4 @@ library RSASHA1Authenticator {
)
}
}

function authenticate(
bytes memory challenge_,
bytes memory s_,
bytes memory e_,
bytes memory n_
) internal view returns (bool) {
if (s_.length == 0 || e_.length == 0 || n_.length == 0) {
return false;
}

bytes memory decipher_ = decrypt(s_, e_, n_);

assembly {
mstore(decipher_, sub(mload(decipher_), 1))
}

bytes memory prepared_ = new bytes(decipher_.length - HASH_LEN - 1);
bytes memory digest_ = new bytes(HASH_LEN);

for (uint256 i = 0; i < prepared_.length; ++i) {
prepared_[i] = decipher_[i + 1];
}

for (uint256 i = 0; i < digest_.length; ++i) {
digest_[i] = decipher_[decipher_.length - HASH_LEN + i];
}

return bytes20(digest_) == abi.encodePacked(prepared_, challenge_).sha1();
}
}
15 changes: 12 additions & 3 deletions contracts/dispatchers/RSASHA1Dispatcher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ import {RSASHA1Authenticator} from "../authenticators/RSASHA1Authenticator.sol";

contract RSASHA1Dispatcher is IPassportDispatcher, Initializable {
using VerifierHelper for address;
using RSASHA1Authenticator for bytes;

uint256 public constant E = 65537;

address public authenticator;
address public verifier;

function __RSASHA1Dispather_init(address verifier_) external initializer {
function __RSASHA1Dispatcher_init(
address authenticator_,
address verifier_
) external initializer {
authenticator = authenticator_;
verifier = verifier_;
}

Expand All @@ -28,7 +32,12 @@ contract RSASHA1Dispatcher is IPassportDispatcher, Initializable {
bytes memory passportPublicKey_
) external view returns (bool) {
return
challenge_.authenticate(passportSignature_, abi.encodePacked(E), passportPublicKey_);
RSASHA1Authenticator(authenticator).authenticate(
challenge_,
passportSignature_,
abi.encodePacked(E),
passportPublicKey_
);
}

function verifyZKProof(
Expand Down
17 changes: 0 additions & 17 deletions contracts/mock/authenticators/RSASHA1AuthenticatorMock.sol

This file was deleted.

5 changes: 5 additions & 0 deletions contracts/registration/Registration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ contract Registration is OwnableUpgradeable, PoseidonSMT, TSSSigner {
address signer_,
bytes32 icaoMasterTreeMerkleRoot_
) external initializer {
__Ownable_init();
__PoseidonSMT_init(treeHeight_);
__TSSSigner_init(signer_);

Expand Down Expand Up @@ -204,6 +205,10 @@ contract Registration is OwnableUpgradeable, PoseidonSMT, TSSSigner {
delete passportDispatchers[dispatcherType_];
}

function getDispatcher(bytes32 dispatcherType_) external view returns (address) {
return address(passportDispatchers[dispatcherType_]);
}

function getPassportInfo(
bytes32 passportKey_
)
Expand Down
39 changes: 29 additions & 10 deletions deploy/1_setup.migration.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
import { ethers } from "hardhat";
import { Deployer, Reporter } from "@solarity/hardhat-migrate";
import { deployPoseidons } from "./helpers/helper";

import { Registration__factory, RegistrationVerifier__factory } from "@ethers-v6";
import {
Registration__factory,
RSASHA1Dispatcher__factory,
RSASHA1Authenticator__factory,
RSASHA1Verifier__factory,
} from "@ethers-v6";

import { RSA_SHA1_2688 } from "@/scripts/utils/passport-types";

const treeHeight = 80;
const tssSigner = "0x038D006846a3e203738cF80A02418e124203beb2";
const icaoMasterTreeMerkleRoot = "0x2c50ce3aa92bc3dd0351a89970b02630415547ea83c487befbc8b1795ea90c45";

const deployRSASHA1Disaptcher = async (deployer: Deployer) => {
const rsaSha1Verifier = await deployer.deploy(RSASHA1Verifier__factory);
const rsaSha1Authenticator = await deployer.deploy(RSASHA1Authenticator__factory);
const rsaSha1Dispatcher = await deployer.deploy(RSASHA1Dispatcher__factory);

await rsaSha1Dispatcher.__RSASHA1Dispatcher_init(
await rsaSha1Authenticator.getAddress(),
await rsaSha1Verifier.getAddress(),
);

return rsaSha1Dispatcher;
};

export = async (deployer: Deployer) => {
await deployPoseidons(deployer, [1, 2, 3, 5]);

const rsaSha1Dispatcher = await deployRSASHA1Disaptcher(deployer);
const registration = await deployer.deploy(Registration__factory);
const registrationVerifier = await deployer.deploy(RegistrationVerifier__factory);

await registration.__Registration_init(
treeHeight,
tssSigner,
await registrationVerifier.getAddress(),
icaoMasterTreeMerkleRoot,
);
await registration.__Registration_init(treeHeight, tssSigner, icaoMasterTreeMerkleRoot);

Reporter.reportContracts(["Registration", `${await registration.getAddress()}`]);
await registration.addDispatcher(RSA_SHA1_2688, await rsaSha1Dispatcher.getAddress());

Reporter.reportContracts(
["Registration", `${await registration.getAddress()}`],
["RSASHA1Dispatcher", `${await rsaSha1Dispatcher.getAddress()}`],
);
};
4 changes: 4 additions & 0 deletions scripts/utils/passport-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { ethers } from "hardhat";

export const RSA_SHA1_2688 = ethers.solidityPackedKeccak256(["string"], ["RSA_SHA1_2688"]);
export const RSA_SHA1_2704 = ethers.solidityPackedKeccak256(["string"], ["RSA_SHA1_2704"]);
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ import { ethers } from "hardhat";
import { expect } from "chai";
import { Reverter } from "@/test/helpers/";

import { RSAVerifierMock } from "@ethers-v6";
import { RSASHA1Authenticator } from "@ethers-v6";

describe("RSA", () => {
describe("RSASHA1Authenticator", () => {
const reverter = new Reverter();

let rsaVerifier: RSAVerifierMock;
let auth: RSASHA1Authenticator;

before("setup", async () => {
const RSAVerifierMock = await ethers.getContractFactory("RSAVerifierMock");
const RSASHA1Authenticator = await ethers.getContractFactory("RSASHA1Authenticator");

rsaVerifier = await RSAVerifierMock.deploy();
auth = await RSASHA1Authenticator.deploy();

await reverter.snapshot();
});

afterEach(reverter.revert);

describe("#verify", () => {
it("should verify passport signature", async () => {
describe("#authenticate", () => {
it("should authenticate passport", async () => {
const challenge = "0x5119311531111100";

const signature =
Expand All @@ -29,7 +29,7 @@ describe("RSA", () => {
const modulus =
"0xd21f63969effab33383ab4f8a3955739ad8ae14879d17509b4f444284e52de3956ed40e5245ea8d9db9540c7ed21aa5ca17fb84f1651d218d183a19b017d80335dbcc2e8c5c2ba1705235ac897f942190d2a2ad60119178ef2b555ea5772c65a32bf42699ee512949235702c7b9d2176e498fef69be5651f8434686f7aa1adf7";

expect(await rsaVerifier.verifyPassport(challenge, signature, exponent, modulus)).to.be.true;
expect(await auth.authenticate(challenge, signature, exponent, modulus)).to.be.true;
});
});
});
119 changes: 119 additions & 0 deletions test/dispatchers/RSASHA1Dispatcher.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { ethers } from "hardhat";
import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
import { expect } from "chai";
import { Reverter, deployPoseidons, getPoseidon } from "@/test/helpers/";

import { RSASHA1Dispatcher } from "@ethers-v6";
import { VerifierHelper } from "@/generated-types/ethers/contracts/dispatchers/RSASHA1Dispatcher";

describe("RSASHA1Dispatcher", () => {
const reverter = new Reverter();

let OWNER: SignerWithAddress;

let dispatcher: RSASHA1Dispatcher;

before("setup", async () => {
[OWNER] = await ethers.getSigners();

await deployPoseidons(OWNER, [5], false);

const RSASHA1Verifier = await ethers.getContractFactory("RSASHA1Verifier");
const RSASHA1Authenticator = await ethers.getContractFactory("RSASHA1Authenticator");
const RSASHA1Dispatcher = await ethers.getContractFactory("RSASHA1Dispatcher", {
libraries: {
PoseidonUnit5L: await (await getPoseidon(5)).getAddress(),
},
});

dispatcher = await RSASHA1Dispatcher.deploy();

const rsaSha1Verifier = await RSASHA1Verifier.deploy();
const rsaSha1Authenticator = await RSASHA1Authenticator.deploy();
dispatcher = await RSASHA1Dispatcher.deploy();

await dispatcher.__RSASHA1Dispatcher_init(
await rsaSha1Authenticator.getAddress(),
await rsaSha1Verifier.getAddress(),
);

await reverter.snapshot();
});

afterEach(reverter.revert);

describe("#init", () => {
it("should not init twice", async () => {
expect(
dispatcher.__RSASHA1Dispatcher_init(
ethers.hexlify(ethers.randomBytes(20)),
ethers.hexlify(ethers.randomBytes(20)),
),
).to.be.revertedWith("Initializable: contract is already initialized");
});
});

describe("#authenticate", () => {
it("should authenticate", async () => {
const challenge = "0x69c8975afb4717e5";
const signature =
"0xad778f0761f791cef96619cefd7709c031eeaec86c158eb5d58ad636bc494bd84cd2bc9cf21e27ff17479abbecc7bfa284f9d20505b129db8c02cbf9cacc7f883e4d2552565854ec6db2ec736133eea3d6cd0ce514c413ecc7e73dabe7bd09b96638048aff55cd495b800b93c4d8f6ca52c1bd11727aa03056dafcb83ea18364";
const publicKey =
"0xae782184c70d1c9829be95f23b2c21abf5a82019a6648b933ca8abe4dc837582068d45d0b5f94cc4cd4c7cde9bef0f4d79534469997d95018e6391d294000d536c2654f79a829ff8cb74a32fdbbab73e16cab87ff600344ef9dda6cc11c4d67672d66e875bbacd4de1e5b2d4efdd50b027bc16f357218c345861c1bc8f38b28d";

expect(await dispatcher.authenticate(challenge, signature, publicKey)).to.be.true;
});
});

describe("#zkProof", () => {
it("should verify the zk proof", async () => {
const formattedProof: VerifierHelper.ProofPointsStruct = {
a: [
"0x27f38de50a94be7ee0800af286e325c7f511fbf0efc5a2e5f0ebe91452afc2de",
"0x1f83fc36e33638f87842f9b73b2dd5d78b3f0739916ba5de83cd649ab9832188",
],
b: [
[
"0x01002b749e10d2c8c5b1096bc357ad5c717cea22e3dcf74ff6d54c48c7a6996e",
"0x2d150a719a453e518547933898b3018ee0c411cab31fa1e65c2a7d23ed1db71f",
],
[
"0x291074f584c7ccd96d5eaf4343b5cd845958f878be4d48475bbb04dea0eb423a",
"0x2806f8db67b0903f06d519fa4f19f4b24ec46cb23e54cbe1d2a78abb6010fbf1",
],
],
c: [
"0x040a8f87dafa269268d4f8ac56b555c827575c39b329dbd05d4f8747df0f1727",
"0x18d2c06b3d99d63d5ae9fa29b560f6cad6d213f7974d2f187fb17d6e1cdc8e21",
],
};
const publicSignals = [
"0x2baee9a30a3e327ebe5153524acfde2674bb4d54146c903ed8969c94d1f20301",
"0x2d7a28fe5dcf90a75e00ebb85bf867efec70b2644f4533e617710ed8b816c5f8",
"0x07fe70c27b421e662c5099a884fc3291d8893391740320be101514d74801c43f",
"0x2c50ce3aa92bc3dd0351a89970b02630415547ea83c487befbc8b1795ea90c45",
];

expect(await dispatcher.verifyZKProof(publicSignals, formattedProof)).to.be.true;
});
});

describe("#getPassportChallenge", () => {
it("should get the challenge correctly", async () => {
const input = "0xced3831dcf3a96049d93cbbd3eaa0010f3b97a70ef591269c8975afb4717e5";
const result = "0x69c8975afb4717e5";

expect(await dispatcher.getPassportChallenge(input)).to.equal(result);
});
});

describe("#getPassportKey", () => {
it("should get the key correctly", async () => {
const input =
"0xae782184c70d1c9829be95f23b2c21abf5a82019a6648b933ca8abe4dc837582068d45d0b5f94cc4cd4c7cde9bef0f4d79534469997d95018e6391d294000d536c2654f79a829ff8cb74a32fdbbab73e16cab87ff600344ef9dda6cc11c4d67672d66e875bbacd4de1e5b2d4efdd50b027bc16f357218c345861c1bc8f38b28d";
const result = "0x2baee9a30a3e327ebe5153524acfde2674bb4d54146c903ed8969c94d1f20301";

expect(await dispatcher.getPassportKey(input)).to.equal(result);
});
});
});
Loading

0 comments on commit fe4d047

Please sign in to comment.