2013-10-28 24 views
7

Nella mia app genera una coppia di chiavi pubblica/privata e li memorizza per un utilizzo successivo su disco. Il caricamento e la reinizializzazione della chiave privata funzionano bene, ma per la chiave privata ottengo un tipo KeySpec sconosciuto: java.security.spec.PKCS8EncodedKeySpec - e non ho idea del perché.Carica i dati della chiave pubblica dal file

Ecco come creano e salvano i tasti (codice un po 'semplificata per essere più facile da leggere):

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
kpg.initialize(4096); 
KeyPair keyPair = kpg.generateKeyPair(); 
privKey =keyPair.getPrivate(); 
pubKey =keyPair.getPublic();   

DataOutputStream out=new DataOutputStream(ctx.openFileOutput(PRIVKEY_FILE,Context.MODE_PRIVATE)); 
byte[] data=privKey.getEncoded(); 
out.write(data); 
out.close(); 

DataOutputStream out=new DataOutputStream(ctx.openFileOutput(PUBKEY_FILE,Context.MODE_PRIVATE)); 
byte[] data=pubKey.getEncoded(); 
out.write(data); 
out.close(); 

carico successivo della chiave privata funziona bene:

DataInputStream in=new DataInputStream(ctx.openFileInput(PRIVKEY_FILE)); 
byte[] data=new byte[in.available()]; 
in.readFully(data); 

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 
KeyFactory kf = KeyFactory.getInstance("RSA"); 
privKey = kf.generatePrivate(keySpec); 

decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
decryptCipher.init(Cipher.DECRYPT_MODE, privKey); 

codice simile per la chiave pubblica fallisce miseramente:

DataInputStream in=new DataInputStream(ctx.openFileInput(PUBKEY_FILE)); 
byte[] data=new byte[in.available()]; 
in.readFully(data); 

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 
KeyFactory kf = KeyFactory.getInstance("RSA"); 
pubKey = kf.generatePublic(keySpec); --> here the exception is thrown 

encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey);    

Quindi cosa sto facendo male? Qual è il modo corretto di caricare dati di chiavi pubbliche dal disco?

Grazie!

risposta

14

Le chiavi pubbliche e private sono codificate in modo diverso. Mentre le chiavi private sono codificate in PKCS # 8, le chiavi pubbliche non lo sono. Sono invece codificati in X.509 secondo le specifiche ASN.1.

Descrizione del metodo Key.getFormat():

Restituisce il nome del formato di codifica primario di questa chiave, oppure null se questa chiave non supporta la codifica. Il formato di codifica principale è denominato in termini del formato di dati ASN.1 appropriato, se esiste una specifica ASN.1 per questa chiave. Ad esempio, il nome del formato dati ASN.1 per le chiavi pubbliche è SubjectPublicKeyInfo, come definito dallo standard X.509; in questo caso, il formato restituito è "X.509". Allo stesso modo, il nome del formato dati ASN.1 per le chiavi private è PrivateKeyInfo, come definito dallo standard PKCS # 8; in questo caso, il formato restituito è "PKCS # 8".

In base a questo, invece di leggere le chiavi pubbliche come PKCS # 8, dovresti leggerlo come X.509.

pensare di cambiare il codice di lettura di chiave pubblica da:

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data); 

a:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);