Что не так с провайдером IBM JCE? - PullRequest
4 голосов
/ 02 февраля 2011

У меня есть тест JCE, который отлично работает со всеми JDK Sun, которые я пробовал, но не работает с различными JDK IBM J9 (например, 1.6.0 build pwi3260sr8-20100409_01 (SR8)).Исключение ниже происходит, когда шифр инициализируется в режиме шифрования.Почему IBM JCE не может использовать свой собственный закрытый ключ?Я что-то упустил в своем коде?

  public void testBasicKeyGeneration() throws NoSuchAlgorithmException, 
      NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, 
      BadPaddingException, NoSuchProviderException, SignatureException {
      KeyPairGenerator generator = KeyPairGenerator.getInstance( "RSA" );
      generator.initialize( 2048 );
      KeyPair pair = generator.generateKeyPair();

      String data1 = "123456789012345678901234567890123456789012345678901234567890";
      Cipher cipher = Cipher.getInstance( "RSA" );
      cipher.init( Cipher.ENCRYPT_MODE, pair.getPrivate() );
      byte[] encrypted = cipher.doFinal( data1.getBytes() );

      cipher.init( Cipher.DECRYPT_MODE, pair.getPublic() );
      byte[] decrypted = cipher.doFinal( encrypted );
      String data2 = new String( decrypted );
      assertEquals( "en/decryption failed", data1, data2 );
  }

Вот трассировка стека:

java.security.InvalidKeyException: Private key cannot be used to encrypt.
at com.ibm.crypto.provider.RSA.engineInit(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at test.Test.testBasicKeyGeneration(LicenseHelperTest.java:56)

Ответы [ 6 ]

5 голосов
/ 12 августа 2014

Есть решение, см. http://www -01.ibm.com / support / docview.wss? Uid = swg1IV18625

со свойством

-Dcom.ibm.crypto.provider.DoRSATypeChecking=false

вы можете использовать закрытые ключи для шифрования данных.

5 голосов
/ 02 февраля 2011

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

В примере кода шифрование выполнялось с помощью закрытого ключа.Для этого потребуется расшифровать открытый ключ, что означает, что любой пользователь с открытым ключом может получить доступ к закодированным данным.Несмотря на то, что он использует его, он не является принятым шаблоном, и реализация IBM может «защищать» вас от случайного создания зашифрованных данных, которые были общедоступными для чтения.мои подозрения, но я еще не нашел официальный документ с указанием так много.

3 голосов
/ 31 марта 2014

Я недавно столкнулся с той же проблемой. В конечном итоге это было решено с помощью реализации надувного замка и добавлением этой строки в файл java.security

security.provider.1 = org.bouncycastle.jce.provider.BouncyCastleProvider

3 голосов
/ 12 ноября 2011

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

Вот как я работалвокруг этой проблемы:

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

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

2 голосов
/ 20 февраля 2013

@ Стивен C / @FelixM: IBM, похоже, совершенно не знает, как работает криптография RSA и как она предназначена для использования. В основном обе операции (шифрование / дешифрование) должны быть доступны для открытого и закрытого ключа.

Шифрование с открытым ключом необходимо для передачи клиентской части предварительного главного секрета при рукопожатиях SSL / TLS. Сервер должен расшифровываться с помощью своего закрытого ключа. Но если они договариваются о чем-то вроде ECDHE_RSA, серверу необходимо ПОДПИСАТЬ части рукопожатия с закрытым ключом - это шифруется с помощью PrivateKey. Наоборот, клиент должен расшифровать с помощью открытого ключа из сертификата сервера, чтобы проверить значение хэша подписи. (подтверждение подлинности сообщения)

Поэтому, если я попытаюсь запустить ECDHE_RSA (на стороне сервера) в последней версии IBM JDK 7, произойдет следующее:

java.security.InvalidKeyException: Private key cannot be used to encrypt.
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
   at java.lang.Thread.run(Thread.java:777)
   at com.ibm.crypto.provider.RSASSL.engineInit(Unknown Source)
   at javax.crypto.Cipher.init(Unknown Source)
   at javax.crypto.Cipher.init(Unknown Source)
   at java.security.Signature$CipherAdapter.engineInitSign(Signature.java:1239)
   at java.security.Signature$Delegate.init(Signature.java:1116)
   at java.security.Signature$Delegate.chooseProvider(Signature.java:1076)
   at java.security.Signature$Delegate.engineInitSign(Signature.java:1140)
   at java.security.Signature.initSign(Signature.java:522)
   at net.vx4.lib.tls.core.TLSSignature.createSignature(TLSSignature.java:120)

Как вы можете видеть, мы используем "Signature" и вызываем "initSign", что действительно требует PrivateKey. Это доказывает, что IBM ничего не знает об этом факте, и, очевидно, они даже не иметь действительные регрессионные тесты!

Воспользуйтесь другим провайдером шифрования и не верьте IBM, пока они не передумают.

С наилучшими пожеланиями, Christian

2 голосов
/ 02 февраля 2011

@T.Rob отметил, что вы могли ошибиться при шифровании с помощью закрытого ключа. Если «каждый» знает открытый ключ, тогда любой может расшифровать ваш файл. Таким образом, поведение IBM JCE защищает людей от этой ошибки.

Я вижу логику этого.

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

Если это действительно то, что вы хотите сделать, вам, вероятно, нужно использовать недавнюю реализацию Sun JCE (более ранние версии Sun JCE не использовали RSA) или Bouncy Castle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...