Apache Commons Codec 也就那样吧!!!

1,514 阅读5分钟

杨超越~35.jpg

一、简介

  commons-codec是Apache开源组织提供的用于摘要运算、编码解码的包,常见的编码解码工具Base64、MD5、Hex、SHA1、DES等。常规加密解密算法它由一组实用程序和一个用于编码和解码文本和二进制数据的简单框架组成。
Apache Commons Codec 编解码器的形成是为了将开发工作集中在一种确定的 Base64 编码器实现上。在该编解码器开发之时,大约有 34 种不同的 Java 类用于处理遍布 Apache 软件基金会 CVS 存储库的 Base64 编码。虽然这个包包含一个用于创建编码器和解码器的抽象框架,但 Codec 本身主要侧重于提供用于处理常见编码的功能实用程序。

  • 二进制编码器
    • Base32:定义了 Base32 的编码和解码
    • Base32InputStream:以流的方式(无限大小)提供 Base32 编码和解码
    • Base64:定义了 Base64 的编码和解码
    • Base64InputStream:以流方式(无限大小)提供base 64编码和解码
    • BinaryCodec:在 “0” 和 “1” 的字节数组和字符串之间进行转换
    • Hex:转换十六进制字符串
  • 消息摘要编码器
    • DigestUtils:简化了常见的MessageDigest任务,并提供了与GNU libc crypt(3)兼容的密码哈希函数
  • 语言编码器
    • Caverphone 1.0:将字符串编码为 Caverphone 1.0 值。
    • Caverphone 2.0:将字符串编码为 Caverphone 2.0 值。
    • Cologne Phonetic:将字符串编码为科隆语音(Cologne Phonetic)值。
    • Double Metaphone:将字符串编码为双 Metaphone 值。
    • Metaphone:将字符串编码为Metaphone值。
    • Refined Soundex:将字符串编码为完善的Soundex值。
    • Soundex:将字符串编码为Soundex值。
  • 网络编码器
    • BCodec:与 RFC 1521 定义的 Base64 编码相同,并允许指定字符集。
    • QCodec:类似于 RFC 1521 中定义的 “加引号可打印的内容传输编码”,该设计旨在允许在 ASCII 终端上无需解码就可以解密包含大部分ASCII字符的文本。
    • Quoted Printable Codec:RFC 1521 的 Quoted-Printable 部分的编解码器。
    • URLCodec:实现 www-form-urlencoded 编码方案,也被误称为 URL 编码。

二、二进制编码器

2.1 Base64 编解码

2.1.1 什么是 Base64 编码

  Base64 编码是使用 64 个可打印 ASCII 字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成 ASCII 字符串;另外,还有一个 “=” 符号用作填充。
Base64 将输入字符串按字节切分,取得每个字节对应的二进制值(若不足 8 比特则高位补 0),然后将这些二进制数值串联起来,再按照 6 比特一组进行切分(因为 2^6 = 64),最后一组若不足 6 比特则末尾补 0。将每组二进制值转换成十进制,然后在 Base64 字符映射表格中找到对应的符号并串联起来就是 Base64 编码结果。
由于二进制数据是按照 8 比特一组进行传输,因此 Base64 按照 6 比特一组切分的二进制数据必须是 24 比特的倍数(6 和 8 的最小公倍数)。24 比特就是 3 个字节,如果不足 3 字节,则使用 “=” 进行填充。如下:

  • 若最后一组只有 1 个输入数据,则在编码结果后加 2 个=;
  • 若最后一组只有 2 个输入数据,则在编码结果后加 1 个 =。

2.1.2 Commons Codec 实现

  在 Apache Commons Codec 库中,提供了 Base64、Base64InputStream 和 Base64OutputStream 三个类实现 base64 编码和解码,这里主要以 Base64 说明,其他的基本没有使用过,故此不在浪费时间了,让我们先看下 Base64 的构造方法。

