Java 256 位 AES 基于密码的加密 [英] Java 256-bit AES Password-Based Encryption

查看:37
本文介绍了Java 256 位 AES 基于密码的加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要实现 256 位 AES 加密,但是我在网上找到的所有示例都使用KeyGenerator"来生成 256 位密钥,但我想使用自己的密钥.如何创建自己的密钥?我曾尝试将其填充为 256 位,但随后我收到一条错误消息,指出密钥太长.我确实安装了无限管辖权补丁,所以这不是问题:)

I need to implement 256 bit AES encryption, but all the examples I have found online use a "KeyGenerator" to generate a 256 bit key, but I would like to use my own passkey. How can I create my own key? I have tried padding it out to 256 bits, but then I get an error saying that the key is too long. I do have the unlimited jurisdiction patch installed, so thats not the problem :)

即.KeyGenerator 看起来像这样......

Ie. The KeyGenerator looks like this ...

// 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();

取自此处的代码

编辑

我实际上是将密码填充到 256 字节,而不是位,这太长了.以下是我现在使用的一些代码,因为我对此有了更多的经验.

I was actually padding the password out to 256 bytes, not bits, which is too long. The following is some code I am using now that I have some more experience with this.

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"部分:-)

The "TODO" bits you need to do yourself :-)

推荐答案

Share the password (a char[]) 和 salt (byte[]——由 SecureRandom 选择的 8 个字节是一个很好的盐——它不需要保密)与接收者带外.然后从这些信息中导出一个好的密钥:

Share the password (a char[]) and salt (a byte[]—8 bytes selected by a SecureRandom makes a good salt—which doesn't need to be kept secret) with the recipient out-of-band. Then to derive a good key from this information:

/* 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 分别是密钥派生迭代次数和密钥大小.

The magic numbers (which could be defined as constants somewhere) 65536 and 256 are the key derivation iteration count and the key size, respectively.

密钥派生函数被迭代,需要大量的计算工作,这可以防止攻击者快速尝试许多不同的密码.迭代次数可以根据可用的计算资源进行更改.

The key derivation function is iterated to require significant computational effort, and that prevents attackers from quickly trying many different passwords. The iteration count can be changed depending on the computing resources available.

密钥大小可以减少到 128 位,这仍然被认为是强"的;加密,但如果发现削弱 AES 的攻击,它不会提供很大的安全余量.

The key size can be reduced to 128 bits, which is still considered "strong" encryption, but it doesn't give much of a safety margin if attacks are discovered that weaken AES.

与适当的区块链模式一起使用,相同的派生密钥可用于加密许多消息.在 密码块链接 (CBC) 中,随机初始化向量 (IV) 是为每条消息生成不同的密文,即使纯文本相同.CBC 可能不是您可用的最安全模式(请参阅下面的 AEAD);还有许多其他具有不同安全属性的模式,但它们都使用类似的随机输入.在任何情况下,每个加密操作的输出都是密文初始化向量:

Used with a proper block-chaining mode, the same derived key can be used to encrypt many messages. In Cipher Block Chaining (CBC), a random initialization vector (IV) is generated for each message, yielding different cipher text even if the plain text is identical. CBC may not be the most secure mode available to you (see AEAD below); there are many other modes with different security properties, but they all use a similar random input. In any case, the outputs of each encryption operation are the cipher text and the initialization vector:

/* 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(StandardCharsets.UTF_8));

存储密文iv.在解密时,SecretKey 以完全相同的方式重新生成,使用具有相同盐和迭代参数的密码.用这个密钥初始化密码存储在消息中的初始化向量:

Store the ciphertext and the iv. On decryption, the SecretKey is regenerated in exactly the same way, using using the password with the same salt and iteration parameters. Initialize the cipher with this key and the initialization vector stored with the message:

/* 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), StandardCharsets.UTF_8);
System.out.println(plaintext);


Java 7 包含的 API 支持 AEAD 密码模式 和SunJCE"OpenJDK 和 Oracle 发行版中包含的提供程序从 Java 8 开始实现这些.强烈建议使用这些模式之一代替 CBC;它将保护数据的完整性及其隐私.


Java 7 included API support for AEAD cipher modes, and the "SunJCE" provider included with OpenJDK and Oracle distributions implements these beginning with Java 8. One of these modes is strongly recommended in place of CBC; it will protect the integrity of the data as well as their privacy.

带有消息非法密钥大小或默认参数"的 java.security.InvalidKeyException意味着密码强度有限的;无限强度管辖策略文件不在正确位置.在 JDK 中,它们应该放在 ${jdk}/jre/lib/security

A java.security.InvalidKeyException with the message "Illegal key size or default parameters" means that the cryptography strength is limited; the unlimited strength jurisdiction policy files are not in the correct location. In a JDK, they should be placed under ${jdk}/jre/lib/security

根据问题描述,策略文件似乎没有正确安装.系统可以轻松拥有多个 Java 运行时;仔细检查以确保使用了正确的位置.

Based on the problem description, it sounds like the policy files are not correctly installed. Systems can easily have multiple Java runtimes; double-check to make sure that the correct location is being used.

这篇关于Java 256 位 AES 基于密码的加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