细心的开发会发现,我们在下载文件时,会带有密文,这是干嘛的呢,是用来校验下载的文件完整性和正确性,防止文件被篡改。
如下图:
加解密测试代码:
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);
}
}
}