获取条目后的 KeyStore EOFException

KeyStore EOFException after getting entry

我创建了一个 KeyStore 来在 Web 服务器中保存一组私钥。创建 KeyStore.jks 文件后,我成功添加了私钥并从密钥库中检索了它。但是,当我尝试添加新密钥时,我在 KeyStore.load(...).

中得到一个 EOFException
public void setPrivateKey(String deviceSerialNumber, PrivateKey priv) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, InvalidKeySpecException, NotSupportedException {
    File privateKeyFile = getFile(Constants.JKS_PRIVATE_FILE_NAME);//Get the KeyStore.jks file
    synchronized (privateKeyFile) {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(privateKeyFile), Constants.JKS_PRIVATE_FILE_PASSWORD); //This is where the error happens 
        FileOutputStream file = null;
        try {
            file = new FileOutputStream(privateKeyFile);//Get the JKS file with the private keys


            //Write the private key to the file
            KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(Constants.JKS_PRIVATE_FILE_PASSWORD);
            KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry(priv, new Certificate[] { createCertificate() });
            keyStore.setEntry(deviceSerialNumber, pke, protParam);

            //Save changes to key store file
            keyStore.store(file, Constants.JKS_PRIVATE_FILE_PASSWORD);

        } finally {
            file.close();//Close the private key file output stream
        }

    }
}

public PrivateKey getPrivateKey(String deviceSerialNumber) throws NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, KeyStoreException, InvalidKeySpecException, NotSupportedException, UnrecoverableEntryException {
    PrivateKey key = null;
    File privateKeyFile = getFile(Constants.JKS_PRIVATE_FILE_NAME);//Get the keyStore.jks file
    synchronized (privateKeyFile) {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(privateKeyFile), Constants.JKS_PRIVATE_FILE_PASSWORD);
        FileOutputStream file = null;
        try {
            file = new FileOutputStream(privateKeyFile);//Get the JKS file with the private keys


            //Write the private key to the jks file
            boolean isKeyEntry = keyStore.isKeyEntry(deviceSerialNumber);//Check if there is a key with the alias deviceSerialnumber
            if (isKeyEntry) {//If the key does exist
                System.err.println("Key does exist!!!!1");
                KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(Constants.JKS_PRIVATE_FILE_PASSWORD);
                KeyStore.PrivateKeyEntry pke =  (PrivateKeyEntry) keyStore.getEntry(deviceSerialNumber, protParam);
                key = pke.getPrivateKey();
            } else {//If the key does not exist
                System.err.println("No key!!!!!!!!");
                //HANDLE THIS
                return null;
            }

        } finally {
            file.close();//Close the private key file output stream
        }
    }
    return key;
}

private Certificate createCertificate() throws CertificateException, IOException {
    FileInputStream fis = new FileInputStream(getFile(Constants.CERTIFICATE_FILE));


    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    Collection<? extends Certificate> c = cf.generateCertificates(fis);
    Iterator<? extends Certificate> i = c.iterator();

    if (i.hasNext())
        return (Certificate) i.next();
    else 
        return null;
}

错误发生在 setPrivateKey(...)keyStore.load(...) 第二次调用该方法以将额外的私钥添加到密钥库。

我使用 keytool

生成 KeyStore.jks 文件和 server.cer 文件
keytool -genkey -alias keyAlias -keyalg RSA  -keystore KeyStore.jks -keypass password -storepass password
keytool -export -alias keyAlias -file server.cer -keystore KeyStore.jks -storepass password

我在密钥库中存储和检索私钥的方式有问题吗?如何阻止 EOFException 发生?

去掉getPrivateKey

这一行
file = new FileOutputStream(privateKeyFile);

它没有被使用并关闭您之前创建的 FileInputStream,而不是输出流。您在同一个文件上有两个打开的流

 keyStore.load(new FileInputStream(privateKeyFile), Constants.JKS_PRIVATE_FILE_PASSWORD);