发布日期:2018-03-26
Java中基于AES256的加密+ 查看更多
Java中基于AES256的加密
+ 查看更多
发布日期:2018-03-08 17:54
分类:JAVA
浏览次数:556
我想要通过使用自己的密钥实现AES256加密,但是在网上找到的所有示例都是使用“KeyGenerator”生成256位密钥。所以我应该如何创建自己的密钥?我曾经尝试直接添加256位密码,然后我得到一个错误,错误提示我密钥太长。 而我在电脑上安装了许多控制强度权限的文件,所以这不是文件的问题:)
其中KeyGenerator看起来是这样的:
// Get the KeyGenerator KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); // 192 and 256 bits may not be available // Generate the secret key specs. SecretKey skey = kgen.generateKey(); byte[] raw = skey.getEncoded();
Code taken from here(代码在这个链接中)
修订后:
实际上我填充的是256个字节的密码,而不是256位,虽然我也知道这太长了。 以下是我有了更多的经验后使用的一部分代码。
byte[] key = null; // TODO byte[] input = null; // TODO byte[] output = null; SecretKeySpec keySpec = null; keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); output = cipher.doFinal(input)
其中“TODO”表示这里的位数由你自己写入:-)
回答:
通过接受者的传输层协议使用带外数据(OOB)共享password(一个char [])和salt(一个byte [] - 由SecureRandom提供的8个字节组成一个salt值 – 并且这不需要保密)。然后从这些信息中导出一个好的密钥:
导出密钥,给定密码和salt:
/* Derive the key, given password and salt. */ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(password, salt, 65536, 256); SecretKey tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
其中65536和256(可以在某处被定义为常数)分别是密钥导出迭代计数和密钥大小。
密钥导出被迭代的函数需要大量的计算工作,并且防止攻击者快速地用许多不同的密码进行尝试攻击。迭代计数可以根据可用的计算资源的大小进行改变。
密钥大小可以减少到128位,并且仍然被认为是“强”加密。但是如果发现有攻击并且这个攻击削弱了AES,它的安全程度就会大大减小。
相同的密钥与合适的链接模式一起使用可以用于加密许多消息。在CBC(密码分组链接模式)中,为每个消息生成随机的初始化向量(IV),即使明文是相同的,也产生不同的密文。 CBC可能不是最可靠的模式(见下面的AEAD);还有许多中具有不同的安全属性的模式,不过他们都使用类似的随机输入。在任何情况下,每个加密操作的输出都是密文和初始化向量。
加密消息:
/* Encrypt the message. */ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret); AlgorithmParameters params = cipher.getParameters(); byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));
存储ciphertext(密文)和iv。在解密时,SecretKey以完全相同的方式被重新生成,即使用具有相同salt和迭代参数的密码。然后使用SecretKey和存储消息的初始化向量初始化密码:
解密消息,给定导出密钥和初始化向量:
/* Decrypt the message, given derived key and initialization vector. */ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv)); String plaintext = new String(cipher.doFinal(ciphertext), "UTF-8"); System.out.println(plaintext);
Java 7含有支持AEAD加密模式的API。而从Java 8 开始,“SunJCE”提供了包括OpenJDK和Oracle分布实施的模式。强烈建议使用这些模式来代替CBC,因为它们都可以保护数据的完整性以及数据的隐私性。
带有“Illegal key size or default parameters(非法密钥大小或默认参数)”提示的java.security.InvalidKeyException意味着密码的加密强度有限;许多控制强度权限的文件不在正确的位置。在JDK中,它们应该放在$ {jdk} / jre / lib / security中。
你的问题描述听起来像策略文件没有正确安装。系统可以运行拥有多个Java时,请仔细检查以确保你正在使用的文件都在正确的位置。