public Base64(int lineLength,byte[] lineSeparator,boolean urlSafe,CodecPolicy decodingPolicy)
  • lineLength:每行编码数据最多为给定长度(四舍五入为最接近的 4 的倍数)。如果 lineLength <= 0,则输出将不会分为几行。
  • lineSeparator:每一行编码数据将以此字节序列结尾。
  • urlSafe:我们将使用 “-” 和 “_” 字符分别替换 “+” 和 “/” 字符。urlSafe 参数仅仅适用于编码操作,解码可无缝处理两种模式。 注意:使用网址安全字母时,不会添加任何填充。
  • decodingPolicy:指定解码策略。

接下来,再看看几个常用的方法:

方法说明
byte[] decodeBase64(byte[] base64Data)将给定的数据 base64 解码
byte[] decodeBase64(String base64String)
BigInteger decodeInteger(byte[] pArray)根据诸如W3C的XML签名之类的加密标准对byte64编码的整数进行解码
byte[] encodeBase64(byte[] binaryData)使用base64算法对二进制数据进行编码
String encodeBase64String(byte[] binaryData)
byte[] encodeBase64(byte[] binaryData, boolean isChunked)使用base64算法对二进制数据进行编码
boolean isBase64(String base64)判断是否仅包含Base64字母内的有效字符
boolean isBase64(byte octet)
isBase64(byte[] arrayOctet)
isInAlphabet(byte octet)判断参数 octet 是否在 Base64 字母表中
isUrlSafe()返回当前的编码模式

最后,让我们看下示例:

@Test
public void testBase64() throws UnsupportedEncodingException {
	byte[] str = "hello world".getBytes("UTF-8");
	String encodeStr = Base64.encodeBase64String(str);
	System.out.println("Base64 编码后:" + encodeStr);
	String decodeStr = new String(Base64.decodeBase64(encodeStr));
	System.out.println("Base64 解码后:" + decodeStr);
}

2.2 十六进制转码

  在 Apache Commons Codec 中提供了 Hex 工具类,该类用来转换十六进制字符串。可以设置用于某些操作的字符集,默认值在DEFAULT_CHARSET_NAME中设置。此类是线程安全的。一如既往,首先来看下其构造方法:

/**
 * 使用默认字符集名称 DEFAULT_CHARSET 创建一个新的编解码器
 */
public Hex() {}

/**
 * 使用给定的字符集创建一个新的编解码器
 */
public Hex(Charset charset) {}

/**
 * 使用给定的字符集名称创建一个新的编解码器
 */
public Hex(String charsetName) {}

接下里,让我们具体看下常用的方法吧!

  • 使用 Hex 类的静态方法 encodeHexString() 和 decodeHex() 实现十六进制编码和解码

    @Test
    public void testHex() throws UnsupportedEncodingException, DecoderException {
    	byte[] str = "hello world".getBytes("UTF-8");
    	String hexString = Hex.encodeHexString(str);
    	System.out.println("Hex 编码后:" + hexString);
    	byte[] decodeHex2 = Hex.decodeHex(hexString.toCharArray());
    	System.out.println("Hex 编码后:" + new String(decodeHex2));
    }
    
  • 使用 Hex 的实例方法 encode() 和 decode() 实现十六进制编码和解码

    @Test
    public void testHex() throws UnsupportedEncodingException, DecoderException {
    	byte[] str = "hello world".getBytes("UTF-8");
    	Hex hex = new Hex();
    
    	// 将字符串字节数组使用十六进制表示
    	byte[] bytes = hex.encode(str);
    	String hexStr = new String(bytes);
    	System.out.println(hexStr);
    
    	// 将十六进制字符串解析成字节数组
    	byte[] result = hex.decode(hexStr.getBytes());
    	System.out.println(new String(result));
    }
    
  • 利用 Hex 类的 encodeHex() 和 decodeHex() 方法实现十六进制编码和解码

    @Test
    public void testHex() throws UnsupportedEncodingException, DecoderException {
    	byte[] str = "hello world".getBytes("UTF-8");
    	// 将 “hello” 字符串字节数组使用十六进制表示
    	String hexStr = new String(Hex.encodeHex(str));
    	System.out.println(hexStr);
    
    	// 将 “hello” 字符串字节数组使用十六进制表示
    	System.out.println(new String(Hex.decodeHex(hexStr.toCharArray())));
    }
    

三、消息摘要编码器

