简体   繁体   中英

Using PHP/Python to verify ECDSA signature

I write the code to generate ECDSA signature on Android using spongycastle lib. Then I send the sign string and public-key to server (Ubuntu 16.04) and try to use php and python to verify this sign.

I test verify on my android app. It worked well.

I use php-openssl extension and with Python I use ecdsa 0.13. But, both of this failed. I try again, using openssl command and it can't verify too.

I don't know, where I am wrong.

Why is the ECDSA verification failing?


Here is my code:

  1. Generate signature (android):

     ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1"); try { KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA","SC"); g.initialize(spec, new SecureRandom()); KeyPair keyPair = g.generateKeyPair(); privateKey = keyPair.getPrivate(); publicKey = keyPair.getPublic(); ///write public key to pem file ...... FileOutputStream fileOutputStream1 = new FileOutputStream(file1); StringWriter writer1 = new StringWriter(); PemWriter pemWriter1 = new PemWriter(writer1); pemWriter1.writeObject(new PemObject("PUBLIC KEY",publicKey.getEncoded())); pemWriter1.flush(); pemWriter1.close(); String publickeyPem = writer1.toString(); fileOutputStream1.write(publickeyPem.getBytes()); fileOutputStream1.close(); } catch (Exception e) { e.printStackTrace();} ...... //Sign and veryfied String chuoi = txtChuoi.getText().toString(); byte[] chuoiInput = chuoi.getBytes("UTF-8"); Signature sig = Signature.getInstance("NONEwithECDSA","SC"); sig.initSign(privateKey); sig.update(chuoiInput); ///SIGN byte[] signatureBytes = sig.sign() txtMaHoa.setText(Base64.encodeToString(signatureBytes,Base64.DEFAULT)); sig.initVerify(publicKey); sig.update(chuoiInput); ///VERIFIED txtGiaiMa.setText(sig.verify(signatureBytes)+""); ///Write string sign in txtMahoa to file ....... 
  2. Output I have Signature and publickey are:

     (Signature string) MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9j iAT1x0q2C5Mdu+2aZKtN 

    (Publickey)

     -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEj07XEM+ulPyrdsfAf9prN2L2dNUd /Yy0rABcFdueAwYUf86f8Cc93Ws6sxzIvf2iKOapFby7EjHewjhLM/z7Qg== -----END PUBLIC KEY----- 
  3. Verify using PHP:

     $pubkeyid = openssl_pkey_get_public("/var/www/html/ca.pem"); $data = "nguyen tran thanh Lam"; $signature = "MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9jiAT1x0q2C5Mdu+2aZKtN"; $ok = openssl_verify($data, $signature, $pubkeyid); if ($ok == 1) { echo "good"; } elseif ($ok == 0) { echo "bad"; } else { echo "ugly, error checking signature"; } ?> 

Comment : ... but the verify function don't return anything. So I not sure

If crypto.verify(... don't throw an Error, this means Verify is OK. See updated Code below.
Verify with using WRONG Certificat, Signature or Data .


Comment : what do you think about add base64.b64decode. ... because in android code I have this linetxtMaHoa.setText(Base64.encodeToString(signatureBytes,Ba‌​se64.DEFAULT));

PEM is already base64 , check if the above .setText(Base64... can omitted. For now I have updated the Code below with base64.b64decode .


Question : Example ---- b"sha256"? "b" is a binary (built-in funtion or I must convert string sha256 to binary?)

Works for me only as String ( digest-names ), for example:

import pem, base64
from OpenSSL import crypto

signature  = b"MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9jiAT1x0q2C5Mdu+2aZKtN"

# As Creator of the Signatur do additional base64 encoding!
signature = base64.b64decode(signature)

data = "nguyen tran thanh Lam"

certificate = pem.parse_file('Android.pem')[0]
cert = crypto.load_certificate(crypto.FILETYPE_PEM, certificate.as_bytes())

try:
    crypto.verify(cert=cert, signature=signature, data=data, digest='sha256')
except crypto.Error as exp:
    print('crypto.Error:{}'.format(exp.args))

>>>crypto.Error:([('', 'ECDSA_do_verify', 'bad signature')],)

Note : Throws crypto.Error because not using the certificate which created the signature .


OpenSSL.crypto.verify(certificate, signature, data, digest)

Verify the signature for a data string.
certificate is a X509 instance corresponding to the private key which generated the signature.
signature is a str instance giving the signature itself.
data is a str instance giving the data to which the signature applies.
digest is a str instance naming the message digest type of the signature, for example b"sha256" .

New in version 0.11.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM