Заредете данни за публичен ключ от файл

В моето приложение генерирам двойка публичен/личен ключ и ги съхранявам за по-късна употреба на диск. Зареждането и повторното инициализиране на частния ключ работи добре, но за частния ключ получавам Unknown KeySpec тип: java.security.spec.PKCS8EncodedKeySpec - и нямам представа защо.

Ето как създавам и запазвам ключовете (кодът е малко опростен, за да бъде по-лесен за четене):

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

Следващото зареждане на частния ключ работи добре:

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

Подобен код за публичния ключ се проваля мизерно:

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

И така, какво правя грешно? Какъв е правилният начин за зареждане на данни за публични ключове от диск?

Благодаря!


person Elmi    schedule 28.10.2013    source източник


Отговори (1)


Публичните и частните ключове са кодирани по различен начин. Докато частните ключове са кодирани в PKCS #8, публичните ключове не са. Вместо това те са кодирани в X.509 съгласно спецификациите на ASN.1.

Описание от метода Key.getFormat():

Връща името на основния формат на кодиране на този ключ или нула, ако този ключ не поддържа кодиране. Основният формат на кодиране се наименува по отношение на подходящия формат на данни ASN.1, ако съществува спецификация ASN.1 за този ключ. Например името на формата на данните ASN.1 за публични ключове е SubjectPublicKeyInfo, както е дефинирано от стандарта X.509; в този случай върнатият формат е "X.509". По същия начин, името на формата на данни ASN.1 за частни ключове е PrivateKeyInfo, както е дефинирано от стандарта PKCS #8; в този случай върнатият формат е "PKCS#8".

Според това, вместо да четете публичните ключове като PKCS #8, трябва да го четете като X.509.

Обмислете промяна на вашия код за четене на публичен ключ от:

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);

to:

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);
person initramfs    schedule 28.10.2013
comment
Можете също да използвате метода getFormat, за да отпечатате формата на кодиране. Напр.: privKey.getFormat(); - person Sebinjude Shaolin; 31.12.2019