赞
踩
Base64算法并不是真正意义上的加密算法。不过在加密与解密方面经常看到它的身影,比如Base64算法常作为密钥、密文和证书的的一种通用存储编码格式。这是笔者在加解密算法这一系列文章中引入它的原因。
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)); } }
引入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)); } }
引入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算法是一种基于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)对应的十进制为基准,做编码操作:
步骤 | 结果 |
---|---|
原文字符 | B |
ASCII码 | 66 |
8位二进制码 | 01000010 |
4-6二进制码 | 010000 100000 |
4-8二进制码 | 00010000 00100000 |
十进制码 | 16 32 |
字符表映射码 | Q g |
进行补位 | Qg== |
当原文的二进制码长度不足24位,最终转换成十进制码时也不足4项,就需要用等号补位
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 |
按照以上的步骤,可以使用以下工具类,找到转换后的十进制码,最后在对照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不适用此场景。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。