PDA

View Full Version : [JAVA] Suddividere PKCS#12 Chiave privata e file di certificato


ermasto
05-06-2006, 16:15
ciao ragazzi come da titolo cerco un programma java che dato un PKCS#12 mi crea 2 nuovi file uno contenente solo la chiave privata che mi servirà dopo per firmare un messaggio e il corrispettivo certificato con la chiave pubblica in formato der.

Grazie mille
Ciao Ciao

ermasto
06-06-2006, 18:30
nessuno mi puo aiutare :muro:

ermasto
06-06-2006, 20:09
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream in = new FileInputStream("x509pri.p12");
ks.load(in,null);
PrivateKey priv = (PrivateKey) ks.getKey("","");
java.security.cert.Certificate cert = ks.getCertificate("");
byte[] encodedCert = cert.getEncoded();

FileOutputStream certfos = new FileOutputStream("suecert.der");
certfos.write(encodedCert);
certfos.close();

allora ho trovato questo programmino che fa al caso mio ma ho due piccoli problemini
nel metodo ks.getkey() vuole essere passato l'alias e la password, ma il problema è che non so qual'è l'alias del mio certificato e lo stesso vale per il metodo getCertificate. c'è un modo per rimediare a ciò??

Grazie mille

kingv
06-06-2006, 20:56
Enumeration aliases = ks.aliases();
while(aliases.hasMoreElements())
System.out.println(aliases.nextElement());

ermasto
06-06-2006, 21:07
ho provato con il tuo codice kingv ma mi torna un errore: il codice modificato è:


package Perform;

import java.util.*;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;

