【问题标题】:Local encryption and decryption of data数据的本地加密和解密
【发布时间】:2018-10-30 03:50:46
【问题描述】:

你好,亲爱的stackoverflow,

我目前正在我的应用程序中开发/实施安全措施,并且在某些数据的加密和解密方面遇到了一些问题。

事实上,昨天我能够加密一条消息,然后使用该类的相同实例解密加密的消息 - 但反之亦然。这就是我今天想发布的(关于这个问题) -

从我工作过的linux系统推送最新的修改,尝试在windows pc上继续工作,抛出如下错误:

    java.security.InvalidKeyException: Illegal key size or default parameters
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026)
    at javax.crypto.Cipher.implInit(Cipher.java:801)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
    at javax.crypto.Cipher.init(Cipher.java:1249)
    at javax.crypto.Cipher.init(Cipher.java:1186)
    at com.x.backend.security.Decrypter.encrypt(Decrypter.java:43)
    at crypto.CryptoTest.main(CryptoTest.java:11)
java.lang.NullPointerException
    at javax.crypto.spec.IvParameterSpec.<init>(IvParameterSpec.java:53)
    at com.x.backend.security.Decrypter.decrypt(Decrypter.java:54)
    at crypto.CryptoTest.main(CryptoTest.java:12)

所以我试图找到一个解决方案,但没有找到任何解决方案,所以这是我目前尝试的:

  • 更新到 JDK 9/10/11 对我来说不是一个选择,我试过了,我失败得很惨,如果我要升级的话,会有太多的调整(不值得目前为止的努力)

  • 我读过一些关于 Java Cryptography Extension (JCE) 的文章,但这不适用于我,因为我运行的是 JDK 版本 1.8.66(从 1.8.55 开始)不再需要在 java 目录中安装任何类型的文件)

  • 缓存无效 (IntelliJ) + 重新启动了我的 PC

  • 将项目状态重置为初始提交(git 硬重置)

我的班级:

public class Decrypter {

    private static Decrypter instance;

    private Cipher cipher;

    private byte[] IV;

    private SecretKeySpec secretKeySpec;

    private Decrypter() {
        initialize();
    }

    private void initialize() {
        try {
            final byte[] salt = "@1jq3#-o1_uHvaL:".getBytes();
            final String key = "hehexd";
            final int iterationCount = 12;
            final int keyStrength = 256;
            this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            this.secretKeySpec = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(new PBEKeySpec(key.toCharArray(), salt, iterationCount, keyStrength)).getEncoded(), "AES");
        } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException e) {
            e.printStackTrace();
        }
    }

    public final String encrypt(String data) {
        try {
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            IV = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
            return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public final String decrypt(String base64EncryptedData) {
        try {
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(IV));
            byte[] decryptedData = Base64.getDecoder().decode(base64EncryptedData);
            byte[] utf8 = cipher.doFinal(decryptedData);
            return new String(utf8, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static Decrypter getInstance() {
        return instance == null ? instance = new Decrypter() : instance;
    }
}

我的测试课:

    public class CryptoTest {

    public static void main(String[] args) {
        String encrypted = Decrypter.getInstance().encrypt("lol");
        String decrypted = Decrypter.getInstance().decrypt(encrypted);
        System.out.println("Verification: PLAINTEXT -> ENCRYPT: " + encrypted);
        System.out.println("Verification: ENCRYPT -> DECRYPT: " + decrypted);
    }
}

请不要介意任何传统的错误/不良做法,我是密码学的新手(目前正在阅读我的方法)

任何帮助或意见将不胜感激!

编辑:

感谢您的即时回复!

不幸的是,我又抛出了一个错误。 完整输出:

    Verification: PLAINTEXT -> ENCRYPT: 
java.security.InvalidKeyException: Illegal key size
Verification: PLAINTEXT -> DECRYPT: 
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
    at javax.crypto.Cipher.implInit(Cipher.java:805)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
    at javax.crypto.Cipher.init(Cipher.java:1396)
    at javax.crypto.Cipher.init(Cipher.java:1327)
    at com.x.backend.security.Decrypter.encrypt(Decrypter.java:48)
    at crypto.CryptoTest.main(CryptoTest.java:11)
java.security.InvalidKeyException: No installed provider supports this key: javax.crypto.spec.SecretKeySpec
    at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
    at javax.crypto.Cipher.init(Cipher.java:1396)
    at javax.crypto.Cipher.init(Cipher.java:1327)
    at com.x.backend.security.Decrypter.decrypt(Decrypter.java:58)
    at crypto.CryptoTest.main(CryptoTest.java:12)

更改代码:

 public final String encrypt(String data) {
        try {
            IV = new IvParameterSpec("testtesttesttest".getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, IV);
            return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

【问题讨论】:

    标签: java encryption


    【解决方案1】:

    我不知道你从哪里得到 JDK 1.8.66 附带无限强度 JCE 的信息。美国以外的情况并非如此。

    您仍然需要从Oracle 下载并安装无限强度的 JCE JAR。

    如果您确定您拥有无限的 JCE,请尝试添加到jre/lib/security/java.security

    crypto.policy=unlimited
    

    仅从 Java SE 8u161 开始默认启用无限强度。所以这里不需要这个设置。


    附带说明 - 可以改进您的错误处理。将e.printStackTrace() 替换为throw new RuntimeException(e) 可能会更好,以将所有这些初始化错误视为致命错误(它们在那个阶段会破坏交易)。

    【讨论】:

    • 我已经调整了文件,但在错误输出中没有任何改变 - 也感谢您的提示! - 另外,我现在将安装 SE 8u161,只是为了验证它
    • 那你需要从Oracle下载无限强度JCE
    • stackoverflow.com/questions/37741142/… - 原来你提到的机制是从 151 到 166 发明的,并且可以! JCE 部分是否会影响任何用户,他们是否需要执行任何类似的步骤?
    【解决方案2】:

    事实证明,对最新 JDK 的更新修复了所有出现的问题。我现在可以轻松地独立解密和加密东西了!

    感谢所有参与寻找解决方案的人!

    【讨论】:

    • 你应该接受@rustyx 的回答。很高兴找到了解决方案!
    • 我忘了,哎呀,是的!
    猜你喜欢
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2013-03-23
    • 2013-10-28
    相关资源
    最近更新 更多