java实现Base64编码与解码


前言

Base64算法并不是真正意义上的加密算法。不过在加密与解密方面经常看到它的身影,比如Base64算法常作为密钥、密文和证书的的一种通用存储编码格式。这是笔者在加解密算法这一系列文章中引入它的原因。


一、Base64的3种实现方式

1.Jdk8实现

public class JdkBase64 {
    public static void main(String[] args) {
        String encode = jdkBase64Encode();
        jdkBase64Decode(encode);
    }

    private static String jdkBase64Encode() {
        String result = Base64.getEncoder().encodeToString("helloWorld".getBytes(StandardCharsets.UTF_8));
        System.out.println(result);
        return result;
    }

    private static void jdkBase64Decode(String src) {
        byte[] decode = Base64.getDecoder().decode(src.getBytes(StandardCharsets.UTF_8));
        System.out.println(new String(decode, StandardCharsets.UTF_8));
    }
}

2.Bouncy Castle实现

引入jar包

<dependency>
     <groupId>org.bouncycastle</groupId>
     <artifactId>bcprov-jdk15on</artifactId>
     <version>1.67</version>
</dependency>

代码

public class CastleBase64 {
    public static void main(String[] args) {
        String encode = encode();
        decode(encode);
    }

    private static String encode() {
        String result = Base64.toBase64String("helloWorld".getBytes(StandardCharsets.UTF_8));
        System.out.println(result);
        return result;
    }

    private static void decode(String src) {
        byte[] decode = Base64.decode(src.getBytes(StandardCharsets.UTF_8));
        System.out.println(new String(decode, StandardCharsets.UTF_8));
    }
}

3.Commons Codec实现

引入jar包

<dependency>
   <groupId>commons-codec</groupId>
   <artifactId>commons-codec</artifactId>
   <version>1.14</version>
</dependency>

代码

public class CodecBase64 {
    public static void main(String[] args) {
        String encodeStr = encode();
        System.out.println(encodeStr);
        decode(encodeStr);
    }

    private static String encode() {
        byte[] result = Base64
                .encodeBase64("helloWorld".getBytes(StandardCharsets.UTF_8));
        return new String(result, StandardCharsets.UTF_8);
    }

    private static void decode(String encodeStr) {
        byte[] decode = Base64.decodeBase64(encodeStr);
        System.out.println(new String(decode, StandardCharsets.UTF_8));
    }
}

二、什么是Base64算法

Base64算法是一种基于64个字符的编码算法,根据RFC2045的定义:

The Base64 Content-Transfer-Encoding is designed to represent arbitrary sequences of octets in a form that need not be humanly readable.

经过Base64编码后的数据会比原来数据略长,为原来的4/3倍。编码后的字符串的字符数是以4位单位的整数倍。
在RFC 2045文件中给出的字符映射表如下:
在这里插入图片描述
这张字符映射表中,Value指的是十进制编码,Encoding指的是字符,共映射了64个字符,这也是该算法命名的由来。映射表的最后一个字符是等号,是用来补位的,看到有一串字符以等号结尾的,基本上会联想到Base64

三、原理简述

Base64算法主要是将给定的字符以字符编码(如ASCII码,UTF-8)对应的十进制为基准,做编码操作:

  1. 将给定的字符串转换成对应的字符编码(如ASCII码)
  2. 将获得的字符编码转换成二进制码
  3. 对获得的二进制码做分组转换:每3个8位二进制码为一组,转换为每4个6位的二进制码(不足6位补0)
  4. 对获得4-6二进制码进行补位,向6位二进制码添加2位高位0,组成4个8位二进制码
  5. 将获得的4-8二进制码转换成十进制码
  6. 将获得的十进制码转换成Base64字符表中对应的字符。

1.ASCII字符编码推导

步骤结果
原文字符B
ASCII码66
8位二进制码01000010
4-6二进制码010000 100000
4-8二进制码00010000 00100000
十进制码16 32
字符表映射码Q g
进行补位Qg==

当原文的二进制码长度不足24位,最终转换成十进制码时也不足4项,就需要用等号补位


2.非ASCII码字符推导

ASCII码可以表示十进制范围为0~127的字符,对应的二进制范围是0000 0000 ~ 0111 1111。ASCII码包括阿拉伯数字、大小写英文字母和一些控制符,没有包含双字节编码的字符如中文字符。UTF-8编码使用3个字节表示一个汉字。
下面对中文进行推导

步骤结果
原文字符
UTF-8码字节-27 -91 -67
8位二进制码11100101 10100101 10111101
4-6二进制码111001 011010 010110 111101
4-8二进制码00111001 00011010 00010110 00111101
十进制码57 26 22 61
字符表映射码5aW9

3.推导工具类

按照以上的步骤,可以使用以下工具类,找到转换后的十进制码,最后在对照Base64编码表,即可得到映射码。最后结果可以以上面提到的实现方式进行比较。

public class BinaryUtil {
    public static void main(String[] args) {
        byte[] bytes = utfByte("好"); // 根据utf-8编码字节
        for (byte eachByte : bytes) {
            String binary = byteToBinary(eachByte); // 转换成二进制
            System.out.println(eachByte + ":" + binary);
        }
        System.out.println(binaryToDecimal("00011010")); // 二进制装换成十进制
    }

    public static byte[] utfByte(String msg) {
        return msg.getBytes(StandardCharsets.UTF_8);
    }

    public static String byteToBinary(byte src) {
        return Integer.toBinaryString((src & 0xFF) + 0x100).substring(1);
    }

    public static Map<Byte, String> stringToBinary(String src) {
        Map<Byte, String> result = new HashMap<Byte, String>();
        for (byte each : src.getBytes()) {
            result.put(each, byteToBinary(each));
        }
        return result;
    }

    public static int binaryToDecimal(String src) {
        return Integer.parseInt(src, 2);
    }
}

总结

Base64加密解密经常用到。不过其并不是真正意义上的加密解密算法。通过上面的原理推导,知道一串Base64编码的字符串完成能够找到其原码。所以,对于实际需要传输个人数据和敏感信息,Base64不适用此场景。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值