Cipher類介紹
此類為加密和解密提供密碼功能蛀柴。它構(gòu)成了 Java Cryptographic Extension (JCE) 框架的核心。
Cipher類是一個引擎類驼修,它需要通過getInstance()工廠方法來實(shí)例化對象渴肉。為創(chuàng)建 Cipher 對象,應(yīng)用程序調(diào)用 Cipher 的 getInstance 方法并將所請求轉(zhuǎn)換 的名稱傳遞給它景殷。還可以指定提供者的名稱(可選)。
之后通過其init方法初始化它的模式 (加密 / 解密) 澡屡, update方法進(jìn)行數(shù)據(jù)塊的加密猿挚。
例如:
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
生成秘鑰
Java的java.security算法內(nèi)置了很多加密算法,比如AES驶鹉,DES绩蜻,RSA等。
使用這些算法需要用專門的秘鑰對象SecretKey室埋。
密鑰生成可以使用KeyGenerator生成秘鑰办绝,保存這個秘鑰的方式有3種:
- 通過ObjectOutputStream把這個KeyGenerator保存下來;
- 通過一般的OutputStream把秘鑰的字節(jié)保存下來姚淆;
- 把秘鑰的字節(jié)進(jìn)行BASE64處理成字符串孕蝉;
下面有一個簡單實(shí)例。
public static String generateKey(final String Algorithm) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
SecureRandom random = new SecureRandom();
keyGenerator.init(random);
SecretKey key = keyGenerator.generateKey();
byte[] bytes = key.getEncoded();
return Base64.getEncoder().encodeToString(bytes);
}
會生成形如0ZRmCCkKnd4eO/QoU8X0uA==的字符串
文件的加解密
Java內(nèi)置的CipherOutputStream流可以對流對象進(jìn)行自動加密解密腌逢,用起來很方便降淮。
但是我在使用的過程發(fā)現(xiàn)一個問題,就是文件的最后幾個字節(jié) (不足16字節(jié)的那部分) 可能存在丟失搏讶,所以我進(jìn)行了小小的改進(jìn)骤肛,當(dāng)加密到文件的最后一個數(shù)據(jù)塊時纳本,調(diào)用cipher的doFinal方法,這樣可以有效避免字節(jié)丟失問題腋颠。
具體實(shí)現(xiàn)如下:
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class CryptoCipher {
private static final int ENCRYPT_MODE = Cipher.ENCRYPT_MODE;
private static final int DECRYPT_MODE = Cipher.DECRYPT_MODE;
private static final int BLOCK_SIZE = 1024;
public static String generateKey(final String Algorithm) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
SecureRandom random = new SecureRandom();
keyGenerator.init(random);
SecretKey key = keyGenerator.generateKey();
byte[] bytes = key.getEncoded();
return Base64.getEncoder().encodeToString(bytes);
}
private static void Encode_Decode(final int MODE,InputStream is, OutputStream os, String keyStr) {
try {
byte[] bytes = Base64.getDecoder().decode(keyStr);
SecretKey key = new SecretKeySpec(bytes, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(MODE, key);
CipherOutputStream out = new CipherOutputStream(os, cipher);
byte[] buff = new byte[BLOCK_SIZE];
int length;
while ((length = is.read(buff)) != -1) {
if (length == BLOCK_SIZE)
out.write(buff, 0, length);
else {
byte[] finalBytes = cipher.doFinal(buff, 0, length);
os.write(finalBytes);
}
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
}
public static void encode(InputStream is, OutputStream os, String keyStr) {
Encode_Decode(ENCRYPT_MODE, is, os, keyStr);
}
public static void decode(InputStream is, OutputStream os, String keyStr) {
Encode_Decode(DECRYPT_MODE, is, os, keyStr);
}
}