Git Product home page Git Product logo

secp256k1-zkp's People

Contributors

antiochp avatar apoelstra avatar bgorlick avatar codeshark avatar davidburkett avatar excentertex avatar fanatid avatar garyyu avatar gmaxwell avatar greenaddress avatar ignopeverell avatar instagibbs avatar jaspervdm avatar jgriffiths avatar jonasnick avatar kallewoof avatar laanwj avatar llamasoft avatar luke-jr avatar paveljanik avatar peterdettman avatar practicalswift avatar quentinlesceller avatar real-or-random avatar rustyrussell avatar sipa avatar tdaede avatar thebluematt avatar theuni avatar yeastplume avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

secp256k1-zkp's Issues

Bug in scalar addition

Some scalars add to the wrong number (see webwarrior-ws@1c27f70).
Numbers in that commit were cross-checked using Wolfram Alpha, Python and Pharo.
So I assume there is either a bug in addition or in byte array representation of scalars.

Open SSL 3 test failures

Note that when built on a system using openssl 3.0, (more recent arch distros, for instance), the test

run_ecdsa_der_parse on line 4654 of tests.c fails.

I have not looked into the reason, (this function is unused by grin) but we'll likely need to revisit the build when most of the world moves on to openssl 3.

modify the file header part of aggsig code

Gary Yu @garyyu 14:35
Oh, I can’t find file aggsig/main_impl.h in upstream BlockstreamResearch/secp256k1-zkp#23 ? @yeastplume
but the first commit message of this file is updating BPs with master and upstream PR 23, what’s exact origin writer of this aggsig/main_impl.h?


Yeastplume @yeastplume 16:18
I wrote the aggsig code based on something andrew did earlier. It doesn't exist anywhere upstream.


Gary Yu @garyyu 16:19
Ok @yeastplume

" I wrote the aggsig code based on something andrew did earlier."

The git commit log lost? I can’t find the andrew’s record.


Yeastplume @yeastplume 16:21
it was in a PR that was withdrawn
and it was set up to do multisig while holding a context internally, which didn't really work for us, hence me rewriting it


Gary Yu @garyyu 16:21
Oh, that make sense.


Gary Yu @garyyu 16:23
@yeastplume Could you add yourself into the header?

/**********************************************************************
 * Copyright (c) 2017 Andrew Poelstra, Pieter Wuille                  *
 * Distributed under the MIT software license, see the accompanying   *
 * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 **********************************************************************/

It’s awkward I send question to Pieter Wuille about this code, but actually it’s written by you or/and Andrew.


Yeastplume @yeastplume 16:26
at some point we'll add grin developers to it


Gary Yu @garyyu 16:30
👍 I will submit an issue to remind you to change this,...

bulletproof requires nonce == blind

If I understand it correctly, then the blind and nonce can be chosen independently (even if the rust api sets nonce = blind) when creating and unwinding bulletproofs. However, if nonce != blind, then only the first 32 bytes of the message can be unwinded as in the following test which can be inserted into perdersen.rs.

	#[test]
	fn test_bullet_nonce_neq_blind() {
		use std;
		use super::*;
		let secp = Secp256k1::with_caps(ContextFlag::Commit);
		let mut rng = OsRng::new().unwrap();
		let value = 1234567;
		let blind = SecretKey::new(&secp, &mut rng);
		let nonce = SecretKey::new(&secp, &mut rng);
		//let nonce = blind; // this works
		let mut msg = [0u8; 64];
		rng.fill_bytes(&mut msg);

		// ffi structures
		let n_bits = 64;
		let mut proof = [0; constants::MAX_PROOF_SIZE];
		let mut plen = constants::MAX_PROOF_SIZE as size_t;
		let extra_data = vec![];

		// create proof
		let success = unsafe {
			ffi::secp256k1_bulletproof_rangeproof_prove_single_w_scratch(
				secp.ctx,
				proof.as_mut_ptr(),
				&mut plen,
				value,
				blind.as_ptr(),
				constants::GENERATOR_H.as_ptr(),
				n_bits as size_t,
				nonce.as_ptr(),
				extra_data.as_ptr(),
				extra_data.len() as size_t,
				msg.as_ptr()
			) == 1
		};
		assert!(success);

		// unwind proof
		let mut unwinded_msg = [0u8; 64];
		let commit = secp.commit(value, blind).unwrap();
		let success = unsafe {
			ffi::secp256k1_bulletproof_rangeproof_unwind_message(
				secp.ctx,
				proof.as_ptr(),
				plen as size_t,
				commit.as_ptr(),
				n_bits as size_t,
				constants::GENERATOR_H.as_ptr(),
				extra_data.as_ptr(),
				extra_data.len() as size_t,
				nonce.as_ptr(),
				unwinded_msg.as_mut_ptr(),
			) == 1
		};
		assert!(success);

		println!("msg:     {:?}", msg.to_vec());
		println!("unwinded:{:?}", unwinded_msg.to_vec());

		for i in 0..msg.len() {
			assert_eq!(msg[i], unwinded_msg[i]);
		}
	}

