使用Java签署X.509证书

时间:2017-03-28 15:01:20

标签: java certificate x509 signing asn.1

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

我已经设置了一个OpenSSL CA来创建一个演示证书。证书很好,我可以使用名为dumpasn1的工具查看所有相关元素。 从理论上讲,我知道我必须签署名为" tbsCertificate"其中包括属性版本,序列号签名,发行者,有效性,主题,subjectPublicKeyInfo和扩展名。

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

  • 我阅读了" tbsCertificate" - DER编码证书的部分
  • 然后我从颁发CA
  • 获取私钥
  • 最后我尝试使用以下代码签署tbsCertificate-structure:

public static void sign(byte [] data) throws Exception  
{
    String algorithm = "SHA256withECDSA";
    PrivateKey privKey;
    KeyPair keyPair;

    keyPair = getKeyPairFomPEM();
    privKey = keyPair.getPrivate();

    Signature ecdsa;
    ecdsa = Signature.getInstance(algorithm, "BC");
    ecdsa.initSign(privKey);
    ecdsa.update(data);
    byte[] baSignature = ecdsa.sign(); 
}

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

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

任何人都可以判断这是否是我必须为" 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;
}

1 个答案:

答案 0 :(得分:0)

ECDSA没有产生稳定的签名,所以如果你的测试是你产生了相同的答案,那就不会起作用。您可以通过验证针对tbsCertificate数据提供的签名来验证证书上的签名。

您的方法适用于RSA签名,因为它是一种稳定的签名算法(使用PKCS1填充,而不是PSS)。

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

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

证书结构可在RFC 3280中找到。 (RFC 5280中有更新,但我听说有人说'#34;没有被批准为标准"。)它也可用,以及ITU-T X.509中的属性证书 - 这是X.509证书中X.509的来源。我链接到2012版本,因为2016版本支持付费墙。