Skip to content

Instantly share code, notes, and snippets.

@earthchie
Created September 8, 2021 09:56
Show Gist options
  • Save earthchie/90efd4227b7b5e21c97ed03238f4d46b to your computer and use it in GitHub Desktop.
Save earthchie/90efd4227b7b5e21c97ed03238f4d46b to your computer and use it in GitHub Desktop.
Verify blind signature for e-Election
// SPDX-License-Identifier: COPYRIGHT 2021 DOMECLOUD CO. LTD. ALL RIGHTS RESERVED.
pragma solidity >=0.4.20 <0.6;
import "hardhat/console.sol";
contract Election{
// N factor can be retrived from Election Comission's public key.
// use for Blind Signature verification
bytes public N_factor;
constructor(bytes memory N) public {
N_factor = N;
}
function verifySignature(bytes memory ballotBody, bytes memory ballotSignature) public view returns (bool){
uint E_factor = 65537; // always 65537 for RSA-2048 public key
// sha256 body of ballot
bytes memory bodyHash = abi.encodePacked(sha256(ballotBody));
bytes32 compare_item_1 = keccak256(bodyHash); // prepare for compare
// decipher signature
bytes memory decipher = modexp(ballotSignature, abi.encodePacked(E_factor), N_factor);
bytes32 compare_item_2 = keccak256(decipher); // prepare for compare
return compare_item_1 == compare_item_2; // compare ballot body with signature
}
function modexp(bytes memory _base, bytes memory _exp, bytes memory _mod) private view returns(bytes memory ret) {
assembly {
let bl := mload(_base)
let el := mload(_exp)
let ml := mload(_mod)
let freemem := mload(0x40) // Free memory pointer is always stored at 0x40
mstore(freemem, bl) // arg[0] = base.length @ +0
mstore(add(freemem,32), el) // arg[1] = exp.length @ +32
mstore(add(freemem,64), ml) // arg[2] = mod.length @ +64
// arg[3] = base.bits @ + 96
// Use identity built-in (contract 0x4) as a cheap memcpy
let success := staticcall(450, 0x4, add(_base,32), bl, add(freemem,96), bl)
// arg[4] = exp.bits @ +96+base.length
let size := add(96, bl)
success := staticcall(450, 0x4, add(_exp,32), el, add(freemem,size), el)
// arg[5] = mod.bits @ +96+base.length+exp.length
size := add(size,el)
success := staticcall(450, 0x4, add(_mod,32), ml, add(freemem,size), ml)
switch success case 0 { invalid() } //fail where we haven't enough gas to make the call
// Total size of input = 96+base.length+exp.length+mod.length
size := add(size,ml)
// Invoke contract 0x5, put return value right after mod.length, @ +96
success := staticcall(sub(gas, 1350), 0x5, freemem, size, add(96,freemem), ml)
switch success case 0 { invalid() } //fail where we haven't enough gas to make the call
let length := ml
let length_ptr := add(96,freemem)
///the following code removes any leading words containing all zeroes in the result.
//start_ptr := add(start_ptr,0x20)
for { } eq ( eq(mload(length_ptr), 0), 1) { } {
length_ptr := add(length_ptr, 0x20) //push up the start pointer for the result..
length := sub(length,0x20) //and subtract a word (32 bytes) from the result length.
}
ret := sub(length_ptr,0x20)
mstore(ret, length)
// point to the location of the return value (length, bits)
//assuming mod length is multiple of 32, return value is already in the right format.
//function visibility is changed to internal to reflect this.
//ret := add(64,freemem)
mstore(0x40, add(add(96, freemem),ml)) //deallocate freemem pointer
}
}
}
@earthchie
Copy link
Author

earthchie commented Sep 8, 2021

// hardhat
await Contract.deploy(N_factor);

N_factor ได้จาก public key ของกกต.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment