使用Bouncy Castle和PKCS11库生成签名的CSR

时间:2019-04-04 03:11:22

标签: java bouncycastle

我正在尝试使用Bouncy Castle fips库生成签名的CSR,并在USB令牌中提供一个私钥。

当前充气城堡不提供将签名字节(使用USB令牌生成)附加到pkcs10certificationRequest的选项。

如何使用充气城堡库实现此目标??

我正在使用PKCS10CertificationRequest对象生成一个Signed CSR,它希望将ContentSigner对象作为输入,因此我通过实现方法创建了自己的contentsigner 1. getSignature()。 2. getoutputstream()。 3. getalgorithmidentifier()。

其中的getsignature函数调用PKCS11库调用以使用x500Name和公钥作为输入来生成签名,并使用令牌中存在的私钥对输入数据进行签名。

使用此流,我可以生成一个签名的CSR,但是当我尝试使用isvalid()函数验证生成的签名的CSR时,会抛出错误“无效签名”

使用以下代码通过带有PKCS11库的充气城堡生成签名的CSR:

其中

publicKeyInfo is a public key retrieved from usb token. 
signingPrivKey is a handle for the private key present in usb token.

CertificationRequestInfo certificateRequestInfo = new CertificationRequestInfo(subject, publicKeyInfo, new DERSet());
    ContentSigner contentSigner = new ContentSigner() {

        @Override
        public byte[] getSignature()
        {
            try 
            {
                PrivateKey signingPrivKey = null;
                RSAPrivateKey templateForSignKey = new RSAPrivateKey();
                templateForSignKey.getId().setByteArrayValue(id);
                session.findObjectsInit(templateForSignKey);
                Object[] privKeyObjects = session.findObjects(1);
                if (privKeyObjects.length > 0)
                {
                    signingPrivKey = (PrivateKey) privKeyObjects[0];
                }
                session.findObjectsFinal();

                ByteArrayInputStream dataInputStream = new ByteArrayInputStream(certificateRequestInfo.getEncoded());
                MessageDigest digestEngine = MessageDigest.getInstance("SHA-256", "BCFIPS");
                Mechanism signatureMechanism = Mechanism.get(PKCS11Constants.CKM_RSA_PKCS);
                //Initialize for signing
                session.signInit(signatureMechanism, signingPrivKey);

                byte[] dataBuffer = new byte[1024];
                int bytesRead;

                // feed all data from the input stream to the message digest
                while ((bytesRead = dataInputStream.read(dataBuffer)) >= 0)
                {
                    digestEngine.update(dataBuffer, 0, bytesRead);
                }
                byte[] digest = digestEngine.digest();
                byte[] signatureValue = session.sign(digest);
                return signatureValue;
            }
            catch (TokenException e)
            {
                setMsg(e.getMessage());
            }
            catch (NoSuchAlgorithmException e)
            {
                setMsg(e.getMessage());
            }
            catch (FileNotFoundException e)
            {
                setMsg(e.getMessage());
            }
            catch (IOException e)
            {
                setMsg(e.getMessage());
            }

            return null;
        }

        @Override
        public OutputStream getOutputStream()
        {
            return null;
        }

        @Override
        public AlgorithmIdentifier getAlgorithmIdentifier()
        {
            AlgorithmIdentifier algorithmIdentifier = new DefaultSignatureAlgorithmIdentifierFinder().find(hashingAlgo);
            return algorithmIdentifier;
        }
    };

    AlgorithmIdentifier algorithmId = contentSigner.getAlgorithmIdentifier();
    byte[] signData = contentSigner.getSignature();
    DERBitString derBitStr = new DERBitString(signData);

    CertificationRequest certReq = new CertificationRequest(certificateRequestInfo, algorithmId, derBitStr);
    PKCS10CertificationRequest pkcs10Req = new PKCS10CertificationRequest(certReq);

1 个答案:

答案 0 :(得分:0)

经过大量的头脑风暴,最终使用Bouncy castle FIPS,PKCS11库生成了完美的签名CSR。

上面代码的变化是,我们必须将消息摘要字节数据包装在MessageDigestInfo对象中,并将编码后的数据从MessageDigestInfo发送到PKCS11 Sign Function。