Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add OidcKeyRegistry contract #4

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
6 changes: 6 additions & 0 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const ACCOUNT_IMPL_NAME = "SsoAccount";
const FACTORY_NAME = "AAFactory";
const PAYMASTER_NAME = "ExampleAuthServerPaymaster";
const BEACON_NAME = "SsoBeacon";
const OIDC_KEY_REGISTRY_NAME = "OidcKeyRegistry";

async function deploy(name: string, deployer: Wallet, proxy: boolean, args?: any[], initArgs?: any): Promise<string> {
// eslint-disable-next-line @typescript-eslint/no-require-imports
Expand Down Expand Up @@ -84,6 +85,8 @@ task("deploy", "Deploys ZKsync SSO contracts")
const guardianInterface = new ethers.Interface((await hre.artifacts.readArtifact(GUARDIAN_RECOVERY_NAME)).abi);
const recovery = await deploy(GUARDIAN_RECOVERY_NAME, deployer, !cmd.noProxy, [webauth], guardianInterface.encodeFunctionData("initialize", [webauth]));
const paymaster = await deploy(PAYMASTER_NAME, deployer, false, [factory, sessions, recovery]);
const oidcKeyRegistryInterface = new ethers.Interface((await hre.artifacts.readArtifact(OIDC_KEY_REGISTRY_NAME)).abi);
await deploy(OIDC_KEY_REGISTRY_NAME, deployer, !cmd.noProxy, [], oidcKeyRegistryInterface.encodeFunctionData("initialize", []));
matias-gonz marked this conversation as resolved.
Show resolved Hide resolved

await fundPaymaster(paymaster, cmd.fund);
} else {
Expand All @@ -107,6 +110,9 @@ task("deploy", "Deploys ZKsync SSO contracts")
}
args = [cmd.factory, cmd.sessions];
}
if (cmd.only == OIDC_KEY_REGISTRY_NAME) {
args = [];
}
const deployedContract = await deploy(cmd.only, deployer, false, args);

if (cmd.only == PAYMASTER_NAME) {
Expand Down
55 changes: 55 additions & 0 deletions src/OidcKeyRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract OidcKeyRegistry is Initializable, OwnableUpgradeable {
uint8 public constant MAX_KEYS = 5;

struct Key {
bytes32 kid; // Key ID
bytes n; // RSA modulus
bytes e; // RSA exponent
}

// Mapping uses keccak256(iss) as the key
mapping(bytes32 => Key[MAX_KEYS]) public OIDCKeys; // Stores up to MAX_KEYS per issuer
mapping(bytes32 => uint8) public keyIndexes; // Tracks the latest key index for each issuer

constructor() {
initialize();
}

function initialize() public initializer {
__Ownable_init();
}

function hashIssuer(string memory iss) public pure returns (bytes32) {
return keccak256(abi.encodePacked(iss));
}

function setKey(bytes32 issHash, Key memory key) public onlyOwner {
uint8 index = keyIndexes[issHash];
uint8 nextIndex = (index + 1) % MAX_KEYS; // Circular buffer
OIDCKeys[issHash][nextIndex] = key;
keyIndexes[issHash] = nextIndex;
}

function setKeys(bytes32 issHash, Key[] memory keys) public onlyOwner {
for (uint8 i = 0; i < keys.length; i++) {
setKey(issHash, keys[i]);
}
}

function getKey(bytes32 issHash, bytes32 kid) public view returns (Key memory) {
matias-gonz marked this conversation as resolved.
Show resolved Hide resolved
require(kid != 0, "Invalid kid");
Key[MAX_KEYS] storage keys = OIDCKeys[issHash];
for (uint8 i = 0; i < MAX_KEYS; i++) {
if (keys[i].kid == kid) {
return keys[i];
}
}
revert("Key not found");
}
}