Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Java签署X.509证书_Java_Certificate_X509_Signing_Asn.1 - Fatal编程技术网

用Java签署X.509证书

用Java签署X.509证书,java,certificate,x509,signing,asn.1,Java,Certificate,X509,Signing,Asn.1,我想了解如何签署x.509证书 我已经设置了一个OpenSSL CA来创建一个演示证书。证书很好,我可以使用名为dumpasn1的工具查看所有相关元素。 理论上,我知道我必须对名为“tbsCertificate”的结构进行签名,该结构包含属性版本、序列号签名、颁发者、有效性、主题、主题PublicKeyInfo和扩展 然而,当我试图在Java中模仿它时,不幸的是它不起作用。 我所做的是: 我阅读了DER编码证书的“tbsCertificate”部分 然后我从颁发CA获得私钥 最后,我尝试使用以

我想了解如何签署x.509证书

我已经设置了一个OpenSSL CA来创建一个演示证书。证书很好,我可以使用名为dumpasn1的工具查看所有相关元素。 理论上,我知道我必须对名为“tbsCertificate”的结构进行签名,该结构包含属性版本、序列号签名、颁发者、有效性、主题、主题PublicKeyInfo和扩展

然而,当我试图在Java中模仿它时,不幸的是它不起作用。 我所做的是:

  • 我阅读了DER编码证书的“tbsCertificate”部分
  • 然后我从颁发CA获得私钥
  • 最后,我尝试使用以下代码对tbsCertificate结构进行签名:

不幸的是,结果与证书中的签名不匹配,因此显然我犯了某种错误。 签名算法与证书中使用的相同(SHA256withECDSA),因此我怀疑我没有选择tbsCertificate结构的正确部分

我的证书大约有530字节长。我开始从偏移量4(跳过初始序列标记和长度字节)读取到扩展的末尾(在证书部分开始之前停止)

有人能告诉我这是否是我必须为“tbsCertificate”结构读取的正确字节数组吗? 或者我还可能犯了什么现在看不到的错误? 证书本身是确定的,我使用以下Java代码仔细检查了证书和签名算法

public static X509Certificate loadCertificate(String fileName)
{
    InputStream in;
    byte [] signature;
    X509Certificate cert = null;
    try
    {
        in = new FileInputStream(fileName);
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        cert = (X509Certificate) factory.generateCertificate(in);
        signature = cert.getSignature();
        System.out.println("Signature Algorithm: " + cert.getSigAlgName());
        System.out.println(signature);
        return cert;
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (CertificateException e)
    {
        e.printStackTrace();
    }
    return cert;
}

ECDSA不会生成稳定的签名,因此,如果您的测试是生成相同的答案,那么该测试将不起作用。您可以通过根据tbsCertificate数据验证签名来验证证书上的签名

您的方法可以使用RSA签名,因为这是一种稳定的签名算法(使用PKCS1填充,而不是PSS)

至于找到tbsCertificate:您似乎确实知道DER编码是什么,但我觉得有必要根据问题中的松散描述提供指导:

证书的二进制编码形式为DER。第一个字节将是0x30((构造)序列)。下一个字节是序列的长度(<0x80)或长度(0x82=>下两个字节是大端长度)。下一个字节将再次为0x30,即tbsCertificate编码值的开始。然后可以读取该结构的长度,并计算tbsCertificate的正确端点偏移量


可以在中找到证书结构。(在中有一个更新,但我听到有人说“这没有作为标准获得批准”。)它也可以与属性证书一起在中使用——这就是X.509中的X.509证书的来源。我链接到2012版是因为2016版是在付费墙后面。

谢谢你的回答。我知道DER编码,它是从一个序列开始的。我只是不想让这个问题变得更长更复杂。我也知道RFC3280,它或多或少是关于tbsCertificate清楚。如果我解释正确,它应该从第二个“序列”字节开始,偏移量为4,并一直延伸到给定的长度。你说ECDSA不能产生稳定的签名是什么意思?我想做的正是您所描述的——我想在tbsCertificate上运行签名算法,以便重新创建签名。我想我现在明白了稳定的含义——谢谢你对此事的评论。我原以为我可以重新制作签名。多亏了你的提示,我试着重新签署了考试证书,似乎效果不错。当我验证修补后的证书时,它会验证ok。很高兴我能提供帮助:)。在“谢谢”上写上:如果答案是正确的,请标记为正确。如果有帮助,你也可以选择向上投票。
public static X509Certificate loadCertificate(String fileName)
{
    InputStream in;
    byte [] signature;
    X509Certificate cert = null;
    try
    {
        in = new FileInputStream(fileName);
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        cert = (X509Certificate) factory.generateCertificate(in);
        signature = cert.getSignature();
        System.out.println("Signature Algorithm: " + cert.getSigAlgName());
        System.out.println(signature);
        return cert;
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (CertificateException e)
    {
        e.printStackTrace();
    }
    return cert;
}