bg-tutorials

Come generare una CSR per un certificato Code Signing con Java Keytool

L’utility keytool, distribuita con il Java Development Kit (JDK), crea una coppia di chiavi all’interno di un keystore Java e la trasforma in una CSR (Certificate Signing Request), il blocco codificato che una Certificate Authority (CA) legge per identificarti prima di emettere un certificato. Per la firma del codice, l’uso legittimo di keytool è cambiato il 1 giugno 2023. Questa guida illustra prima la regola, poi passa in rassegna i comandi keytool che sono ancora corretti: contro un keystore software per la firma interna e contro un token hardware o un HSM tramite PKCS#11.

Le chiavi per la firma del codice devono essere generate su hardware

Dal 1 giugno 2023, i CA/Browser Forum Code Signing Baseline Requirements impongono che la chiave privata di ogni certificato di firma del codice pubblicamente attendibile venga generata e archiviata in un modulo crittografico hardware conforme a FIPS 140-2 Level 2, Common Criteria EAL4+, o uno standard equivalente. La chiave deve essere non esportabile. Questo vale sia per i certificati standard (Organization Validation) sia per quelli Extended Validation. I certificati EV per la firma del codice hanno sempre richiesto l’hardware; il cambiamento del 2023 ha esteso la stessa regola ai certificati standard. Gli stessi requisiti stabiliscono una dimensione minima della chiave di RSA 3072 per i certificati di firma del codice, in vigore dal 1 giugno 2021.

La conseguenza per questa pagina è diretta. Un file keystore che keytool crea sul tuo laptop o server, sia esso in formato PKCS12 o nel più vecchio formato JKS, contiene una chiave software. Una CSR generata da esso non viene accettata da una Certificate Authority pubblica per un certificato di firma del codice. Le Certificate Authority hanno smesso di supportare la generazione delle chiavi tramite browser e i file di chiave scaricabili per questi prodotti. La tua chiave ora ha origine in uno di questi due luoghi:

  • Un token pre-configurato che la CA ti invia. La CA genera la coppia di chiavi e la CSR su un token USB certificato dal proprio lato, carica il certificato emesso su di esso e ti invia il token per posta. Non c’è alcuna CSR da creare da parte tua.
  • Il tuo HSM o token, con attestazione della chiave. Generi la chiave all’interno del dispositivo, produci una CSR da essa e invii un file di attestazione che dimostra alla CA che la chiave è stata creata su hardware conforme e non può essere esportata. Entrambe le parti sono richieste; una CSR senza attestazione valida viene respinta.

Quale percorso si applica viene deciso al momento dell’ordine. Per il confronto, consulta i metodi di consegna dei certificati di firma del codice. Se possiedi già hardware conforme, segui la guida per il tuo dispositivo: generazione e attestazione della CSR YubiKey 5 FIPS oppure la guida alla CSR e attestazione per Luna Network Attached HSM v7.x.

Dove keytool trova ancora applicazione

Nulla di quanto sopra rende keytool obsoleto. Rimane lo strumento giusto in tre situazioni, e solo la prima produce una CSR che puoi inviare a una CA pubblica:

  • Come front end PKCS#11 per il tuo token o HSM. keytool parla PKCS#11 in modo nativo. Puntalo sulla libreria PKCS#11 del tuo fornitore e la chiave non lascia mai il dispositivo, mentre il familiare comando -certreq produce comunque la CSR. I comandi sono riportati nella sezione hardware più avanti.
  • Per la firma interna o aziendale. Se firmi software interno con la CA della tua stessa organizzazione, la tua politica interna governa l’archiviazione delle chiavi, non i Baseline Requirements pubblici. Un keystore software è lì una scelta normale.
  • Per fare pratica. Ottenere il nome soggetto corretto al primo tentativo è più facile se hai già eseguito le richieste una volta contro un keystore usa e getta.

Un limite da conoscere prima di iniziare: keytool non genera l’attestazione della chiave. L’attestazione viene prodotta dallo strumento proprio del fornitore del token o dell’HSM, quindi anche sul percorso PKCS#11 userai l’utility del fornitore per quel file e keytool solo per la CSR.

