Mi rivolgo a voi ancora una volta per un dilemma che mi affligge:
Ho creato un'applicazione per la crittografia dei file,per quanto riguarda il metodo di sostituzione e trasposizione tutto ok , ma quando ho provato ad implementare l'RSA mi sono trovato in difficoltà.
Creo la coppia di chiavi nel momento in cui vado a criptare.
Uso la chiave pubblica per criptare il file e fin lì tutto ok.
Quando devo decifrare il file crittografato parte un errore "Data must start with 0"
Posto parti di codice per rendere il tutto più comprensibile:
codice:
// GENERA COPPIA DI CHIAVI
//Un reader per leggere la console
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Inizio generazione chiavi RSA");
//inizializza un generatore di coppie di chiavi usando RSA
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
System.out.print(".");
// le chiavi sono molto lunghe: 1024 bit sono 128 byte.
// La forza di RSA è nell'impossibilità pratica di fattorizzare
// numeri così grandi.
kpg.initialize(1024);
System.out.print(".");
// genera la coppia
KeyPair kp = kpg.generateKeyPair();
System.out.print(". Chiavi generate!\n");
// SALVA CHIAVE PUBBLICA
System.out.print("Inserire keystore per la chiave pubblica: ");
String publicKeystore = "C:\\Java Passwords\\chiavipubbliche.txt";
// ottieni la versione codificata in X.509 della chiave pubblica
// (senza cifrare)
byte[] publicBytes = kp.getPublic().getEncoded();
// salva nel keystore selezionato dall'utente
FileOutputStream fos = new FileOutputStream(publicKeystore);
fos.write(publicBytes);
fos.close();
// SALVA CHIAVE PRIVATA
System.out.print("Inserire keystore per la chiave privata: ");
String privateKeystore = "C:\\Java Passwords\\chiaviprivate.txt";
// ottieni la versione codificata in PKCS#8
byte[] privateBytes = kp.getPrivate().getEncoded();
fos = new FileOutputStream(privateKeystore);
fos.write(privateBytes);
fos.close();
// LEGGI CHIAVE PUBBLICA CODIFICATA IN X509
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Inserire keystore della chiave pubblica: ");
publicKeystore = "C:\\Java Passwords\\chiavipubbliche.txt";
FileInputStream fis = new FileInputStream(publicKeystore);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i = 0;
while((i = fis.read()) != -1) {
baos.write(i);
}
fis.close();
byte[] publicKeyBytes = baos.toByteArray();
baos.close();
// CONVERTI CHIAVE PUBBLICA DA X509 A CHIAVE UTILIZZABILE
// Inizializza convertitore da X.509 a chiave pubblica
X509EncodedKeySpec ks = new X509EncodedKeySpec(publicKeyBytes);
// Inizializza un KeyFactory per ricreare la chiave usando RSA
KeyFactory kf = KeyFactory.getInstance("RSA");
// Crea una chiave pubblica usando generatePublic di KeyFactory in base la chiave decodificata da ks
PublicKey publicKey = kf.generatePublic(ks);
pubblica=publicKey;
Per la parte del crittografare :
codice:
public static byte[] crypt(byte[] b,int c,PublicKey publicKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
System.out.print("\nInizio codifica");
// Inizializzo un cifrario che usa come algoritmo RSA, come modalità ECB e come padding PKCS1
Cipher cifrario = Cipher.getInstance("RSA/ECB/PKCS1Padding");
System.out.print(".");
// Lo inizializzo dicendo modalità di codifica e chiave pubblica da usare
cifrario.init(Cipher.ENCRYPT_MODE, publicKey);
System.out.print(".");
b=blockCipher(b,Cipher.ENCRYPT_MODE);
// codifico e metto il risultato in encodeFile
byte[] encodeFile = cifrario.doFinal(b);
System.out.println(". Codifica terminata!");
b= new byte[encodeFile.length];
System.out.println("criptazione");
c=encodeFile.length;
b=encodeFile.clone();
return b;
}
Nota importante*:b[] contiene un array di byte nudo e crudo ovvero una porzione di file letto così com'è
Nel momento in cui devo decifrare il messaggio prendo il testo mediante
codice:
byte b[];
b=new byte[lByte];
int c=fis.read(b);
while (c != -1){
b=select_decrypt(b,c,k);
out.write(b,0,c);
c= fis.read(b);
}
fis.close();
out.flush();
out.close();
E poi parte (nel ciclo while) il decript che è:
codice:
public static byte[] decrypt(byte[] b,int c,Key privateKey) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, IOException{
System.out.print("\nInizio decodifica");
Cipher cifrario = Cipher.getInstance("RSA/ECB/PKCS1Padding");
System.out.print(".");
cifrario.init(Cipher.DECRYPT_MODE, privateKey);
System.out.print(".");
byte[] encodeFile = cifrario.doFinal(b);
b= new byte[encodeFile.length];
c=encodeFile.length;
b=encodeFile.clone();
System.out.println(". Decodifica terminata!");
return b;
}
Lasciando perdere l'utilizzo inutile di variabili supporto ecc, non capisco perchè venga dato l'errore riportato all'inizio , l'unica cosa che mi viene in mente è che possa dipendere da una possibile formattazione del testo che necessita il cifrario
L'errore è in byte[] encodeFile = cifrario.doFinal(b);
Spero in una risposta anche perchè è molto importante per me riuscire a risolvere tale dilemma , se servono delucidazioni sul codice chiedete .
Grazie in anticipo.