細心的開發會發現,我們在下載文件時,會帶有密文,這是幹嘛的呢,是用來校驗下載的文件完整性和正確性,防止文件被篡改。
如下圖:
加解密測試代碼:
package com;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
public class Test {
//DES也可以用,要保證明文字節數爲8字節
private final static String CIPHER_ALGORITHM_AES = "AES";
private final static String CIPHER_ALGORITHM_RSA = "RSA";
private final static String KEY_CHARSET_NAME = "ASCII";
private final static String PLAIN_TEXT_CHARSET_NAME = "UTF-8";
public static void main(String[] args) throws Exception {
//測試的明文
String str = "hello world";
//明文密鑰
String aesKey = "1";
//MD5,常用於校驗網絡上下載的文件的完整性和正確性
String md5 = DigestUtils.md5Hex(new FileInputStream(new File("D://apache-activemq-5.15.10-bin.tar.gz")));
System.out.println("MD5:" + md5 + ",位數:" + md5.length());
//SHA512,常用於校驗網絡上下載的文件的完整性和正確性
String sha512 = DigestUtils.sha512Hex(new FileInputStream(new File("D://apache-activemq-5.15.10-bin.tar.gz")));
System.out.println("SHA512:" + sha512 + ",位數:" + sha512.length());
System.out.println();
System.out.println("明文:" + str);
//base64
//編碼
String base64Encode = new String(Base64.encodeBase64(str.getBytes()));
System.out.println("------------------base64編碼,解碼-----------------------------");
System.out.println("base64編碼:" + base64Encode);
//解碼
String base64Decode = new String(Base64.decodeBase64(base64Encode.getBytes()));
System.out.println("base64解碼:" + base64Decode);
System.out.println();
//AES/DES,加解密
String enctrypt = aesEncrypt(str, aesKey);
System.out.println("------------------AES加解密-----------------------------");
System.out.println("密文:" + enctrypt);
System.out.println("明文:" + aesDecrypt(enctrypt, aesKey));
System.out.println();
//RSA,非對稱加解密
String publicKey = getPublicKey(aesKey);
String privateKey = getPrivateKey(aesKey);
System.out.println("------------------RSA公鑰,私鑰,對明文生成公鑰和私鑰,公鑰加密,私鑰解密,或者私鑰加密,公鑰解密-----------------------------");
System.out.println("RSA公鑰:" + publicKey);
System.out.println("RSA私鑰:" + privateKey);
//公鑰加密
String encStr = RSAencrypt(str, publicKey);
//私鑰解密
String decStr = RSAdecrypt(encStr, privateKey);
System.out.println("-------------------------------------------------------");
System.out.println("RSA密文:" + encStr);
System.out.println("RSA明文:" + decStr);
}
/**
* RSA公鑰加密
*
* @param str
* @param publicKey
* @return
* @throws Exception
*/
public static String RSAencrypt(String str, String publicKey) throws Exception {
//base64編碼的公鑰
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey)KeyFactory.getInstance(CIPHER_ALGORITHM_RSA).generatePublic(
new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_RSA);
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(PLAIN_TEXT_CHARSET_NAME)));
return outStr;
}
/**
* rsa私鑰解密
*
* @param str
* @param privateKey
* @return
* @throws Exception
*/
public static String RSAdecrypt(String str, String privateKey) throws Exception {
//64位解碼加密後的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes(PLAIN_TEXT_CHARSET_NAME));
//base64編碼的私鑰
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey)KeyFactory.getInstance(CIPHER_ALGORITHM_RSA).generatePrivate(
new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_RSA);
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
}
private static String getPublicKey(String slatKey) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CIPHER_ALGORITHM_RSA);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(slatKey.getBytes());
keyPairGenerator.initialize(1024, random);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
}
/**
* 根據slatKey獲取私匙,傳入的slatKey作爲SecureRandom的隨機種子
*/
private static String getPrivateKey(String slatKey) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CIPHER_ALGORITHM_RSA);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(slatKey.getBytes());
keyPairGenerator.initialize(1024, random);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
}
/**
* 加密
*
* @param plainText
* @param aesKey
* @return
*/
private static String aesEncrypt(String plainText, String aesKey) {
try {
SecretKey key = generateAesKey(aesKey, KEY_CHARSET_NAME);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_AES);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainBytes = plainText.getBytes(PLAIN_TEXT_CHARSET_NAME);
byte[] cipherBytes = cipher.doFinal(plainBytes);
return new String(Hex.encodeHex(cipherBytes));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解密
*
* @param content
* @param aesKey
* @return
*/
private static String aesDecrypt(String content, String aesKey) {
try {
SecretKey key = generateAesKey(aesKey, KEY_CHARSET_NAME);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_AES);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptBytes = Hex.decodeHex(content.toCharArray());
byte[] plainBytes = cipher.doFinal(encryptBytes);
return new String(plainBytes, PLAIN_TEXT_CHARSET_NAME);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static SecretKeySpec generateAesKey(final String key, final String encoding) {
try {
final byte[] finalKey = new byte[16];
int i = 0;
for (byte b : key.getBytes(encoding)) {
finalKey[i++ % 16] ^= b;
}
return new SecretKeySpec(finalKey, CIPHER_ALGORITHM_AES);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}