2009-09-08 12 views
10

Próbuję zaszyfrować niektóre treści kluczem prywatnym RSA.Szyfrowanie za pomocą klucza prywatnego RSA w Javie

Obserwuję ten przykład: http://www.junkheap.net/content/public_key_encryption_java

ale przekształcenie go używać kluczy prywatnych niż publicznych. W następstwie tego przykład, myślę, że to, co trzeba zrobić, to:

  • Czytaj w DER formacie klucza prywatnego
  • Generowanie PCKS8EncodedKeySpec
  • rozmowę generatePrivate() z KeyFactory aby mieć prywatny obiektu Key
  • użyj tego obiektu klucza prywatnego z obiektu Szyfrów zrobić szyfrowania

Więc kroki:

klucz został wygenerowany fro m openssl z:

openssl genrsa -aes256 -out private.pem 2048

a następnie przekształcono w formacie DER z:

openssl rsa -in private.pem -outform DER -out private.der

I wygenerować PKCS8EncodedKeySpec z:

byte[] encodedKey = new byte[(int)inputKeyFile.length()]; 

try { 
    new FileInputStream(inputKeyFile).read(encodedKey); 
} catch (FileNotFoundException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey); 
return privateKeySpec; 

a następnie wygenerować klucz prywatny obiekt z:

PrivateKey pk = null; 

try { 
    KeyFactory kf = KeyFactory.getInstance(RSA_METHOD); 
    pk = kf.generatePrivate(privateKeySpec); 
} catch (NoSuchAlgorithmException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} catch (InvalidKeySpecException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 
return pk; 

Jednak na wezwanie do:

pk = kf.generatePrivate(privateKeySpec); 

uzyskać:

java.security.spec.InvalidKeySpecException: Unknown key spec. 
at com.sun.net.ssl.internal.ssl.JS_KeyFactory.engineGeneratePrivate(DashoA12275) 
at com.sun.net.ssl.internal.ssl.JSA_RSAKeyFactory.engineGeneratePrivate(DashoA12275) 
at java.security.KeyFactory.generatePrivate(KeyFactory.java:237) 

pytania:

  • Czy ogólne podejście prawda?
  • Czy PCKS8EncodedKeySpec jest właściwym kluczem klucza?
  • Jakieś przemyślenia na temat błędu nieprawidłowego klucza?
+0

Przeszedłem przez ten i generowane je z Java: http://stackoverflow.com/questions/19640735/load-public-key-data-from -file – Hayro

Odpowiedz

6

Przede wszystkim, jestem zdezorientowany dlaczego planujesz używać Cipher do szyfrowania z kluczem prywatnym, a nie podpisania z Signature. Nie jestem pewien, czy wszyscy dostawcy RSA Cipher będą używać prawidłowego typu bloku do konfiguracji, ale warto spróbować.

Odkładając to na bok, myślę, że próbujesz załadować niestandardowy klucz w formacie OpenSSL. Konwertowanie go na DER z rsa jest w zasadzie tylko dekodowaniem base-64; struktura klucza nie jest PKCS # 8.

Zamiast po genrsa, użyj komendy openssl pkcs8 do konwersji wygenerowanego klucza do niezaszyfrowanej PKCS # 8 formacie DER:

openssl pkcs8 -topk8 -nocrypt -in private.pem -outform der -out private.der 

To będzie produkować niezaszyfrowany klucz prywatny, który może być ładowany z PKCS8EncodedKeySpec.

+0

Szczerze mówiąc, nie wiedziałem o podpisie. Aby upewnić się, że rozumiem jego użycie, zainicjowałbym obiekt podpisu, wywołanie aktualizacji z bajtami, które chcę podpisać, a następnie wywołanie znaku? A następnie mogę przechowywać bajty zwrócone ze znaku jako mój podpis cyfrowy? – wadesworld

+0

Tak, to jest poprawne użycie. – erickson

+0

Witaj. Ktoś w końcu rozwiązał problem? Mam klucz prywatny, którego nie mogę załadować do języka Java, aby kontynuować fazę podpisywania. Mój klucz prywatny to RSA, PKCS # 8 DER i ma hasło. Jak mogę załadować to do java? Wyjątek w moim przypadku to 'java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: wejście DER, błąd znacznika Integer' – BRabbit27

10

Nie można szyfrować za pomocą klucza prywatnego. Jeśli JCE pozwoli ci to zrobić, to tylko przez przypadek.

Musisz użyć podpisu. Oto fragment kodu służący do tego,

signer = Signature.getInstance("SHA1withRSA"); 
signer.initSign(privateKey); // PKCS#8 is preferred 
signer.update(dataToSign); 
byte[] signature = signer.sign(); 
+1

's/public/private /' w pierwszym wierszu. – caf

+0

Perfect - wielkie dzięki! – wadesworld

4

To nie jest przypadek, że szyfrowanie za pomocą klucza prywatnego jest dozwolone. Jeśli chcesz złamać podpis w indywidualnym haszowaniu i szyfrowaniu, kluczowe znaczenie ma szyfrowanie za pomocą klucza prywatnego. Powiedzmy, że mam dokument, który muszę podpisać, a mój klucz znajduje się w sieci HSM. Teraz albo przesyłam cały dokument do HSM, żeby podpisać, albo mogę utworzyć lokalny skrót i przesłać go do HSM tylko w celu zaszyfrowania. Mój wybór będzie zależeć od tego, czy lokalne obliczanie skrótu daje mi lepszą wydajność, a mianowicie delegowane obliczanie wartości skrótu z opóźnieniem sieci.

2

To pytanie jest dość stare, ale ostatnio natknąłem się na problem (implementuję wymagania niektórych protokołów, które wymagają szyfrowania kluczem prywatnym). Ja po prostu zacytować post z forum:

Niedawno natknęliśmy się na tym samym numerze, przedłożony PMR 22265,49R i IBM Support po konsultacji z „rozwoju” (kto to są) orzekł, że klucze prywatne nie mogą być wykorzystywane do szyfrowania. Bez względu na to, jak bardzo starałem się z nimi spierać, że klucze prywatne nie powinny być używane do ochrony danych, co jest tylko jednym z celów kryjących się za szyfrowaniem i że używanie kluczy prywatnych do szyfrowania jest całkowicie w porządku, aby osiągnąć niezaprzeczalność, były one niewzruszone w ich przekonaniu. Musisz kochać ludzi, którzy twierdzą, że 2x2 = 5.

Oto jak obejść ten problem: Zasadniczo stworzyłem obiekt klucza publicznego z materiałem kryptograficznym klucza prywatnego. Musisz wykonać odwrotność, utworzyć obiekt klucza prywatnego z materiałem kryptograficznym klucza publicznego, aby odszyfrować klucz publiczny, jeśli chcesz uniknąć wyjątku "Klucz publiczny nie może być użyty do odszyfrowania".

RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) ks.getKey(keyAlias, ksPassword.trim().toCharArray()); 
RSAPublicKeySpec spec = new RSAPublicKeySpec(
    privateKey.getModulus(), 
    privateKey.getPrivateExponent() 
); 
Key fakePublicKey = KeyFactory.getInstance("RSA").generatePublic(spec); 
encryptCipher.init(Cipher.ENCRYPT_MODE, fakePublicKey); 
+1

