2013-08-21 19 views
6

Chcę wygenerować klucz prywatny z ciągu (plik .pem) w Javie.Jak wygenerować klucz prywatny RSA z ciągu * pem w Javie

private static final String test = "-----BEGIN RSA PRIVATE KEY-----\n" + 
     "MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" + 
// and so on 
     "-----END RSA PRIVATE KEY-----"; 

try { 
    String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", ""); 
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", ""); 

    byte [] encoded = Base64.decode(privKeyPEM); 

    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); 
    KeyFactory kf = KeyFactory.getInstance("RSA"); 
    PrivateKey privKey = kf.generatePrivate(keySpec); 
} 
catch (Exception e) { 
    e.printStackTrace(); 
} 

Ostatnia linia (funkcja generatePrivate) rzuca ten wyjątek:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence 
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source) 
    at java.security.KeyFactory.generatePrivate(Unknown Source) 
    at Test.main(Test.java:52) 
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence 
    at sun.security.pkcs.PKCS8Key.decode(Unknown Source) 
    at sun.security.pkcs.PKCS8Key.decode(Unknown Source) 
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source) 
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source) 
    at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source) 
    ... 3 more 

Jeśli zmienić klucz prywatny do wartości z pliku .der to działa poprawnie, ale muszę wygenerować prywatny plik klucza z pliku .pem.

Dołączyłem zrzut ekranu bajtów wydrukowanych jako ciągi (raz zakodowane na stałe przez \ n i raz zakodowany bez \ n) i jeden raz z pliku.

Bigger Image

Output

Dziwne jest to, że wyjście z pliku różni się od wyjścia ze strun.

Jeśli spróbuję zakodować plik .der za pomocą Base64, wynik będzie inny niż ciąg w pliku .pem. Dlaczego to jest takie?

+0

Czy znalazłeś odpowiedź w ogóle? –

+0

@SankarP nie tak naprawdę. – Niklas

+0

w porządku. Znalazłem rozwiązanie. Klucze zaczynające się od "----- BEGIN RSA PRIVATE KEY" to pliki zakodowane w pkcs1. To kodowanie pkcs1 nie jest obsługiwane przez Javę, chyba że korzystasz z zewnętrznej biblioteki, takiej jak BouncyCastle. Wpadłem na ten sam problem wczoraj i po około 8 godzinach znalazłem rozwiązanie. Jeśli zakodujesz klucz prywatny z pkcs8, zacznie się on jak "--- BEGIN PRIVATE KEY ---", który będzie obsługiwany przez zapasy java. HTH. –

Odpowiedz

1

Mówisz, że ostatnia linia rzuca wyjątek, tj

PrivateKey privKey = kf.generatePrivate(keySpec);

Powyższa linia działa na keyspecs jest ustawiona prawidłowa, tzn

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

więc rzeczywisty problem jest z zakodowanych bajtów szyk. Zrobiłeś System.out po byte [] encoded = Base64.decode(privKeyPEM); i zobaczysz, jakie są dane wyjściowe.

Rozumiem, że jeśli wiadomość jest w formacie MIME, to po pewnych znakach dołącza kombinację powrotu karetki i nowej linii, aby ciągi nie były zbyt długie dla systemu e-mail lub gdziekolwiek go używasz.

Ostateczny test ciągów ma pewne "\ n" w oryginalnym tekście, którego używasz. Państwo nie pozbyć się inny tekst w wierszu poniżej,

String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", ""); 
    privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", ""); 

Ale spojrzeć na napis,

"MIIEpAIBAAKCAQEAvcCH8WsT1xyrZqq684VPJzOF3hN5DNbowZ96Ie//PN0BtRW2\n" + 
// and so on 
     "-----END RSA PRIVATE KEY-----"; 

może mieć kilka „\ n” w lewo, które mogą prowadzić do pewnych niechcianych znaków kiedy generujesz keyspec. Wypróbuj więcej System.out i zobacz, jak wygląda zakodowana tablica bajtów, a także przed tym sprawdzić String privKeyPEM i sprawdź, czy nie ma w nim dodatkowego znaku.

Mam nadzieję, że to hepls.

+1

Przesłałem dane wyjściowe "kodowane". http://pastebin.com/YUsNdhgW. Zmieniłem również test na czysty ciąg bez '\ n' i to też nie działało. – Niklas

+0

Przesłałem również zrzut ekranu z danymi wyjściowymi jako ciągiem znaków. – Niklas

+0

Dekodowanie Base64 ignoruje linie podziału i zwykle wszystkie białe znaki. –