当前位置: 首页 > 面试题库 >

创建用于SSL通信的证书

常元章
2023-03-14
问题内容

我正在使用具有多个唯一标识的从属进程的分布式应用程序,这些进程将通过启用SSL的套接字与主应用程序进行通信。该应用程序用Java编写。

我需要一些帮助来了解SSLSocket,或者更确切地说,是它们使用的证书。

我正在寻找的人可以告诉我我是否正确理解了证书链的基本工作原理,但是我也不会拒绝代码示例

我想要一个服务器本身具有CA签名证书的设置,每个从属服务器都将获得由主应用程序创建的自己的证书。

CA->Main server cert->Master SSL cert
CA->Main server cert->Slave SSL cert 1
CA->Main server cert->Slave SSL cert 2
CA->Main server cert->Slave SSL cert 3

第一个问题:这种证书链是解决问题的正确方法吗?我认为这是实现主机和从机都具有唯一身份而不必CA对每个证书进行签名的最简单方法。

第二个问题:如何以编程方式在Java中创建SSL证书?我正在尝试在这里创建链中的最后一个证书,假设我现在已经拥有“主服务器证书”。到目前为止,我已经生成了证书的密钥(类型为RSA):

public KeyPair generateKeypair(String type, int bytes) 
throws NoSuchAlgorithmException{
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(type);
    keyPairGenerator.initialize(bytes);
    return keyPairGenerator.generateKeyPair();
}

X509Principal issuer = PrincipalUtil.getSubjectX509Principal(serverCert);
SubjectPublicKeyInfo key 
    = SubjectPublicKeyInfo.getInstance(kpair.getPublic().getEncoded());
X509v3CertificateBuilder certGen 
    = new X509v3CertificateBuilder(
        issuer, 
        BigInteger.valueOf(new SecureRandom().nextInt()), 
        before, 
        after, 
        subject, 
        key
    );
AlgorithmIdentifier sigAlgId 
    = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
AlgorithmIdentifier digAlgId 
    = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);

我不认为将serverCert设置为颁发者足以签署证书吗?据我了解,我需要以某种方式在链中的下一个证书上签名新证书,但是我该怎么做?我是否使用serverCert的私钥对证书签名:

AsymmetricKeyParameter akp 
    = PrivateKeyFactory.createKey(serverPrivateKey.getEncoded());
AlgorithmIdentifier sigAlgId 
    = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
AlgorithmIdentifier digAlgId 
    = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
ContentSigner sigGen 
    = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(akp);

我还有其他步骤吗?


问题答案:

从技术角度来看,您的解决方案是正确的。但是,请不要忘记安全方面的考虑:谁可以请求证书,如何执行身份验证,如何将证书/私钥分发到服务器

这些元素对于生成证书是必不可少的:

  • 主题名称
  • 发行人名称
  • 证书序列号
  • 主题公钥
  • 有效期(不早于,不晚于)

添加一些扩展名也是一个好习惯:

  • 主题密钥标识符
  • 权限密钥标识符
  • 基本约束
  • 按键用法
  • 扩展密钥用法

此代码段概述了证书的生成:

ContentSigner getCertSigner(PrivateKey issuerKey) {
  AsymmetricKeyParameter akp = PrivateKeyFactory.createKey(issuerKey.getEncoded());
  AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA");
  AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
  return new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(akp);
}

X509CertificateHolder generateCertificate(X509Certificate issuerCert, PrivateKey issuerKey, X500Name subject, PublicKey subjectKey, Date notBefore, Date notAfter) {
  X509Principal issuerDN = PrincipalUtil.getSubjectX509Principal(issuerCert);
  SubjectPublicKeyInfo key = SubjectPublicKeyInfo.getInstance(subjectKey.getEncoded());
  X509v3CertificateBuilder builder = new X509v3CertificateBuilder(issuerDN, BigInteger.valueOf(new SecureRandom().nextInt()), before, after, subject, key);

  // Add authority key identifier
  builder.addExtension(X509Extension.authorityKeyIdentifier, false, JcaX509ExtensionUtils.createAuthorityKeyIdentifier(issuerCert));

  // Add subject key identifier
  builder.addExtension(X509Extension.subjectKeyIdentifier, false, JcaX509ExtensionUtils.createSubjectKeyIdentifier(subjectKey));

  // Add basic constraints
  builder.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(false));

  // Add key usage
  KeyUsage keyUsage = new KeyUsage(KeyUsage.keyEncipherment|KeyUsage.digitalSignature);
  builder.addExtension(X509Extension.keyUsage, true, keyUsage);

  // Add extended key usage
  ExtendedKeyUsage extKeyUsage = new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth);
  builder.addExtension(X509Extension.extendedKeyUsage, false, extKeyUsage);

  return builder.build(getCertSigner(issuerKey));
}

更新: 根据Martin Nielsen的评论修复了代码。



 类似资料:
  • 尝试按照关于创建用于localhost的自签名证书的各种说明进行操作,大多数说明似乎是针对IIS的,但我尝试使用NodeJS/Express。它们都无法正常工作,因为在安装证书时,它不受信任。以下是我尝试失败的方法: null 编辑:在注释中建议问题是不受信任的证书根。我通过IE安装了证书,但它仍然不受信任。

  • 我想生成一个自签名SSL证书,并将其与Tomcat一起使用。 我怎么能这样呢?

  • 我创建了两个类:-这一个扩展了OkHttp,并有一个新方法getUnsafeOkHttpClient()。 和其他主要类别: 但我仍然有一个错误: 线程“main”javax中出现异常。网ssl。SSLHandshakeException:太阳。安全验证器。ValidatorException:PKIX路径生成失败:sun。安全供应商。证书路径。SunCertPathBuilderExceptio

  • 我有两个ssl文件- 我如何使Dropwizrad与它的嵌入式码头在SSL中工作? 谢谢。编号

  • 我们需要显式地将受信任的CA证书导入java密钥库吗?如果是,为什么? 我可以理解,我们应该始终将自签名SSL证书导入密钥库,因为它们不是经过验证的证书,除非密钥库中有java,否则无法信任。但是,即使对于可信CA生产证书,我们也需要执行同样的操作吗? 注意:我使用的是jdk v1。6.x。

  • 问题内容: 我正在尝试将Android应用连接到使用自签名证书的启用SSL的服务器。我已经阅读了数十个教程,并且该应用程序现在正在接受证书并连接到服务器,但是我再也收不到任何数据。 我用来初始化套接字的原始代码是这样的: 之后,接收器线程的运行循环使用 socket.getInputStream() 访问输入流。只要我使用未加密的连接,它就可以正常工作。但是安全连接不会从套接字 检索任何数据 。我