libp2p / py-libp2p

The Python implementation of the libp2p networking stack 🐍 [under development]
https://libp2p.io
Other
478 stars 106 forks source link

Signature verification using Ed25519 public key fails #428

Closed wolfgang closed 3 years ago

wolfgang commented 3 years ago

What was wrong?

I expected to verify a signature using a Ed25519 public key, but that threw an exception.

Code that produced the error

from libp2p import crypto
from base64 import b64decode 

public_key_b64 = 'CAESIIsxrBKQAeAtxOF9U5RBGG53bN15kHwUVyldC0PaPFIT'
payload_b64 = 'c29tZSBzdHJpbmc='
signature_b64 = 'YXnK4XqfaIjsZLpUhTv15+fBjUHdKYw95L7eWAziQfH22h8fDpr6lgqAs5xOZNo9fnuyA0rldk1XhxtdHpGLBQ=='

public_key_data = b64decode(public_key_b64)
public_key = crypto.serialization.deserialize_public_key(public_key_data);
payload = b64decode(payload_b64)
signature = b64decode(signature_b64)

result = public_key.verify(payload, signature)
print("verify result", result)

Full error output

Traceback (most recent call last):
  File "src/sandbox/libp2p-error.py", line 14, in <module>
    result = public_key.verify(payload, signature)
  File "/Users/wodev/miniconda3/envs/ipfs-3.7/lib/python3.7/site-packages/libp2p/crypto/ed25519.py", line 29, in verify
    verify_key.verify(h, signature)
  File "/Users/wodev/miniconda3/envs/ipfs-3.7/lib/python3.7/site-packages/nacl/signing.py", line 107, in verify
    smessage = signature + smessage
TypeError: can't concat SHA256Hash to bytes

Expected Result

verify result True

Environment

Python version:
3.7.6 (default, Jan  8 2020, 13:42:34) 
[Clang 4.0.1 (tags/RELEASE_401/final)]

Operating System: Darwin-19.6.0-x86_64-i386-64bit

pip freeze result:
aiohttp==3.6.2
aioipfs-api==0.1.3
asn1crypto==1.4.0
async-exit-stack==1.0.1
async-generator==1.10
async-service==0.1.0a11
async-timeout==3.0.1
attrs==19.3.0
base58==1.0.3
certifi==2020.4.5.1
cffi==1.14.5
chardet==3.0.4
coincurve==10.0.0
cryptography==3.4.6
cytoolz==0.11.0
docopt==0.6.2
eth-hash==0.3.1
eth-typing==2.2.2
eth-utils==1.10.0
fastecdsa==1.7.5
idna==2.8
importlib-metadata==1.5.0
ipfshttpclient==0.4.12
libp2p==0.1.5
lru-dict==1.1.7
mkl-fft==1.0.15
mkl-random==1.1.0
mkl-service==2.3.0
more-itertools==8.2.0
multiaddr==0.0.9
multidict==4.7.4
mypy==0.812
mypy-extensions==0.4.3
netaddr==0.7.19
noiseprotocol==0.3.1
numpy==1.18.1
olefile==0.46
outcome==1.1.0
packaging==20.1
Pillow==7.1.2
pluggy==0.13.1
progressbar2==3.51.3
protobuf==3.15.5
py==1.8.1
pycparser==2.20
pycryptodome==3.10.1
pymultihash==0.8.2
PyNaCl==1.3.0
pyparsing==2.4.6
pytest==5.3.5
python-utils==2.4.0
requests==2.22.0
rpcudp==3.0.0
six==1.14.0
sniffio==1.2.0
sortedcontainers==2.3.0
texturize==0.3.0
toolz==0.11.1
torch==1.5.0
torchvision==0.6.0a0+82fd1c8
trio==0.18.0
trio-typing==0.3.0
typed-ast==1.4.2
typing-extensions==3.7.4.3
u-msgpack-python==2.7.1
urllib3==1.25.8
varint==1.0.2
wcwidth==0.1.8
yarl==1.4.2
zipp==3.0.0

OUTPUT_HERE

How can it be fixed?

Change method Ed25519PublicKey.verify to:

def verify(self, data: bytes, signature: bytes) -> bool:
    verify_key = VerifyKey(self.to_bytes())
    # h = SHA256.new(data)
    try:
        verify_key.verify(data, signature)
    except BadSignatureError:
        return False
    return True

i.e. don't hash the data parameter, as the nacl library expects both inputs to be bytes.

Thanks for reading!

mhchia commented 3 years ago

I haven't tried this but this issue looks legit. Could you have a Pull Request for it?

wolfgang commented 3 years ago

Done

ra0x3 commented 3 years ago

@wolfgang Should this be closed? I see the merge was a while ago. Is anyone waiting for some type of confirmation?

wolfgang commented 3 years ago

@aar3 sorry, yes. My work focus has shifted so I have not paid attention to this.