最近一直在做这方面的东西,先把实现放着,原理慢慢补。
因为jdk本身的加解密算法并不完整,所以需要添加以下两个库的支持。
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
一种可逆的算法,原文可以通过一组密钥被加密,然后通过这个密钥被还原回来。
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
public class AESCoder {
public static final String KEY_ALGORITHM = "AES";
public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
//转换密钥
private static Key toKey(byte[] key) throws Exception{
//实例化DES的材料
SecretKey secretKey = new SecretKeySpec(key,KEY_ALGORITHM);
return secretKey;
}
//解密
public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
//还原密钥
Key k = toKey(key);
//实例化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE,k);
//执行操作
return cipher.doFinal(data);
}
//加密
public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
//还原密钥
Key k = toKey(key);
//实例化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,k);
//执行操作
return cipher.doFinal(data);
}
//生成密钥
public static byte[] initKey() throws Exception{
//实例化
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
//要求密钥长度为256
kg.init(256);
//生成秘密密钥
SecretKey secretKey = kg.generateKey();
//获得秘密密钥
return secretKey.getEncoded();
}
public static void main(String args[]) throws Exception{
String str = "AES" ;
byte[] inputData = str.getBytes();
System.out.println("原文:"+str);
//初始化密钥
byte[] key = AESCoder.initKey();
System.out.println("密钥:"+ Base64.encodeBase64String(key));
//加密
inputData = AESCoder.encrypt(inputData,key);
System.out.println("加密后:"+ new String(Hex.encode(inputData)));
//解密
byte[] outputData = AESCoder.decrypt(inputData,key);
String outstr = new String(outputData);
System.out.println(outstr);
}
}
一组不可逆的hash算法,基于MD4演变而来。
import org.bouncycastle.util.encoders.Hex;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHACoder {
//SHA-256加密算法
public static byte[] encodeSHA(byte[] data){
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return md.digest(data);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
//输出16进制的哈希值
public static String encodeSHAHex(byte[] data){
byte[] b = encodeSHA(data);
return new String(Hex.encode(b));
}
}
一种非对称加密方式,密钥有两个二进制数据,一个作为公钥,一个作为私钥,二进制的数据可以被其中一个密钥加密,然后通过另外一个密钥解密。
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RSACoder {
public static final String KEY_ALGORITHM = "RSA";
//公钥名称
private static final String PUBLIC_KEY = "RSAPublicKey";
//私钥名称
private static final String PRIVATE_KEY = "RSAPrivateKey";
//RSA密钥长度
//默认是1024
//密钥长度必须在64位
//范围在512 ~ 65536之间
private static final int KEY_SIZE = 1024 ;
//私钥解密
public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
//取得私钥
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
//公钥解密
public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception{
//取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成公钥
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
//私钥加密
public static byte[] encryptByPrivateKey(byte[] data,byte[] key) throws Exception{
//取得私钥
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
//公钥加密
public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{
//取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
//生成公钥
PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
//对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
//取得私钥
public static byte[] getPriavteKey(Map<String,Object> keymap) throws Exception{
Key key = (Key)keymap.get(PRIVATE_KEY);
return key.getEncoded();
}
//取得公钥
public static byte[] getPublicKey(Map<String,Object> keymap) throws Exception {
Key key = (Key)keymap.get(PUBLIC_KEY);
return key.getEncoded();
}
//初始化密钥
public static Map<String,Object> initKey() throws Exception{
//实例化密钥对生成
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
//初始化密钥对生成器
keyPairGen.initialize(KEY_SIZE);
//生成密钥对
KeyPair keyPair = keyPairGen.generateKeyPair();
//公钥
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
//私钥
RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
//封装密钥
Map<String,Object> keyMap = new HashMap<>(2);
keyMap.put(PUBLIC_KEY,publicKey);
keyMap.put(PRIVATE_KEY,privateKey);
return keyMap;
}
public static void main(String args[]) throws Exception{
//初始化密钥
Map<String,Object> keymap = RSACoder.initKey();
byte[] publickey = RSACoder.getPublicKey(keymap);
byte[] privatekey = RSACoder.getPriavteKey(keymap);
System.out.println(Base64.encodeBase64String(publickey));
System.out.println(Base64.encodeBase64String(privatekey));
//校验
//私钥加密,公钥解密
String inputstr = "whthomas";
//加密
byte[] encodedeData1 = RSACoder.encryptByPrivateKey(inputstr.getBytes(),privatekey);
System.out.println(Base64.encodeBase64String(encodedeData1));
//解密
byte[] decodedeData1 = RSACoder.decryptByPublicKey(encodedeData1,publickey);
System.out.println(new String(decodedeData1));
//公钥加密,私钥解密
//加密
byte[] encodedeData2 = RSACoder.encryptByPublicKey(inputstr.getBytes(), publickey);
System.out.println(Base64.encodeBase64String(encodedeData2));
//解密
byte[] decodedeData2 = RSACoder.decryptByPrivateKey(encodedeData2, privatekey);
System.out.println(new String(decodedeData2));
}
}
加解密过程中可能会出现这种错误
Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
这是由于一些法律法规的限制,jdk源码包中减弱的加密的强度。
解决这个问题可以从Oracle网站上下载一个压缩文件
将这个包解压,把里面的两个jar包:local_policy.jar 和 US_export_policy.jar 替换掉原来Java安装目录{JAVA_HOME}/jre/lib/security 下的两个jar包接就可以了。