为啥Base64编码有回车换行符

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥Base64编码有回车换行符相关的知识,希望对你有一定的参考价值。

The encoded output stream must be represented in lines of no more than 76 characters each.

Base64一行不能超过76字符,超过则添加回车换行符。

结合前面博客说的“有回车符,导致JSON格式不符合要求”,那就明白了,对附件进行Base64编码,因为超过76字节,所以要添加回车换行符,后台解析带有回车换行符的JSON字符串就出现“ net.sf.json.JSONException : Unterminated string ”。

问题根源就是回车换行符,那删除就行了,谷歌后又发现一问题,原来“回车换行符(\\r\\n)”是在Windows才有,而Linux只有换行(\\n),Mac只有回车(\\r)。

找到了解决办法,调用字符串对象的replaceAll方法替换掉\\r和\\n,代码如下:

字符串对象.replaceAll("\\r|\\n", "");

这样就兼容了不同平台。

参考技术A 如果需要上传附件,将附件转成字节流,再用Base64编码,最后和文章参数一起放入JSON对象。

问题:如果上传附件,后台将字符串解析成JSON对象时出现如下异常:

net.sf.json.JSONException: Unterminated string

有博客说,字符串中有回车换行符,导致JSON格式不符合要求。

用debug查看JSON字符串确实有回车换行符:

谷歌了一下,原来是RFC2045中有规定:

The encoded output stream must be represented in lines of no more than 76 characters each.

Base64一行不能超过76字符,超过则添加回车换行符。

结合前面博客说的“有回车符,导致JSON格式不符合要求”,那就明白了,对附件进行Base64编码,因为超过76字节,所以要添加回车换行符,后台解
析带有回车换行符的JSON字符串就出现“ net.sf.json.JSONException : Unterminated string ”。

问题根源就是回车换行符,那删除就行了,谷歌后又发现一问题,原来“回车换行符(\r\n)”是在Windows才有,而Linux只有换行(\n),Mac只有回车(\r)。

再搜索了一下找到了解决办法,调用字符串对象的replaceAll方法替换掉\r和\n,代码如下:

字符串对象.replaceAll("\r|\n", "");

这样就兼容了不同平台。

安卓逆向 -- 算法基础(Base64与HEX)

    一、Base64

1、所有的数据都能被编码为只用65个字符就能表示的文本。

标准的Base64每行为76个字符,每行末尾添加一个回车换行符(\\r\\n)。不论每行是否满76个字符,都要添加一个回车换行符。

2、65字符:A~Z a~z 0~9 + / =

URL Base64算法中,为了安全,会把 + 替换成 - ,把 / 替换成 _

= 有时候用 ~ 或 . 代替

3、Base64的应用

密钥、密文、图片、数据简单加密或者预处理

4、正常的Base64编码与解码

package com.company;import java.nio.charset.StandardCharsets;import java.util.Base64;import java.util.zip.Deflater;public class Main {    public static void main(String[] args) {        System.out.println("逆向有你");        String bs= "逆向有你a";        String enbs=Base64.getEncoder().encodeToString(bs.getBytes(StandardCharsets.UTF_8));        System.out.println("逆向有你base64编码:"+enbs);        String debs= new String(Base64.getDecoder().decode(enbs));        System.out.println("逆向有你base64解码码:"+debs);    }}运行结果:逆向有你逆向有你base64编码:6YCG5ZCR5pyJ5L2gYQ==逆向有你base64解码码:逆向有你a

二、自己编写Base64算法

1、新建一个java类

2、源码如下

package com.company;public class zbase64 {    private static final char[] Base64ByteToStr = {'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 static final int RANGE = 255;    private static byte[] StrToBase64Byte = new byte[128];    public static String Base64Encode(byte[] bytes) {        StringBuilder res = new StringBuilder();        for (int i = 0; i <= bytes.length - 1; i += 3) {            byte[] enBytes = new byte[4];            byte tmp = 0;            for (int k = 0; k <= 2; k++) {                if (i + k <= bytes.length - 1) {                    enBytes[k] = (byte) (((bytes[i + k] & 255) >>> ((k * 2) + 2)) | tmp);                    tmp = (byte) ((((bytes[i + k] & 255) << (((2 - k) * 2) + 2)) & 255) >>> 2);                } else {                    enBytes[k] = tmp;                    tmp = 64;                }            }            enBytes[3] = tmp;            for (int k2 = 0; k2 <= 3; k2++) {                if (enBytes[k2] <= 63) {                    res.append(Base64ByteToStr[enBytes[k2]]);                } else {                    res.append('=');                }            }        }        return res.toString();    }}主函数调用:String zbx = zbase64.Base64Encode(bs.getBytes(StandardCharsets.UTF_8));System.out.println("自编写base64加密:"+zbx);运行结果:自编写base64加密:6YCG5ZCR5pyJ5L2gYQ==

三、Hex

二进制数据最常用的一种表示方式。用0-9 a-f 16个字符表示。每个十六进制字符代表4bit。也就是2个十六进制字符代表一个字节。在实际应用中,尤其在密钥初始化的时候,一定要分清楚自己传进去的密钥是哪种方式编码的,采用对应方式解析,才能得到正确的结果

public static String bytes2HexString(byte[] b) {    StringBuffer result = new StringBuffer();    for (int i = 0; i < b.length; i++) {        result.append(String.format("%02X",b[i]));    }    return result.toString();}public static byte[] hexString2Bytes(String src) {    int l = src.length() / 2;    byte[] ret = new byte[l];    for (int i = 0; i < l; i++) {        ret[i] = Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();    }    return ret;}主函数调用String hexbm=bytes2HexString(bs.getBytes(StandardCharsets.UTF_8));System.out.println("十六进制编码:"+hexbm);byte[] bytes = hexString2Bytes(hexbm);String hexjm=new String(bytes);System.out.println("十六进制解码:"+hexjm);运行结果:十六进制编码:E98086E59091E69C89E4BDA061十六进制解码:逆向有你a

禁止非法,后果自负

欢迎关注公众号:逆向有你

欢迎关注视频号:之乎者也吧

以上是关于为啥Base64编码有回车换行符的主要内容,如果未能解决你的问题,请参考以下文章

Base64编码后包含换行符问题

Base64编码出现换行符

BASE64解码之中文乱码问题

[编码解码] Base64 编码换行和+号遍空格的处理

PHP - 添加/删除回车返回到 base 64 编码的字符串

base64的MIME