1

I want to proof a Wii signature in PHP. I have 60 bytes of the public key as binary data plus 4 additional bytes. And I know that it is ECDSA (most likely B-233). I already implement it in C, but the PHP interpreter is too slow for my implementation. So I call the external C tool to confirm the signature.

But I want to use openssl_verify($data,$sig,$pubkey). My problem is the third parameter (public key). So I have to convert ECDSA info plus the public key into an accepted format.

Any ideas?

Progress

I tried more and created keys with different algorithms (e.g. sect233k1, sect233r1). My plan is to inject a so generated public key with my key. Now I get the error message:

error:0906D06C:PEM routines:PEM_read_bio:no start line

The public key looks like this:

-----BEGIN PUBLIC KEY-----
MFIwEAYHKoZIzj0CAQYFK4EEABoDPgAEAS+URvH1x1GXfTw6VZh8tLVPq3bgYwl8
g8OHtCKuADoZ8YayIHkJuYEqTJZBgI8YMX8FtrI8BOlBiBLF
-----END PUBLIC KEY-----
Wiimm
  • 2,971
  • 1
  • 15
  • 25
  • How do you know the 4 bytes are not part of the public key? Which curve does the key belong to? – Topaco Oct 22 '19 at 12:06
  • I know, it, because the C implementation ignores the 4 bytes. The curve is most likely B-233. But my main issue in the moment is to get any $pubkey running. Even if using a PEM file created by `openssl ec ...`, `openssl_verify()` throws `supplied key param cannot be coerced into a public key`. – Wiimm Oct 22 '19 at 13:06
  • _But my main issue in the moment is to get **any** $pubkey running._ Does this mean that you are creating a key pair with OpenSSL for B-233 to sign a file and the verification fails? I can't reproduce that! The scenario described above works for me. Post your OpenSSL-statements. – Topaco Oct 22 '19 at 17:06
  • The issue with the key param was, that the installed openssl removed NIST support and so php doesn't know the algorithm. After changing the server and this issue is gone. Anyway, converting the signature to a pub key and verifiying it results in error `error:0906D06C:PEM routines:PEM_read_bio:no start line`. – Wiimm Oct 23 '19 at 07:31

1 Answers1

1

Yeah, you're on the right track. Assuming that the curve is known, you can derive the public key as follows (which is essentially based on an idea of this answer):

  • In the following, curve NIST B-233 (aka sect233r1) is assumed whose raw public key has a size of 60 bytes. If the curve is different, the curve ID must be exchanged accordingly and the size of the curves's public key must be used instead.

  • Use any public key in DER-format that matches your curve.

    If you don't have one, use OpenSSL to create a private key in PEM-format that matches your curve. The private key has the SEC1-format:

      openssl ecparam -out <path to private key file> -genkey -name sect233r1 -noout
    

    From this private key, derive the public key as DER. The public key has the X.509 format:

      openssl ec -in <path to private key file> -pubout -outform der -out <path to public key file>
    
  • Determine the binary data of the public key with a hex-editor, e.g. online. At this point it is made use of the fact that the raw public key is located directly at the end of the public key. In the case of B-233, the raw public key has a length of 60 bytes, i.e. the last 60 bytes of the generated public key must be exchanged with the 60 bytes of your current raw public key. This is the searched public key as DER, which contains your raw public key.

  • For the verification process with OpenSSL, the DER-format is sufficient if the -keyform DER option is used, e.g.

      openssl dgst -ecdsa-with-SHA1 -keyform DER -verify <path to public key file> -signature <path to signature file> <path to file for which signature is>
    
  • For the verification process in PHP with openssl_verify the PEM-format is required. A conversion to the PEM-format is easiest if the DER-data are Base64-encoded, e.g. online. Finally you have to add header (-----BEGIN PUBLIC KEY-----\n) and footer (\n-----END PUBLIC KEY-----). Please make sure that there is exactly one line break immediately after the header and immediately before the footer. In the last parameter, the hash algorithm used to create the signature must be specified, e.g.:

      $data = hex2bin(<binary data from file for which signature is>); 
      $signature = hex2bin(<binary data from signature file>);
      $pub_key_id = "-----BEGIN PUBLIC KEY-----\nMFIwEAYHKoZIzj0CAQYFK4EEABsDPgAEAfERAiIKyPaby4+efUcRmv8ucekCFMnjc6fN1IeQAO6EMcKCcFLhKRJUHijUNp0Dv/CWYLUdeN0qNOI6\n-----END PUBLIC KEY-----";
      $result = openssl_verify($data, $signature, $pub_key_id, OPENSSL_ALGO_SHA1);
      print($result);
    
Community
  • 1
  • 1
Topaco
  • 40,594
  • 4
  • 35
  • 62
  • On the first view: That is exactly what I have done. I'll try it step by step later to find any mistakes by me. Thanks! – Wiimm Oct 23 '19 at 09:41