Base64以及關於Base64遇到的坑

常用的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&timestamp=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);  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章