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

查看:160
本文介绍了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 :-)

推荐答案

分享密码(a char [] )和 salt (a byte [] — 8通过 SecureRandom 选择的字节使得收件人无法保持密码,不需要保密)。然后从这些信息中获得一个好的密钥:

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 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("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), "UTF-8");
System.out.println(plaintext);






Java 7包含了对AEAD加密模式的API支持,而OpenJDK和Oracle发行版中提供的SunJCE提供程序以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.

A 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天全站免登陆