【问题标题】:Verifying Signed Hash using Digital Signature使用数字签名验证签名哈希
【发布时间】:2014-12-10 04:09:38
【问题描述】:

我正在实现一个将 3 个东西作为输入的接口

  1. X509 证书

  2. 使用该证书的私钥签名的签名哈希

  3. 初始哈希

它必须执行以下操作:

  1. 确认此哈希是使用提供的证书签名的。
  2. 使用作为输入提供的证书的公钥解密签名的哈希,并检查它是否与提供的哈希匹配。

我已经实现了以下验证数字签名:-

 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 ?**

非常感谢您的帮助。非常感谢。

【问题讨论】:

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


    【解决方案1】:

    我已复制原始代码并将我的 cmets 放入代码中

    // 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;
    }
    

    【讨论】:

    • 嗨 Divanov,很高兴看到你再次发布我的论坛,仅供参考,我已经使用 signedHash = Base64.decodeBase64(signedHash); 解码了我的字节 [] 现在我得到的返回值为 false,但是我想验证我是否我是否缺少某些东西。我的最新代码如下所示:-
    • 请查看我更新的帖子并检查我是否遗漏了什么?
    • 为什么要将证书保存到文件中并读回?您可以改用 ByteArrayInputStream。
    • 注意,现在我使用 ByteArrayInputStream 写入数据如下:- byte[] data = Base64 .decodeBase64(X509Certificate); try (OutputStream stream = new FileOutputStream("C:\\abc.cer")) { bao.write(data); } // Storing the data in ByteArrayInputStream byte[] datas = bao.toByteArray(); byteInputStream = new ByteArrayInputStream(datas);
    • 除此之外,验证签名是否正确
    猜你喜欢
    • 2017-04-25
    • 1970-01-01
    • 2011-09-22
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多