mirror of
https://github.com/3lLobo/zkAuth.git
synced 2026-01-09 12:27:55 -05:00
backend cleanup
This commit is contained in:
@@ -1,13 +1,40 @@
|
||||
# This is the bacqend, the smart-contract crib
|
||||
# This is the smart-contract crib
|
||||
|
||||

|
||||
|
||||
We proudly present the TotpAuthenticator.
|
||||
One step closer to zero trust and one step away from web2.
|
||||
You can now use 2FA authentication for your business contacts your web-applications or even your IOTs without a centralized database storing your keys and authenticating users. The Blocqchain takes over!
|
||||
We disclose the smart-logic, turing the wheels of the zkAuthenticator.
|
||||
One step closer to zero trust and away from web2.
|
||||
|
||||
The zkAuth onchain authentication can be invoked by both wallets and contracts.
|
||||
For optimal security and user-experience, incorporate it with 2nd gen Wallets (ERC 4337) or similar contracts supporting paymasters.
|
||||
|
||||
|
||||
|
||||
## The turing wheels
|
||||
|
||||
Here an walkthrough of our complete Turing contracts:
|
||||
|
||||
### zkWalletFactory
|
||||
|
||||
TODO:
|
||||
### HashCheckVerifier
|
||||
|
||||
TODO:
|
||||
|
||||
|
||||
### OtpMerkleTreeVerifier
|
||||
|
||||
TODO:
|
||||
|
||||
|
||||
|
||||
## Cyborg Run 🏃♂️
|
||||
|
||||
How to setup the project, compile the contracts, run the test and deploy.
|
||||
|
||||
@Rish check if you can scale scope the tests :)
|
||||
|
||||
|
||||
Yarn, remix and hardhat:
|
||||
|
||||
```shell
|
||||
@@ -18,16 +45,48 @@ yarn remixed -s . --remix-ide https://remix.ethereum.org
|
||||
yarn hardhat test
|
||||
```
|
||||
|
||||
## Optimism-Goerli Contracts
|
||||
|
||||
26.9.2022
|
||||
## Optimism
|
||||
|
||||
HashCeckVerifier = 0xDFD466d2A14cB2895f2C8BCacc67BDEF37C60De0
|
||||
OtpMerkleTreeVerifier = 0x87469041b414E1f2dEC2e79e32f4E911E7f50622
|
||||
ZkWalletFactory = 0x3279ed6de4392babc48a758eddd8687208dcbf4ec8531f17e9bd00ceb9c59e77
|
||||
A blocqchain with free lunch, I mean, free gas! How could we not choose for Optimism?
|
||||
|
||||
|
||||
## Hashing
|
||||
### Contracts on Optimism-Goerli
|
||||
|
||||
Last deployment: 26.9.2022
|
||||
|
||||
```js
|
||||
export const address = {
|
||||
zkWalletFactory: "0xcaF6c8C45c4fA0d2F6BFcE0c904FBedE08c773f1",
|
||||
HashCheckVerifier: "0xDFD466d2A14cB2895f2C8BCacc67BDEF37C60De0",
|
||||
OtpMerkleTreeVerifier: "0x87469041b414E1f2dEC2e79e32f4E911E7f50622",
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Contract TotpAuthenticator deployed to Optimism Goerli:
|
||||
|
||||
```bash
|
||||
0xfa99801Ec6BeFcbfC1eB2d12dc8255453574b276
|
||||
# Deployment transaction hash
|
||||
0x846528416731ddd42e37b8f2dc9fbac24aaf105ebe23d53707a680fc99d68ce0
|
||||
``` -->
|
||||
|
||||
Deployer wallet:
|
||||
|
||||
```sh
|
||||
0x369551E7c1D29756e18BA4Ed7f85f2E6663e1e8d
|
||||
```
|
||||
|
||||
[Testnet Explorer](https://blockscout.com/optimism/goerli)
|
||||
|
||||
[Faucets](https://optimismfaucet.xyz/)
|
||||
|
||||
|
||||
## Notes4devs
|
||||
|
||||
A collection of more and less relevant technical tips and hacqs for our fellow devs and future selfs.
|
||||
|
||||
### Onchain sha256 Hashing
|
||||
|
||||
How to calculate and submit hash:
|
||||
|
||||
@@ -41,36 +100,3 @@ That's it, now it should match the sha256 on-chain.
|
||||
|
||||
[bytes32](https://web3-type-converter.onbrn.com/)
|
||||
[sha256 from hex](https://www.liavaag.org/English/SHA-Generator/)
|
||||
|
||||
## Optimism
|
||||
|
||||
A blocqchain with free lunch, I mean, free gas! How could we not choose for Optimism?
|
||||
|
||||
Contract TotpAuthenticator deployed to Optimism Goerli:
|
||||
|
||||
```bash
|
||||
0xfa99801Ec6BeFcbfC1eB2d12dc8255453574b276
|
||||
# Deployment transaction hash
|
||||
0x846528416731ddd42e37b8f2dc9fbac24aaf105ebe23d53707a680fc99d68ce0
|
||||
```
|
||||
|
||||
Also on Main Goerli bcs Opt Goerli goes not yet get indexed by theGraph:
|
||||
|
||||
```bash
|
||||
0x5E9607EE52286732A5E3A0Fc57dF367bCb8adAa5
|
||||
# Tx hash
|
||||
0x1462f472eb8cda174a47529f6ea0be6a97965e175be9f7f3709a54844228f24a
|
||||
```
|
||||
|
||||
It's the same address, ain't that funney 🤔
|
||||
**Update** not the same anymore after debugging the contract and redeploying. Curious if the new contract would again give the same pub address on Optimism - nope.
|
||||
|
||||
Owner wallet:
|
||||
|
||||
```sh
|
||||
0x369551E7c1D29756e18BA4Ed7f85f2E6663e1e8d
|
||||
```
|
||||
|
||||
[Testnet Explorer](https://blockscout.com/optimism/goerli)
|
||||
|
||||
[Faucets](https://optimismfaucet.xyz/)
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
// Uncomment this line to use console.log
|
||||
// import 'hardhat/console.sol';
|
||||
import '@openzeppelin/contracts/access/Ownable.sol';
|
||||
|
||||
struct AuthData {
|
||||
// fist five digits of the 6-digit totp code tail-padded with a zero and finally parsed to a single number
|
||||
uint256 totp5;
|
||||
// Teh sha256 hash of the complete code parsed to a single number.
|
||||
bytes32 totp6hash;
|
||||
// time-stamp of TOTP code creation.
|
||||
uint256 time;
|
||||
}
|
||||
|
||||
struct Authentication {
|
||||
bool isValid;
|
||||
uint256 time;
|
||||
}
|
||||
|
||||
contract TotpAuthenticator is Ownable {
|
||||
// Counter provides requestId and increments with each request
|
||||
uint256 public requestCounter;
|
||||
// Maps a requestId to the requestor/validator and to the auth requested address
|
||||
mapping(uint256 => address[2]) public requests;
|
||||
// Maps a requestId to a address and its response.
|
||||
mapping(uint256 => AuthData) public responses;
|
||||
// Maps requestId to completes authentication
|
||||
// TODO: make this private and create a function to get this value, which initially checks if the requested Id is below the current counter. Otherwise collisions can happen after reset.
|
||||
mapping(uint256 => Authentication) public completedAuth;
|
||||
|
||||
// Events to index with theGraph in order to notify both parties
|
||||
event EventAuthRequest(address requestor, address target, uint256 requestId);
|
||||
event EventAuthResponse(
|
||||
address responder,
|
||||
uint256 requestId,
|
||||
AuthData response
|
||||
);
|
||||
event EventAuthValid(uint256 requestId, Authentication authentication);
|
||||
event EventResetContract(uint256 time);
|
||||
|
||||
// Create a request for a wallet to authenticate.
|
||||
function setRequest(address _target) public {
|
||||
uint256 _currentCount = requestCounter;
|
||||
requests[_currentCount] = [msg.sender, _target];
|
||||
requestCounter++;
|
||||
|
||||
emit EventAuthRequest(msg.sender, _target, _currentCount);
|
||||
}
|
||||
|
||||
// Submit a repsonse to an authentication request
|
||||
function setResponse(
|
||||
uint256 _requestId,
|
||||
uint256 _totp5,
|
||||
bytes32 _totp6hash,
|
||||
uint256 _time
|
||||
) public {
|
||||
// require reqId lover than count
|
||||
require(_requestId < requestCounter, 'ResuestId too high');
|
||||
require(
|
||||
requests[_requestId][1] == msg.sender,
|
||||
'This Auth requestId does not match this wallet'
|
||||
);
|
||||
require(completedAuth[_requestId].time == 0, 'Request already authorized');
|
||||
require(responses[_requestId].totp5 == 0, 'Response already submitted');
|
||||
AuthData memory _authData = AuthData(_totp5, _totp6hash, _time);
|
||||
responses[_requestId] = _authData;
|
||||
|
||||
emit EventAuthResponse(msg.sender, _requestId, _authData);
|
||||
}
|
||||
|
||||
// // The Requestor can get the repsonse data. Preferably though the event indexer graph
|
||||
// function getResponses(uint256 _requestId, address _responder)
|
||||
// public
|
||||
// view
|
||||
// returns (AuthData memory)
|
||||
// {
|
||||
// // Assert that caller created the AuthRequest
|
||||
// require(isValidator(_requestId), 'U did not submit this request');
|
||||
// // Don't think it's allowed to return a mapping
|
||||
// return responses[_requestId][_responder];
|
||||
// }
|
||||
|
||||
// @param _requestId the id of the request
|
||||
// @_responseAddress the address which submitted the valid response
|
||||
function authenticate(uint256 _requestId, uint256 _lastDigit) public {
|
||||
// Assert that caller created the AuthRequest
|
||||
require(isValidator(_requestId), 'Validation only by requestor');
|
||||
require(
|
||||
responses[_requestId].time > 0,
|
||||
'No auth response from this wallet'
|
||||
);
|
||||
|
||||
AuthData memory _authData = responses[_requestId];
|
||||
bool _isValid = checkHash(_authData.totp5, _lastDigit, _authData.totp6hash);
|
||||
require(_isValid, 'On-chain validation failed');
|
||||
|
||||
Authentication memory authentication = Authentication(
|
||||
_isValid,
|
||||
block.timestamp
|
||||
);
|
||||
completedAuth[_requestId] = authentication;
|
||||
|
||||
emit EventAuthValid(_requestId, authentication);
|
||||
}
|
||||
|
||||
// Returns the authentication details for a completed requestId
|
||||
function getAuthentication(uint256 _requestId)
|
||||
public
|
||||
view
|
||||
returns (Authentication memory)
|
||||
{
|
||||
return completedAuth[_requestId];
|
||||
}
|
||||
|
||||
// Reset the contract by deleting all data
|
||||
function resetAuthenticator() public onlyOwner {
|
||||
requestCounter = 0;
|
||||
// TODO: create zero AuthResponse and set the responses[_requestId] = zeroAuthResponse each time a request is initalized.
|
||||
// How do we empty the mappings?
|
||||
emit EventResetContract(block.timestamp);
|
||||
}
|
||||
|
||||
// Check if the sender also submitted the request
|
||||
function isValidator(uint256 _requestId) private view returns (bool) {
|
||||
return msg.sender == requests[_requestId][0];
|
||||
}
|
||||
|
||||
function toBytes(uint256 x) private pure returns (bytes memory b) {
|
||||
b = new bytes(32);
|
||||
assembly {
|
||||
mstore(add(b, 32), x)
|
||||
}
|
||||
}
|
||||
|
||||
// Multiply the 5 didgit response by 10 (smiliar to padding with zero) and add the 6st digit. Then compare the hashes.
|
||||
function checkHash(
|
||||
uint256 _totp5,
|
||||
uint256 _lastDigit,
|
||||
bytes32 _totp6hash
|
||||
) private pure returns (bool) {
|
||||
uint256 _totp6 = _totp5 * 10 + _lastDigit;
|
||||
|
||||
// console.log('number totp6');
|
||||
// console.log(_totp6);
|
||||
// bytes memory bytestotp6 = toBytes(_totp6);
|
||||
|
||||
// console.log('bytes of totp6');
|
||||
// console.logBytes(bytestotp6);
|
||||
|
||||
// bytes32 shatotp6 = sha256(toBytes(_totp6));
|
||||
// console.log('Sha shatotp6');
|
||||
// console.logBytes32(shatotp6);
|
||||
// console.log('original _totp6hash');
|
||||
// console.logBytes32(_totp6hash);
|
||||
|
||||
return sha256(toBytes(_totp6)) == _totp6hash;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user