2013-11-24 35 views
6

Tôi đang làm việc trên một ứng dụng được phân phối với một số quy trình nô lệ được xác định duy nhất sẽ liên lạc với ứng dụng chính qua ổ cắm được bật SSL. Ứng dụng này được viết bằng java.Tạo chứng chỉ cho giao tiếp SSL

Tôi cần một số trợ giúp để hiểu SSLSockets hoặc đúng hơn là chứng chỉ mà họ sử dụng.

Điều tôi đang tìm kiếm là người có thể cho tôi biết nếu tôi đã hiểu hoạt động cơ bản của chuỗi chứng chỉ chính xác, nhưng tôi cũng sẽ không nói không với mẫu mã.

Tôi muốn thiết lập nơi bản thân máy chủ có chứng chỉ đã ký CA và mọi nô lệ sẽ nhận được chứng chỉ của riêng họ được tạo bởi ứng dụng chính.

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 

Câu hỏi đầu tiên: Loại chuỗi chứng chỉ này có đúng cách để giải quyết vấn đề không? Tôi nghĩ đây là cách đơn giản nhất để đạt được bậc thầy và nô lệ tất cả đều có một bản sắc duy nhất mà không cần phải ký CA mọi chứng chỉ.

Câu hỏi thứ hai: Làm cách nào để lập trình tạo chứng chỉ SSL trong java? Tôi đang cố gắng tạo chứng chỉ cuối cùng trong chuỗi ở đây, giả sử tôi đã có "cert máy chủ chính" cho bây giờ. tôi đã nhận được cho đến nay là tạo ra một chìa khóa cho chứng chỉ (Nơi loại là 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); 

Tôi không cho rằng việc thiết lập serverCert như tổ chức phát hành là đủ để ký vào giấy chứng nhận? Theo như tôi đã hiểu tôi cần phải ký giấy chứng nhận mới với giấy chứng nhận tiếp theo trong chuỗi bằng cách nào đó, nhưng làm thế nào để tôi làm điều đó? Tôi có ký giấy chứng nhận với khóa riêng của serverCert như:

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); 

Tôi có bỏ sót các bước nào khác không?

Trả lời

1

Từ quan điểm kỹ thuật, giải pháp của bạn là chính xác. Tuy nhiên đừng quên những cân nhắc bảo mật: ai có thể yêu cầu một chứng chỉ, cách thực hiện xác thực, cách các khóa chứng chỉ/khóa riêng được phân phối đến các máy chủ ...

Những yếu tố này là bắt buộc đối với một thế hệ giấy chứng nhận:

  • Tiêu đề Tên tên
  • Issuer
  • Giấy chứng nhận số serial
  • chủ đề nào quan trọng
  • ghi thời hạn (không trước, không sau)

Nó cũng là một thực hành tốt để thêm một số phần mở rộng:

  • Chủ đề nhận diện chính
  • Khoá Tổ chức Indentifier
  • hạn chế cơ bản
  • Key Usage
  • mở rộng chính Công dụng

đoạn mã này phác thảo các giấy chứng nhận thế hệ:

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)); 
} 

CẬP NHẬT: sửa mã theo nhận xét của Martin Nielsen.

+0

createAuthorityKeyIdentifier (subjectKey)) createSubjectKeyIdentifier (issuerCert)) Điều này chỉ vì sự thiếu hiểu biết của riêng tôi, nhưng đúng hay không, hoặc subjectKey và issuerCert được đảo ngược? –

+1

Vâng, bạn nói đúng. Tôi đã thực hiện một sai lầm, subjectKey và issuerCert phải được đảo ngược. Thx, tôi cập nhật câu trả lời. – Jcs

+0

Không sao. Không có kiểm tra tốt hơn cho tôi thực sự hiểu những gì đang xảy ra: D –

Các vấn đề liên quan