Genera la CSR con keytool

Se hai già creato la tua CSR e la Certificate Authority ha emesso il certificato, salta direttamente alla sezione importazione della risposta della CA, il passaggio che fallisce silenziosamente quando l’alias non corrisponde.

keytool viene fornito con il JDK, quindi installa prima un JDK aggiornato se non ne hai uno. JDK 25 è l’attuale versione a supporto a lungo termine e JDK 26 è l’attuale versione a supporto a breve termine. I comandi seguenti funzionano su JDK 17 e versioni successive, e le differenze di versione rilevanti sono indicate dove si presentano. Verifica che lo strumento sia nel tuo path:

java -version
keytool -help
jarsigner -version

Un Java Runtime Environment da solo non basta, e un keytool funzionante non è prova del fatto che tu abbia un JDK: la vecchia Oracle JRE 8 include keytool ma non jarsigner. Esegui ora tutti e tre i comandi. Se i primi due rispondono e il terzo no, sei su una JRE, e installare un JDK a quel punto è più semplice che scoprirlo quando vai a firmare.

Fase 1: Crea il keystore e la coppia di chiavi

Esegui questo comando in un terminale, oppure nel Prompt dei comandi o in PowerShell su Windows, dalla directory in cui vuoi che risieda il file keystore:

keytool -genkeypair -alias codesign -keyalg RSA -keysize 3072 -storetype PKCS12 -keystore codesign.p12

Quattro dettagli in quel comando differiscono dalle istruzioni più vecchie, e ognuno di essi è importante:

  • -genkeypair, non -genkey. La vecchia dicitura -genkey viene ancora eseguita e keytool non stampa alcun avviso al riguardo, ma è mantenuta nel codice sorgente solo come alias legacy e non compare più da nessuna parte nella documentazione del JDK. Scrivi -genkeypair.
  • -storetype PKCS12, non JKS. JKS è il formato keystore proprietario di Oracle. PKCS12 è quello standard di settore ed è il formato predefinito del JDK dalla versione 9 di Java. Se crei comunque un keystore JKS, keytool avvisa a ogni comando che lo tocca: “The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format.”
  • Il nome del file non determina il formato. Chiamare un file keystore.jks non lo rende un keystore JKS. keytool ricava il tipo da -storetype, oppure dalla proprietà keystore.type nel file di sicurezza del JDK quando la ometti. Su JDK 9 e versioni successive quella proprietà è pkcs12, quindi un comando che scrive su keystore.jks senza -storetype produce silenziosamente un file PKCS12 con un nome fuorviante.
  • -keysize 3072, non 2048. I Baseline Requirements fissano RSA 3072 come minimo per la firma del codice, quindi una richiesta a 2048 bit viene respinta. I JDK attuali usano 3072 come valore predefinito per RSA, ma JDK 17 e versioni precedenti usano 2048 come predefinito, quindi passa l’opzione esplicitamente e il comando si comporterà allo stesso modo ovunque.

L’alias, codesign nell’esempio, è l’etichetta per questa voce all’interno del keystore. Scegli qualcosa che riconoscerai e annotalo: ogni comando successivo ne ha bisogno, e una mancata corrispondenza è ciò che compromette l’importazione del certificato descritta più avanti.

È consentita anche una chiave ECDSA. Sostituisci -keyalg EC -groupname secp256r1 alle opzioni RSA se preferisci P-256, e conferma con la tua CA che il prodotto ordinato supporti ECDSA.

Fase 2: Rispondi alle richieste che costruiscono il tuo nome distintivo