Why not use GMP num?

From here, the library use builtin num instead of GMP num.

#define USE_NUM_NONE 1
#define USE_FIELD_INV_BUILTIN 1
#define USE_SCALAR_INV_BUILTIN 1
#define USE_FIELD_10X26 1
#define USE_SCALAR_8X32 1

I tested it on local, GMP version is 3 times faster than builtin. What's the consideration?

Is the serialization format of the proof byte-array documented somewhere?

I have been trying to make sense of the proof array filled in by secp256k1_bulletproof_rangeproof_prove, but its format doesn't seem to be documented, so I'm left trying to infer it from the code. Is this documented somewhere?

My assumption is that this is incorrect:

/* Proof format: t, tau_x, mu, a, b, A, S, T_1, T_2, {L_i}, {R_i}
* 5 scalar + [4 + 2log(n)] ge

Am I wrong?

generator problems

The following is called in the various range proof functions -

secp256k1_generator_load(&genp, gen);

We're not passing in gen from Grin (via rust-secp256k1-zkp) and it is not clear to me what we need to be doing here.

Code Audit Diffs

Upstream is the Elements project code with Bulletproof PR 23 applied:
BlockstreamResearch/secp256k1-zkp#23

Downstream is this repository, as of commit 4d64b7b

The major differences are:

  • We've made additions to the bulletproof code, hiding a four byte BIP32 identifier into the nonce 'alpha'. This was just an extension to work Andrew had already done to allow Proofs to be rewound
  • Changes to bulletproofs to allow for multi party proofs. The relevant PR with those changes is:
    #24
  • A completely custom aggsig module that doesn't exist upstream, at https://github.com/mimblewimble/secp256k1-zkp/tree/master/src/modules/aggsig
    This was originally based on Andrew's code, however that code was never particularly reviewed and it's been re-written over time by us to suit Grin's requirements.

Diffs of the include and src directories are here:

diffs_include.txt
diffs_src.txt

Aggsig work to date - merging

Just putting an issue here to keep track of this.. the /aggsig branch has been created, which is:

master
+bitcoin-core/secp256k1#486
+bitcoin-core/secp256k1#461

+Manual tweaks and fixes to get compile/test working, particularly updates to ec_mult functionality as per 486

All tests seem to run without issue.

Please don't make any changes to master without checking with me first, as it would be nice to keep this branch mergeable ... this will have the potential to get very messy if we don't manage changes here properly.

should not mix hash(R,P,m) and hash(P,R,m)

Gary Yu @garyyu 11:00
@jaspervdm Now I remember where I saw e = hash(P,R,m) firstly.
https://github.com/mimblewimble/secp256k1-zkp/blob/master/src/modules/aggsig/main_impl.h#L72-L81

And we both agree to be compatible with BIP-schnorr, that’s why we use e = hash(R,P,m):
https://github.com/mimblewimble/secp256k1-zkp/blob/master/src/modules/aggsig/main_impl.h#L45-L57

We should not mix 2 different definition of e. Please let's stick to BIP-schnorr, and correct the https://github.com/mimblewimble/secp256k1-zkp/blob/master/src/modules/aggsig/main_impl.h#L72-L81

Will give a PR on this.

Fix commitment tests

It turned out that the Pedersen commitment tests were disabled. I re-enabled them in #34 but some of the tests are broken.

related-key attack?

Hello.

I think there is a related-key attack in the way you produce Schnorr signatures.

secp256k1_sha256_write(&hasher, buf+1, sizeof(buf-1));

sizeof(buf-1) = 8
sizeof(buf) - 1 = 32

so to my understanding you're copying only 8 bytes of the public key.

Therefore, if the signature
(s, e) is verified by H(_ || sG - eX) = e for public key X = xG
then, the signature
(s+ev, e) is verified by H(_ || (s+ev)G - e(X+vG)) = e for public key X + vG for any v in \ZZ_p for which X + vG has the same leading 64 bits of X.

Am I doing something wrong in here? Could you help me understand?

Error in build

I tryed to build lirary on Ubuntu 16.04 and met with this error:

gcc -I. -g -O2 -Wall -Wextra -Wno-unused-function -c src/gen_context.c -o gen_context.o
gcc gen_context.o -o gen_context
./gen_context
  CC       src/libsecp256k1_la-secp256k1.lo
In file included from src/field_impl.h:19:0,
                 from src/secp256k1.c:11:
src/field_5x52_impl.h:165:12: error: conflicting types for ‘secp256k1_fe_normalizes_to_zero’
 static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) {
            ^
In file included from src/field_5x52_impl.h:16:0,
                 from src/field_impl.h:19,
                 from src/secp256k1.c:11:
src/field.h:46:12: note: previous declaration of ‘secp256k1_fe_normalizes_to_zero’ was here
 static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r);
            ^
Makefile:1107: ошибка выполнения рецепта для цели «src/libsecp256k1_la-secp256k1.lo»
make: *** [src/libsecp256k1_la-secp256k1.lo] Ошибка 1

How can I fix it?

aggsig: signature with (s,r) instead of (r,s)

https://github.com/mimblewimble/secp256k1-zkp/blob/master/src/modules/aggsig/main_impl.h#L278-L282

    /* finalize */
    secp256k1_scalar_get_b32(sig64, &sec);
    secp256k1_ge_set_gej(&final, &pubnonce_j);
    secp256k1_fe_normalize_var(&final.x);
    secp256k1_fe_get_b32(sig64 + 32, &final.x);

