今天同学请教我这个问题,被坑了次……

实现的功能是2个Java类:一个读取源文件生成加密文件,另一个类读取加密文件来解密。

整个过程其实很简单,java有AES的工具包,设好秘钥,设好输入内容,就得到加密结果和解密结果了。

然而百度搜AES加密,最先跳出的必须是这个博客 http://www.cnblogs.com/freeliver54/archive/2011/10/08/2202136.html

后来才发现下面的评论:

“kgen.init(128, new SecureRandom(password.getBytes()));
我可是被你坑惨了 啊!!!!
你用你的加密算法加密一段字符,一周以后,你再用你的解密方法,看看能否解密!!!!!!
等你回答!!!!!” 

简单的说就是这货给原本约定秘钥A再利用时间种子随机成16位作为加密秘钥B(目的应该是为了避开16位的限制)…虽然约定秘钥都是A,WINS能跑是因为短时间得到秘钥B可能一样,但你长时间随机出来的加密秘钥B就肯定不一样了,这样AES解密就解不开了。。。

所以这个方法是错误的。。(而且里面的UTF-8也不对吧,遇到GBK的就跪了)

一种解决办法是,对把A随机成B的种子变成固定值,这样每次得到B就一样了。而且解决了16位限制的问题。

public static byte[] encrypt(String content, String password) {
try { KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom random=SecureRandom.getInstance("SHA1PRNG");//加解密保持同个随机种子
random.setSeed(password.getBytes());
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content.getBytes());
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}

看网上一个代码,写的比较精简,秘钥必须是16位的,如需要任意位,可以按上面说的加个伪随机,但不要像那位博主一样拿时间做种子了。

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*; /**
* This program generates a AES key, retrieves its raw bytes, and then
* reinstantiates a AES key from the key bytes. The reinstantiated key is used
* to initialize a AES cipher for encryption and decryption.
*/ public class AES { private static final String AES = "AES"; private static final String CRYPT_KEY = "YUUAtestYUUAtest"; /**
* 加密
*
* @param encryptStr
* @return
*/
public static byte[] encrypt(byte[] src, String key) throws Exception {
Cipher cipher = Cipher.getInstance(AES);
SecretKeySpec securekey = new SecretKeySpec(key.getBytes(), AES);
cipher.init(Cipher.ENCRYPT_MODE, securekey);//设置密钥和加密形式
return cipher.doFinal(src);
} /**
* 解密
*
* @param decryptStr
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] src, String key) throws Exception {
Cipher cipher = Cipher.getInstance(AES);
SecretKeySpec securekey = new SecretKeySpec(key.getBytes(), AES);//设置加密Key
cipher.init(Cipher.DECRYPT_MODE, securekey);//设置密钥和解密形式
return cipher.doFinal(src);
} /**
* 二行制转十六进制字符串
*
* @param b
* @return
*/
public static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1)
hs = hs + "0" + stmp;
else
hs = hs + stmp;
}
return hs.toUpperCase();
} public static byte[] hex2byte(byte[] b) {
if ((b.length % 2) != 0)
throw new IllegalArgumentException("长度不是偶数");
byte[] b2 = new byte[b.length / 2];
for (int n = 0; n < b.length; n += 2) {
String item = new String(b, n, 2);
b2[n / 2] = (byte) Integer.parseInt(item, 16);
}
return b2;
} /**
* 解密
*
* @param data
* @return
* @throws Exception
*/
public final static String decrypt(String data) {
try {
return new String(decrypt(hex2byte(data.getBytes()),
CRYPT_KEY));
} catch (Exception e) {
}
return null;
} /**
* 加密
*
* @param data
* @return
* @throws Exception
*/
public final static String encrypt(String data) {
try {
return byte2hex(encrypt(data.getBytes(), CRYPT_KEY));
} catch (Exception e) {
}
return null;
} public static String fromFile(String dir){
String result ="";
try{
FileReader fr = new FileReader(dir);
BufferedReader br = new BufferedReader(fr);
String s=br.readLine();
while(s!=null){
result += s;
s=br.readLine();
}
}
catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
} return result;
} public static void toFile(String s,String dir){
try{
File f = new File(dir);
FileWriter fw = new FileWriter(f);
fw.write(s);
//System.out.println(s);
fw.close();
}
catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) {
String ID = "test";
System.out.println("original string is:"+ID);
String idEncrypt = encrypt(ID);
System.out.println("encode result is:"+idEncrypt);
String idDecrypt = decrypt(idEncrypt);
System.out.println("decode result is:"+idDecrypt);
/*以下同学的要求
String ID = fromFile("/Users/shen/Desktop/source.txt");
String idEncrypt = encrypt(ID);
toFile(idEncrypt,"/Users/shen/Desktop/code.txt");
System.out.println(idEncrypt);
String idDecrypt = decrypt(idEncrypt);
toFile(new String(idDecrypt),"/Users/shen/Desktop/des.txt");
System.out.println(idDecrypt);
*/
} }

最新文章

  1. ReactJS入门(四)—— 组件API
  2. UVa 458 - The Decoder
  3. 爬网页?--Chrome帮你计算XPath
  4. java网络编程基础
  5. Digital Image Processing 学习笔记3
  6. 手机端APP原型相关
  7. homework01
  8. Log4j简单配置
  9. 201521123049 《JAVA程序设计》 第2周学习总结
  10. 关于Mysql下使用Dapper QueryFirstOrDefault的问题
  11. 一起聊聊什么是P问题、NP问题、NPC问题
  12. CF908G New Year and Original Order 数位DP
  13. 20175324 《Java程序设计》第3周学习总结
  14. python基础之Day20part1
  15. .net中 登录 才能下载文件的方法 Response.WriteFile实现下载
  16. CSS定位方法
  17. free命令常用参数详解
  18. Android--将实体类转化成Json和Map的基类
  19. js实现放大缩小页面
  20. vue-cli 引入阿里巴巴字体图标:注意点

热门文章

  1. css一些记录
  2. QDir的mkdir和mkpath区别
  3. favicon.ico文件简介
  4. eval解析JSON字符串的一个小问题
  5. 求解最大矩形面积 — leetcode 85. Maximal Rectangle
  6. unity3d 我的面试经历
  7. 学习SQLite之路(四)
  8. css的active事件在手机端不生效的解决方法
  9. NPOI2.0学习(三)
  10. Verilog代码规范I