Blind signature support in pyelliptic #1509

Merged
PeterSurda merged 4 commits from blindsig1 into v0.6 2019-08-28 13:43:29 +02:00
PeterSurda commented 2019-08-26 17:50:55 +02:00 (Migrated from github.com)
  • add blind signature functionality to pyelliptic as described in #1409
  • add tests for blind signatures
  • PEP8 fixes for pyelliptic
  • some minor refactoring is necessary for further integration, this is just a
    minimal implementation to pass a test
- add blind signature functionality to pyelliptic as described in #1409 - add tests for blind signatures - PEP8 fixes for pyelliptic - some minor refactoring is necessary for further integration, this is just a minimal implementation to pass a test
PeterSurda commented 2019-08-26 18:06:18 +02:00 (Migrated from github.com)

I'll fix the pylint complaints.

I'll fix the pylint complaints.
g1itch (Migrated from github.com) approved these changes 2019-08-27 11:39:33 +02:00
g1itch (Migrated from github.com) left a comment

Honestly, I don't understand what exactly is going on here, but your test case may be better.

Honestly, I don't understand what exactly is going on here, but your test case may be better.
g1itch (Migrated from github.com) commented 2019-08-27 11:09:52 +02:00

Shebang is not needed here.

Shebang is not needed here.
g1itch (Migrated from github.com) commented 2019-08-27 11:15:09 +02:00

from pybitmessage.pyelliptic.eccblind import ECCBlind

`from pybitmessage.pyelliptic.eccblind import ECCBlind`
g1itch (Migrated from github.com) commented 2019-08-27 11:16:07 +02:00

self.assertTrue(blind_sig.verify())

`self.assertTrue(blind_sig.verify())`
g1itch (Migrated from github.com) commented 2019-08-27 11:19:42 +02:00

If you write docstring in one line it will be shown in the test results. e.g.

    def test_blind_sig(self):
        """Test full sequence using a random certifier key and a random msg"""
If you write docstring in one line it will be shown in the test results. e.g. ```python def test_blind_sig(self): """Test full sequence using a random certifier key and a random msg""" ```
PeterSurda commented 2019-08-27 12:16:51 +02:00 (Migrated from github.com)

@g1itch I'll make the changes you requested.

The low level math I also don't understand, but it looks like it does what the paper says. On a high level, the paper mentions 5 steps (in Section 4), these are roughly mapped to 6 high level methods in the ECCBlind class, with some reshuffling because some are executed by the signer and some by the requester. It needs to be refactored, because the signer and requester need to communicate and pass data, so there will be one object at the signer's side and one at the requester's side, but here I just reuse a single object. Also in __init__, it now generates a new pubkey, wereas for actual deployment the pubkey will be loaded from the disk (like a CA for traditional PKI). There still are open questions about how to serialise the data. This all will be solved in the subsequent PRs.

@g1itch I'll make the changes you requested. The low level math I also don't understand, but it looks like it does what the paper says. On a high level, the paper mentions 5 steps (in Section 4), these are roughly mapped to 6 high level methods in the `ECCBlind` class, with some reshuffling because some are executed by the signer and some by the requester. It needs to be refactored, because the signer and requester need to communicate and pass data, so there will be one object at the signer's side and one at the requester's side, but here I just reuse a single object. Also in `__init__`, it now generates a new pubkey, wereas for actual deployment the pubkey will be loaded from the disk (like a CA for traditional PKI). There still are open questions about how to serialise the data. This all will be solved in the subsequent PRs.
PeterSurda (Migrated from github.com) reviewed 2019-08-27 12:25:00 +02:00
PeterSurda (Migrated from github.com) commented 2019-08-27 12:25:00 +02:00

This breaks the test.

This breaks the test.
g1itch (Migrated from github.com) reviewed 2019-08-27 12:27:08 +02:00
g1itch (Migrated from github.com) commented 2019-08-27 12:27:08 +02:00

It depends on how you run it.

It depends on how you run it.
g1itch (Migrated from github.com) reviewed 2019-08-27 12:28:28 +02:00
g1itch (Migrated from github.com) commented 2019-08-27 12:28:27 +02:00

Travis CI should be OK, because I used such imports before: https://github.com/Bitmessage/PyBitmessage/blob/v0.6/src/tests/test_config.py#L8

Travis CI should be OK, because I used such imports before: https://github.com/Bitmessage/PyBitmessage/blob/v0.6/src/tests/test_config.py#L8
g1itch commented 2019-08-27 12:33:19 +02:00 (Migrated from github.com)