Mark here: we're using (s,r) format for signature, which is not the convention.
@yeastplume @jaspervdm Please confirm whether or not we need to correct this?

Conventionally, people stick to (r,s) format for signature.
For example:

def schnorr_sign(msg, seckey):
    k = sha256(seckey.to_bytes(32, byteorder="big") + msg) % n
    R = point_mul(G, k)
    if jacobi(R[1]) != 1:
        k = n - k
    e = sha256(R[0].to_bytes(32, byteorder="big") + bytes_point(point_mul(G, seckey)) + msg) % n
    return R[0].to_bytes(32, byteorder="big") + ((k + e * seckey) % n).to_bytes(32, byteorder="big")
7. The signature is the pair (r,s).

How to convert a pubkey to pedersen commitment?

This function can converts a pedersent commit to a pubkey

SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_pedersen_commitment_to_pubkey(
  const secp256k1_context* ctx,
  secp256k1_pubkey* pubkey,
  const secp256k1_pedersen_commitment* commit
);

How to converts a pubkey to pedersent commit ?

a mistake 'or' on variable retry

https://github.com/mimblewimble/secp256k1-zkp/blob/master/src/modules/aggsig/main_impl.h#L137-L138

int secp256k1_aggsig_generate_nonce_single(const secp256k1_context* ctx, secp256k1_scalar *secnonce, secp256k1_gej* pubnonce, secp256k1_rfc6979_hmac_sha256* rng) {
    int retry;
    ...
    /* generate nonce from the RNG */
    do {
        secp256k1_rfc6979_hmac_sha256_generate(rng, data, 32);
        secp256k1_scalar_set_b32(secnonce, data, &retry);
        retry |= secp256k1_scalar_is_zero(secnonce);
    } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */
    ...

2 problems here:

  • Variable retry should give zero initialization
  • The while loop looks like a trap to infinite loop. If retry becomes not zero, then loop forever.

I guess retry |= should be retry = . Please confirm if it's.

distcheck build fail

One of building job: BUILD=distcheck will fail.

$ make  dist-gzip am__post_remove_distdir='@:'
make: *** No rule to make target 'src/bench_aggsig.c', needed by 'distdir'.  Stop.

Before we find a fix on the Makefile for this, I have to disable it to let all remaining 38 building jobs works for Travis-CI.

How to produce? You can run the following script on Linux:

#!/bin/sh

export FIELD=auto
export BIGNUM=auto
export SCALAR=auto
export ENDOMORPHISM=no
export STATICPRECOMPUTATION=yes
export ASM=no
export BUILD=check
export EXTRAFLAGS=
export HOST=
export ECDH=no
export RECOVERY=no
export EXPERIMENTAL=no
export JNI=no
export GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar
export GUAVA_JAR=src/java/guava/guava-18.0.jar
export BUILD=distcheck
export TRAVIS_COMPILER=gcc
export CC=gcc
export CC_FOR_BUILD=gcc
export CASHER_DIR=${TRAVIS_HOME}/.casher
gcc --version
mkdir -p `dirname $GUAVA_JAR`
if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi
# ./autogen.sh
if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi
if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi
./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-module-generator=$GENERATOR --enable-module-commitment=$COMMITMENT --enable-module-rangeproof=$RANGEPROOF --enable-module-bulletproof=$BULLETPROOF --enable-module-whitelist=$WHITELIST --enable-module-surjectionproof=$SURJECTIONPROOF --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.