pyca / pynacl

Python binding to the Networking and Cryptography (NaCl) library

Home Page:https://pynacl.readthedocs.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Signature failing when sending over HTTP

ApprenticeofEnder opened this issue · comments

Trying to make it so that I can send an ed25519 verifying key over HTTP(S) to a server X, and then later verify from X if something was signed with the corresponding signing key.

Current code:

# Client
sign_key = SigningKey.generate()
verify_key = sign_key.verify_key

encoded_sign_key = sign_key.encode(encoder=encoding.HexEncoder).decode()
encoded_verify_key = verify_key.encode(encoder=encoding.HexEncoder).decode()

print(encoded_sign_key)
print(encoded_verify_key)

r = requests.post("http://localhost:8000/key_setup", json={
    "verifying_key": encoded_verify_key
})

print(r.json())

payload = {
    "msg": "Hello world!",
    "signature": binascii.hexlify(sign_key.sign(("Hello world!").encode('ascii')).signature).decode()
}
r = requests.post("http://localhost:8000/verify", json=payload)

# Server, the /key_setup endpoint trivially saves the key somewhere
# This is the /verify endpoint
msg_hex = encoding.HexEncoder.encode(msg.encode('ascii'))
signature = signature.encode('ascii')
verifying_key = VerifyKey(user_in_db.verifying_key, encoder=encoding.HexEncoder)
result = False
try:
    print(type(msg), type(signature))
    verifying_key.verify(msg, signature, encoder=encoding.HexEncoder)
    result = True
except Exception as e:
    print(e)
return {
    "result": result
}

This however seems to give me an error that the signature was forged or corrupt. Not sure if I'm doing something wrong here, I have tried to fiddle around with the encoding but I'm drawing a blank. Since I need this to be JSON serializable I'm using hex encoding here.

I would suggest removing the HTTP request/response elements: Make sure you can write code to sign and verify a signature correctly, and only then add network requests between them.

Your problem is going to be that you are not actually passing the correct message or signature.

Tried this with two encoders: Raw and Hex.

Raw worked fine:

sign_key = SigningKey.generate()
verify_key = sign_key.verify_key

encoded_sign_key = sign_key.encode()
encoded_verify_key = verify_key.encode()

print(encoded_sign_key)
print(encoded_verify_key)

msg = b"Hello World!"

regen_verifying_key = VerifyKey(key=encoded_verify_key)

signature = sign_key.sign(msg).signature

print(msg, signature)

regen_verifying_key.verify(msg, signature)

But with hex, the signature failed:

sign_key = SigningKey.generate()
verify_key = sign_key.verify_key

encoded_sign_key = sign_key.encode(encoder=encoding.HexEncoder)
encoded_verify_key = verify_key.encode(encoder=encoding.HexEncoder)

print(encoded_sign_key)
print(encoded_verify_key)

msg = b"Hello World!"

regen_verifying_key = VerifyKey(key=encoded_verify_key, encoder=encoding.HexEncoder)

signature = sign_key.sign(msg, encoder=encoding.HexEncoder).signature

print(msg, signature)

regen_verifying_key.verify(encoding.HexEncoder.encode(msg), signature, encoder=encoding.HexEncoder)

Amendment: The following seems to work:

sign_key = SigningKey.generate()
    verify_key = sign_key.verify_key

    encoded_sign_key = sign_key.encode(encoder=encoding.HexEncoder)
    encoded_verify_key = verify_key.encode(encoder=encoding.HexEncoder)

    print(encoded_sign_key)
    print(encoded_verify_key)

    msg = b"Hello World!"

    regen_verifying_key = VerifyKey(key=encoded_verify_key, encoder=encoding.HexEncoder)

    signature = sign_key.sign(msg, encoder=encoding.HexEncoder).signature

    decoded_signature = encoding.HexEncoder.decode(signature)

    print(msg, signature)

    regen_verifying_key.verify(msg, decoded_signature)

Glad to hear you found a working solution.