Java和go加密,解密,Base64失败

Posted 陳英傑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java和go加密,解密,Base64失败相关的知识,希望对你有一定的参考价值。

在客户端和go后台对接口的时候,加解密出现了问题记录。

问题主要出现在base64上,刚开始android使用

import android.util.Base64;

public class AesUtil 

	public static String encryptEcb(String content, String key) 
		if (TextUtils.isEmpty(content) || TextUtils.isEmpty(key)) return "";
        try 
            byte[] raw = key.getBytes("UTF-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance(format);
//            IvParameterSpec iv = new IvParameterSpec(getIv(key));// go后台没有使用向量
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8"));

            return Base64.encodeToString(encrypted, Base64.URL_SAFE);
         catch (Exception e) 
            e.printStackTrace();
            return "";
        
	

go的解密如下:

这里的URLEncoding对应Java的Base64.URL_SAFE,我们知道加密结果中含有3种特殊URL字符/,+,=(只有使用Base64.NO_PADDING模式加密的才没有=),所以这里使用URL_SAFE模式做替换,它是用-替换+,_替换/,=省略,替换好还原,但是=号不只一个找回就比较难了,上面第二张图就是go用来找回我们舍弃掉的=;其中的来龙去脉介绍完了,出问题的地方是Java的Base64.encodeToString出来的结果,go拿到之后decode失败,重点来了,为什么呢?
原因:Java的Base64的结果有一个特殊操作其他语言没有,下面这是Java的Base64结果

ZSDSpCpVGsZf6OAMDaIsyC1Ni2yOnYN1GT9MBTowuGcrYnrL0378CiJWR08lCSvSjnVqF_Bdg7xm
    ZHsP1QGRBKZUBoJJmepryh3jjNhlX9dLRweWIDqjvgZizmucw7NS3MvznJnaAdUkbB8rOcJWB3db
    NWqCTkYQB1AzUyzYky4oJYUJEtBx-RUhXCfYiMqGJ6_V53Xlbky8onJIkHgzmVopa7luko9ihLJY
    LPnOL65SrotvSAHHi_yRIjj2TprZtLH3X_mPjS9GLDoX6dAR-4vfuMwdeSCSpwKP8sq2XxOXXKVb
    r6xmIeVNY-miqBFEDSktj15KxnKADTWQDLJm6NW7tiwq6d0UkLIl0c9u7ViIxBbF3jCfWFulsCG5
    7kvyaE1jDHUjN-R7U0idW5WYLlyBPUvAoQnoXYZZPK2a9jgVoGB-OJpF99_HLbFPoJjN5nJMvPNq
    KCPXiqpkEgF1objdjJjq0JZNw5LhuxZoDPUrmhMlFYrhueyrIjh4rugDlnqp2uZig-ksQocKCQjg
    pGOZ6B_lWHWE5U_FZrhFLYE5hjBNcBiYn1qHV64Z2zkjKm6s5V7wBTXVZQKX6ahvzS4wJzzoarNF
    aStoxG4KM7q1Luv2tQU5ZjYvxYnE3ijJQqOl2UiYd2pv9fPF0eJche0R77tyViVBGrp7Fj79RBrP
    eTsZVnEQ14JojLSTHMiGkk88s8CiP1Mr0kKr6rtnXZsKgXc-8DlafrKfpU2aw1WfjlSFOrMkqF9V
    vs1Y5I3kuIzFBlyXf-9Akku4bNS1raVboYl3W8AefPcW3IF8QlZ904NCGwOwtNfIty0W0vKm

它里面包含换行符,这个就是go使用decode失败的原因,所以我们在和这些语言调试加解密之类的时候可以给换行符去掉,测试发现trim()不可以,使用replace("\\n", "")可以,这里自己写了一个Base64的工具类实现此功能:


import android.text.TextUtils;
import android.util.Base64;

public class Base64UrlSafe 

    private static char[] base64EncodeChars = new char[]'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
            '2', '3', '4', '5', '6', '7', '8', '9', '-', '_';

    private LzBase64() 
    

    public static String base64Encode(String data) 
        if (TextUtils.isEmpty(data)) 
            return "";
        
        byte[] dataBytes = data.getBytes();
        return encode(dataBytes);
    

    public static String base64Decode(String data) 
        if (TextUtils.isEmpty(data)) 
            return "";
        
        return new String(decode(data));
    

    public static String encode(byte[] data) 
        StringBuffer sb = new StringBuffer();
        int len = data.length;
        int i = 0;
        int b1, b2, b3;

        while (i < len) 
            b1 = data[i++] & 0xff;
            if (i == len) 
                sb.append(base64EncodeChars[b1 >>> 2]);
                sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
                sb.append(""); // "=="
                break;
            
            b2 = data[i++] & 0xff;
            if (i == len) 
                sb.append(base64EncodeChars[b1 >>> 2]);
                sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
                sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
                sb.append(""); //  "="
                break;
            
            b3 = data[i++] & 0xff;
            sb.append(base64EncodeChars[b1 >>> 2]);
            sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
            sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
            sb.append(base64EncodeChars[b3 & 0x3f]);


        

        return sb.toString();
    

    private static byte[] decode(String str) 
        return Base64.decode(str, Base64.URL_SAFE);
    


以上是关于Java和go加密,解密,Base64失败的主要内容,如果未能解决你的问题,请参考以下文章

JAVA如何解密用PHP加密的base64编码和RIJNDAEL 256的数据?

Java android DES+Base64加密解密

JAVA怎么样实现Base64加密解密?

Java Base64位加密和解密

Java基础加密之BASE64加解密

为啥我用Base64加密后,不能将它解密?