keytool chiede due volte la password del keystore, poi pone sei domande in questo preciso ordine. L’ordine è importante: la seconda richiesta chiede l’unità organizzativa, non l’organizzazione, e guide più vecchie la elencano in modo errato, così un lettore che digita lì il nome dell’azienda lo inserisce nel componente sbagliato del nome.

  • Qual è il tuo nome e cognome? Questo diventa il Common Name (CN), nonostante la formulazione. Per un certificato di firma del codice il CN è l’identità dell’editore che gli utenti vedranno, quindi inserisci il nome legale esatto della tua organizzazione, oppure il tuo nome legale completo per un certificato individuale. Non inserire qui un nome di dominio.
  • Qual è il nome della tua unità organizzativa? Il dipartimento, ad esempio IT. Non premere Invio per saltarla: keytool scrive allora il valore letterale Unknown nel nome, e OU=Unknown finisce nella tua CSR. Se non vuoi alcuna unità organizzativa, usa la forma -dname qui sotto e ometti il componente OU dalla stringa.
  • Qual è il nome della tua organizzazione? La ragione sociale registrata, scritta come appare nei registri ufficiali. La CA la verifica rispetto a registri pubblici.
  • Qual è il nome della tua città o località? La città di registrazione, scritta per esteso.
  • Qual è il nome del tuo stato o provincia? Il nome completo, non un’abbreviazione.
  • Qual è il codice paese di due lettere per questa unità? Il codice ISO, ad esempio US.

keytool poi stampa il nome assemblato e ti chiede di confermarlo:

Is CN=Example LLC, OU=IT, O=Example LLC, L=Miami, ST=Florida, C=US correct?
  [no]:

La risposta predefinita è no, quindi premere Invio ti riporta indietro attraverso tutte e sei le domande. Digita yes per accettare. Leggi attentamente la riga prima: si tratta dell’intero nome distintivo, non solo del Common Name, e ogni suo componente finisce nella CSR.

Non esiste una password della chiave separata su un keystore PKCS12. Guide più vecchie concludono questo passaggio con “inserisci una password per la chiave”, che è il comportamento di JKS. Su un keystore PKCS12 la password della chiave è la password dello store, e se passi -keypass con un valore diverso keytool te lo comunica: “Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -keypass value.”

Per saltare completamente le richieste, fornisci l’intero nome con -dname. Mantieni il valore tra una coppia di virgolette diritte:

keytool -genkeypair -alias codesign -keyalg RSA -keysize 3072 -storetype PKCS12 -keystore codesign.p12 -dname "CN=Example LLC, OU=IT, O=Example LLC, L=Miami, ST=Florida, C=US"

Non inserire -storepass nella riga di comando e lascia che sia keytool a richiederla. Passare una password come argomento la scrive nella cronologia della tua shell e la espone a chiunque possa elencare i processi in esecuzione.

Fase 3: Crea la CSR

Il keystore ora contiene una chiave privata e un certificato autofirmato temporaneo. Trasforma quella voce in una richiesta di certificato:

keytool -certreq -alias codesign -keystore codesign.p12 -file codesign.csr

Inserisci la password del keystore quando richiesto. Non hai bisogno di -storetype qui: keytool rileva il formato di un file keystore già esistente. L’alias deve essere quello della fase 1, perché la CSR viene firmata dalla chiave privata di quella voce.

Questo comando non crea una chiave privata. La chiave è stata creata nella fase 1 e rimane all’interno del keystore, motivo per cui il file keystore e la sua password sono ora tanto sensibili quanto la chiave stessa. Chiunque possieda entrambi può firmare software a tuo nome.

Fase 4: Verifica la CSR prima di inviarla

Una CSR respinta costa un ciclo di convalida, quindi decodificala e rileggila:

keytool -printcertreq -file codesign.csr

Conferma tre cose nell’output. La riga Subject dovrebbe elencare i tuoi dati nei componenti corretti, con la ragione sociale legale in O e l’identità dell’editore in CN. La riga della chiave pubblica dovrebbe riportare 3072-bit RSA key o superiore. L’algoritmo di firma dovrebbe essere un algoritmo SHA-2: i JDK attuali firmano una richiesta RSA a 3072 bit con SHA384withRSA e quelli più vecchi usano SHA256withRSA, ed entrambi vanno bene. Quell’algoritmo dimostra solo che possiedi la chiave privata, e non è l’algoritmo che la CA userà per firmare il tuo certificato.

Puoi anche incollare la richiesta nel nostro decodificatore di CSR per leggere gli stessi campi in un browser.