public class key {

public static void main(String args[]){



try {

KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream in = new FileInputStream("e://x509pri.p12");
ks.load(in,null);
Enumeration aliases = ks.aliases();
while(aliases.hasMoreElements())
System.out.println(aliases.nextElement());
PrivateKey priv = (PrivateKey) ks.getKey("aliases","aliaseskeypass".toCharArray());
byte[] encodedKey = priv.getEncoded();

/* save the certificate in a file named "suecert" */
FileOutputStream keyfos = new FileOutputStream("suekey.der");
keyfos.write(encodedKey);
keyfos.close();
//You can extract the public key certificate from the keystore and save its encoded bytes to a file named suecert, via the following.

java.security.cert.Certificate cert = ks.getCertificate("aliases");
byte[] encodedCert = cert.getEncoded();

/* save the certificate in a file named "suecert" */
FileOutputStream certfos = new FileOutputStream("suecert.der");
certfos.write(encodedCert);
certfos.close();



} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


questo è l'errore:

Exception in thread "main" java.lang.NullPointerException
at Perform.key.main(key.java:28)

a proposito questo metodo:


PrivateKey priv = (PrivateKey) ks.getKey("aliases","aliaseskeypass".toCharArray());
byte[] encodedKey = priv.getEncoded();

/* save the certificate in a file named "suecert" */
FileOutputStream keyfos = new FileOutputStream("suekey.der");
keyfos.write(encodedKey);
keyfos.close();




va bene per salvare in formato Pkcs#8 la chiave privata che poi posso usare per firmare i messaggi?

Grazie mille

kingv
07-06-2006, 08:36
package Perform;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import java.security.*;
import java.security.cert.CertificateException;

import java.util.*;


public class key
{
public static void main(String[] args)
{
try
{
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream in = new FileInputStream("e://x509pri.p12");
ks.load(in, null);

Enumeration aliases = ks.aliases();
String alias = (String)aliases.nextElement();

PrivateKey priv = (PrivateKey) ks.getKey(alias, "aliaseskeypass".toCharArray());
byte[] encodedKey = priv.getEncoded();

/* save the certificate in a file named "suecert" */
FileOutputStream keyfos = new FileOutputStream("suekey.der");
keyfos.write(encodedKey);
keyfos.close();

//You can extract the public key certificate from the keystore and save its encoded bytes to a file named suecert, via the following.
java.security.cert.Certificate cert = ks.getCertificate(alias);
byte[] encodedCert = cert.getEncoded();

/* save the certificate in a file named "suecert" */
FileOutputStream certfos = new FileOutputStream("suecert.der");
certfos.write(encodedCert);
certfos.close();
}
catch (KeyStoreException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (CertificateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (UnrecoverableKeyException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

prova così.
di solito i p12 sono protetti da password (che può essere differente da quella della chiave). sei sicuro di quel "null" nella load?

kingv
07-06-2006, 08:42
va bene per salvare in formato Pkcs#8 la chiave privata che poi posso usare per firmare i messaggi?



dimenticavo.
sì dovrebbe essere ok. se non sei sicuro controlla col metodo getFormat() di PrivateKey

ermasto
07-06-2006, 09:00
io lo scarico dalla mia CA e se provo a installarlo nel browser mi chiede solo la password per la chiave privata

cmq ho provato il tuo codice e mi da quest errore

java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded
at com.sun.net.ssl.internal.ssl.PKCS12KeyStore.engineGetKey(Unknown Source)
at java.security.KeyStore.getKey(Unknown Source)
at Perform.key.main(key.java:30)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_ab.b(DashoA12275)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede.engineDoFinal(DashoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)
... 3 more

poi anche se tolgo la parte che si riferisce alla chiave privata e voglio solo estrarre il certificato mi da quest errore.

Exception in thread "main" java.lang.NullPointerException
at Perform.key.main(key.java:40)

kingv
07-06-2006, 09:09
puo' essere che le password siano coincidenti, per questo ti viene chiesta una volta sola.

prova a mettere qui:
ks.load(in, null);

la stessa password con cui proteggi la chiave privata al posto di null.


fammi sapere.

ermasto
07-06-2006, 09:22
puo' essere che le password siano coincidenti, per questo ti viene chiesta una volta sola.

prova a mettere qui:
ks.load(in, null);

la stessa password con cui proteggi la chiave privata al posto di null.


fammi sapere.

ma mi sorge un dubbio ma la password come la metto?? nel senso io ho una pass numerica di 10 caratteri ma nel programmino non la inserisco mai direttamente sempre usando "aliaseskeypass".toCharArray().

Poi ho provato a mettere in ks.load(in,"aliaseskeypass".toCharArray()) e mi caccia quest'altra eccezione

java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.net.ssl.internal.ssl.PKCS12KeyStore.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at Perform.key.main(key.java:24)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_ab.b(DashoA12275)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40.engineDoFinal(DashoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)
... 3 more

cosa puo essere??

Grazie mille x l'aiuto

kingv
07-06-2006, 09:47
"aliaseskeypass" è la password.....

ermasto
08-06-2006, 15:21
niente da fare mi sa sempre lo stesso errore:

java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded
at com.sun.net.ssl.internal.ssl.PKCS12KeyStore.engineGetKey(Unknown Source)
at java.security.KeyStore.getKey(Unknown Source)
at Perform.key.main(key.java:32)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
at com.sun.crypto.provider.SunJCE_ab.b(DashoA12275)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede.engineDoFinal(DashoA12275)
at javax.crypto.Cipher.doFinal(DashoA12275)1

non riesco proprio a capire da cosa è provocato :muro:

ermasto
08-06-2006, 15:57
allora il programma ora funziona in parte ecco il codice:

[QUOTE]


[/package Perform;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import java.security.*;
import java.security.cert.CertificateException;

import java.util.*;


public class key
{
public static void main(String[] args)
{
try
{
KeyStore ks = KeyStore.getInstance("PKCS12");
InputStream in = new FileInputStream("e://x509pri.p12");
ks.load(in, null);

Enumeration aliases = ks.aliases();
String alias=null;
while(aliases.hasMoreElements())
{
alias = (String)aliases.nextElement();
System.out.println(alias);
}
PrivateKey priv = (PrivateKey) ks.getKey(alias, "1234567890".toCharArray());
byte[] encodedKey = priv.getEncoded();
System.out.println(priv);
/* save the certificate in a file named "suecert" */
FileOutputStream keyfos = new FileOutputStream("suekey.der");
keyfos.write(encodedKey);
keyfos.close();


//You can extract the public key certificate from the keystore and save its encoded bytes to a file named suecert, via the following.
java.security.cert.Certificate cert = ks.getCertificate(alias);
byte[] encodedCert = cert.getEncoded();
System.out.println(" Certificate : " + cert);
/* save the certificate in a file named "suecert" */
FileOutputStream certfos = new FileOutputStream("suecert.der");
certfos.write(encodedCert);
certfos.close();
}
catch (KeyStoreException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (CertificateException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}

}
}
[QUOTE]

infatti mi stampa la chiave e me la salva pure anche se devo vedere in che estensione salvarla, perche penso che .der non va bene sai in che formato si salvano i pkcs#8??

solo che dopo avermi fatto stampare la chiave privata mi da quest'ecezione sul metodo:
byte[] encodedCert = cert.getEncoded();

eccola qua:
Exception in thread "main" java.lang.NullPointerException
at Perform.key.main(key.java:43)

e non capisco come mai :muro:

kingv
08-06-2006, 17:46
io ti rispondo ma non mi leggi... :(


sostituisci:
ks.load(in, null);
con:
ks.load(in, "1234567890");

ermasto
08-06-2006, 18:01
io ti rispondo ma non mi leggi... :(


sostituisci:
ks.load(in, null);
con:
ks.load(in, "1234567890");

hai ragione :ave: solo che quando avevo provato mi dava lo stesso gli errori e non ci avevo piu fatto caso :doh:

Scusami tanto e grazie mille per il tuo prezioso aiuto

kingv
08-06-2006, 19:27
hai ragione :ave: solo che quando avevo provato mi dava lo stesso gli errori e non ci avevo piu fatto caso :doh:



no problem stavo scherzando ovviamente ;)

CIao

Mazza2
09-06-2006, 23:52
è proprio il topic che cercavo:

ho creato una coppia di chiavi (pubblica,privata), le vorrei salvare in maniera sicura sul pc. Qual è la combinazione migliore( + sicura ) per il salvataggio??...Le chiavi le creo cosi':

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC"); //
keyGen.initialize(512);
KeyPair chiaviRSA = keyGen.generateKeyPair();
PrivateKey chiavePrivata = chiaviRSA.getPrivate();
PublicKey chiavePublica = chiaviRSA.getPublic();

ermasto
10-06-2006, 09:54
ora un altro passo che devo fare è il seguente:

devo creare un messaggio soap e aggiungere ad esso un security token che è il certificato x509 e poi tutto questo messaggio soap lo devo firmare con la chiave privata che appartiene al certificato

Per quanto riguarda la creazione del messaggio soap non ci sono problemi ma non sono riuscito a trovare nulla su come aggiungere il token x509, ho letto in giro che devo usare wss4j ma non ho trovato una buona guida e cercare in tutte le API è uno sbattimento assurdo, che tu sappia esiste una guida o qualche sito che lo spiega meglio magari con qualche esempio??

Mazza2
10-06-2006, 12:20
che differenza c'e' tra pcks 8 e 12??? se salvo la privata con pkcs 8,.,.non capisco come la salva con pcks 8,.., un aiuto pls

kingv
10-06-2006, 19:38
ermasto> non ho mai usato wss4j anche se l'argomento mi interessa parecchio. non posso aiutarti ma se trovi dei link interessanti postali

mazza> pkcs8 è un formato per le chiavi private (neanche molto usato per quello che ho visto), pkcs12 invece è lo standard per contenere chiavi e certificati in un file (protetto da crittografia a chiave simmetrica).

orpheus
11-06-2006, 09:57
ma non sono riuscito a trovare nulla su come aggiungere il token x509, ho letto in giro che devo usare wss4j ma non ho trovato una buona guida e cercare in tutte le API è uno sbattimento assurdo,

guarda la classe BinarySecurity o meglio ancora nel tuo caso X509Security

Mazza2
11-06-2006, 15:47
mazza> pkcs8 è un formato per le chiavi private (neanche molto usato per quello che ho visto), pkcs12 invece è lo standard per contenere chiavi e certificati in un file (protetto da crittografia a chiave simmetrica).


grazie!


dove trovo un esempio di utilizzo del formato pkcs12 ?? devo solo salvare la chiave privata in modo sicuro sul mio pc e nient'altro...

ermasto
11-06-2006, 15:53
guarda la classe BinarySecurity o meglio ancora nel tuo caso X509Security

kingv ti ringrazio per l'aiuto appena trovo qlc di interessante te lo faccio sapere

orpheus ho guardato la class x509security e voglio usare il metodo setx509certificate

io ho immagazzinato il mio certificato publico sul mio hd e allora lo carico con un inputstream solo che quando devo creare il costruttore della classe x509security vuole essere passato un elemento elem che non capisco a chi si riferisce e se lo inizializzo null mi ritorna un eccezione.


Element doc = null;
X509Security x509token = new X509Security(doc);
x509token.setX509Certificate(cert);
X509Security.getType();



mazza2 guarda il mio codice che prende un file pkcs12 e ne estrae il certificato e la chiave privata

Mazza2
11-06-2006, 16:15
mazza2 guarda il mio codice che prende un file pkcs12 e ne estrae il certificato e la chiave privata

piu' che altro mi interessava crearlo un file pkcs12 cmq grazie adesso ci guardo!

ermasto
11-06-2006, 19:43
allora ragazzi per il momento ho trovato un metodo che fa al caso mio ma con un diverso security token che io poi provvederò a cambiare ma per il momento voglio provare il metodo cosi come è.

Il metodo è il seguente:


**
* Sign a soap message.
* We wish to sign both the body and the attachment
* <p/>
*
* @param msg - SOAPMessage object to sign - there is one attachment
present
* @param msgStream - the SOAPMessage represented as an input stream
* @return new Signed SOAPMessage
* @throws Exception
*/

private SOAPMessage signSOAPMessage(SOAPMessage msg, InputStream msgStream) {

Message signedSOAPMsg=null;
Iterator attachmentsIter=null;
FileInputStream attachmentStream = null;

try {
// create an AxisMessage from the SOAPMessage InputStream
// pass false for arg2 as the msgStream contains the ENTIRE message.
Message axisMessage = new Message(msgStream, false,msg.getMimeHeaders());
SOAPEnvelope unsignedEnvelope = axisMessage.getSOAPEnvelope();
Document doc = unsignedEnvelope.getAsDocument();

// WSSignEnvelope signs a SOAP envelope according to the
// WS Specification (X509 profile) and adds the signature data
// to the envelope.
WSSecSignature signer = new WSSecSignature();

String alias = "16c73ab6-b892-458f-abf5-2f875f74882e";
String password = "security";
signer.setUserInfo(alias, password);

// create a vector of WSEncryptPart parts to sign, both the soap body
//and the attachments
SOAPConstants soapConstants =WSSecurityUtil.getSOAPConstants(unsignedEnvelope);

Vector parts = new Vector();

// add the body part
String localPart = soapConstants.getBodyQName().getLocalPart();
String envelopeURI = soapConstants.getEnvelopeURI();
WSEncryptionPart body = new WSEncryptionPart(localPart, envelopeURI,
"Content");

parts.add(body);

// how to add the attachment part?????
signer.setParts(parts);

// The "build" method, creates the signed SOAP envelope.
// It takes a SOAP Envelope as a W3C Document and adds
// a WSS Signature header to it. The signed elements
// depend on the signature parts that are specified by
// the WSBaseMessage.setParts(java.util.Vector parts)
// method. By default, SOAP Body is signed.
// The "crypto" parameter is the object that implements
// access to the keystore and handling of certificates.
// A default implementation is included:
// org.apache.ws.security.components.crypto.Merlin

Document signedDoc = signer.build(doc, CryptoFactory.getInstance(),null);

// Convert the signed document into a SOAP message.
signedSOAPMsg = (Message) toSOAPMessage(signedDoc);

} catch (Exception e) {
e.printStackTrace();
}
return signedSOAPMsg;
}


allora io ho costruito la parte rimanente di codice per farlo funzionare, eccola qua:


public class sign {
public static void main(String[] args) {
try {

// Crea message factory
MessageFactory messageFactory = MessageFactory.newInstance();

// Creazione di un messaggio
SOAPMessage message = messageFactory.createMessage();

// Creazione attachment part per il certificcato
URL url = new URL("file:e:/Prova.der");
DataHandler dataHandler = new DataHandler(url);
AttachmentPart attachment = message.createAttachmentPart(dataHandler);
attachment.setContentId("Certificato");
message.addAttachmentPart(attachment);
int i=message.countAttachments();
System.out.println("Numero Allegati al messaggio:"+i);

InputStream inStream = new FileInputStream(cosa ci metto qui??);
inStream.close();

questa è la chiamata a metodo
sign mess = null;
mess.signSOAPMessage(message,inStream);

} catch (IOException e) {
System.out.println("I/O exception: " + e.toString());
System.exit(1);
} catch (Exception ex) {
ex.printStackTrace();
}
}


ho creato un messaggio soap e aggiunto un allegato
il problema sorge quando nel main vado a richiamare il metodo che come vedo accetta 2 parametri il messaggio soap e fin qui ci siamo e poi accetta sempre il messaggio soap ma stavolta come inputstream e questo è il mio problema come glielo passo??

Mazza2
12-06-2006, 12:18
cavolo non riesco a trovare il modo di salvare la chiave privata in pkcs12,.., un aiuto per favore??

kingv
12-06-2006, 18:15
piu' che altro mi interessava crearlo un file pkcs12 cmq grazie adesso ci guardo!



lo fai alla stessa maniera, poi chiami il metodo (store) per salvarlo su un Output Stream

Mazza2
12-06-2006, 23:38
public final void setKeyEntry(String alias,
Key key,
char[] password,
Certificate[] chain)



non posso caricare la privateKey che voglio salvare se non ho il certificato,.., come faccio il certificato???

kingv
13-06-2006, 08:01
Mazza> spiga esattamente che cos'hai e che cosa vuoi ottenere.
in particolare la coppia di chiavi l'hai già o la vuoi creare da codice?

Mazza2
13-06-2006, 13:18
la creo da codice.


ho una coppia di chiavi. vorrei salvare la chiave privata in maniera sicura sul disco con pkcs12 (o lo standard per fare questo in generale che non so qual è.,..,),.,. illuminatemi!! :sofico:

Mazza2
14-06-2006, 09:43
up