首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >证书主题和颁发者中颠倒的属性

证书主题和颁发者中颠倒的属性
EN

Stack Overflow用户
提问于 2011-09-27 18:44:06
回答 3查看 6K关注 0票数 11

我正在尝试用bouncycastle 1.46生成X509证书,代码如下。我遇到的问题是,当证书在JKS中写入,然后重新读取时,DNs是颠倒的。例如,如果我运行下面的代码,我会得到以下输出:

代码语言:javascript
运行
复制
CN=test,O=gina
CN=test,O=gina
CN=test,O=gina
O=gina, CN=test

有人知道这是什么原因吗?如何避免呢?提前谢谢。

代码:

代码语言:javascript
运行
复制
public static void main(String[] args) {
    try {
        Security.addProvider(new BouncyCastleProvider());

        KeyPair pair = generateKeyPair("RSA", 1024);
        X500Name principal = new X500Name("cn=test,o=gina");
        System.out.println(principal);
        BigInteger sn = BigInteger.valueOf(1234);
        Date start = today();
        Date end = addYears(start, 2);
        X509Certificate cert = generateCert(principal, pair, sn, start, end,
                "SHA1withRSA");
        cert.verify(pair.getPublic());
        System.out.println(cert.getSubjectDN());

        // Store the certificate in the JKS
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(null, null);
        ks.setKeyEntry("alias", pair.getPrivate(), KEY_PWD,
                new X509Certificate[] {cert});
        X509Certificate c
                = (X509Certificate)ks.getCertificateChain("alias")[0];
        System.out.println(c.getSubjectDN());
        OutputStream out = new FileOutputStream("text.jks");
        try {
            ks.store(out, KEYSTORE_PWD);
        } finally {
            out.close();
        }

        // Reread the JKS
        ks = KeyStore.getInstance("JKS");
        InputStream in = new FileInputStream("text.jks");
        try {
            ks.load(in, KEYSTORE_PWD);
        } finally {
            in.close();
        }
        c = (X509Certificate)ks.getCertificateChain("alias")[0];
        c.verify(pair.getPublic());
        System.out.println(c.getSubjectDN());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static X509Certificate generateCert(X500Name principal,
        KeyPair pair, BigInteger sn, Date start, Date end, String sigalg)
        throws OperatorCreationException, CertificateException {
    JcaX509v3CertificateBuilder certGen
            = new JcaX509v3CertificateBuilder(principal, sn, start, end,
                    principal, pair.getPublic());
    JcaContentSignerBuilder builder
            = new JcaContentSignerBuilder(sigalg);
    builder.setProvider("BC");
    ContentSigner signr = builder.build(pair.getPrivate());
    X509CertificateHolder certHolder = certGen.build(signr);
    JcaX509CertificateConverter conv
            = new JcaX509CertificateConverter();
    conv.setProvider("BC");
    return conv.getCertificate(certHolder);
}

private static KeyPair generateKeyPair(String algorithm, int keySize)
        throws NoSuchAlgorithmException {
    KeyPairGenerator gen = KeyPairGenerator.getInstance(algorithm);
    gen.initialize(keySize);
    return gen.generateKeyPair();
}

private static Date today() {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}

private static Date addYears(Date date, int count) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.add(Calendar.YEAR, count);
    return cal.getTime();
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-29 02:16:03

我遇到了同样的问题,并通过以下几点快速解决了它:

代码语言:javascript
运行
复制
//CREATES AN X500 CA SUBJECT FOR ISSUER

X500Name issuerName = new JcaX509CertificateHolder((X509Certificate) caCert).getSubject();

然后,我将其与以下代码一起使用:

代码语言:javascript
运行
复制
//CONSTRUCTS THE X509 CERTIFIFATE OBJECT

X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(
issuerName, 
serialNumber, 
startDate, endDate, 
DevCsr.getSubject(), 
DevCsr.getSubjectPublicKeyInfo());

Java Keystore end end实体证书中的颁发者名称现在以正确的顺序显示。

干杯!

票数 8
EN

Stack Overflow用户

发布于 2016-07-07 05:30:23

这可能会简单一点。至少在BC 1.48+中,您可以这样构造X500Name,并且OID将按照预期的方式(或至少按照您指定的方式)排序:

代码语言:javascript
运行
复制
final X500Name subject = new X500Name(RFC4519Style.INSTANCE, "CN=test,O=gina");
票数 11
EN

Stack Overflow用户

发布于 2012-09-19 05:55:22

我在bouncy 1.47上也遇到了同样的问题。

首先,您必须小心使用类X500Name和X500Principal。有太阳课和弹力课。它们是完全不同的!

应该使用X500NameBuilder创建X500Name (反弹)。但是如果您需要使用字符串创建它,那么您的属性必须与RFC2253的顺序相反,这意味着您的属性必须是这样的顺序:“CN,L,ST,O,OU,C,STREET,DC,UID”。

这并不方便,因为,例如,在我的例子中,我必须从一个X500Principal (SUN)创建一个X500Name (bouncy),唯一的方法是使用X500Principal:getName()方法,它根据RFC2253顺序打印属性。所以我创建了这个方法:

代码语言:javascript
运行
复制
private org.bouncycastle.asn1.x500.X500Name toBouncyX500Name( javax.security.auth.x500.X500Principal principal) {

    String name = principal.getName();

    String[] RDN = name.split(",");

    StringBuffer buf = new StringBuffer(name.length());
    for(int i = RDN.length - 1; i >= 0; i--){
        if(i != RDN.length - 1)
            buf.append(',');

        buf.append(RDN[i]);
    }

    return new X500Name(buf.toString());
}

希望它对某些人有用:)

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7567837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档