Quando invii la richiesta, apri il file in un editor di testo semplice e copia tutto, comprese la prima e l’ultima riga. keytool scrive esattamente questi marcatori, con cinque trattini su ciascun lato:

-----BEGIN NEW CERTIFICATE REQUEST-----
MIID3TCCAkUCAQAwaDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0Zsb3JpZGExDjAM
...base64 encoded request...
-----END NEW CERTIFICATE REQUEST-----

La dicitura NEW CERTIFICATE REQUEST è normale per l’output di keytool e i moduli di registrazione la accettano. Se il tuo editor ha sostituito una sequenza di trattini con un trattino lungo, la richiesta verrà rifiutata: riscrivi i marcatori come trattini semplici oppure copia il file con un editor di codice.

Genera la CSR su un token o HSM con keytool

Questo è il percorso che produce una CSR su cui una CA pubblica può agire. keytool comunica con un token hardware tramite il provider SunPKCS11, quindi la coppia di chiavi viene creata all’interno del dispositivo e non esiste mai come file. Inizia scrivendo un piccolo file di configurazione, ad esempio token.cfg, che nomini il tuo token e punti alla libreria PKCS#11 installata dal tuo fornitore:

name = token
library = /usr/local/lib/libeToken.so

Quelle due righe, name e library, sono le uniche obbligatorie. Il percorso della libreria è specifico del fornitore e varia in base al sistema operativo, quindi ricavalo dalla documentazione del tuo token piuttosto che da questo esempio. Su Windows è una DLL nella directory di sistema. Senza una riga slot, il provider si collega al primo slot segnalato dal dispositivo, il che è ciò che vuoi quando è collegato un solo token. Se hai più di un lettore o token, aggiungi slotListIndex con la posizione in quell’elenco, contando da zero, oppure slot con l’ID numerico dello slot stampato dall’utility del tuo fornitore. Solo uno dei due può comparire nel file, e un ID slot non è lo stesso numero di una posizione in elenco, quindi non indovinare con slot = 0.

Elenca ciò che c’è sul dispositivo. Il token fornisce l’alias, quindi ti serve questo prima di ogni altra cosa:

keytool -list -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg token.cfg

-keystore NONE è richiesto ogni volta che il keystore non è un file, e la richiesta di password sta chiedendo il PIN del token. keytool accetta anche -addprovider SunPKCS11 -providerarg token.cfg al posto della coppia -providerClass e -providerArg; entrambe le forme funzionano, e la documentazione delle Certificate Authority di solito mostra quella più vecchia.

Con l’alias in mano, genera la chiave sul dispositivo e poi richiedi la CSR su di essa:

keytool -genkeypair -alias codesign -keyalg RSA -keysize 3072 -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg token.cfg -dname "CN=Example LLC, O=Example LLC, L=Miami, ST=Florida, C=US"
keytool -certreq -alias codesign -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg token.cfg -file codesign.csr

Si applicano due avvertenze. Alcuni token non consentono la generazione delle chiavi tramite PKCS#11 e si aspettano che tu usi l’utility del fornitore, il che va bene: keytool può comunque creare la CSR su una chiave generata dallo strumento del fornitore. E keytool non può produrre il file di attestazione che la tua CA richiederà, quindi generalo con lo strumento del fornitore contemporaneamente alla chiave, seguendo la guida YubiKey o Luna HSM.

Importa la risposta della CA nello stesso alias

Quando arriva il certificato, deve tornare nella voce che ha generato la CSR. Importalo altrove e keytool riporta comunque il successo producendo un keystore che non può firmare, quindi leggi questa sezione prima di eseguire qualsiasi cosa.

Importa per prima cosa il certificato root della CA e qualsiasi certificato intermedio, ciascuno con il proprio alias:

keytool -importcert -trustcacerts -alias caroot -file root.crt -keystore codesign.p12

keytool stampa il certificato che sta per archiviare e chiede Trust this certificate? con no come predefinito, quindi digita yes. Controlla l’impronta digitale rispetto a quella pubblicata dalla tua Certificate Authority prima di rispondere.

