Certificate 证书密钥使用和密码加密模式

Certificate 证书密钥使用和密码加密模式,certificate,encryption,Certificate,Encryption,我正在尝试使用cxf和sprint加密传出的SOAP头。由于使用spring进行了配置,我最终使用OutiterCeptor作为客户端: " 方法,我逐步通过调试器找到其源: try { **cipher.init(Cipher.ENCRYPT_MODE, remoteCert);** } catch (InvalidKeyException e) { throw new WSSecurityException( WSSecurit

我正在尝试使用cxf和sprint加密传出的SOAP头。由于使用spring进行了配置,我最终使用OutiterCeptor作为客户端:

"

方法,我逐步通过调试器找到其源:

try {
        **cipher.init(Cipher.ENCRYPT_MODE, remoteCert);**
    } catch (InvalidKeyException e) {
        throw new WSSecurityException(
            WSSecurityException.FAILED_ENCRYPTION, null, null, e
        );
    }
此时它抛出:无效密钥使用“异常

最后我编写了一个测试java类,在该类中我手动读取证书,然后尝试使用Cipher.ENCRYPT\u MODE参数初始化密码, 我最终得到了相同的异常。以下是具体的代码片段:

        InputStream inStream = new FileInputStream("our_cert.cer");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert =(X509Certificate)cf.generateCertificate(inStream);
        inStream.close();

        // Read the public key from certificate file
        RSAPublicKey pubkey = (RSAPublicKey) cert.getPublicKey();
        cipher.init(Cipher. ENCRYPT_MODE, certif);  // it breaks at this point
我将最后一行替换为

cipher.init(Cipher. PRIVATE_KEY, certif);
而且一切顺利

我认为这不是正确的密钥用法,我认为加密模式也应该有效

通过查看证书密钥使用部分,我注意到它的密钥使用定义如下:

ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
  Key_Encipherment
]
它没有其他的关键部分

从其作用方式来看,Cipher.init(..)似乎只适用于数字签名(即密码.私钥),而不适用于密钥加密(即密码.加密模式

因此,我的问题是,KeyUsage是否可能没有为该证书正确定义。 我不是密码专家,但我读过的一些留言板建议,如果密钥使用是关键的,可能需要使用 数据加密以及

谢谢你的帮助

在中,有两种情况会引发该异常,一种是“永不发生”错误,另一种是检查相关证书是否支持相关操作

if (critSet != null && !critSet.isEmpty()
    && critSet.contains(KEY_USAGE_EXTENSION_OID)) {
  boolean[] keyUsageInfo = cert.getKeyUsage();
  // keyUsageInfo[2] is for keyEncipherment;
  // keyUsageInfo[3] is for dataEncipherment.
  if ((keyUsageInfo != null) &&
      (((opmode == Cipher.ENCRYPT_MODE) &&
      (keyUsageInfo.length > 3) &&
      (keyUsageInfo[3] == false)) ||
      ((opmode == Cipher.WRAP_MODE) &&
      (keyUsageInfo.length > 2) &&
      (keyUsageInfo[2] == false)))) {
      throw new InvalidKeyException("Wrong key usage");
    }
}
这表明您使用的证书对加密无效。也许您试图使用公钥证书进行加密


代码似乎没有检查像私钥一样总是无效的opmode,而只是检查像加密模式一样有时无效的opmode,这可能就是为什么您的测试代码没有问题。

最近遇到了这个问题。如果公钥证书创建正确,则可以使用公钥证书进行加密。证书应具有密钥使用对象ID(ObjectId:2.5.29.15 Criticality=true),设置为“b0”(10110000),基本上启用了数据加密位。否则,您将遇到错误的密钥使用错误。任何CA颁发的证书都将使密钥使用关键性变为true。自签名证书(如在dev/sandbox环境中)不会将临界值设置为true,因此这些证书可以工作,当然前提是您已设置为信任它们。 我尝试使用服务器上的公钥证书,但遇到了这个错误。然后我们的IT部门拿着用于数据加密的正确公钥证书回来了,它开始为我工作。

是的,通过调试Cipher.init(),我确实看到第一个条件得到了满足,即:
(keyUsageInfo!=null)&((opmode==Cipher.ENCRYPT_MODE)&&(keyUsageInfo.length>3)&(keyUsageInfo[3]==false)
证书中的密钥使用应该支持加密,因为它有以下部分:
ObjectId:2.5.29.15 Criticality=true-Keyusage[DigitalSignature Key\u encryption]
还是我误读了它?非常感谢!我相信你在寻找“数据加密”而不是“密钥加密”我想那应该是Cipher.WRAP_模式。
ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
  Key_Encipherment
]
if (critSet != null && !critSet.isEmpty()
    && critSet.contains(KEY_USAGE_EXTENSION_OID)) {
  boolean[] keyUsageInfo = cert.getKeyUsage();
  // keyUsageInfo[2] is for keyEncipherment;
  // keyUsageInfo[3] is for dataEncipherment.
  if ((keyUsageInfo != null) &&
      (((opmode == Cipher.ENCRYPT_MODE) &&
      (keyUsageInfo.length > 3) &&
      (keyUsageInfo[3] == false)) ||
      ((opmode == Cipher.WRAP_MODE) &&
      (keyUsageInfo.length > 2) &&
      (keyUsageInfo[2] == false)))) {
      throw new InvalidKeyException("Wrong key usage");
    }
}