I also expected to find the blinded message and its signature and check the signature's validity.

I also expected to find the blinded message and its signature and check the signature's validity.
PeterSurda commented 2019-08-27 13:02:47 +02:00 (Migrated from github.com)

@g1itch The message is only blinded internally and such blinded message is only available to the requester, it's not made public. Similarly with the blinded signature, that's calculated by the signer and then transmitted to the requester and unblinded by him.

What you see publicly is the message (in the case of PyBitmessage's wire protocol, this will be the object data), the signature (which has two components, s and F), and pubkey of the signer (Q). There is also r, but that's derived from F. F is a point on a finite field and r is its x coordinate modulo n, although it looks to me like the current code skips the modulo n, the way I understand the code is that n is selected from the elliptic curve used, so x can't higher than that. But I don't really understand ECC so I may be wrong.

Then during the verification, you take the signature, the signer's pubkey and the message, and if verification succeeds, it means the singer signed the message, just like with traditional PKI, except here the signer doesn't know which of the requests he signed correspond to which message..

@g1itch The message is only blinded internally and such blinded message is only available to the requester, it's not made public. Similarly with the blinded signature, that's calculated by the signer and then transmitted to the requester and unblinded by him. What you see publicly is the message (in the case of PyBitmessage's wire protocol, this will be the object data), the signature (which has two components, `s` and `F`), and pubkey of the signer (`Q`). There is also `r`, but that's derived from `F`. `F` is a point on a finite field and `r` is its x coordinate modulo n, although it looks to me like the current code skips the modulo n, the way I understand the code is that n is selected from the elliptic curve used, so x can't higher than that. But I don't really understand ECC so I may be wrong. Then during the verification, you take the signature, the signer's pubkey and the message, and if verification succeeds, it means the singer signed the message, just like with traditional PKI, except here the signer doesn't know which of the requests he signed correspond to which message..
g1itch (Migrated from github.com) reviewed 2019-08-27 13:20:30 +02:00
@ -0,0 +59,4 @@
"""
Generate an ECC keypair
"""
d = ECCBlind.ec_get_random(group, ctx)
g1itch (Migrated from github.com) commented 2019-08-27 13:20:29 +02:00

d = self.ec_get_random(group, ctx) ?

d = self.ec_get_random(group, ctx) ?
PeterSurda (Migrated from github.com) reviewed 2019-08-27 13:38:07 +02:00
@ -0,0 +59,4 @@
"""
Generate an ECC keypair
"""
d = ECCBlind.ec_get_random(group, ctx)
PeterSurda (Migrated from github.com) commented 2019-08-27 13:38:07 +02:00

pylint/flake8 complained.

pylint/flake8 complained.
g1itch (Migrated from github.com) reviewed 2019-08-27 13:48:20 +02:00
@ -0,0 +59,4 @@
"""
Generate an ECC keypair
"""
d = ECCBlind.ec_get_random(group, ctx)
g1itch (Migrated from github.com) commented 2019-08-27 13:48:19 +02:00

because of @staticmethod. well, maybe this really should be a static method

because of `@staticmethod`. well, maybe this really should be a static method
g1itch commented 2019-08-27 14:35:54 +02:00 (Migrated from github.com)

I am trying to split signer and requester with no luck ):

    def test_blind_sig(self):
        """Test full sequence using a random certifier key and a random msg"""
        signer_obj = ECCBlind()
        signer_obj.signer_init()
        signer_obj.create_signing_request('dummy')

        requester_obj = ECCBlind()
        requester_obj.R = signer_obj.R
        requester_obj.keypair = (0, signer_obj.keypair[1])

        msg = os.urandom(64)
        requester_obj.create_signing_request(msg)

        signer_obj.m_ = requester_obj.m_
        signer_obj.blind_sign()

        requester_obj.s_ = signer_obj.s_
        requester_obj.unblind()

        signer_obj.m = requester_obj.m
        signer_obj.signature = requester_obj.signature
        signer_obj.F = signer_obj.signature[1]
        self.assertTrue(signer_obj.verify())
I am trying to split signer and requester with no luck ): ```python def test_blind_sig(self): """Test full sequence using a random certifier key and a random msg""" signer_obj = ECCBlind() signer_obj.signer_init() signer_obj.create_signing_request('dummy') requester_obj = ECCBlind() requester_obj.R = signer_obj.R requester_obj.keypair = (0, signer_obj.keypair[1]) msg = os.urandom(64) requester_obj.create_signing_request(msg) signer_obj.m_ = requester_obj.m_ signer_obj.blind_sign() requester_obj.s_ = signer_obj.s_ requester_obj.unblind() signer_obj.m = requester_obj.m signer_obj.signature = requester_obj.signature signer_obj.F = signer_obj.signature[1] self.assertTrue(signer_obj.verify()) ```
PeterSurda commented 2019-08-27 15:34:44 +02:00 (Migrated from github.com)

