base64:(兼容所有bit8位的字符,然后用64种字符进行转码,达到一致性)
意思就是:考虑到多语言原因,有的特殊字符传输不兼容,因为很多都是只支持ASSIC码,那么特殊字符就会找不到对应的ASSIC码,所以采用BASE64 可以叫全天下所有字符用 64中字符表示,而且这64种字符都在 ASSIC 中,所以在网络传输中很流行。
特点:
首先这算法是编码, 不是压缩, 编码后只会增加字节数;
算法简单, 几乎不会影响效率;
算法可逆, 解码很方便, 不用于私密信息通信;
虽然解码方便, 但毕竟编码了, 肉眼还是不能直接看出原始内容;
加密后的字符串只有[0-9a-zA-Z+/=], 不可打印字符(包括转移字符)也可传输;
AES 对称加密算法
这是加密算法,base64只是编码,不是加密,AES 加密和解密效率高,双方必须使用同一个秘钥,如果不考虑秘钥被偷窃,那么AES 是很安全的
代码:
private static final String PRIVATE_KEY = "P9F4D5AGV214D56AFD231AF5D6SA4FDS";
private static final String ARITHMETIC = "AES";
// 秘钥自定义,算法必须是关键字 AES 或者 AES/ECB/PKCS5Padding,还没有找到第三种
public static String AESEncode(String privateKey,String content){
try {
// 根据密钥生成AES密钥
SecretKey key = new SecretKeySpec(privateKey.getBytes(), ARITHMETIC);
// 获取密码器实例
Cipher cipher = Cipher.getInstance(ARITHMETIC);
// 初始化 AES 密码器
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] doFinal = cipher.doFinal(content.getBytes(UTF_8));
return new BASE64Encoder().encode(doFinal);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String AESDecode(String privateKey, String content){
try {
// 根据密钥生成AES密钥
SecretKey key = new SecretKeySpec(privateKey.getBytes(), ARITHMETIC);
// 获取密码器实例
Cipher cipher = Cipher.getInstance(ARITHMETIC);
// 初始化 AES 密码器
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] doFinal = cipher.doFinal(new BASE64Decoder().decodeBuffer(content));
return new String(doFinal,UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Test
public void fun1(){
String secret = AESEncode(PRIVATE_KEY, "我是快乐的程序员!");
System.out.println(secret);
String content = AESDecode(PRIVATE_KEY, secret);
System.out.println(content);
}
由于秘钥在 A 给B 的时候,容易泄露,所以出现非对称加密
RSA 非对称加密
概念:如果B只给A传加密数据,那么B需要A给的公钥,B用这个公钥进行加密,A用自己对应的私钥解密即可
场景问题:
公钥是公开的,大家都可以给A传数据,A都能用自己的私钥解开(因为大家都是用对应且公开
的公钥加密的),那么A就不晓得到底哪个才会B发送的,所以就有了签名
签名:就是用私钥签名(说白了就是用私钥加密,只有公钥才能解开)
为了让A知道是B发送的,所以B需要给A自己的公钥(这个公钥不是上面说的公钥,而是B提供的
另一套公私-钥匙)
解决方案:
1 A有一套公-私钥,B也有一套公私要,A把自己的公钥给B,B把自己的公钥给A
2 B给A传数据text,首先用A给的公钥加密(防止别的看到)
3 B 再将加密的结果 用B自己的私钥签名(因为公钥在A,如果A解开了,说明A晓得就是B发送的)
其实B的公钥不但A有,大家都是公开的,所以大家都可以解开,都知道是B发送的,但是B在
发送前用A的公钥加密了,所以对大家而言,虽然解开了第一层,还有第二层加密
4 A收到消息,必须先用B的公钥解签,成功了(这里只能证明,这个东西是B发送的),然后再用自己
的私钥解密(因为B用A的公钥加密,所以A肯定可以用自己的私钥解开),这样就完美了
注意:非对称加密性能比堆成加密差很多,为了两者结合,所以对称加密的私钥,用非对称加密方式传输(刚刚说了,决定安全),安全获得到对称私钥后,A 和 B 的通信都用 这个对称私钥进行加解密,效率得到解决。
对称秘钥是自定义
但是非对称的公-私钥可不能自定义,因为公钥和私钥肯定是一一对应的,生成规则:
生成密钥对,在linux下
1. 生成私钥 (也可以用2048,但是加密过程负责)
openssl genrsa -out private.pem 1024
2. 生成公钥
openssl rsa -in private.pem -pubout -out public.pem
3. 私钥转码
(某些语言需要pkcs8格式的公钥, 否则报错
Java报错:java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence)
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform PEM -nocrypt
将1,2,3步后得到的密钥对作为公私密钥
代码:
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import mons.codec.binary.Base64;
public class RSACodeUtil {
public static final String KEY_ALGORTHM = "RSA";
private static final String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2R1XOJeXrCYAsKOHA7ELiIVzrfrFI7eD9LexmFe0Gs2i47zhoicTUP2MKvU5/s14Ze0fLeDe8hG8To+hL7oviTH4MF8SpY+lojj7vUMBzeu3v5Q1Px2VW1eNJ0aE7Bs1V7+LMYl/tjWIQbaFHxEXfguzb9X0o/SANSwS5cUyVzQIDAQAB";
private static final String privateKeyStr = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALZHVc4l5esJgCwo4cDsQuIhXOt+sUjt4P0t7GYV7QazaLjvOGiJxNQ/Ywq9Tn+zXhl7R8t4N7yEbxOj6Evui+JMfgwXxKlj6WiOPu9QwHN67e/lDU/HZVbV40nRoTsGzVXv4sxiX+2NYhBtoUfERd+C7Nv1fSj9IA1LBLlxTJXNAgMBAAECgYAFm2woS0InWMN4mElZhesIyb3yAJOzip3BLAh5m3MPIbW2+qThkltbrBd/3RLtGrdqUUCEIc6VHf3MvN4Id+4VmriQdTFi9SEr7GxVGJbHAstQrKfglyFPDhYTIFikDvxl4D98cEXy74Epr5wwgnQbQFi8+Z+Wp+vt5UW/MPSkgQJBAN9wT17D2rEW+VC8xJnJ8tAEfZDDUDvqfL8BQ0NXQri7HGYvsFMSax5rek5cjJVPangKUImOY3+5M/xf3geSbYMCQQDQ134F+a1c9t9KrqwfGx/1yoeqkXWDHJsunMrR38KC1q/OGR4fQOlcKDaILFXEucvXla2pUkqhpRgjg8hGs15vAkEAqj75ytvyMsKtfm4GYqN0Jjl1ryqSZMS6/hIpPRMs3HJ9JgMqF3HOOqRr0W9FErMrDYHWcakTeQsVaDNnil9wnwJAZ7Y8bXc6suoepZXtAF2WF5gGm5w1AXGZVyKiTmuSyysWj4FFxjuUKCIIQsPRrCqgomVAos+tJG06eZieQw4cnQJATuVeuGSu8zy8cm2r93KZ+mlqSu7ijwY2BjRI/1rqWF4dhScfZ+aLw72O7I8yPbeKEOWRZuHfzLEajOA3b4/wCg==";
private static String encrypt(String content, PrivateKey privateKey) throws Exception{
String encodeContent = null;
Cipher cipher = Cipher.getInstance( "rsa" );
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
Base64 base64 = new Base64();
byte [] cipherData = cipher.doFinal(content.getBytes());
encodeContent = base64.encodeToString(cipherData);
return encodeContent;
}
private static String decrypt(String content, PublicKey publicKey) throws Exception{
Base64 base64 = new Base64();
byte[] byteArray = base64.decodeBase64(content);
String decodeContent = null;
Cipher cipher = Cipher.getInstance( "rsa" );
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte [] cipherData = cipher.doFinal(byteArray);
return new String(cipherData);
}
private static PrivateKey getPrivateKey(String privateKeyStr2) throws Exception {
byte[] keyBytes = decryptBASE64(privateKeyStr2);
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory;
keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
return privateKey;
}
private static PublicKey getPublicKey(String publicKey) throws Exception{
byte[] keyBytes = decryptBASE64(publicKey);
//构造X509EncodedKeySpec对象
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
//指定加密算法
KeyFactory keyFactory;
keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);
return publicKey2;
}
private static byte[] decryptBASE64(String keys) {
Base64 base64 = new Base64();
return base64.decode(keys);
}
public static String encode(String content) throws Exception{
return encrypt(content, getPrivateKey(privateKeyStr));
}
public static String decode(String content) throws Exception{
return decrypt(content, getPublicKey(publicKeyStr));
}
public static void main(String[] args) {
try {
String content = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
// String content = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
String code = encode(content);
System.out.println("code:"+code);
String content2 = decode(code);
System.out.println("content:"+content2);
} catch (Exception e) {
e.printStackTrace();
}
}
}