2013-11-24 5 views
6

Sto lavorando a un'applicazione distribuita con un numero di processi slave identificati in modo univoco che comunicheremo con un'applicazione master tramite socket abilitati SSL. L'applicazione è scritta in java.Creazione di certificati per comunicazioni SSL

Ho bisogno di aiuto per capire SSLSockets, o meglio, i certificati che usano.

Quello che sto cercando è qualcuno che possa dirmi se ho compreso correttamente il funzionamento di base delle catene di certificati, ma non direi di no a un esempio di codice.

Vorrei una configurazione in cui il server stesso ha un certificato firmato dalla CA e ogni slave riceverà il proprio certificato creato dall'applicazione principale.

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 

Prima domanda: questo tipo di certificato indica il modo corretto di affrontare il problema? Penso che questo sia il modo più semplice per ottenere il master e gli slave abbiano tutti un'identità univoca senza dover firmare ogni certificato.

Seconda domanda: Come faccio a programmare in modo programmatico sulla creazione di un certificato SSL in java? Sto cercando di creare l'ultimo certificato nella catena qui, supponendo che ho già il "Cert server principale" per ora. ho ottenuto quanto generare una chiave per il certificato (dove tipo è 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); 

non mi assumo che l'impostazione della serverCert come l'emittente è abbastanza per firmare il certificato? Per quanto ho capito ho bisogno di firmare il nuovo certificato con il prossimo certificato della catena in qualche modo, ma come faccio? Firmo il certificato con la chiave privata del serverCert come:

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

Sono mancati altri passaggi?

risposta

1

Da un punto di vista tecnico la soluzione è corretta. Tuttavia, non dimenticare le considerazioni sulla sicurezza: chi può richiedere un certificato, come viene eseguita l'autenticazione, come i certificati/chiavi private vengono distribuiti ai server ...

Questi elementi sono obbligatori per una generazione del certificato:

  • nome soggetto nome
  • Emittente
  • numero di serie del certificato
  • soggetti chiave
  • date di validità pubblici (non prima, non dopo)

È anche un buona pratica di aggiungere alcune estensioni:

  • Soggetto Identifier Key
  • Authority Key Identifier
  • Restrizioni di base
  • Utilizzo chiave
  • estesa chiave Usi

Questo frammento di codice illustra il certificato generazione:

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: risolto il codice in base al commento di Martin Nielsen.

+0

createAuthorityKeyIdentifier (subjectKey)) createSubjectKeyIdentifier (issuerCert)) Questo è solo a causa della mia ignoranza, ma sono questi corretta, o se il subjectKey e issuerCert essere invertito? –

+1

Sì, hai ragione. Ho fatto un errore, subjectKey e issuerCert devono essere invertiti. Thx, aggiorno la risposta. – Jcs

+0

Nessun problema. Non esiste un test migliore per me effettivamente capire cosa sta succedendo: D –