3.1 什么是消息摘要算法

  消息摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法或散列算法。消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。
消息摘要的特点

  • 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
  • 一般地,只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。
  • 只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息(不可逆性)。
  • 好的摘要算法,没有人能从中找到 “碰撞” 或者说极度难找到,虽然 “碰撞” 是肯定存在的(碰撞即不同的内容产

3.2 DigestUtils 类

3.2.1 介绍

  Apache Commons Codec 库提供了 DigestUtils 工具类,该类用于简化常见 MessageDigest(消息摘要)任务的操作。 此类是不可变的并且是线程安全的。 但是,它创建的 MessageDigest 实例通常不是线程安全的。
MessageDigestAlgorithms 类为标准消息摘要算法提供常量,提供了 DigestUtils 支持的消息摘要算法名称常亮。它可与 getDigest(String) 方法和其他需要摘要算法名称的方法一起使用。源码如下:

public class MessageDigestAlgorithms {
    public static final String MD2 = "MD2";
    public static final String MD5 = "MD5";
    public static final String SHA_1 = "SHA-1";
    public static final String SHA_224 = "SHA-224";
    public static final String SHA_256 = "SHA-256";
    public static final String SHA_384 = "SHA-384";
    public static final String SHA_512 = "SHA-512";
    public static final String SHA_512_224 = "SHA-512/224";
    public static final String SHA_512_256 = "SHA-512/256";
    public static final String SHA3_224 = "SHA3-224";
    public static final String SHA3_256 = "SHA3-256";
    public static final String SHA3_384 = "SHA3-384";
    public static final String SHA3_512 = "SHA3-512";
}

3.2.2 方法说明

DigestUtils 类还提供了很多静态方法,这些方法的名称命名跟具体的消息摘要算法相关。而且还重载了很多方法;它的参数可以是字节数组、字符串、文件、Buffer等。

方法说明
byte[] digest(String data)生成消息摘要
String digestAsHex(String data)生成消息摘要
MessageDigest getMessageDigest()获取当前实例中的 MessageDigest 实例对象
MessageDigest getDigest(String algorithm)获取 MessageDigest 消息摘要对象
boolean isAvailable(String messageDigestAlgorithm)验证是否支持给定的消息摘要算法
byte[] md5(String data)
String md5Hex(String data)
MD5 消息摘要算法
byte[] sha1(String data)
String sha1Hex(String data)
支持 SHA1 消息摘要算法
byte[] sha256(String data)
String sha256Hex(String data)
支持 SHA256 消息摘要算法
byte[] sha384(String data)
String sha384Hex(String data)
支持 SHA384 消息摘要算法
byte[] sha512(String data)
String sha512Hex(String data)
支持 SHA512 消息摘要算法

举例说明:

/**
 * MD5是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文
 */
@Test
public void testMD5() throws UnsupportedEncodingException {
	byte[] str = "hello world".getBytes("UTF-8");
	System.out.println("MD5 编码后:" + DigestUtils.md5Hex(str));
}

/**
 * 可以对任意长度的数据运算生成一个固定长度位数的数值
 */
@Test
public void testSHA() throws UnsupportedEncodingException {
	byte[] str = "hello world".getBytes("UTF-8");
	System.out.println("SHA1    编码后:" + DigestUtils.sha1Hex(str));
	System.out.println("SHA256 编码后:" + DigestUtils.sha256Hex(str));
	System.out.println("SHA384 编码后:" + DigestUtils.sha384Hex(str));
	System.out.println("SHA512 编码后:" + DigestUtils.sha512Hex(str));
}

四、网络编码

  Apache Commons 库中的 URLCodec 类,使用该类实现 “www-form-urlencoded” 编码方案,也被误称为 URL 编码。该编解码器旨在替代旧 Java 平台上的标准 Java 类 URLEncoder 和 URLDecoder,因为 1.4 以下 Java 版本中的这些类依赖于平台的默认字符集编码。从 1.11 版本开始,此类是线程安全的。

在工作中貌似没怎么使用到,也不想再做过多的说明,若是想查看其详细用法,请参考官网 API 文档,地址如下:commons.apache.org/proper/comm…