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

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

Ie。 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();

取自此处的代码

EDIT

我实际上是把密码填充到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 :-)

推荐答案

共享密码 $ c> 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天全站免登陆