字节数组Base64和16进制编码对比

前言

最近在开发的一个项目涉及到国密改造。国密算法有多种,常用的有SM2SM3SM4,分别对应非对称加密(RSA等)、消息摘要(MD5、SHA等)、对称加密(AES、DES、3DES等)。
底层国密类库,都是采用byte数组进行加密换算,而在应用层,通常需要将byte数组进行转换,以便将数据进行传输和处理。

问题

将byte数组进行不同编码格式转换,会存在多种问题。例如:

  • 将byte数组转成ASCII编码,必须确保byte数组的值在ASCII的可视字符范围,否则会出现乱码,因为ASCII的取值范围比byte小(0~255)。
  • 将byte数组转成UTF8等其他类型编码,也有可能导致转换后的String长度与byte数组长度不同,因为不同的编码格式,占用的byte个数不同。
  • 可以将byte数组转成Base64编码。
  • 可以将byte数组转成Hex的16进制字符串,一个byte占8位,正好对应两个16进制的字符。

后面两种方式在密码学中比较常用,能很好的解决byte数组转换过程中的乱码问题。然而后两种方式也有需要注意的地方,例如:
【1】Base64编码后会在结果中出现+号,如果直接拼接在url后面进行get请求,接收方在解码的时候,很有可能会被自动转换成空格,导致错误结果。+号变空格的解决方案有两种,第一种采用post方式传输,因为body内容通常都会进行application/x-www-form-urlencoded;第二种主动调用urlencode方法对字符串进行url编码,再使用get请求。
【2】将byte数组转成16进制字符串的时候,得到的结果会比Base64编码长,在传输过程中数据量更大。因为传输过程通常都是将string转成utf8传输,不同长度的string,对应的utf8字节数组长度当然不同。

1
BMtED46hiTpdTKirGEiLDCexCOy/Ztqk06L7vwuGkIEnaP0u00QF1XchLlztdb8khitlwzYdTTAQ/Ng01fJN3UEBib1LsvLO6Muk4zCxCDU/vP9KkiFVXOaqP/df3l8ar085uiLjRXj27iUrnvx4

1
04CB440F8EA1893A5D4CA8AB18488B0C27B108ECBF66DAA4D3A2FBBF0B8690812768FD2ED34405D577212E5CED75BF24862B65C3361D4D3010FCD834D5F24DDD410189BD4BB2F2CEE8CBA4E330B108353FBCFF4A9221555CE6AA3FF75FDE5F1AAF4F39BA22E34578F6EE252B9EFC78

总结

1、同样长度的byte数组转换,Base64比HexString更短,传输过程更有优势。
2、HexString不需要处理特殊字符,更加方便。
只要处理好了Base64过程中+号可能变空格的问题,使用Base64进行通信,比采用16进制的String更优。