Salta l’importazione del root e il comando successivo fallisce con un messaggio che non offre alcun indizio sulla causa:

keytool error: java.lang.Exception: Failed to establish chain from reply

Ora importa il tuo certificato emesso usando lo stesso alias usato nella fase 1:

keytool -importcert -alias codesign -file codesign.crt -keystore codesign.p12

Il messaggio che vuoi vedere è Certificate reply was installed in keystore. Significa che keytool ha riconosciuto una chiave privata esistente sotto quell’alias e vi ha collegato il certificato emesso e la sua catena.

Se invece inventi un nuovo alias, keytool accetta il file e stampa Certificate was added to keystore. Sembra un successo ma non lo è. keytool ha archiviato il certificato come voce attendibile autonoma senza alcuna chiave privata dietro, e quella voce non potrà mai firmare nulla. L’alias originale, nel frattempo, mantiene ancora il certificato autofirmato temporaneo della fase 1. Verifica quale dei due possiedi:

keytool -list -keystore codesign.p12

Il tuo alias di firma deve essere elencato come PrivateKeyEntry. Un alias mostrato come trustedCertEntry è l’errore descritto sopra. Eliminalo con keytool -delete -alias wrongalias -keystore codesign.p12 e ripeti l’importazione sull’alias corretto. Aggiungi -v al comando di elenco per confermare che la voce ora porta una catena di certificati completa anziché un singolo certificato autofirmato.

Su un token hardware nella maggior parte dei casi non c’è nulla da importare, perché la CA carica il certificato sul dispositivo prima di spedirlo. Se la tua CA ti invia un file di certificato per una chiave che hai generato sul tuo stesso HSM, usa lo stesso comando -importcert con le opzioni PKCS#11 della sezione precedente.

Firma un file JAR con il certificato

Lo scopo di inserire un certificato di firma del codice in un keystore Java è firmare file JAR con jarsigner, che viene anch’esso distribuito con il JDK. Con il certificato installato sotto l’alias corretto:

jarsigner -keystore codesign.p12 -tsa https://your-ca-timestamp-url application.jar codesign

Passa sempre -tsa con l’URL della marca temporale pubblicato dalla tua Certificate Authority. Una marca temporale registra che il JAR è stato firmato mentre il certificato era ancora valido, così la firma continua a funzionare dopo la scadenza del certificato. Senza di essa, ogni copia del tuo software smette di convalidare il giorno in cui il certificato scade.

Quando la chiave risiede su un token, punta jarsigner su PKCS#11 esattamente come fa keytool:

jarsigner -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg token.cfg -tsa https://your-ca-timestamp-url application.jar codesign

Se il token ha troppo poco spazio per l’intera catena di certificati, fornisciscila separatamente con -certchain. Verifica il risultato in seguito:

jarsigner -verify -verbose -certs application.jar

Un’esecuzione riuscita stampa jar verified insieme al nome distintivo del firmatario e ai dettagli della marca temporale. I JDK attuali usano SHA-384 come algoritmo di digest predefinito, quindi raramente devi impostare manualmente -digestalg o -sigalg.

Altri modi per creare questa richiesta sono trattati nelle guide OpenSSL, CertReq, Microsoft Management Console e macOS Keychain Access, e la stessa regola sull’hardware si applica a tutte. Consulta anche il nostro set completo di tutorial sulla firma del codice e la panoramica sulla generazione della CSR per i certificati di firma del codice. Se ti serve una CSR keytool per un certificato di sito web anziché per la firma del codice, segui invece la guida Tomcat o JBoss.

Domande Frequenti

Posso ancora ottenere un certificato di firma del codice da una CSR creata con keytool?

Solo se keytool ha generato la chiave all’interno di un token hardware o HSM tramite PKCS#11, e puoi fornire l’attestazione richiesta dalla Certificate Authority. Una CSR creata da un normale file keystore sul tuo computer è una chiave software, e dal 1 giugno 2023 le CA pubbliche non emettono certificati di firma del codice su chiavi software. I keystore software rimangono adatti per la firma con una CA interna o aziendale.

