Java加密解密(二) Base64编码

1. Base64的由来

Base64最早用于解决电子邮件传输问题。由于“历史问题”,早期的电子邮件网关只允许传输ASCII(二进制为00000000-01111111)字符,如果有非ASCII字符经过这种网关时, 字符的二进制位可能会被篡改(如将10000001改为00000001)。由此产生了Base64编码来保证非ASCII字符的传输。

2. 原理

Base64顾名思义是一种基于64个字符的编码算法。
如下是Base64的字符映射表,详情参见RFC 2045

Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y

其中的value是10进制的值,Encoding是与之相对应的编码字符

因为Base64中共有64个字符,所以只需要6个bit就可以表示一个base64字符(*1<<6=64*)。另外,由于计算机基本处理单位为字节,所以字符编码是以字节为单位对字符进行编码,比如,字符’A’的ASCII编码为01000001,汉字’你’的UTF-8编码为11100100 10111101 10100000, GBK编码为11000100 11100011。由此,Base64的编码步骤如下:
step1 将待转码字符串以某种编码格式(如UTF-8)进行编码,得到一个字节数组
step2 将字节数组按三个字节为一组进行分组(24个bit)
step3 将每个分组按6 bit进行划分(不足6位时低位补0),得到N(*2<=N<=4*)个6位二进制码(以下称为Base64编码单元)。
step4 将每个Base64编码单元转换为10进制值,并根据上表得到相应的Base64编码字符,不足4个编码单元的分组要用=进行填充。

Base64编码过程示例 -
原始字符串 我x
UTF-8编码,分组 0xe6 0x88 0x91; 0x78
二进制表示 11100110, 10001000, 10010001; 01111000
划分编码单元 111001,101000,100010,010001; 011110,0000000(补位)
Value 57,40,34,17; 30,0
对应Encoding 5,o,i,R; e,A, =,=(填充符)
最终结果 5oiReA==

3. 用途

1) 保存二进制数据,如密钥等。
2) 使用Http协议在url中传输二进制数据。
将Base64编码中不符合URL规定的字符替换成其他合法的字符,并去掉回车换行就得到了UrlBase64编码。经过UrlBase64编码,就可以将二进制参数直接放在url中。
这些功能也可以用hex编码实现,但base64编码的结果要比hex结果短。

4. 实现

jdk中的类sun.misc.BASE64Encodersun.misc.BASE64Decoder提供了Base64的编码解码实现,但jdk中sun开头的包是sun公司的内部实现,该包下的代码不保证与其他jave平台的兼容性(见Why Developers Should Not Write Programs That Call ‘sun’ Packages),所以需要使用第三方实现,也可将这两个类复制到自己的代码中。
笔者测试环境中使用的maven依赖如下:

    <!--bouncycastle依赖-->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk16</artifactId>
        <version>1.46</version>
    </dependency>
    <!--commons-codec-->
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.10</version>
    </dependency>

4.1 BouncyCastle实现

org.bouncycastle.util.encoders下提供了工具类Base64,UrlBase64与Hex用于Base64,UrlBase64与hex编码/解码操作。

final String charset="UTF-8";
String input="Base64编/解码";
//编码
String encoded=new String(Base64.encode(input.getBytes(charset)),"ASCII");
String urlSafeEncoded=new String(UrlBase64.encode(input.getBytes(charset)),"ASCII");
//解码
Assert.assertEquals(input,new String(Base64.decode(encoded),charset));
Assert.assertEquals(input,new String(UrlBase64.decode(urlSafeEncoded),charset));

4.2 commons-codec实现

工具类org.apache.commons.codec.binary.Base64提供了Base64与UrlBase64的编码解码方法。

final String charset="UTF-8";
String input="Base64编/解码";
String encoded= Base64.encodeBase64String(input.getBytes(charset));
String urlSafeEncoded=Base64.encodeBase64URLSafeString(input.getBytes(charset));
Assert.assertEquals(input, new String(Base64.decodeBase64(encoded), charset));
Assert.assertEquals(input, new String(Base64.decodeBase64(urlSafeEncoded), charset));

4.3 BouncyCastle与commons-codec区别

标准Base64编码后的字符串每76个字符为一行(称为分块),行尾要添加一个回车换行符“\r\n”。但bouncycastle并没有这样做,而commons-codec支持标准实现,但默认并没有使用。

