Base64自定义编码表及破解

什么是Base64

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64并不是安全领域的加密算法,其实Base64只能算是一个编码算法,对数据内容进行编码来适合传输。标准Base64编码解码无需额外信息即完全可逆,即使你自己自定义字符集设计一种类Base64的编码方式用于数据加密,在多数场景下也较容易破解。Base64编码本质上是一种将二进制数据转成文本数据的方案。对于非二进制数据,是先将其转换成二进制形式,然后每连续6比特(2的6次方=64)计算其十进制值,根据该值在A--Z,a--z,0--9,+,/ 这64个字符中找到对应的字符,最终得到一个文本字符串。

Base64 编码要求把 3 个 8 位字节(3x8=24)转化为 4 个 6 位的字节(4x6=24),之后在 6 位的前面补两个 0 ,形成 8 位一个字节的形式。 如果剩下的字符不足 3 个字节,则用 0 填充,输出字符使用 ‘=’,因此编码后输出的文本末尾可能会出现 1 或 2 个 ‘=’。

java实现

public abstract class Base64 {
	private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
			.toCharArray();

	public static String encode(byte[] data) {
		int start = 0;
		int len = data.length;
		StringBuilder buf = new StringBuilder(data.length * 3 / 2);

		int end = len - 3;
		int i = start;
		int n = 0;

		while (i <= end) {
			int d = ((((int) data[i]) & 0x0ff) << 16)
					| ((((int) data[i + 1]) & 0x0ff) << 8)
					| (((int) data[i + 2]) & 0x0ff);

			buf.append(legalChars[(d >> 18) & 63]);
			buf.append(legalChars[(d >> 12) & 63]);
			buf.append(legalChars[(d >> 6) & 63]);
			buf.append(legalChars[d & 63]);

			i += 3;

			if (n++ >= 14) {
				n = 0;
				buf.append(" ");
			}
		}

		if (i == start + len - 2) {
			int d = ((((int) data[i]) & 0x0ff) << 16)
					| ((((int) data[i + 1]) & 255) << 8);

			buf.append(legalChars[(d >> 18) & 63]);
			buf.append(legalChars[(d >> 12) & 63]);
			buf.append(legalChars[(d >> 6) & 63]);
			buf.append("=");
		} else if (i == start + len - 1) {
			int d = (((int) data[i]) & 0x0ff) << 16;

			buf.append(legalChars[(d >> 18) & 63]);
			buf.append(legalChars[(d >> 12) & 63]);
			buf.append("==");
		}

		return buf.toString();
	}

}

复制代码

自定义 Base64 编码表及破解

标准的base64编码表是A--Z,a--z,0--9,+,/,但是我们完全可以替换这64个字符或者打乱顺序,这样只有我们知道编码表才能解码。通过拼接0~63的6位2进制字符串,然后分割转换成长度为48的byte数组,便可以得到编码表。详细步骤如下:

  • 计算出0-63这64个数字的6位2进制数,转换成字符串拼接成一个完整的字符串,长度就是64x6
  • 将字符串每8个(1byte就是8位)一组,分割成48份,48x8
  • 通过Integer.parseInt(binaryString, 2)解析成数字,再强转成byte
  • 对这个长度为48的byte数组进行编码
  • 编码的结果就是编码表了
public class test {

    public static void main(String[] args) {

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 64; i++) {
            stringBuilder.append(binary2decimal(i, 6));
        }

        byte[] byteDecode = new byte[48];
        System.out.println(stringBuilder.toString());
        for (int i = 0; i < 48; i++) {
            String binaryString = stringBuilder.substring(i * 8, (i + 1) * 8);
            byteDecode[i] = (byte) Integer.parseInt(binaryString, 2);
        }
        System.out.println(Base64.encode(byteDecode));

    }

    //十进制转换为指定位数的二进制
    private static String binary2decimal(int decNum, int digit) {
        StringBuilder binStr = new StringBuilder();
        for (int i = digit - 1; i >= 0; i--) {
            binStr.append((decNum >> i) & 1);
        }
        return binStr.toString();
    }

}
复制代码

打印如下:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567 89+/
复制代码

猜你喜欢

转载自juejin.im/post/5c120d36f265da6172655a4c
今日推荐