purificant / python-paseto

Platform-Agnostic Security Tokens for Python
MIT License
24 stars 1 forks source link

Two different token produces same message #5

Open sumitsharansatsangi opened 2 years ago

sumitsharansatsangi commented 2 years ago

I am not an security expert, I was just playing with the example provided in the package and found two different token is presenting the same message.

Code to produce the result :-

from paseto.protocol.version4 import create_asymmetric_key, sign, verify
message = b"this is a public message"
public_key, secret_key = create_asymmetric_key()
token = sign(message, secret_key)
token1=v4.public.dGhpcyBpcyBhIHB1YmxpYyBtZXNzYWdlu0p4hKsaiWr0VJOPTK_2Pcf_HNQ9QpFmW93jqUCQ8Hc19z0oeOSs3ftduKNrNZ-KQu_vFokm2PIvnaZGl8mCh
verified_message = verify(token1, public_key)

public_key was b'k4.public.3xOkgS26nr1iGMcpz8njtioRcgceaUTgfngWgwDq9ec=' private key was b'k4.secret.RAoDZGPQRFWJ5uLghlBKYR8BJgBNhAwlzkJj2EPzffDfE6SBLbqevWIYxynPyeO2KhFyBx5pROBeBaDAOr15w==' token was b'v4.public.dGhpcyBpcyBhIHB1YmxpYyBtZXNzYWdlu0p4hKsaiWr0VJOPTK_2Pcf_HNQ9QpFmW93jqUCQ8Hc19z0oeOSs3ftduKNrNZ-KQu_vFokm2PIvnaZGl8mCg'

I am not sure whether this is a serious concern or not, but I'll request to have a look on it.

purificant commented 2 years ago

It looks like you are referring to the message signing example from here: https://github.com/purificant/python-paseto/blob/1f3b2a77b9e1d0a4cd807275338b934698f59949/docs/examples/example4.py

from paseto.protocol.version4 import create_asymmetric_key, sign, verify

message = b"this is a public message"  # your data
public_key, secret_key = create_asymmetric_key()  # signing / verifying keys

token = sign(message, secret_key)
verified_message = verify(token, public_key)

assert verified_message == message
print(f"token={token}")
print(f"verified_message={verified_message}")
print(f"message={message}")

If you run the above block of code multiple times, each run will produce a different public_key, secret_key and token. The message remains a constant. The value of token changes with every run because the public and secret keys also change.

If you modify the example as follows and keep using the same public / secret keys, the token will remain the same. For example:

from paseto.protocol.version4 import create_asymmetric_key, sign, verify

message = b"this is a public message"  # your data
public_key, secret_key = create_asymmetric_key()  # signing / verifying keys

token = sign(message, secret_key)
verified_message = verify(token, public_key)
assert verified_message == message
print(f"token={token}")
print(f"verified_message={verified_message}")
print(f"message={message}")

token2 = sign(message, secret_key)
assert token == token2
assert verify(token2, public_key) == message

token3 = sign(message, secret_key)
assert token == token3
assert verify(token3, public_key) == message

token, token2 and token3 all have the same value.

The sign() method allows creation of digital signatures that can be used to verify the authenticity of the message. The contents of the message remains public. Different public / secret keys will generate a different signature for the same message, which will result in a different token.

sumitsharansatsangi commented 2 years ago

I think I was not able to convey my message to you properly. Let me try again. When I am changing the last letter of the token, I am still getting the same message during verification. eg:-

token = b'v4.public.dGhpcyBpcyBhIHB1YmxpYyBtZXNzYWdludssvJJdDHxRwo7W1WQEyrxLIq0WIXN5NeqFNXNXsqriInH3VkrDXGotXJT0jwvNcdq1eqwSPwzjK88SRU-xDS'

and

token1 = b'v4.public.dGhpcyBpcyBhIHB1YmxpYyBtZXNzYWdludssvJJdDHxRwo7W1WQEyrxLIq0WIXN5NeqFNXNXsqriInH3VkrDXGotXJT0jwvNcdq1eqwSPwzjK88SRU-xDT'

will produce the same message for the same private key and public key.

Note:- Last character of token is 'S' , whereas last character of token1 is 'T'.