好问题
Good  Question
  • 首 页
  • 问题
    • PHP
    • JAVA
    • CPlusPlus
    • C#
    • SQL
  • 关 于
  • 联 系
Java中基于AES256的加密 关闭 返回上一级  

Java中基于AES256的加密
+ 查看更多

发布日期:2018-03-08 17:54
分类:JAVA
浏览次数:490
我想要通过使用自己的密钥实现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时,请仔细检查以确保你正在使用的文件都在正确的位置。
上一篇JAVA中如何从数组列表中删除重复元素?
在java中如何发送HTTP请求,有没例子代码?下一篇
下一篇在java中如何发送HTTP请求,有没例子代码?

最新文章

  • 函数`__construct`用来干嘛的
    发布日期:2018-03-26
  • 通过访客的IP得到他们的地区
    发布日期:2018-03-26
  • 合并两个PHP对象的最好的方法是什么?
    发布日期:2018-03-26
  • 该如何把一该如何把一个对象转化成数组?
    发布日期:2018-03-26
  • 什么是输出缓冲区?
    发布日期:2018-03-26
  • 在PHP中怎么把用逗号分隔的字符串分隔在一个数组里?
    发布日期:2018-03-26
  • 在PHP中使用foreach循环时查找数组的最后一个元素
    发布日期:2018-03-26
关于好问
收集整理一些有用的问题和回答,造福中国的程序旺和IT喵们!
友情链接
起飞页 
相关信息
版权声明
Copyright © 2016 - 2022  苏州卡达网络科技有限公司 备案号:苏ICP备09008221号