android studio 使用base64_密码学 | Base64是加密算法吗?

3f68a88e9e00de23ce6788d93e94845c.png

前言

  • 对网络通信有所了解的同学,应该都听过Base64编码。例如,我们一段数据通过MD5 、SHA等手段加密后,经过Base64编码为字符串就可以很方便地在网路上传输。那么Base64也算是一种加密算法吗?
  • 在这篇文章里,我将带你理解Base64的基本原理 & 实现,希望能帮上忙

系列文章

  • 《密码学 | Base64是加密算法吗?》
  • 《密码学 | 什么是散列算法?》

延伸文章

  • 《计算机组成原理 | Unicode 和 UTF-8 是什么关系?》

目录

d5d3f2ad2bd17bd67d0e2af621275b44.png

1. 基本原理

Base64是一种将二进制流表示为 64 个字符的编码方式。标准的 Base64 使用的索引表为:

4278c54ad27d4b8aeb2c773a42785062.png

举个例子,字符串"Base64 编码"经过编码后的结果为:QmFzZTY0IOe8lueggQ==。当然,这里隐含了以UTF-8作为字符编码的前提,如果使用了其他的字符编码方式,用Base64编码后就不是这个结果了。很多在线编解码的网站其实也是默认使用了UTF-8,但是没有明确说明。

1.1 标准 Base64 编码步骤

下面解释一下Base64的编码步骤: - 步骤1:数据输入 在这一步骤,需要将原数据(字符串、图片、音频等任何数据)转换为二进制流。例如前面举的字符串的例子,则需要经过字符编码转换为二进制流。

  • 步骤2:分组转换
  • 从二进制流头部开始,每 6 位为一组,若不足 6 位,则低位补0
  • 每 6 位组成一个新的字节,高位 2 位补 0 ,此时已经获得二进制的Base64编码
  • 步骤3:转换为字符串 将二进制的Base64编码每个字节映射为一个字符,例如0000 0000映射为 A0011 1111映射为/,此时已经获得Base64编码字符串
  • 步骤4:末尾补位 标准Base64编码字符串的长度为 4 的倍数,否则,在末尾补充=。例如前面的QmFzZTY0IOe8lueggQ==长度就是补充了两个=后,长度为 20。

整个编码步骤并不复杂,我们用一张示意图表示为:

29f3bfc40c4b8d147cfbb1a13201580f.png

1.2 非标准 Base64

  • Url Base 64 标准Base 64中使用了'/',这在URL和文件系统中存在冲突,因此延伸出 Url Base64 算法,主要就是将'+''/'符号替换成了'-''_'符号。
  • MIME Base 64 这是一种MIME友好格式,它输出每行为 76 个字符,每行末需追加回车换行符rn,不论每行是否够 76 个字符,都要添加一个回车换行符

1.3 意义

Base64能够将任何数据转换为易移植的字符串,避免了传输过程中失真问题。最初,Base64是为了解决电子邮件中无法直接使用非ASCII字符的问题。一段数据先经过Base64编码为ASCII字符串后,可以在接收端,通过Base64解码还原为原数据后,而无需担心传输过程中失真。

很多时候,我们都将Base64编码作为数据加密后的传输 / 存储格式。例如,一段明文数据通过MD5 、SHA等手段加密后,经过Base64编码为字符串,就可以很方便地进行传输 & 存储。再比如,网络上的数字证书其实也是使用Base64编码的形式传输的,我们可以在浏览器上查看百度官网的数字证书:

  • 1、 查看百度官网的数字证书

27a7a483abd63c175d5f0e29ad989aa6.png
  • 2、将证书保存到本地

44c17d9c164f3dddfd0f4d212f5440d3.png
  • 3、证书以 Base64 编码格式存储

df5ce853eca6566fceeb6c8632064611.png

需要注意的是,Base64并不是一种加密方式,明文使用Base64编码后的字符串通过索引表可以直接还原为明文。因此,Base64只能作为一种数据的存储格式。


2. 算法实现

2.1 Java 环境

Java 8之前,JDK中并没有提供Base64的算法实现,这其实挺让人纳闷的。虽然源码中sun.misc.BASE64Encoder,但是它其实并不是公有 API,而是 sun 团队内部使用的 API,最好不要在生产中使用。从Java 8,JDK 总算是补充了Base64的实现,例如:

import java.util.Base64;

标准 Base 64
System.out.println(Base64.getEncoder().encodeToString("".getBytes()));

Url Base 64
System.out.println(Base64.getUrlEncoder().encodeToString("".getBytes()));

MIME Base 64
System.out.println(Base64.getMimeEncoder().encodeToString("".getBytes()));

Java 8之前,Bouncy CastleApache也提供了Base64的算法实现。

2.2 Android环境

Android SDK提供了Base64的算法实现,例如:

import android.util.Base64;

System.out.println(Base64.encodeToString("".getBytes(),Base64.DEFAULT));

相对于Java 8的算法实现,Android提供的 API 更为灵活,可以通过flag自定义控制算法的输出。


3. 总结

  • Base 64能够将任何数据转换为易移植的字符串,避免了传输过程中失真问题。
  • 需要注意的是,Base 64不是一种加密方式,只是一种编码方式。很多时候,我们都将Base64编码作为数据加密后的传输 / 存储格式

参考资料

  • 《Java加密与解密的艺术》(第5章) —— 梁栋 著
  • 《HTTP权威指南》 —— [美] David Gourley,Brian Totty等 著
  • 《Base64》 —— 维基百科

推荐阅读

  • Java | 带你理解 ServiceLoader 的原理与设计思想
  • Java | 请概述一下 Class 文件的结构
  • Java | 聊一聊编译过程(编译前端 & 编译后端)
  • Java | 为什么 Java 实现了平台无关性?
  • Android | 一个进程有多少个 Context 对象(答对的不多)
  • Android | 带你理解 NativeAllocationRegistry 的原理与设计思想
  • Android | 一文带你全面了解 AspectJ 框架
  • 计算机组成原理 | Unicode 和 UTF-8是什么关系?
  • 计算机组成原理 | 为什么浮点数运算不精确?(阿里笔试)

感谢喜欢!你的点赞是对我最大的鼓励!欢迎关注彭旭锐的GitHub!

a851e01bbdee5c29273d48b5dd40b588.png
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值