Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么';IBM有什么问题;谁是JCE提供商?_Java_Jce - Fatal编程技术网

Java 什么';IBM有什么问题;谁是JCE提供商?

Java 什么';IBM有什么问题;谁是JCE提供商?,java,jce,Java,Jce,我有一个JCE测试,它可以与我尝试过的所有Sun JDK一起正常工作,但在各种IBM J9 JDK(例如1.6.0构建pwi3260sr8-20100409_01(SR8))中失败。在加密模式下初始化密码时,会发生以下异常。为什么IBMJCE不能使用自己的私钥?我的代码中遗漏了什么吗 public void testBasicKeyGeneration() throws NoSuchAlgorithmException, NoSuchPaddingException, Inva

我有一个JCE测试,它可以与我尝试过的所有Sun JDK一起正常工作,但在各种IBM J9 JDK(例如1.6.0构建pwi3260sr8-20100409_01(SR8))中失败。在加密模式下初始化密码时,会发生以下异常。为什么IBMJCE不能使用自己的私钥?我的代码中遗漏了什么吗

  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)

@T.Rob评论说,您可能在使用私钥加密时犯了错误。如果“每个人”都知道公钥,那么任何人都可以解密您的文件。因此,IBM的JCE行为可以保护人们避免犯这种错误

我能理解其中的逻辑

但是,在某些情况下,您确实需要使用私钥进行加密;e、 g.作为协议的一部分,需要证明您知道与已发布公钥对应的私钥


如果这真的是您想要做的,您可能需要使用最近的Sun JCE实现(较旧的Sun JCE没有实现RSA)或Bouncy Castle。

我不确定这一点,但我相信JCE有一个嵌入式策略,将加密限制为公钥,解密限制为私钥

在示例代码中,加密是使用私钥完成的。这将需要公钥解密,这意味着任何拥有公钥的人都可以访问编码的数据。尽管这有它的用途,但它不是公认的模式,IBM实现可能会“保护”您,使您不会意外地创建公开可读的加密数据


事实上,当这些被逆转时,它进行了正确的测试,这证实了我的怀疑,但我还没有找到一份官方文件说明这一点。

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

本质上,我用私钥的加密材料创建了一个公钥对象。如果要避免“公钥不能用于解密”异常,则需要执行相反的操作,使用公钥的加密材料创建私钥对象,以使用公钥进行解密

@Stephen C/@FelixM:IBM似乎对RSA密码术的工作原理以及打算如何使用它完全一无所知。基本上,这两种操作(加密/解密)都必须可用于公钥和私钥

在SSL/TLS握手中传输预主密钥的客户端部分时,需要使用公钥进行加密。服务器需要使用其私钥解密。但是如果他们协商类似于ECDHE_RSA的东西,服务器需要用私钥对握手的部分内容进行签名,这就是用私钥加密。反之亦然,客户端需要使用服务器证书中的公钥进行解密,以验证签名的哈希值。(证明信息的真实性)

因此,如果我尝试在最新的IBM JDK 7上运行ECDHE_RSA(服务器端),会发生以下情况:

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)
如您所见,我们使用“签名”并调用“initSign”,这确实需要私钥。这证明IBM对这一事实一无所知,显然他们甚至不知道 有有效的回归测试

使用另一个加密提供商,在他们改变主意之前不要相信IBM

致以最良好的祝愿,
克里斯汀

我最近遇到了同样的问题。通过使用实现并将这一行添加到java.security文件中,最终解决了这个问题

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

有一个解决方案,请参阅

关于财产

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

您可以使用私钥来加密数据。

只是好奇-如果您切换并使用公钥进行加密,使用私钥进行解密,会发生什么情况?通常你不会用私钥加密,因为任何拥有公钥的人都可以解密它。如果IBM采取只使用公钥加密、使用私钥签名然后将其嵌入代码的策略,我也不会感到惊讶。很长时间,但很好奇你发现了什么。当我按照你的建议做的时候,它很有魅力。我想我的逻辑被改变了,因为我加密了许可证,不想把私钥放进附带的软件中。如果你把它写在一个答案里,我可以接受。@Stephen C:解密一封用公钥加密的邮件,这不是同样有效的证明吗?(当然,可能仍有预定义的协议可以按照您所描述的那样执行…)如上所述:对使用公钥加密的消息进行解密不是同样有效地证明了这一点吗?(当然,可能仍有预定义的协议可以按照您所描述的那样执行…@FelixM-我认为这是一个经过深思熟虑的功能。@Stephen C-我同意这是深思熟虑的,但它仍然可能是一个bug;)鉴于IBM的API文档只是Sun的副本,并且都指定Cipher.init()接受Key类型的值(与PrivateKey或PublicKey相反),我也倾向于使用bug。如果它没有文档记录,并且没有按照指定的方式工作…@FelixM,@t.Rob-那么发送一份bug报告。如果IBM同意这是一个bug并修复了它,那么您已经取得了一些成就。但我怀疑他们会这么做。这个想法很有趣,但反过来对我来说并不适用:`X509EncodedKeySpec=newx509encodedkeyspec(bout.toByteArray());KeyFactory=KeyFactory.getInstance(“RSA”);RSAPublicKey pukey=(RSAPublicKey)factory.generatePublic(spec);RSAPrivateKeySpec rspec=新的RSAPrivateKeySpec(pukey.getmodule(),pukey.getPublicExponent());key=factory.generatePrivate(rspec);`工作正常,但在解密时出现填充错误…JP的上述问题当然可以通过使用
“RSA/ECB/NoPadding”
来解决。不过,在这种情况下,您需要自己处理填充,这是PKCS#1 v1.5中指定的