++++++++++++ BouncyCastle commons-codec
标准(分块)编码 不支持 Base64.encodeBase64ChunkedBase64.encodeBase64(binaryData, true)
UrlBase64 没有回车换行,‘+’变为’-‘, ’/‘变为’_‘, ’=‘变为’.’ 与bouncyCastle相同,但去掉了填充符
时间: 2024-08-03 22:14:53

Java加密解密(二) Base64编码的相关文章

java加密基础(一) —— BASE64编码

工作之后第一次接触到java加密机制,当时需求是使用RSA做数字签名.当时看到之后一脸懵逼,就查了各种资料. 对于学习过程中我走了不少弯路,主要是因为不知道先看什么在看什么.下面说一下我的学习经历 首先,要了解BASE64算法,因为java加密基本上都用到了BASE64:然后就是对称加密和非对称加密了(下一章节着重介绍,这里就不多做描述了):最后就是了解下数字签名(会在第三章节中介绍到) 我们都知道ASCII字符一共有256,而计算机记录数据的方式只有0.1,所以就只能使用8bit才能表示一个A

Java加密解密与数字证书的操作

1 keytool命令总结 一.创建数字证书 交互模式 使用默认的密钥库.keystore(文件夹是c: Documents and Settingusername)和算法(DSA) keytool -genkey 默认的别名mykey 密钥库中能够存放多个条目(公钥/私钥对和证书),它们在密钥库中以别名(alias)区分. [plain] view plaincopy keytool -genkey -alias mytest -keyalg RSA -keysize 1024 -keysto

java加密解密算法位运算

一.实例说明 本实例通过位运算的异或运算符 “ ^ ” 把字符串与一个指定的值进行异或运算,从而改变每个字符串中字符的值,这样就可以得到一个加密后的字符串.当把加密后的字符串作为程序输入内容,异或运算会把加密后的字符串还原为原有字符串的值.效果图如下: 二.实现过程 1 package com.itxxz; 2 3 import java.util.Scanner; 4 5 /** 6 * java加密解密算法 7 * 8 * @author 螃蟹 9 * 网站:IT学习者 10 * 网址:ht

Java加密解密字符串

http://www.cnblogs.com/vwpolo/archive/2012/07/18/2597232.html Java加密解密字符串 旧文重发:http://www.blogjava.net/vwpolo/archive/2009/12/05/304874.html#383365 import java.security.Key; import java.security.Security; import javax.crypto.Cipher; /** * DES加密和解密工具,

Java 加密解密之对称加密算法AES

Java 加密解密之对称加密算法AES 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准.2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一.该算法

Java加密解密(一)Java加密体系基础

Java加密解密(一)Java加密体系基础 1. JCA(Java Cryptography Architecture) 提供基本的加密框架,如证书,数字签名,消息摘要和密钥对生成器.其主要实现在java.security包中. 2. JCE(Java Cryptography Extension) 在JCA的基础了作了扩展,提供了各种加密算法.消息摘要算法和密钥管理等功能.JDK提供的JCE实现主要在javax.crypto包中.第三方提供的JCE也称为安全提供者.由于出口限制,可能需要一个或

密码学——Java 加密解密基础

Java  加密解密基础 密码学是研究编制密码和破译密码的技术科学.研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学:应用于破译密码以获取通信情报的,称为破译学,总称密码学. 密码学常用术语 明文: 待加密数据. 密文: 明文经过加密后数据. 加密: 将明文转换为密文的过程. 加密算法: 将明文转换为密文的转换算法. 加密密钥: 通过加密算法进行加密操作的密钥. 解密: 将密文转换为铭文的过程. 解密算法: 将密文转换为明文的转换算法. 解密密钥: 通过解密短发进行解密操作的密

java加密解密和证书的demo

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.KeyPa

密码学4——Java 加密解密之消息摘要算法(MD5 SHA MAC)

Java 加密解密之消息摘要算法(MD5 SHA MAC) 消息摘要 消息摘要(Message Digest)又称为数字摘要(Digital Digest).它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生.如果消息在途中改变了,则接收者通过对收到消息的新产生的摘要与原摘要比较,就可知道消息是否被改变了.因此消息摘要保证了消息的完整性.消息摘要采用单向Hash 函数将需加密 的明文"摘要"成一串128bit的密文,这一串密文亦称为数字指纹(