To bardzo ryzykowne, jeśli potraktujesz wykładnik klucza prywatnego jako wykładnik publiczny i rozdzielisz go, ponieważ biorąc pod uwagę klucz prywatny (który nazywasz "kluczem publicznym"), łatwo jest uzyskać rzeczywisty klucz publiczny (którym jesteś teraz). wywołanie "klucza prywatnego"). Nie pozwól, aby ten "klucz publiczny" został publicznie ujawniony lub Twój system zostanie naruszony. Może to być tak proste, jak przypuszczenie, że wykładnik "klucza prywatnego" to 65537. –

+0

Tak długo tego szukałem. Jestem bardzo wdzięczny za tę odpowiedź. Nazwa "klucz prywatny i publiczny" jest całkowicie błędna w tym przypadku użycia, ale są sytuacje, w których jest to istotne. –

+0

@JimFlood Jeśli rozumiem poprawnie, a moja sytuacja jest podobna, dmitry utworzył 'RSAPublicKeySpec' do przechowywania danych klucza prywatnego. Oczywiście nie zamierza dystrybuować klucza prywatnego, tylko oryginalny klucz publiczny, który może być teraz użyty do udowodnienia (odszyfrowania), że klucz prywatny był do szyfrowania - tj. Niezaprzeczalności. – Guss

0

spróbuj tego:

java.security.Security.addProvider(
        new org.bouncycastle.jce.provider.BouncyCastleProvider() 
      );