代码之家  ›  专栏  ›  技术社区  ›  ThanhLam112358

使用PHP/Python验证ECDSA签名

  •  1
  • ThanhLam112358  · 技术社区  · 8 年前

    我编写了使用spongycastle库在Android上生成ECDSA签名的代码。然后我将符号字符串和公钥发送到服务器(Ubuntu 16.04),并尝试使用php和python来验证这个符号。

    我在我的android应用程序上进行了测试验证。它运行良好。

    我不知道,我哪里错了。

    为什么ECDSA验证失败?


    1. 生成签名(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. (Signature string) MEYCIQC7Hz631IFGsUOogcRLeN99uM9hWgLr+LGzuJvR/6nBrgIhAMXgZcvXyMRCAELXlNNS1a9j iAT1x0q2C5Mdu+2aZKtN
      

      (公钥)

      -----BEGIN PUBLIC KEY-----
      MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEj07XEM+ulPyrdsfAf9prN2L2dNUd /Yy0rABcFdueAwYUf86f8Cc93Ws6sxzIvf2iKOapFby7EjHewjhLM/z7Qg==
       -----END PUBLIC KEY-----
      
    3. 使用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";
      }
      ?>
      
    1 回复  |  直到 8 年前
        1
  •  2
  •   stovfl    8 年前

    如果 crypto.verify(...
    使用错误的证书、签名或数据进行验证


    议论 :您对add base64.B64解码有何看法。。。因为在android代码中我有这个 linetxtMaHoa.setText(Base64.encodeToString(signatureBytes,Ba‌​se64.DEFAULT));

    PEM base64 .setText(Base64... 可以省略。现在,我已经用更新了下面的代码 base64.b64decode .


    问题 :示例----b“sha256”?“b”是二进制(内置函数,或者我必须将字符串sha256转换为二进制?)

    仅作为字符串对我有效( digest-names

    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')],)
    

    笔记 :抛出 crypto.Error 因为没有使用 certificate signature .


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

    验证数据字符串的签名。
    证书是一个X509实例,对应于生成签名的私钥。
    签名是给出签名本身的str实例。

    digest is a str instance naming the message digest type of the signature, for example b"sha256" .

    版本0.11中新增。

    推荐文章