標籤:generate overflow 阻塞 關於 sys 指定 www. 使用 encode
使用AES演算法的時候,會發現下面的代碼在windows每次產生確定的結果,但Linux就不同,導致無法正確解密
public static String encrypt(String content, String password) { try { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128, new SecureRandom(password.getBytes())); SecretKey secretKey = kgen.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");// 建立密碼器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化 byte[] result = cipher.doFinal(byteContent); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); random.setSeed(password.getBytes()); kgen.init(128, random); return parseByte2HexStr(result); // 加密 } catch (Exception e) { System.out.print(e); } return null;}
原因在於加紅的部分SecureRaom的產生,Linux下預設的演算法是“NativePRNG”, 而windows下預設是“SHA1PRNG”(sun提供的演算法)
對於這兩種演算法
相同點: 1. 都是偽隨即演算法, 2. 預設都是阻塞式不同點: 1. SHA1PRNG使用的seed是在系統啟動時就指定的,而NativePRNG會在核心中隨機取得(這也是Linux下每次結果不同的原因) 2. 正是因為每次隨機取,NativePRNG開銷要更大些
雖然Linux認為最佳隨機演算法是NativePRNG(安全因素),但使用每次都變化的radom是無法正確解密的,所以並不適用於此種場合。
解決辦法
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );secureRandom.setSeed(password.getBytes());kgen.init(128, secureRandom);
另外,這兩種演算法都是阻塞式演算法,會讀取/var/random,如果想非阻塞,啟動時加上下面參數
Djava.security=file:/dev/urandom
參考:
http://www.cjsdn.net/Doc/JDK50/java/security/SecureRandom.html
https://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html
http://calvin1978.blogcn.com/articles/securerandom.html
https://stackoverflow.com/questions/27622625/securerandom-with-nativeprng-vs-sha1prng
關於 java中的SecureRandom在linux中每次產生不同結果