使用数字签名验证签名哈希

时间:2014-10-15 07:09:54

标签: x509certificate digital-signature bouncycastle pki key-management

我正在实现一个接受三项内容作为输入的接口

  1. X509证书

  2. 使用该证书的私钥

  3. 签名的signedHash
  4. 初始哈希

  5. 必须执行以下操作:

    1. 使用提供的证书确认此哈希是否已签名。
    2. 使用作为输入提供的证书的公钥解密签名的哈希,并检查它是否与提供的哈希匹配。
    3. 我已经实现了以下功能来验证数字签名: -

       public static boolean verifySignedHash(String X509Certificate, String hash,
                  String signedHash) {
      
              boolean isVerified = false;
      
              ByteArrayInputStream inputStream = null;
              ByteArrayOutputStream outputStream = null;
              ByteArrayOutputStream byo = null;
      
      
              try {
      
                  outputStream = new ByteArrayOutputStream();
      
                  byte[] data = Base64.decodeBase64(X509Certificate);
      
                  /* writing decoded X509 certificate to the ByteArrayOutputStream */
      
                  outputStream.write(data);
      
                  byte[] inp = outputStream.toByteArray();
                  inputStream = new ByteArrayInputStream(inp);
      
                  /* Getting the certificate from the Input */
      
                  CertificateFactory cf = CertificateFactory.getInstance("X.509");
      
                  X509Certificate certs = (X509Certificate) cf
                          .generateCertificate(inputStream);
      
                  /* import encoded public key */
      
                  X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(certs
                          .getPublicKey().getEncoded());
      
                  /* Instantiating KeyFactory for accesing the Keys as Object */
      
                  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      
                  /*
                   * using the KeyFactory object to generate a PublicKey from the key
                   * specification.
                   */
      
                  publickKey = keyFactory.generatePublic(pubKeySpec);
      
                  byte[] signHash = Base64.decodeBase64(signedHash);
      
                  byo = new ByteArrayOutputStream();
      
                  byo.write(signHash);
      
                  byte[] signChar = byo.toByteArray();
      
                  ByteArrayInputStream byi = new ByteArrayInputStream(signChar);
      
                  /* Next, input the signature bytes from the file specified */
      
                  byte[] sigToVerify = new byte[byi.available()];
                  byi.read(sigToVerify);
                  byi.close();
      
                  /* Instantiating Signature */
                  Signature signature = Signature.getInstance(certs.getSigAlgName());
      
                  /* Initializing the Public Key in Signature */
      
                  signature.initVerify(publickKey);
      
                  /* Supply the Signature Object With the Data to be Verified */
      
                  BufferedInputStream bufin = new BufferedInputStream(byi);
      
                  byte[] buffer = new byte[1024];
                  int len;
                  while (bufin.available() != 0) {
                      len = bufin.read(buffer);
                      signature.update(buffer, 0, len);
                  };
      
                  bufin.close();
      
                  /* Verify the Signature */
      
                  isVerified = signature.verify(sigToVerify);
      
              } catch (Exception e) {
                  System.err.println("Caught exception " + e.toString());
              }
      
              return isVerified;
          }
      

      我将结果视为错误

      **Am i Missing something or is this piece of code correct ?**
      

      我非常感谢你的帮助。非常感谢。

1 个答案:

答案 0 :(得分:1)

我已复制原始代码并将我的评论放在代码中

// X509Certificate is class name, it cannot be variable name
public static boolean verifySignedHash(String X509Certificate, String hash,
        String signedHash) {

    // Java is not C89 you don't have to declare variables in the beginning
    // of function, this reduces readability of the code and allows misuse
    boolean isVerified = false;

    ByteArrayInputStream inputStream = null;
    ByteArrayOutputStream outputStream = null;
    ByteArrayOutputStream byo = null;

    try {

        outputStream = new ByteArrayOutputStream();

        byte[] data = Base64.decodeBase64(X509Certificate);

        /* writing decoded X509 certificate to the ByteArrayOutputStream */

        outputStream.write(data);

        byte[] inp = outputStream.toByteArray();

        // at this point inp is the same array as data, this makes no sence
        // and reduce performance

        inputStream = new ByteArrayInputStream(inp);

        /* Getting the certificate from the Input */

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        X509Certificate certs = (X509Certificate) cf
                .generateCertificate(inputStream);

        /* import encoded public key */
        // certs.getPublicKey() returns publicKey immediately, why to do
        // all these conversions?

        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(certs
                .getPublicKey().getEncoded());

        /* Instantiating KeyFactory for accesing the Keys as Object */

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        /*
         * using the KeyFactory object to generate a PublicKey from the key
         * specification.
         */

        publickKey = keyFactory.generatePublic(pubKeySpec);

        byte[] signHash = Base64.decodeBase64(signedHash);

        byo = new ByteArrayOutputStream();

        byo.write(signHash);

        byte[] signChar = byo.toByteArray();

        // Again, signChar is the same as signHash, why would you do that?

        ByteArrayInputStream byi = new ByteArrayInputStream(signChar);

        /* Next, input the signature bytes from the file specified */

        byte[] sigToVerify = new byte[byi.available()];
        byi.read(sigToVerify);
        byi.close();

        // And now sigToVerify is the same as signChar and signHash.

        /* Instantiating Signature */
        Signature signature = Signature.getInstance(certs.getSigAlgName());

        /* Initializing the Public Key in Signature */

        signature.initVerify(publickKey);

        /* Supply the Signature Object With the Data to be Verified */

        // byi is already closed, you will get java.io.IOException: Stream closed
        BufferedInputStream bufin = new BufferedInputStream(byi);

        byte[] buffer = new byte[1024];
        int len;
        while (bufin.available() != 0) {
            len = bufin.read(buffer);
            signature.update(buffer, 0, len);
            // Any way bufin contained signature, while you need feed
            // plaintext to signature.update()
            // I could assume unused parameter hash has something to do
            // with plaintext
        };

        bufin.close();

        /* Verify the Signature */

        isVerified = signature.verify(sigToVerify);

    } catch (Exception e) {
        System.err.println("Caught exception " + e.toString());
    }

    return isVerified;
}