2013-11-24 91 views
6

我正在使用一系列唯一標識的從屬進程處理分佈式應用程序,這些進程將通過啓用SSL的套接字與主應用程序進行通信。該應用程序是用java編寫的。爲SSL通信創建證書

我需要一些幫助來理解SSLSockets,或者更確切地說,他們使用的證書。

我在找的是能夠告訴我,如果我已經正確理解證書鏈的基本工作原理的人,但是我也不會對代碼示例說不。

我想要一個安裝程序,其中服務器本身有一個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); 

是否還有其他步驟我錯過了?

回答

1

從技術角度來看,您的解決方案是正確的。但是請不要忘記安全考慮:誰可以請求證書,如何執行身份驗證,如何將證書/私鑰分發到服務器......

這些元素是強制性的證書生成:

  • 主題名稱
  • 發行人名稱
  • 證書序列號
  • 主體公鑰
  • 有效日期(不前,而不是之後)

它也是一個很好的做法,增加了一些擴展:

  • 主題密鑰識別
  • 管理局重點Indentifier
  • 基本約束
  • 密鑰用法
  • 擴展密鑰用法

這段代碼概述證書代:

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的評論修復了代碼。

+0

createAuthorityKeyIdentifier(subjectKey)) createSubjectKeyIdentifier(issuerCert)) 這完全是我自己的無知,因爲,但這些正確的,還是應該subjectKey和issuerCert被逆轉? –

+1

是的,你是對的。我犯了一個錯誤,subjectKey和issuerCert必須顛倒過來。 Thx,我更新了答案。 – Jcs

+0

沒問題。對於我來說沒有更好的測試來真正瞭解發生了什麼:D –