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

Add Jubjub to ECC stdlib #1333

Merged
merged 11 commits into from
Oct 4, 2023
2 changes: 1 addition & 1 deletion zokrates_core_test/tests/tests/arrays/fun_spread.zok
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "utils/pack/bool/nonStrictUnpack256.zok" as unpack256;

def main(field[2] inputs) -> bool[512] {
bool[512] preimage512 = [...unpack256(inputs[0]), ...unpack256(inputs[1])];
bool[512] preimage512 = [...unpack256(inputs[0], 254), ...unpack256(inputs[1], 254)];
return preimage512;
}
46 changes: 46 additions & 0 deletions zokrates_stdlib/stdlib/ecc/babyjubjub.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma curve bn128

import "./proofOfOwnership" as edwardsProofOfOwnership;
import "./verifyEddsa" as edwardsSignature;
import "utils/pack/bool/nonStrictUnpack256" as unpack256;


// The `a` coefficient of the twisted Edwards curve
const field EDWARDS_A = 168700;

// The `d` coefficient of the twisted Edwards curve
const field EDWARDS_D = 168696;

// The generator point
const field[2] G = [
16540640123574156134436876038791482806971768689494387082833631921987005038935, // Gx
20819045374670962167435360035096875258406992893633759881276124905556507972311 // Gy
];

const u32 bit_size = 254;


def proofOfOwnership(field[2] pk, field sk) -> bool {

return edwardsProofOfOwnership(pk, sk, G, EDWARDS_A, EDWARDS_D, bit_size);
}


def verifyEddsa(field[2] R, field S, field[2] A, u32[8] M0, u32[8] M1) -> bool {

return edwardsSignature(R, S, A, M0, M1, G, EDWARDS_A, EDWARDS_D, bit_size);
}


def compress(field[2] pt) -> bool[256] {
field x = pt[0];
field y = pt[1];

bool[256] xBits = unpack256(x, 254);
bool[256] mut yBits = unpack256(y, 254);

bool sign = xBits[255];
yBits[0] = sign;

return yBits;
}
20 changes: 0 additions & 20 deletions zokrates_stdlib/stdlib/ecc/babyjubjub/compress.zok

This file was deleted.

13 changes: 0 additions & 13 deletions zokrates_stdlib/stdlib/ecc/babyjubjub/params.zok

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma curve bls12_381

import "./proofOfOwnership" as edwardsProofOfOwnership;
import "./verifyEddsa" as edwardsSignature;


// The `a` coefficient of the twisted Edwards curve
const field EDWARDS_A = -1;

Expand All @@ -10,4 +14,18 @@ const field EDWARDS_D = 19257038036680949359750312669786877991949435402254120286
const field[2] G = [
11076627216317271660298050606127911965867021807910416450833192264015104452986, // Gx
44412834903739585386157632289020980010620626017712148233229312325549216099227 // Gy
];
];

const u32 bit_size = 255;


def proofOfOwnership(field[2] pk, field sk) -> bool {

return edwardsProofOfOwnership(pk, sk, G, EDWARDS_A, EDWARDS_D, bit_size);
}