Dovrei usare -genkey o -genkeypair?

Usa -genkeypair. La dicitura -genkey è un alias legacy che il JDK accetta ancora senza alcun avviso, ma è assente dalla documentazione da molte versioni. Entrambe fanno oggi la stessa cosa; solo una delle due è documentata.

JKS o PKCS12, e l’estensione del file .jks è importante?

Usa PKCS12. È un formato standard di settore ed è il tipo di keystore predefinito del JDK dalla versione 9 di Java, mentre JKS è proprietario di Oracle e fa stampare a keytool un avviso di migrazione a ogni comando. L’estensione del file non ha alcun effetto: keytool decide il formato in base a -storetype, o alla proprietà di sicurezza keystore.type quando la ometti, quindi un file chiamato keystore.jks creato su un JDK moderno è di solito un file PKCS12. Per convertire un keystore esistente, esegui keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.p12 -deststoretype pkcs12.

Quale dimensione della chiave e algoritmo dovrebbe usare una CSR per la firma del codice?

RSA a 3072 bit o superiore, richiesto dai Code Signing Baseline Requirements dal 1 giugno 2021, oppure una chiave ECDSA equivalente come P-256. Passa -keysize 3072 esplicitamente, perché JDK 17 e versioni precedenti usano 2048 bit come predefinito e quella richiesta viene respinta.

Ho importato il mio certificato e jarsigner ancora non firma. Cosa è successo?

Molto probabilmente hai importato la risposta della CA in un nuovo alias anziché nell’alias che ha generato la CSR. keytool lo archivia allora come certificato attendibile autonomo senza alcuna chiave privata collegata, e stampa Certificate was added to keystore, che sembra un successo. Esegui keytool -list -keystore codesign.p12: l’alias di firma deve apparire come PrivateKeyEntry, non come trustedCertEntry. Elimina la voce sbagliata e importa nuovamente con l’alias originale, e dovresti vedere Certificate reply was installed in keystore.

Perché ricevo l’errore “Failed to establish chain from reply”?

keytool non riesce a costruire un percorso dal tuo certificato emesso fino a un certificato che già considera attendibile. Importa prima nello stesso keystore il certificato root e quelli intermedi della CA, ciascuno con il proprio alias tramite -importcert -trustcacerts, poi importa di nuovo il tuo certificato. In alternativa, importa un unico file che contenga il tuo certificato seguito dagli intermedi e dal root.

Devo scegliere “Java” come tipo di certificato al momento dell’ordine?

No. Un certificato di firma del codice è identificato dal suo utilizzo esteso della chiave per la firma del codice, non da una toolchain, quindi lo stesso certificato firma file JAR con jarsigner ed eseguibili Windows con signtool. Ciò che scegli al momento dell’ordine è il metodo di consegna, che determina se la CA ti spedisce un token pre-configurato oppure se generi la chiave su hardware che già possiedi.

Dove si trova la chiave privata, e come la proteggo?

Con un token o un HSM la chiave è all’interno del dispositivo e non può essere copiata all’esterno, il che è l’intero scopo del requisito. Con un keystore software usato per la firma interna, la chiave risiede nel file keystore, quindi il file e la sua password insieme costituiscono il segreto: conservali in un luogo ad accesso limitato, non eseguire mai il commit di nessuno dei due nel controllo di versione, e lascia che sia keytool a richiedere la password anziché passare -storepass sulla riga di comando dove finirebbe nella cronologia della tua shell.

Risparmia il 10% sui certificati SSL ordinando oggi stesso da SSL Dragon!

Emissione rapida, crittografia avanzata, affidabilità del browser al 99,99%, assistenza dedicata e garanzia di rimborso entro 25 giorni. Codice coupon: SAVE10

Un'immagine dettagliata di un drago in volo
Scritto da

Scrittore di contenuti con esperienza, specializzato in certificati SSL. Trasforma intricati argomenti di cybersicurezza in contenuti chiari e coinvolgenti. Contribuisci a migliorare la sicurezza digitale attraverso narrazioni d'impatto.