trezor / trezor-core

:lock: Don't use this repo, use the new monorepo instead:
https://github.com/trezor/trezor-firmware
GNU General Public License v3.0
353 stars 204 forks source link

Add extmod for secp256k1-zkp #500

Closed real-or-random closed 5 years ago

real-or-random commented 5 years ago

This includes the https://github.com/ElementsProject/secp256k1-zkp library (which is a fork from sipa/secp256k1 used in Bitcoin Core) and uses it for signing transactions and signing and verifying messages for ECDSA on the secp256k1 curve.

The Ethereum app is left untouched. I assume because they use Keccak-256 as a message digest and not SHA256. @apoelstra

This is the first step towards solving #282.

Some background to understand the open issues below: secp256k1-zkp (and in fact sipa/secp256k1) relies on two precomputation tables to speed up signing and for verification. secp256k1(-zkp) supports that the precomputed table values for the signing table are stored in the executable (by defining USE_ECMULT_STATIC_PRECOMPUTATION) and thus do not need to be created at running time.

It's WIP because the following is still open (and maybe more):

We opened this mostly to get some feedback on the build system. We can also decide to use this PR just for the build system and handle the other stuff in a different PR if that works better for you.

cc @romanz @apoelstra

real-or-random commented 5 years ago

Note to self: We should also call secp256k1_context_randomize (https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1.h#L641) after creating the context

prusnak commented 5 years ago

1) I would prefer not changing import secp256k1 to import secp256k1_zkp in our Python code via this pull request. It simplifies reviewing and I am not sure whether we are going to switch immediately. It makes sense to use secp256k1_zkp for Liquid, but I am not in favor of using it everywhere unless there are benchmarks done which prove the zkp implementation is faster and/or has other big advantages. 2) I agree we should use directories in #include to avoid clashes. I will address this in another pull request.

real-or-random commented 5 years ago

I would prefer not changing import secp256k1 to import secp256k1_zkp in our Python code via this pull request. It simplifies reviewing and I am not sure whether we are going to switch immediately. It makes sense to use secp256k1_zkp for Liquid, but I am not in favor of using it everywhere unless there are benchmarks done which prove the zkp implementation is faster and/or has other big advantages.

No problem, then we should first focus on just getting zkp imported and included in the build. I'll update this PR then. Anyway, it was still good to have these other commits to demonstrate that the build worked and can actually be used, and for the future.

I agree we should use directories in #include to avoid clashes. I will address this in another pull request.

Okay, I can also just do it when I update this.

prusnak commented 5 years ago

Anyway, it was still good to have these other commits to demonstrate that the build worked and can actually be used, and for the future.

Sure, I 100% agree. To be clear, I am not opposed to using secp256k1_zkp globally for ECDSA/ECDH operations. But let's test that first.

prusnak commented 5 years ago

Maybe we can leverage the fact the tests for secp256k1 and secp256k1_zkp ar the same. Something like this comes to mind:

from trezor.crypto.curve import secp256k1, secp256k1_zkp

class Secp256k1Common(unittest.TestCase):
   # all existing unit tests go here

   def test_foo(self):
       # use impl.method instead of secp256k1.method

class TestCryptoSecp256k1(Secp256k1Common): 
    def __init__(self):
         self.impl = secp256k1

class TestCryptoSecp256k1Zkp(Secp256k1Common): 
    def __init__(self):
         self.impl = secp256k1_zkp
romanz commented 5 years ago

A small update to the PR (following a discussion with @real-or-random): I have replaced https://github.com/trezor/trezor-core/commit/f8b5bbc17f70be4333666fd8421b47c0dfa3cc97 by https://github.com/trezor/trezor-core/commit/55a39486ce9a06a0251c329aa036d34a551f77ba (moving the read-only precomputed tables from the .flash to .flash2 section, which AFAIU is not used for storing executable code). The resulting binary should compile and run successfully on TREZOR model T.

prusnak commented 5 years ago

moving the read-only precomputed tables from the .flash to .flash2 section, which AFAIU is not used for storing executable code

Good!

real-or-random commented 5 years ago

I added two commits to address the file name issues and the size of the context. (I'm leaving the replacement of the internal secp256k1 in at the moment for testing, we can remove that if everything looks good.)

@prusnak Do the callbacks look right to you?

prusnak commented 5 years ago

@real-or-random offtopic: How hard is to add NIST P-256 curve to secp256k1 library? Is this even possible or desired?

apoelstra commented 5 years ago

@prusnak it would basically mean rewriting the library. It is neither possible nor desired :)

prusnak commented 5 years ago

Got it :)

real-or-random commented 5 years ago

We have now https://github.com/ElementsProject/secp256k1-zkp/pull/53 which (when merged) removes the need to use a modified branch/version of secp256k-zkp.

The remaining issues are the top three items in the list in first comment here in this PR @prusnak Can you comment on these? :)

prusnak commented 5 years ago

I replaced them by functions which throw Python exceptions. Is this the right thing to do on trezor?

Yes

4096 bytes (of RAM). Is this is fine for you as memory footprint?

Yes

The table(s) are stored in a secp256k1_context which is currently created when it's first used. Is that okay or do we want to create at program startup?

I think that's fine as a PoC.

prusnak commented 5 years ago

Can you please squash the changes into a single commit and resolve conflicts (rebase on top of the current master)? We have reformatted our code using clang-format. Config is in the .clang-format file but it should be picked up automatically, just use clang-format -i on newly added C files. This should help with the resolution.

real-or-random commented 5 years ago

Okay, I squashed and changed it to remove the commits that change the apps. Two issues open left:

real-or-random commented 5 years ago

The table(s) are stored in a secp256k1_context which is currently created when it's first used. Is that okay or do we want to create at program startup?

I think that's fine as a PoC.

Yes, indeed. I think in a PR that actually changes apps to use secp256k1-zkp, it's best to change this to a model where the verification table is only created when it's necessary (which is rare). Currently, we would create the verification table even when we would call into secp256k1-zkp for signing, which is kind of silly because signing is much more common and we don't need to build a table for signing (because the signing table it's statically built).

real-or-random commented 5 years ago

I added two commits (will squash again if you approve):

With these two commits, this PR is ready to be merged except that we need to wait for https://github.com/ElementsProject/secp256k1-zkp/pull/53 to be merged and adjust the submodule.

prusnak commented 5 years ago

(will squash again if you approve):

Agreed. Please squash.

this PR is ready to be merged except that we need to wait for #53 to be merged and adjust the submodule.

Ack. we'll review it in the meantime. @jpochyla can you have a look, please?

real-or-random commented 5 years ago

Squashed.

real-or-random commented 5 years ago

Okay, sorry, I pushed again because I additionally enabled some ASM optimizations for ASM in secp256k1-zkp.

prusnak commented 5 years ago

Okay @real-or-random, great job! We are ready to merge. We'll wait until you merge https://github.com/ElementsProject/secp256k1-zkp/pull/53 and adjust the submodule in this PR.

real-or-random commented 5 years ago

Okay force-pushed, I touched only .gitmodules. The other PR is not merged yet but should be today.

apoelstra commented 5 years ago

Merged the other PR.

prusnak commented 5 years ago

@real-or-random do you want to change the revision of the included submodule to reflect the last change from @apoelstra or should we merge as is?

real-or-random commented 5 years ago

Oh yes I should have done this. I'll update it later. :)

real-or-random commented 5 years ago

fixed

prusnak commented 5 years ago

Great work @real-or-random, thanks for the contribution!