def verifyEddsa(field[2] R, field S, field[2] A, u32[8] M0, u32[8] M1) -> bool {

return edwardsSignature(R, S, A, M0, M1, G, EDWARDS_A, EDWARDS_D, bit_size);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import "utils/pack/bool/nonStrictUnpack256" as unpack256;
from "./params" import EDWARDS_A, EDWARDS_D, G;
from "ecc/edwards" import scalarMul;

/// Verifies match of a given public/private keypair.
Expand All @@ -14,8 +13,8 @@ from "ecc/edwards" import scalarMul;
/// sk: Private key
///
/// Returns true for pk/sk being a valid keypair, false otherwise.
def main(field[2] pk, field sk) -> bool {
bool[256] sk_bits = unpack256(sk);
def main(field[2] pk, field sk, field[2] G, field EDWARDS_A, field EDWARDS_D, u32 bit_size) -> bool {
bool[256] sk_bits = unpack256(sk, bit_size);
field[2] res = scalarMul(sk_bits, G, EDWARDS_A, EDWARDS_D);
return (res[0] == pk[0] && res[1] == pk[1]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import "utils/pack/bool/nonStrictUnpack256" as unpack256bool;
import "utils/pack/u32/nonStrictUnpack256" as unpack256u;
from "utils/casts" import cast;
from "ecc/edwards" import add, scalarMul, onCurve, orderCheck;
from "./params" import EDWARDS_A, EDWARDS_D, G;

/// Verifies an EdDSA Signature.
///
Expand All @@ -25,18 +24,18 @@ from "./params" import EDWARDS_A, EDWARDS_D, G;
///
/// Returns:
/// Return true for S being a valid EdDSA Signature, false otherwise.
def main(field[2] R, field S, field[2] A, u32[8] M0, u32[8] M1) -> bool {
def main(field[2] R, field S, field[2] A, u32[8] M0, u32[8] M1, field[2] G, field EDWARDS_A, field EDWARDS_D, u32 bit_size) -> bool {
// Check if R is on curve and if it is not in a small subgroup. A is public input and can be checked offline
assert(onCurve(R, EDWARDS_A, EDWARDS_D)); // throws if R is not on curve
assert(orderCheck(R, EDWARDS_A, EDWARDS_D));

u32[8] Rx = unpack256u(R[0]);
u32[8] Ax = unpack256u(A[0]);
u32[8] Rx = unpack256u(R[0], bit_size);
u32[8] Ax = unpack256u(A[0], bit_size);

u32[8] h = sha256(Rx, Ax, M0, M1);
bool[256] hRAM = cast(h);

bool[256] sBits = unpack256bool(S);
bool[256] sBits = unpack256bool(S, bit_size);
field[2] lhs = scalarMul(sBits, G, EDWARDS_A, EDWARDS_D);

field[2] AhRAM = scalarMul(hRAM, A, EDWARDS_A, EDWARDS_D);
Expand Down
3 changes: 1 addition & 2 deletions zokrates_stdlib/stdlib/hashes/pedersen/512bitBool.zok
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import "utils/multiplexer/lookup3bitSigned" as sel3s;
import "utils/multiplexer/lookup2bit" as sel2;
import "ecc/babyjubjub/compress";
from "ecc/edwards" import add;
from "ecc/babyjubjub/params" import EDWARDS_A, EDWARDS_D;
from "ecc/babyjubjub" import EDWARDS_A, EDWARDS_D, compress;

// Code to export generators used in this example:
// import bitstring
Expand Down
10 changes: 5 additions & 5 deletions zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma curve bn128

import "./unpack_unchecked";

// Unpack a field element as 256 big-endian bits
// Note: uniqueness of the output is not guaranteed
// For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)`
def main(field i) -> bool[256] {
bool[254] b = unpack_unchecked(i);
return [false, false, ...b];
def main(field i, u32 bit_size) -> bool[256] {
assert(bit_size == 254 || bit_size == 255);
u32 padding_size = 256 - bit_size;
bool[bit_size] b = unpack_unchecked(i);
return [...[false; padding_size], ...b];
}
1 change: 0 additions & 1 deletion zokrates_stdlib/stdlib/utils/pack/bool/pack256.zok
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#pragma curve bn128

import "./pack" as pack;

Expand Down
6 changes: 2 additions & 4 deletions zokrates_stdlib/stdlib/utils/pack/u32/nonStrictUnpack256.zok
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#pragma curve bn128

import "../bool/nonStrictUnpack256" as unpack;
import "../../casts/bool_256_to_u32_8" as from_bits;

// Unpack a field element as a u32[8] (big-endian)
// Note: uniqueness of the output is not guaranteed
// For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)`
def main(field i) -> u32[8] {
return from_bits(unpack(i));
def main(field i, u32 bit_size) -> u32[8] {
return from_bits(unpack(i, bit_size));
}
3 changes: 1 addition & 2 deletions zokrates_stdlib/tests/tests/ecc/babyjubjub/compress.zok
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import "ecc/babyjubjub/compress";
from "ecc/babyjubjub/params" import G;
from "ecc/babyjubjub" import G, compress;

// Code to create test cases:
// https://github.com/Zokrates/pycrypto
Expand Down
2 changes: 1 addition & 1 deletion zokrates_stdlib/tests/tests/ecc/babyjubjub/edwardsAdd.zok
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import add, negate;
from "ecc/babyjubjub/params" import G, EDWARDS_A, EDWARDS_D;
from "ecc/babyjubjub" import G, EDWARDS_A, EDWARDS_D;

// Code to create test cases:
// https://github.com/Zokrates/pycrypto
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import onCurve;
from "ecc/babyjubjub/params" import EDWARDS_A, EDWARDS_D;
from "ecc/babyjubjub" import EDWARDS_A, EDWARDS_D;

// Code to create test cases:
// https://github.com/Zokrates/pycrypto
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import orderCheck;
from "ecc/babyjubjub/params" import EDWARDS_A, EDWARDS_D;
from "ecc/babyjubjub" import EDWARDS_A, EDWARDS_D;

// Code to create test cases:
// https://github.com/Zokrates/pycrypto
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import scalarMul as mul;
from "ecc/babyjubjub/params" import G, EDWARDS_A, EDWARDS_D;
from "ecc/babyjubjub" import G, EDWARDS_A, EDWARDS_D;

// Code to create test cases:
// https://github.com/Zokrates/pycrypto
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "ecc/babyjubjub/proofOfOwnership" as proofOfOwnership;
from "ecc/edwards" import scalarMul;
from "ecc/babyjubjub" import proofOfOwnership;


// Code to create test cases:
// https://github.com/Zokrates/pycrypto
Expand Down
2 changes: 1 addition & 1 deletion zokrates_stdlib/tests/tests/ecc/babyjubjub/verifyEddsa.zok
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import "ecc/babyjubjub/verifyEddsa" as verifyEddsa;
from "ecc/babyjubjub" import verifyEddsa;

// Code to create test case:
// https://github.com/Zokrates/pycrypto
Expand Down
2 changes: 1 addition & 1 deletion zokrates_stdlib/tests/tests/ecc/jubjub/edwardsAdd.zok
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import add, negate;
from "ecc/jubjub/params" import G, EDWARDS_A, EDWARDS_D;
from "ecc/jubjub" import G, EDWARDS_A, EDWARDS_D;

def testDoubleViaAdd() -> bool {
field[2] out = add(G, G, EDWARDS_A, EDWARDS_D);
Expand Down
2 changes: 1 addition & 1 deletion zokrates_stdlib/tests/tests/ecc/jubjub/edwardsOnCurve.zok
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import onCurve;
from "ecc/jubjub/params" import EDWARDS_A, EDWARDS_D;
from "ecc/jubjub" import EDWARDS_A, EDWARDS_D;

def main() {
field u = 11076627216317271660298050606127911965867021807910416450833192264015104452986;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import orderCheck;
from "ecc/jubjub/params" import EDWARDS_A, EDWARDS_D;
from "ecc/jubjub" import EDWARDS_A, EDWARDS_D;

def testOrderCheckTrue() -> bool {
field u = 11076627216317271660298050606127911965867021807910416450833192264015104452986;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from "ecc/edwards" import scalarMul as mul;
from "ecc/jubjub/params" import G, EDWARDS_A, EDWARDS_D;
from "ecc/jubjub" import G, EDWARDS_A, EDWARDS_D;

/*
def testCyclic() -> bool {
Expand Down
16 changes: 16 additions & 0 deletions zokrates_stdlib/tests/tests/ecc/jubjub/proofOfOwnership.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"entry_point": "./tests/tests/ecc/jubjub/proofOfOwnership.zok",
"curves": ["Bls12_381"],
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": []
}
}
}
]
}
29 changes: 29 additions & 0 deletions zokrates_stdlib/tests/tests/ecc/jubjub/proofOfOwnership.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from "ecc/jubjub" import proofOfOwnership;


// Code to create test cases:
// https://github.com/Zokrates/pycrypto
def testOwnershipTrue() -> bool {
field[2] pk = [14197449566532409051373899088449039913101429151158365207762164998470111126084, 39815292783067036895376009933490224522172606808755118734518018525613835149403];
field sk = 24537266074035586913841246471742714563414767347802800698790739697702568093815;

bool out = proofOfOwnership(pk, sk);

assert(out);
return true;
}

def testOwnershipFalse() -> bool {
field[2] pk = [14197449566532409051373899088449039913101429151158365207762164998470111126084, 39815292783067036895376009933490224522172606808755118734518018525613835149403];
field sk = 47423927973606838312622698773159954626747140530476271492884670927146733875544;

bool out = proofOfOwnership(pk, sk);

assert(!out);
return true;
}

def main() {
assert(testOwnershipTrue());
assert(testOwnershipFalse());
}
16 changes: 16 additions & 0 deletions zokrates_stdlib/tests/tests/ecc/jubjub/verifyEddsa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"entry_point": "./tests/tests/ecc/jubjub/verifyEddsa.zok",
"curves": ["Bls12_381"],
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": []
}
}
}
]
}
21 changes: 21 additions & 0 deletions zokrates_stdlib/tests/tests/ecc/jubjub/verifyEddsa.zok
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from "ecc/jubjub" import verifyEddsa;


// Code to create test case:
// https://github.com/Zokrates/pycrypto
def main() {

// TODO: Jubjub currently work only for keys <=254 bit long
// With the following keys should also work:
field[2] R = [32866767109220564315580607107081162920517672350707254238793964527466586251974, 31852087390335520207922973662676180854641055992940928475111512263314053365736];
field S = 43627586196239283173178511316555190744314536456808505435494185841008559853678;

// Public Key
field[2] A = [26479653887939839327536384197110148123933856719900448942651733342668343953867, 21757919891968253927635241665494706427345455214116275076018069565740804326091];

u32[8] M0 = [0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000];
u32[8] M1 = [0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000005];

bool isVerified = verifyEddsa(R, S, A, M0, M1);
assert(isVerified);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"entry_point": "./tests/tests/utils/pack/bool/nonStrictUnpack256.zok",
"curves": ["Bn128"],
"curves": ["Bls12_381"],
"tests": [
{
"input": {
Expand Down
Loading