Created
September 8, 2021 09:56
-
-
Save earthchie/90efd4227b7b5e21c97ed03238f4d46b to your computer and use it in GitHub Desktop.
Verify blind signature for e-Election
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
N_factor ได้จาก public key ของกกต.