ECDSA:将60字节的二进制公钥转换为PEM格式,以与PHP openssl_verify()结合使用

时间:2019-10-22 07:35:00

标签: php ecdsa

我想证明PHP中的Wii签名。我有60个字节的公共密钥作为二进制数据,外加4个附加字节。我知道这是ECDSA(很可能是B-233)。我已经用C实现了它,但是PHP解释器对于我的实现来说太慢了。因此,我调用外部C工具来确认签名。

但是我想使用opencv_createsamples: command not found。我的问题是第三个参数(公钥)。因此,我必须将ECDSA信息和公共密钥转换为可接受的格式。

有什么想法吗?

进度

我尝试了更多,并使用不同的算法(例如sect233k1,sect233r1)创建了密钥。我的计划是用我的密钥注入这样生成的公共密钥。现在,我收到错误消息:

openssl_verify($data,$sig,$pubkey)

公钥如下:

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

1 个答案:

答案 0 :(得分:1)

是的,您的路线正确。假定曲线是已知的,则可以按以下方式导出公钥(这基本上基于此answer的思想):

  • 在下面,假设曲线NIST B-233 (aka sect233r1)的原始公钥大小为60个字节。如果曲线不同,则必须相应地交换曲线ID,而必须使用曲线公钥的大小。

  • 使用与您的曲线相匹配的DER格式的任何公钥。

    如果没有,请使用OpenSSL以PEM格式创建与曲线匹配的私钥。私钥具有SEC1格式:

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

    从此私钥中将公钥导出为DER。公钥具有X.509格式:

    openssl ec -in <path to private key file> -pubout -outform der -out <path to public key file>
    
  • 用十六进制编辑器确定公钥的二进制数据,例如online。此时,利用了以下事实:原始公钥直接位于公钥的末尾。对于B-233,原始公共密钥的长度为60个字节,即生成的公共密钥的最后60个字节必须与当前的原始公共密钥的60个字节交换。这是搜索到的公共密钥DER,其中包含您的原始公共密钥。

  • 对于使用OpenSSL进行的验证过程,如果使用了-keyform DER选项,例如,使用DER格式就足够了。

    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>
    
  • 对于使用openssl_verify的PHP验证过程,需要PEM格式。如果DER数据是Base64编码的,则最容易转换为PEM格式。 online。最后,您必须添加页眉(-----BEGIN PUBLIC KEY-----\n)和页脚(\n-----END PUBLIC KEY-----)。请确保紧接在页眉之后和页脚之前有一个换行符。在最后一个参数中,必须指定用于创建签名的哈希算法,例如:

    $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);