Шифрование с помощью закрытого ключа RSA в Java

Я пытаюсь зашифровать некоторый контент с помощью закрытого ключа RSA.

Я следую этому примеру: http://www.junkheap.net/content/public_key_encryption_java

но преобразование его в использование закрытых ключей, а не открытых. Следуя этому примеру, я думаю, что мне нужно сделать следующее:

  • чтение в закрытом ключе DER-формата
  • создать PCKS8EncodedKeySpec
  • вызов generatePrivate() из KeyFactory в получить объект закрытого ключа
  • используйте этот объект закрытого ключа с объектом Cipher для шифрования

Итак, действия:

ключ был сгенерирован из openssl с помощью:

openssl genrsa -aes256 -out private.pem 2048

а затем был преобразован в формат DER с:

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

я генерирую PKCS8EncodedKeySpec с:

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;

а затем сгенерируйте объект закрытого ключа с помощью:

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;
, на вызов:
pk = kf.generatePrivate(privateKeySpec);

Я:

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)

вопросы:

  • общий подход правильный?
  • - это PCKS8EncodedKeySpec право keyspec использовать?
  • любые мысли о недопустимой ошибке спецификации ключа?

5 ответов


прежде всего, я смущен, почему вы планируете использовать Cipher для шифрования с помощью закрытого ключа, а не подписи с помощью Signature. Я не уверен, что все RSA Cipher провайдеры будут использовать правильный тип блока для настройки, но стоит попробовать.

отложив это в сторону, я думаю, что вы пытаетесь загрузить нестандартный ключ формата OpenSSL. Преобразование его в DER с помощью rsa по существу, это просто декодирование base-64; структура ключа не является PKCS #8.

, после genrsa используйте openssl pkcs8 команда для преобразования сгенерированного ключа в незашифрованный PKCS #8, DER формат:
openssl pkcs8 -topk8 -nocrypt -in private.pem -outform der -out private.der

это создаст незашифрованный закрытый ключ, который может быть загружен с PKCS8EncodedKeySpec.


вы не можете зашифровать с помощью закрытого ключа. Если JCE позволяет вам это делать, это просто случайно.

вам нужно использовать подпись. Вот фрагмент кода для этого,

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

Это не случайно, что шифрование с закрытым ключом разрешено. Если вы хотите разбить подпись на отдельные хэширование и шифрование, то шифрование с помощью закрытого ключа имеет важное значение. Допустим, у меня есть документ, который мне нужно подписать, и мой ключ находится в сети HSM. Теперь либо я передаю весь документ в HSM для подписи, либо я могу создать локальный хэш и передать его в HSM только для шифрования. Мой выбор будет зависеть от того, дает ли локальное вычисление хэша мне лучше производительность viz Viz делегированное вычисление хэша с задержкой сети.


этот вопрос довольно старый, но я недавно наткнулся на проблему (я реализую требования некоторого протокола, который требует шифрования с закрытым ключом). Я просто процитирую сообщение от форуме:

недавно я наткнулся на ту же проблему, представил PMR 22265,49 R, и поддержка IBM после консультации с "разработкой" (кем бы они ни были) постановил, что закрытые ключи не могут использоваться для шифрования. Как бы я ни пытался с ними спорить, что закрытые ключи не должны использоваться для защиты данных, что является только одной целью шифрования, и что совершенно нормально использовать закрытые ключи для шифрования для достижения непоколебимости, они были непоколебимы в своей вере. Вы должны любить людей, которые настаивают на том, что 2х2=5.

вот как я работал вокруг этой проблемы: по сути, я создал объект с открытым ключом с крипто материал закрытого ключа. Вам нужно будет сделать обратное, создать объект закрытого ключа с помощью криптоматериал открытого ключа для расшифровки с помощью открытого ключа, если вы хотите избежать исключения" открытый ключ нельзя использовать для расшифровки".

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

попробуйте это:

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