【问题标题】:InvalidKeyException: Key Spec Not RecognisedInvalidKeyException:无法识别密钥规范
【发布时间】:2017-01-26 20:42:46
【问题描述】:

我得到了一个

InvalidKeyException:非法密钥大小或默认参数

尝试运行已部署 WAR 的 Web 应用程序时。我将它托管在 Linux 环境中的 Tomcat 上。我已经把这两个UnlimitedJCEPolicy文件放到了目的地/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.55.x86_64/jre/lib/security,看来还是出现错误。请注意,这只在我在 linux 环境中运行时才会抛出。在本地,它工作正常。这是我的代码:

public static final void decryptFile(File inputFile, File outputFile) throws 
IOException, PGPException {
    // Add Bouncy Castle provider
    Security.addProvider(new BouncyCastleProvider());

    // Grab secret key that's in folder with AE classes
    Resource resource = new ClassPathResource(Env.getSecretKeyAE());
    log.debug("Resource: " + Env.getSecretKeyAE());
    File keyFileName = resource.getFile();
    log.debug("Key File Name: " + keyFileName);
    // Decryption password
    String pass = "pass";
    char[] passwd = pass.toCharArray();

    // Read files into streams
    log.info("Reading files into streams");
    InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName));
    InputStream in = PGPUtil.getDecoderStream(new BufferedInputStream(new 
FileInputStream(inputFile)));

    // I don't even know what these do
    PGPObjectFactory pgpObjFactory = new PGPObjectFactory(in);
    PGPEncryptedDataList pgpEncryptedDataList = null;

    Object o = pgpObjFactory.nextObject();
    log.info("Checking instance of PGPEncryptedDataList");
    if (o instanceof PGPEncryptedDataList) {
        pgpEncryptedDataList = (PGPEncryptedDataList)o;
    }
    else {
        pgpEncryptedDataList = (PGPEncryptedDataList)pgpObjFactory.nextObject();
    }

    // This will be the PGPPrivateKey we use to decrypt
    log.info("Initializing secret key");
    PGPPrivateKey secretKey = null;
    PGPPublicKeyEncryptedData publicKeyEncryptedData = null;
    PGPSecretKeyRingCollection pgpSecretKeyRingCollection = new    
PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));

    // This iterates the key file as if it has many keys, this file has only one
    // This is the only way I could find to construct a PGPPrivateKey
    log.info("Iterating through key file");
    Iterator<?> it = pgpEncryptedDataList.getEncryptedDataObjects();
    while(it.hasNext() && secretKey == null) {
        publicKeyEncryptedData = (PGPPublicKeyEncryptedData) it.next();
        PGPSecretKey pgpSecKey = 
pgpSecretKeyRingCollection.getSecretKey(publicKeyEncryptedData.getKeyID());

        if (pgpSecKey != null) {
            Provider provider = Security.getProvider("BC");
            secretKey = pgpSecKey.extractPrivateKey(new   

JcePBESecretKeyDecryptorBuilder(new  
JcaPGPDigestCalculatorProviderBuilder().setProvider(provider)
.build()).setProvider(provider).build(passwd));
           }
    }
    log.info("PGPPrivateKey has been constructed");
    if (secretKey == null) {
        throw new IllegalArgumentException("secret key for message not found.");
    }
    log.info("Secret Key found!");

    if(publicKeyEncryptedData == null) {
        throw new NullPointerException("cannot continue with null public key encryption 
data.");
    }
    log.info("Public Key Encrypted Data found!");

    // More stuff I don't fully understand, I think this is just standard way to   
decrypt files once the above is all set up
    log.info("Starting actual decryption");
    //get data stream where our publicKeyDataDecrypterFactory sets ours provider to BC 
and we build our secretKey
    //secretkey is our PGPPrivateKey

    log.info("start");

    //=====================================================================
    //ERROR IS OCCURRING HERE
    InputStream clear = publicKeyEncryptedData.getDataStream(new  
JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(secretKey));
    log.info("1");
    PGPObjectFactory plainFact = new PGPObjectFactory(clear);
    log.info("2");
    PGPCompressedData compressedData = (PGPCompressedData)plainFact.nextObject();
    log.info("3");
    InputStream compressedStream = new 
BufferedInputStream(compressedData.getDataStream());
    log.info("4");
    PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream);
    log.info("5");
    Object message = pgpFact.nextObject();
    log.info("6");

    if (message instanceof PGPLiteralData) {
        log.info("Our message is an instance of PGP Literal Data.");
        PGPLiteralData literalData = (PGPLiteralData)message;
        InputStream literalDataInputStream = literalData.getInputStream();
        OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile));
        Streams.pipeAll(literalDataInputStream, out);
        out.close();
    }
    else if (message instanceof PGPOnePassSignatureList) {
        log.error("encrypted message contains a signed message - not literal data.");
        throw new PGPException("encrypted message contains a signed message - not  

literal data.");
    }
    else {
        log.error("message is not a simple encrypted file - type unknown.");
        throw new PGPException("message is not a simple encrypted file - type  
unknown.");
    }
    log.info("Checking if public key encrypted data is integrity protected");
    if (publicKeyEncryptedData.isIntegrityProtected()) {
        if (!publicKeyEncryptedData.verify()) {
            throw new PGPException("message failed integrity check");
        }
    }

    keyIn.close();
    in.close();
}

使用日志,我能够发现错误发生的时间

InputStream clear = publicKeyEncryptedData.getDataStream(new  
JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(secretKey));

但我不知道为什么。就像我说的,我已经适当地放置了 JCEUnlimited 文件,但错误仍然存​​在。

编辑我修复了非法密钥大小问题,但现在出现“无法识别密钥规范”

EDIT 对错误“关键规范无法识别”的详细说明: 所以正如我所说,非法密钥大小已经消失,但“密钥规格无法识别”似乎仍然是一个问题。奇怪的是,我的 encryptFile 方法运行良好,但 decryptFile 抛出错误。我不完全确定为什么。下班前,我又测试了一次,似乎没有抛出错误。我几乎似乎这个错误是随机发生的,具体取决于 WAR 到 tomcat 的部署。如果我部署我的 WAR,则在某些时候不会发生错误,但如果我取消部署并使用更新的 WAR 文件重新部署,则会引发错误。我不知道是什么原因造成的,而且基于研究也没有人真正知道。显然这曾经是 1.5 之前 Bouncy Castle 中的一个错误,但 1.5 是我正在运行的版本,所以这不是问题。如果我发现任何可以修复此错误的内容,我会发布。

【问题讨论】:

  • 因为我使用的是 Tomcat,所以我的 java home 实际上在我的 opt 文件夹中。我必须放置 UnlimitedJCEPolicy 文件的确切位置是 /opt/jre1.7.0_60/lib/security。将文件放在那里并重新部署我的 war 文件后,我不再遇到这个问题了。

标签: java linux bouncycastle pgp


【解决方案1】:

解决:

java.security.spec.InvalidKeySpecException:无法识别密钥规范

修改安全提供者:

sudo nano $JAVA_HOME/jre/lib/security/java.security

添加安全提供者:

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

复制bcprov-jdk15on-1.54.jar到:

$JAVA_HOME/jre/lib/ext/bcprov-jdk15on-1.54.jar

重启 Tomcat。

【讨论】:

    【解决方案2】:
    if (o instanceof PGPEncryptedDataList) {
            pgpEncryptedDataList = (PGPEncryptedDataList)o;
    

    如果 o 已经是 PGPEncryptedDataList 的一个实例,为什么要将它转换为 PGPEncryptedDataLIST?

    我对您所做工作的具体细节了解得不够多,所以我只是想提供一些一般性的代码分析。抱歉,我无法提供更多帮助。

    【讨论】:

    • 说实话,这是以前的同事,所以我自己也不能告诉你为什么会这样。不过感谢您引起我的注意!
    【解决方案3】:

    为了防止出现“非法密钥大小或默认参数”错误,我只需将 UnlimitedJCEPolicy 文件放在我的工作 java 目录 /opt/jre1.7.0_60/lib/security 中。将文件放在那里并重新部署我的 war 文件后,我不再遇到这个问题了。

    为了防止出现“key spec not recognize”错误,我必须在重新部署我的 WAR 文件时重新启动我的 tomcat 服务器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 2011-04-21
      • 1970-01-01
      • 2016-09-23
      • 2014-12-01
      • 2022-01-14
      • 1970-01-01
      相关资源
      最近更新 更多