常用的Java加密技術和核心代碼系列:
Base64以及關於Base64遇到的坑 https://blog.csdn.net/haponchang/article/details/106094115
消息摘要算法 https://blog.csdn.net/haponchang/article/details/106096542
對稱加密(DES、3DES、AES、PBE) https://blog.csdn.net/haponchang/article/details/106096766
非對稱加密(RSA、DH) https://blog.csdn.net/haponchang/article/details/106097998
數字簽名證書 https://blog.csdn.net/haponchang/article/details/106098779
使用Base64
public String encode(String src)
{
byte[] encodeBytes = Base64.getEncoder().encode(src.getBytes());
return new String(encodeBytes);
}
public String decode(String src)
{
byte[] decodeBytes = Base64.getDecoder().decode(src.getBytes());
return new String(decodeBytes);
}
Base64編碼對應關係表
使用Base64可能遇到的坑
1,編碼格式問題,encode或decode是getBytes()的編碼不一致導致結果不一致
public class Base64Strategy {
public String encode(String src) throws UnsupportedEncodingException {
byte[] encodeBytes = Base64.getEncoder ( ).encode (src.getBytes ("utf-8"));
return new String (encodeBytes);
}
public String encode2(String src) throws UnsupportedEncodingException {
byte[] encodeBytes = Base64.getEncoder ( ).encode (src.getBytes ("GBK"));
return new String (encodeBytes);
}
public String decode(String src) throws UnsupportedEncodingException {
byte[] decodeBytes = Base64.getDecoder ( ).decode (src.getBytes ());
return new String (decodeBytes);
}
public static void main(String[] args) {
String ps = "密碼";
Base64Strategy b = new Base64Strategy ( );
String encodePs = null;
String decode = null;
try {
encodePs = b.encode (ps);
System.out.println ("encode:utf-8 " + encodePs);
decode = b.decode (encodePs);
System.out.println ("decode:utf-8 " + decode);
encodePs = b.encode2 (ps);
System.out.println ("encode:GBK " + encodePs);
decode = b.decode (encodePs);
System.out.println ("decode:utf-8 " + decode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace ( );
}
}
}
結果
2. jdk版本不同導致結果不一致
JDK1.7與JDK1.8 base64的結果可能不一樣,因爲1.7的編解碼有換行符,1.8沒有。
在對接一個第三方api接口時,對方的JDK8編碼與我方線上JDK版本要保持一致(通常見於簽名部分)
如果不方便更換JDK也可以強行去掉空格,上代碼
package com.test.strategy;
import sun.misc.BASE64Decoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
public class Base64EncodeDemo {
public static final String CHARSET_UTF_8 = "UTF-8";
public static final String ALGORITHM_RSA = "RSA";
public static final String ALGORITHM_SHA1_WITH_RSA = "SHA1withRSA";
private static String signWithRSAJdk7(String source, String privateKey, String algorithm) {
String result = null;
try {
// 修改爲 1.7語法
// PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec (new BASE64Decoder ( ).decodeBuffer (privateKey));
KeyFactory keyFactory = KeyFactory.getInstance (ALGORITHM_RSA);
PrivateKey pk = keyFactory.generatePrivate (spec);
Signature signature = Signature.getInstance (algorithm);
signature.initSign (pk);
signature.update (source.getBytes (CHARSET_UTF_8));
// 修改爲 1.7語法
//result = Base64.getEncoder().encodeToString(signature.sign());
result = new sun.misc.BASE64Encoder ( ).encode (signature.sign ( ));
System.out.println ("jdk7解碼簽名換行符去掉前:" + result);
// 1.7語法需要去掉換行符 這裏是重點
result = result.replaceAll ("\\n", "");
System.out.println ("jdk7解碼簽名換行符去掉後:" + result);
} catch (Exception e) {
System.out.println ("RSA 簽名出錯!");
e.printStackTrace ( );
}
return result;
}
private static String signWithRSAJdk8(String source, String privateKey, String algorithm) {
String result = null;
try {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec (Base64.getDecoder ( ).decode (privateKey));
KeyFactory keyFactory = KeyFactory.getInstance (ALGORITHM_RSA);
PrivateKey pk = keyFactory.generatePrivate (spec);
Signature signature = Signature.getInstance (algorithm);
signature.initSign (pk);
signature.update (source.getBytes (CHARSET_UTF_8));
result = Base64.getEncoder ( ).encodeToString (signature.sign ( ));
System.out.println ("jdk8解碼簽名:" + result);
} catch (Exception e) {
System.out.println ("RSA 簽名出錯!");
e.printStackTrace ( );
}
return result;
}
public static void main(String[] args) throws Exception {
String source = "app_id=89be0bb80a7a4e219b4011168c478f0c&biz_content={\"user_id\":\"17681865480\",\"idcard\":\"09612707419874225X\",\"name\":\"張三\",\"mobile\":\"17681865480\"}&format=JSON&method=moxie.api.risk.magicwand3.enhance-multi-info&sign_type=RSA×tamp=1567593061041&version=1.0";
String privatekey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDjAKaU7DbXOMoa63pF1ArcyMPWmMxmmfpBlewFHDnqFee5Gm3XdLR+fvGj+ZwddEx27ZJkkjVoXmk1/NqT+9nFXvXSctfHu6OsmYaWguCCHDjMLzuWKhuTtFohFUJQLIyfuVImzGKPv1WMoPsjouz1trTXHwpF5oj0mqI1B0HZDBsb55Dyl3DkfIaZBkr7s0tuJ/LBIhengMp2gBc9d61Qr1S6mSAv1Hj6IrL34gkZv0U0+bdDO227/r14KS4MTaHudYM7fb43f0+VEcBXUKnQgR+f6yCq67JJyPaPQYtvrf+J6azrr1+hlX6FFGWNYwaKRblgg+b5ICw5hrR2H97LAgMBAAECggEAPH565isA/mAC9COWxS8Z6faSwgicSCd2mq3SZRY9lNVbmGejqAxQ4XkA+lrVsL/CdNsg7S5Nj0/BqAKHWXJ/eWqyBfBW8sJdfuy3AjtEi0fsFvXrYjw8dyNT9YcN0gHdQ9+GNhK3nWk26jAoXTnY/i4/iSibez9RdiYTXiBd+vIPXC/KpjyN8GXiDNg2Zc9aSK6M7Bqvy5w7QDyl+YHw55DIAjdXYkGR645xO3rhMaLcQ1SiUN0lvjKqGaHIjSYBPRjPuk4GFz6Ews0d+xdl3cMNodVosx3yNjKLTSYbJlwIYrcSMlBDjN3h6ZwY4znrehNuWAjhUvn0SI2NUupRAQKBgQD7BLyJXWsItGZPFTa8KBlg1GHphzmFXO6izZNb7CQPEklyDYKsrU2ZgMWtNJ2vDJ2d8PyzO5qILp8WUFOKgQTK7NJNemH1c2dcRVINRgiK5wN7xwp4mpm396X8flbArYYkHFXzFrt62DeJtvOWDgnUTETA/fvs2HdbUuQgLYBzSwKBgQDngeeTkKumR4NAFD7pC6galxB1vlzl3cAYQyCPE/DNo9INX+TmFPH1/JrSwSPUqC6KBTIJ2zkUpJm1XpGb4QZnlx4xNWwpjE+1fpjjer1a60t9V7Jur2DOiR83kzhE7NJ2ymnVv94v9wje1yhDnMyHY9KOppWeSIoam6XSB8+SgQKBgHHJd92c50QO4sG+kA1C8B4gqDHABqcZtWM/ZSkqJj5ev8Rfs3irJp4K7ZDSZRhQ07Ig56wnvKk22Q64YuZKDe4e5EYS0Az/vz7ofYVe1ciBZ+bYFzsMedoW/Ls0WgcFoeUEo0GKcHoDQUnAETNYMcR2vkPt3iFDDvfq31Zmye95AoGBALoQ1U/ryZnGBj49R2bEoKJmYatQiZeSR274nLWCIFsW3J81QGKP2PyMvt6+ro6fcXAqxtHXKSRnOsbjsAHptN0TPwfr2Pf3tqS3kCfcoU3uqOif0GBXgmXdHYLsRyBWer1Q6AkMwYYpdS6tHMZiwpvaZgOS7dOel6jVCkwpTPKBAoGBALu3R6ABaZx8c4C56ucL79akf1iw7s/3tpS3h3FJ5NzNeovtkmCuHosFWQkA4VKXQvL0S1zwWVd9/YJot5q05o5xn13yDhhmXqd8Da+ZMQJH0PMMyVlKF9tj7o6G5ZhFCTqZdVDdKE05De89d9ybNH3dGWU4ZycfbRa3pHmRuaHO";
String sign7 = signWithRSAJdk7 (source, privatekey, ALGORITHM_SHA1_WITH_RSA);
String sign8 = signWithRSAJdk8 (source, privatekey, ALGORITHM_SHA1_WITH_RSA);
// System.out.println(msg);
System.out.println ("--------------");
System.out.println (sign7.equals (sign8));
}
}
3. base64方法來自不同jar包
通常我們使用的是java.util.Base64;
但有的項目中會使用sun.misc.BASE64Decoder,不推薦。
如果已經使用,可引用 import org.apache.commons.codec.binary.Base64;進行替換
將
byte[] encrypted1 = new BASE64Decoder().decodeBuffer(text);
替換爲
import org.apache.commons.codec.binary.Base64;
byte[] encrypted1 =Base64.decodeBase64(text);