starkbank / ecdsa-php

A lightweight and fast PHP ECDSA library
https://starkbank.com
MIT License
82 stars 13 forks source link

closed #4

Closed Obnotname closed 4 years ago

Obnotname commented 4 years ago

[Closed]

cdottori-stark commented 4 years ago

Hi Obnotname,

There a few issues with the usage of the library in your code, here is the corrected example:

` $publicKeyPem = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+nzvoGqvDeB9+SzE6igTl7TyK4JB\nbglwir9oTcQta8NuG26ZpZFxt+F2NDk7asTE6/2Yc8i1ATcGIqtuS5hv0Q==\n-----END PUBLIC KEY-----"; $signatureBase64 = "MEQCIB5DcAc4SO-gjbEFu-ZYfG_LGkX-tp4Nb0DIMjh71SQeAiBAwXcveOUVDcmQ4Royc1Fxbzd13n7gc3AN4QXbPsdvSw"; $message = "some_message";

$publicKey = EllipticCurve\PublicKey::fromPem($publicKeyPem); $signature = EllipticCurve\Signature::fromBase64($signatureBase64); echo "\n" . EllipticCurve\Ecdsa::verify($message, $signature, $publicKey); `

Hope you find it useful!

cdottori-stark commented 4 years ago

No problem! And sorry about the huge delay on our reply. In case you're interested, we actually implemented the same ECDSA interface in several languages, including Python.

Obnotname commented 4 years ago

Ah no problem :) Great to know that 👍

Obnotname commented 4 years ago

Hi, it's me again.

I have now tried your example, however it still returns false on verification

cdottori-stark commented 4 years ago

That's because either the public key or the signature do not match the provided message. Here is an example that returns true on verification:

`<?php require_once "vendor/autoload.php";

$message = "some_message";

$privateKey = new EllipticCurve\PrivateKey(); $publicKeyPem = $privateKey->publicKey()->toPem(); $signatureBase64 = EllipticCurve\Ecdsa::sign($message, $privateKey)->toBase64(); echo "public key: " . $publicKeyPem; echo "signature: " . $signatureBase64;

$publicKey = EllipticCurve\PublicKey::fromPem($publicKeyPem); $signature = EllipticCurve\Signature::fromBase64($signatureBase64); if (EllipticCurve\Ecdsa::verify($message, $signature, $publicKey)) { echo "\nMessage is valid\n"; } else { echo "\nMessage is invalid\n"; }`

cdottori-stark commented 4 years ago

I am not familiar with the lib you're using. The same example would look like this using our python lib:

from ellipticcurve.publicKey import PublicKey
from ellipticcurve.ecdsa import Ecdsa
from ellipticcurve.signature import Signature
import base64
import urllib

publicKey = """
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEGpRlChCiilDu5el58I5Vp6YEmyuvVgzq
Z6VzxPayVUj95fgucEt2SZMVSCO5NE5ngErDC7W/BGROltpc4sMe6w==
-----END PUBLIC KEY-----"""
signature = "MEYCIQDGj4F6TW79PT3lA6dHSNdya-OgVZuyHoWt2n4ZlFGvawIhAOftl2zIq7Ki2HQujVOzWAsia_uO4ojCtLJM4ZGvpk94"
message = "ad_network=5450213213286189855&ad_unit=3430014594&reward_amount=7&reward_item=Reward&timestamp=1593684944978&transaction_id=0cb3fbbe45d94d991763e98fe3668d44&user_id=erik.boscher%40web.de"

prepared_msg = urllib.parse.unquote(message)
prepared_key = PublicKey.fromPem(publicKey)
prepared_sig = Signature.fromDer(base64.urlsafe_b64decode(signature + "==="))

result = Ecdsa.verify(
    message=prepared_msg,
    signature=prepared_sig,
    publicKey=prepared_key,
)

print(result)

Which, as you noted, prints False.

My only guess is that the code is not correctly rebuilding the prepared_msg with the current parsing. If any message bytes are out of place during verification, the signature and public key won't verify it. If possible, try to understand exactly how the message was encoded for transmission, as the process has to be precisely reversed for this verification to work.

KuLi commented 3 years ago

The signature is base64 encoded websafe! You must convert the signature before.

// credits to https://www.php.net/manual/de/function.base64-encode.php#103849
function base64url_decode($data) {

    return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}

After that you can use it like this

$signature = \EllipticCurve\Signature::fromDer(base64url_decode("MEYCIQCQfAX-JkarkUSduywcSAm00wN0UfhUmXQvaZSci4chVgIhAMbl6ZXX_dKl5BWYhLLWzlsUrgr_ptpxEJvHsZJCLL2e"));