let me try...

let me try...
PeterSurda commented 2019-08-27 23:22:01 +02:00 (Migrated from github.com)

@g1itch here you go.

@g1itch here you go.
g1itch (Migrated from github.com) reviewed 2019-08-28 11:46:50 +02:00
@ -0,0 +24,4 @@
requester_obj = ECCBlind(pubkey=signer_obj.pubkey)
# only 64 byte messages are planned to be used in Bitmessage
msg = os.urandom(64)
msg_blinded = requester_obj.create_signing_request(point_r, msg)
g1itch (Migrated from github.com) commented 2019-08-28 11:46:50 +02:00

Maybe self.assertNotEqual(msg, msg_blinded)?

Maybe `self.assertNotEqual(msg, msg_blinded)`?
PeterSurda (Migrated from github.com) reviewed 2019-08-28 12:05:48 +02:00
@ -0,0 +24,4 @@
requester_obj = ECCBlind(pubkey=signer_obj.pubkey)
# only 64 byte messages are planned to be used in Bitmessage
msg = os.urandom(64)
msg_blinded = requester_obj.create_signing_request(point_r, msg)
PeterSurda (Migrated from github.com) commented 2019-08-28 12:05:48 +02:00

Well that will always succeed as msg is a string and msg_blinded is an openssl bignum, but I can convert it before comparison, and I can also compare blinded an unblinded signature (those should both be bignums already).

As I said before, there is still no serialisation for the wire protocol, as that has to be designed first, then there will be minor refactoring here.

Well that will always succeed as msg is a string and msg_blinded is an openssl bignum, but I can convert it before comparison, and I can also compare blinded an unblinded signature (those should both be bignums already). As I said before, there is still no serialisation for the wire protocol, as that has to be designed first, then there will be minor refactoring here.
g1itch (Migrated from github.com) reviewed 2019-08-28 12:34:57 +02:00
@ -0,0 +24,4 @@
requester_obj = ECCBlind(pubkey=signer_obj.pubkey)
# only 64 byte messages are planned to be used in Bitmessage
msg = os.urandom(64)
msg_blinded = requester_obj.create_signing_request(point_r, msg)
g1itch (Migrated from github.com) commented 2019-08-28 12:34:57 +02:00

They will obviously differ. That's just a tests logic (as I understand it) to compare just in case and document it. Maybe that's unnecessary.

Serialization will be probably done in the network package, so it's not related to the blind signature implementation itself. The signatures seems to work well. So are you going to merge this now?

They will obviously differ. That's just a tests logic (as I understand it) to compare just in case and document it. Maybe that's unnecessary. Serialization will be probably done in the `network` package, so it's not related to the blind signature implementation itself. The signatures seems to work well. So are you going to merge this now?
PeterSurda (Migrated from github.com) reviewed 2019-08-28 12:43:01 +02:00
@ -0,0 +24,4 @@
requester_obj = ECCBlind(pubkey=signer_obj.pubkey)
# only 64 byte messages are planned to be used in Bitmessage
msg = os.urandom(64)
msg_blinded = requester_obj.create_signing_request(point_r, msg)
PeterSurda (Migrated from github.com) commented 2019-08-28 12:43:01 +02:00

I'll add the tests and then merge.

I'll add the tests and then merge.
PeterSurda commented 2019-08-28 13:25:05 +02:00 (Migrated from github.com)

@g1itch I added tests to compare signature with blinded signature, and message with blinded message, all in form which serialises data to bytes with OpenSSL.BN_bn2bin and ctypes.cast. I think this format is usable on wire but more tests are needed.

@g1itch I added tests to compare signature with blinded signature, and message with blinded message, all in form which serialises data to bytes with OpenSSL.BN_bn2bin and ctypes.cast. I think this format is usable on wire but more tests are needed.
This repo is archived. You cannot comment on pull requests.
No description provided.