Creating certificates for SSL communication

I am working on a distributed application with several unique subordinate processes that will interact with the main application through SSL-compatible sockets. The application is written in java.

I need help understanding SSLSockets, or rather, the certificates that they use.

What I'm looking for is someone who can tell me if I understood correctly the basic actions of certificate chains, but I would not say no as an example code.

I need a setting in which the server itself has a certificate with a CA certificate, and each subordinate will receive their own certificate created by the main application.

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 

First question: is this certificate chain the right way to solve this problem? I think this is the easiest way to reach the master, and the slaves all have a unique identity, without forcing the CA to sign each certificate.

Second question: How am I going to programmatically create an SSL certificate in java? I am trying to create the last certificate in the chain here, assuming that I already have a "Master Server Certificate". So far I have received the key for the certificate (where is the RSA type):

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

I do not assume that setting serverCert as an issuer is enough to sign a certificate? As I understand it, I need to somehow sign a new certificate with the next certificate in the chain, but how to do it? I sign the certificate using the serverCert private key, for example:

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

Are there any other steps that I skipped?

+6
source share
1 answer

From a technical point of view, your decision is correct. However, do not forget about security considerations: who can request a certificate, how authentication is performed, how certificates / private keys are distributed on servers ...

These elements are required to create a certificate:

  • Topic Title
  • Issuer Name
  • certificate serial number
  • public key
  • valid dates (not earlier than after)

It is also recommended to add some extensions:

  • Keyword ID
  • Authorization Key Hole
  • Main limitations
  • Key usage
  • Using Extended Key

This code snippet describes certificate generation:

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

UPDATE: fixed the code according to Martin Nielsen's comment.

+1
source

Source: https://habr.com/ru/post/958725/


All Articles