-
Notifications
You must be signed in to change notification settings - Fork 29
Added Schnorr Signature & EC256 libraries #142
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
Merged
Merged
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
4d69bb8
init bn254 & schnorr
dovgopoly 99953b8
fixes & added basic test for schnorr
dovgopoly 1325d23
small adjustments
dovgopoly afc9ad9
rewrote schnorr for any curve
dovgopoly c775895
adjustments
dovgopoly d006fbd
refactored
dovgopoly bd67b74
refactored
dovgopoly 2f9084a
refactored ecdsa
dovgopoly bb7278f
renamed
dovgopoly 39d04e5
rm unused fn
dovgopoly 0a18ae7
added docs
dovgopoly aef3904
upd comment
dovgopoly 8b0ba21
added tests
dovgopoly 56f5611
basic fixes
dovgopoly 17228c6
fix
dovgopoly af5b6df
fixes
dovgopoly 14e74aa
bumped version
dovgopoly 1d6cff5
cov 100
dovgopoly cc17f8a
upd readme
dovgopoly eb6bceb
quick readme fix
Arvolear File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.21; | ||
|
||
library BN254 { | ||
uint256 internal constant SCALAR_FIELD_SIZE = | ||
21888242871839275222246405745257275088548364400416034343698204186575808495617; | ||
uint256 internal constant BASE_FIELD_SIZE = | ||
21888242871839275222246405745257275088696311157297823662689037894645226208583; | ||
|
||
struct Scalar { | ||
uint256 data; | ||
} | ||
|
||
struct G1Affine { | ||
uint256 x; | ||
uint256 y; | ||
} | ||
|
||
function g1Basepoint() internal pure returns (G1Affine memory basepoint_) { | ||
return G1Affine(1, 2); | ||
} | ||
|
||
function scalarFromUint256(uint256 a_) internal pure returns (Scalar memory scalar_) { | ||
scalar_ = Scalar(a_); | ||
|
||
require(validateScalar(scalar_), "BN: invalid scalar"); | ||
} | ||
|
||
function scalarFromUint256ModScalar(uint256 a_) internal pure returns (Scalar memory scalar_) { | ||
return Scalar(a_ % SCALAR_FIELD_SIZE); | ||
} | ||
|
||
function g1PointFromAffine( | ||
uint256 x_, | ||
uint256 y_ | ||
) internal pure returns (G1Affine memory point_) { | ||
point_ = G1Affine(x_, y_); | ||
|
||
require(validateG1Point(point_), "BN254: invalid point"); | ||
} | ||
|
||
function pointNeg(G1Affine memory a_) internal pure returns (G1Affine memory r_) { | ||
dovgopoly marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return G1Affine(a_.x, BASE_FIELD_SIZE - a_.y); | ||
} | ||
|
||
function pointEqual( | ||
G1Affine memory a_, | ||
G1Affine memory b_ | ||
) internal pure returns (bool isEqual_) { | ||
return a_.x == b_.x && a_.y == b_.y; | ||
} | ||
|
||
function pointSub( | ||
G1Affine memory a_, | ||
G1Affine memory b_ | ||
) internal view returns (G1Affine memory r_) { | ||
return pointAdd(a_, pointNeg(b_)); | ||
} | ||
|
||
function pointAdd( | ||
G1Affine memory a_, | ||
G1Affine memory b_ | ||
) internal view returns (G1Affine memory r_) { | ||
assembly { | ||
let call_ := mload(0x40) | ||
mstore(0x40, add(call_, 0x80)) | ||
|
||
mstore(call_, mload(a_)) | ||
mstore(add(call_, 0x20), mload(add(a_, 0x20))) | ||
mstore(add(call_, 0x40), mload(b_)) | ||
mstore(add(call_, 0x60), mload(add(b_, 0x20))) | ||
|
||
pop(staticcall(gas(), 0x6, call_, 0x80, r_, 0x40)) | ||
} | ||
} | ||
|
||
function pointMul( | ||
G1Affine memory p_, | ||
Scalar memory a_ | ||
) internal view returns (G1Affine memory r_) { | ||
assembly { | ||
let call_ := mload(0x40) | ||
mstore(0x40, add(call_, 0x60)) | ||
|
||
mstore(call_, mload(p_)) | ||
mstore(add(call_, 0x20), mload(add(p_, 0x20))) | ||
mstore(add(call_, 0x40), mload(a_)) | ||
|
||
pop(staticcall(gas(), 0x7, call_, 0x60, r_, 0x40)) | ||
} | ||
} | ||
|
||
function basepointMul(Scalar memory a_) internal view returns (G1Affine memory point_) { | ||
return pointMul(g1Basepoint(), a_); | ||
} | ||
|
||
function scalarAdd( | ||
Scalar memory a_, | ||
Scalar memory b_ | ||
) internal pure returns (Scalar memory r_) { | ||
return Scalar(addmod(a_.data, b_.data, SCALAR_FIELD_SIZE)); | ||
} | ||
|
||
function scalarSub( | ||
Scalar memory a_, | ||
Scalar memory b_ | ||
) internal pure returns (Scalar memory r_) { | ||
if (a_.data > b_.data) { | ||
return Scalar(a_.data - b_.data); | ||
} | ||
|
||
return Scalar(SCALAR_FIELD_SIZE - (b_.data - a_.data)); | ||
} | ||
|
||
function scalarMul( | ||
Scalar memory a_, | ||
Scalar memory b_ | ||
) internal pure returns (Scalar memory r_) { | ||
return Scalar(mulmod(a_.data, b_.data, SCALAR_FIELD_SIZE)); | ||
} | ||
|
||
function validateScalar(BN254.Scalar memory scalar_) internal pure returns (bool isValid_) { | ||
return scalar_.data < SCALAR_FIELD_SIZE; | ||
} | ||
|
||
function validateG1Point(BN254.G1Affine memory point_) internal pure returns (bool isValid_) { | ||
if (point_.x == 0 && point_.y == 0) { | ||
return true; | ||
} | ||
|
||
if (point_.x > BASE_FIELD_SIZE || point_.y > BASE_FIELD_SIZE) { | ||
return false; | ||
} | ||
|
||
uint256 lhs_ = mulmod(point_.y, point_.y, BASE_FIELD_SIZE); | ||
uint256 rhs_ = mulmod(point_.x, point_.x, BASE_FIELD_SIZE); | ||
rhs_ = mulmod(rhs_, point_.x, BASE_FIELD_SIZE); | ||
rhs_ = (rhs_ + 3) % BASE_FIELD_SIZE; | ||
|
||
return lhs_ == rhs_; | ||
} | ||
} |
dovgopoly marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.21; | ||
|
||
import {BN254} from "./BN254.sol"; | ||
import {MemoryUtils} from "../utils/MemoryUtils.sol"; | ||
|
||
library SchnorrSignature { | ||
using MemoryUtils for *; | ||
|
||
function verifySignature( | ||
bytes32 hashedMessage_, | ||
bytes memory signature_, | ||
bytes memory pubKey_ | ||
) internal view returns (bool isVerified_) { | ||
(BN254.G1Affine memory r_, BN254.Scalar memory e_) = parseSignature(signature_); | ||
BN254.G1Affine memory a_ = parsePubKey(pubKey_); | ||
|
||
BN254.G1Affine memory lhs_ = BN254.basepointMul(e_); | ||
|
||
uint256 challenge_ = uint256(keccak256(abi.encodePacked(r_.x, r_.y, hashedMessage_))); | ||
BN254.Scalar memory c_ = BN254.scalarFromUint256ModScalar(challenge_); | ||
|
||
BN254.G1Affine memory rhs_ = BN254.pointAdd(r_, BN254.pointMul(a_, c_)); | ||
|
||
return BN254.pointEqual(lhs_, rhs_); | ||
} | ||
|
||
function parseSignature( | ||
bytes memory signature_ | ||
) internal pure returns (BN254.G1Affine memory r_, BN254.Scalar memory e_) { | ||
(uint256 pointX_, uint256 pointY_, uint256 scalar_) = abi.decode( | ||
signature_, | ||
(uint256, uint256, uint256) | ||
); | ||
|
||
r_ = BN254.g1PointFromAffine(pointX_, pointY_); | ||
e_ = BN254.scalarFromUint256(scalar_); | ||
} | ||
|
||
function parsePubKey(bytes memory pubKey_) internal pure returns (BN254.G1Affine memory a_) { | ||
(uint256 pointX_, uint256 pointY_) = abi.decode(pubKey_, (uint256, uint256)); | ||
|
||
return BN254.g1PointFromAffine(pointX_, pointY_); | ||
} | ||
} |
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.21; | ||
|
||
import {BN254} from "../../../libs/crypto/BN254.sol"; | ||
|
||
contract BN254Mock { | ||
function pointAdd( | ||
BN254.G1Affine memory a_, | ||
BN254.G1Affine memory b_ | ||
) external view returns (BN254.G1Affine memory r_) { | ||
return BN254.pointAdd(a_, b_); | ||
} | ||
|
||
function pointSub( | ||
BN254.G1Affine memory a_, | ||
BN254.G1Affine memory b_ | ||
) external view returns (BN254.G1Affine memory r_) { | ||
return BN254.pointSub(a_, b_); | ||
} | ||
|
||
function pointMul( | ||
BN254.G1Affine memory p_, | ||
BN254.Scalar memory a_ | ||
) external view returns (BN254.G1Affine memory r_) { | ||
return BN254.pointMul(p_, a_); | ||
} | ||
} |
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.21; | ||
|
||
import {SchnorrSignature} from "../../../libs/crypto/SchnorrSignature.sol"; | ||
|
||
contract SchnorrSignatureMock { | ||
function verifySignature( | ||
bytes32 hashedMessage_, | ||
bytes memory signature_, | ||
bytes memory pubKey_ | ||
) external view returns (bool isVerified_) { | ||
return SchnorrSignature.verifySignature(hashedMessage_, signature_, pubKey_); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.