Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个位元为一个单元,对应某个可打印字符。三个字节有24个位元,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后binhex的版本使用不同的64字符集来代表6个二进制数字,但是它们不叫Base64。【摘自维基百科】
为了保证所输出的编码位可读字符,Base64制定了一个编码表,以便进行统一转换。编码表的大小为2^6=64,这也是Base64名称的由来。
Base64编码表
Java代码中Base64的使用示例:
package cn.com.base64; import java.io.IOException; public class Test { /** * 编码 * @param bstr * @return String */ public static String encode(byte[] bstr){ return new sun.misc.BASE64Encoder().encode(bstr); } /** * 解码 * @param str * @return string */ public static byte[] decode(String str){ byte[] bt = null; try { sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder(); bt = decoder.decodeBuffer( str ); } catch (IOException e) { e.printStackTrace(); } return bt; } /** * @param args */ public static void main(String[] args) { /* Test te = new Test(); String aa = "hello world"; System.out.println("加密前:"+aa); aa = te.encode(aa.getBytes()); System.out.println("经过BASE64加密后:"+aa); String str = aa; String str2 = new String(te.decode(str)); System.out.println("经过BASE64解密后:"+str2); */ }
说明:第一次在Eclipse中引入BASE64Encoder /BASE64Decoder类,无法引入,解决办法请参 考:http://blog.csdn.net/a0501bqzhxy/article/details/6441526
运行后的结果:
加密前:hello world
经过BASE64加密后:aGVsbG8gd29ybGQ=
经过BASE64解密后:hello world
一步步解读Base64的执行过程:
Base64的编码都是按字符串长度,以每3个8bit的字符为一组,然后针对每组,首先获取每个字符的ASCII编码,然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节,然后再将这24bit划分为4个6bit的字节,并在每个6bit的字节前面都填两个高位0,得到4个8bit的字节。然后将这4个8bit的字节转换成10进制,对照Base64编码表(下表),得到对应编码后的字符。(注:1. 要求被编码字符是8bit的,所以须在ASCII编码范围内,\u0000-\u00ff,中文就不行。 2. 如果被编码字符长度不是3的倍数的时候,则都用0代替,对应的输出字符为=
例1)字符长度为能被3整除时:
ASCII: 84 111 109
8bit字节: 01010100 01101111 01101101
6bit字节: 010101 000110 111101 101101
十进制: 21 6 61 45
对应编码: V G 9 t
例2)字符串长度不能被3整除时,比如“Lucy”:
L u c y ASCII: 76 117 99 121 8bit字节: 01001100 01110101 01100011 01111001 00000000 00000000 6bit字节: 010011 000111 010101 100011 011110 010000 000000 000000 十进制: 19 7 21 35 30 16 (异常) (异常) 对应编码: T H V j e Q = =说明:由于Lucy只有4个字母,所以按3个一组的话,第二组还有两个空位,所以需要用0来补齐。这里就需要注意,因为是需要补齐而出现的0,所以转化成十进制的时候就不能按常规用base64编码表来对应,所以不是a,可以理解成为一种特殊的“异常”,编码应该对应“=”。
接下来解读上面的类Test.java运行的过程:
hello world
对应的ASCII码序列为:
[104,101,108,108,111,32,119,111,114,108,100]
对应的8bit字节序列为:
[01101000,01100101,01101100,01101100,01101111,00100000,01110111,01101111,01110010,01101100,
01100100,00000000]
对应的6bit字节序列为:
[011010,000110,010101,101100,011011,000110,111100,100000,011101,110110,111101,110010,011011
,000110,010000,000000]
十进制序列为:
[26,6,21,44,27,6,60,32,29,54,61,50,27,6,16, (异常)]
对应base64编码序列(对照base64编码表)为:
[aGVsbG8gd29ybGQ=]
和类Test.java运行的结果是一样的。其中值得注意的是Java中的getBytes()方法,可以获得字符的ASCII码值。
根据上面的推理,我实现了Base64加密与解密的算法:
public class Base64 { private static final String base64code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/"; private static final String PADDING_STR = "="; private static final String PADDING_STR_BINARRY ="00000000"; private static final String PADDING_STR_BINARRY2 ="000000"; /**加密 * @param string 加密的报文 * @return 返回 加密后的报文 */ public static String encode(String string) { Integer[] asciiArray = stringToASCII(string); String binarryStr = asciiToBinarry(asciiArray); //补"0" int zeroPaddingNum = 0; int length = asciiArray.length; while(length%3!=0){ binarryStr += PADDING_STR_BINARRY; length++; zeroPaddingNum++; } //查Base64编码表,进行"偷天换日" StringBuffer retvalue = new StringBuffer(); while(binarryStr.length()>0){ String str = binarryStr.substring(0,6); int temp = Integer.valueOf(str,2); //二进制转十进制 if(binarryStr.length()>zeroPaddingNum*6){ retvalue.append(base64code.charAt(temp)); }else{ retvalue.append(PADDING_STR); } binarryStr = binarryStr.substring(6); } return retvalue.toString(); } /**解密 * @param string 解密的报文 * @return 返回 解密后的报文 */ public static String decode(String string) { char[] charArray = string.toCharArray(); //转二进制字符串 int zeroPaddingNum = 0; StringBuffer sb = new StringBuffer(); for(int i=0;i<charArray.length;i++){ if(base64code.indexOf(String.valueOf(charArray[i]))>-1){ int tempI = base64code.indexOf(String.valueOf(charArray[i])); String temp = Integer.toBinaryString(tempI); while(temp.length()<6){ temp = "0"+temp; } sb.append(temp); }else{ sb.append(PADDING_STR_BINARRY2); zeroPaddingNum++; } } String binarryStr = sb.toString(); StringBuffer retvalue = new StringBuffer(); while(binarryStr.length()>0){ String str = binarryStr.substring(0,8); int temp = Integer.valueOf(str,2); //二进制转十进制 if(binarryStr.length()>zeroPaddingNum*8){ retvalue.append((char)temp); } binarryStr = binarryStr.substring(8); } return retvalue.toString(); } /**把String转为ASCII码数组 * 1.先把String转为char[]数组 * 2.char数组转为ascii数组 * @param value * @return */ private static Integer[] stringToASCII(String value){ Integer[] retInt = new Integer[value.length()]; char[] charArray = value.toCharArray(); for(int i=0;i<charArray.length;i++){ retInt[i] = (int)charArray[i]; } return retInt; } /**把 ASCII码数组转为二进制字符串 * @param value * @return */ private static String asciiToBinarry(Integer[] asciiArray){ StringBuffer sb = new StringBuffer(); for(Integer i : asciiArray){ String temp = Integer.toBinaryString(i); while(temp.length()<8){ temp = "0"+temp; } sb.append(temp); } return sb.toString(); } public static void main(String[] args) { System.out.println(encode("Tom")); System.out.println(decode(encode("Tom"))); System.out.println(encode("Lucy")); System.out.println(decode(encode("Lucy"))); System.out.println(encode("hello world")); } }
下面是摘自高人的Base64源码:
package cn.com.base; public class Base64 { private static final String base64code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/"; private static final int splitLinesAt = 76; public static byte[] zeroPad(int length, byte[] bytes) { byte[] padded = new byte[length]; // initialized to zero by JVM System.arraycopy(bytes, 0, padded, 0, bytes.length); return padded; } public static String encode(String string) { String encoded = ""; byte[] stringArray; try { stringArray = string.getBytes("UTF-8"); // use appropriate encoding string! } catch (Exception ignored) { stringArray = string.getBytes(); // use locale default rather than croak } // determine how many padding bytes to add to the output int paddingCount = (3 - (stringArray.length % 3)) % 3; // add any necessary padding to the input stringArray = zeroPad(stringArray.length + paddingCount, stringArray); // process 3 bytes at a time, churning out 4 output bytes // worry about CRLF insertions later for (int i = 0; i < stringArray.length; i += 3) { int j = ((stringArray[i] & 0xff) << 16) + ((stringArray[i + 1] & 0xff) << 8) + (stringArray[i + 2] & 0xff); encoded = encoded + base64code.charAt((j >> 18) & 0x3f) + base64code.charAt((j >> 12) & 0x3f) + base64code.charAt((j >> 6) & 0x3f) + base64code.charAt(j & 0x3f); } // replace encoded padding nulls with "=" return splitLines(encoded.substring(0, encoded.length() - paddingCount) + "==".substring(0, paddingCount)); } public static String splitLines(String string) { String lines = ""; for (int i = 0; i < string.length(); i += splitLinesAt) { lines += string.substring(i, Math.min(string.length(), i + splitLinesAt)); lines += "\r\n"; } return lines; } public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.err.println("encoding \"" + args[i] + "\""); System.out.println(encode(args[i])); } } }
其中核心算法一系列的左移与右移运算,实现是理解不了!这个必须得有高人指点。
参考资料:
http://snowolf.iteye.com/blog/379860
http://my.eoe.cn/indexer/archive/1055.html
http://www.iteye.com/topic/605714
http://java.chinaitlab.com/Special/javajm/Index.html
http://www.wikihow.com/Encode-a-String-to-Base64-With-Java
相关推荐
【描述】中的"用过无问题,已经写了一份好详细的word文档"暗示了在实际Java开发中,BASE64加密解密已经被成功应用,并且有详细的文档记录了整个过程,这表明BASE64作为一种简单易用的编码手段,在处理二进制数据时...
在Java编程中,图片Base64加密解密是一种常见的数据处理技术,特别是在网络传输和存储时,由于Base64编码可以将二进制数据转换为可打印的ASCII字符,因此非常适用。`sun.misc.BASE64Encoder`和`sun.misc.BASE64...
在IT领域,尤其是在编程...理解并掌握字符进制转换和Base64加密解密对于提升软件的安全性和数据处理能力至关重要。在PowerBuilder这样的开发环境中,熟练运用这些技术能够帮助开发者更好地处理数据,保障系统的安全性。
总结,虽然SQL Server 2005本身并不提供内置的Base64加密解密功能,但通过创建自定义函数,我们可以实现类似的功能。需要注意的是,上述函数仅适用于简单场景,对于更复杂的需求,可能需要更完善的Base64编码解码...
解密Base64字符串则需要用到`FromBase64String`方法,它接受Base64字符串并返回字节数组。解码后的字节数组可以保存为文件或者进一步处理。例如: ```csharp string encodedData = "your_base64_string"; byte[] ...
以下是对Base64加密解密的详细讲解以及如何在C# WinForm应用中实现。 首先,理解Base64的基本原理。Base64使用64个不同的字符(包括大小写字母、数字以及"+"和"/")来表示二进制数据,每个字符代表6位二进制数。...
Java Base64加密解密方法工具类
c++实现base64算法加密解密,不需要修改,直接运行即可
标题"jquery-base64加密解密,支持中文"表明这个示例着重于使用`jQuery`进行Base64编码和解码,并且特别强调了对中文字符的支持。在Web开发中,中文字符的编码可能会引起问题,因为它们不在标准ASCII范围内。`jQuery...
以下是一个简单的Base64加密和解密UDF示例: 1. 创建一个Java项目,引入Hive相关的依赖库,如`hive-exec`和`hive-serde`。 2. 编写一个名为`Base64UDF`的类,继承`org.apache.hadoop.hive.ql.udf.generic....
本篇将详细讲解微信小程序中使用AES(Advanced Encryption Standard)ECB(Electronic Codebook)模式进行Base64编码的加密与解密操作。 首先,AES是一种广泛使用的对称加密算法,它基于块密码,每个块大小为128位...
非常实用的Base64加密,解密角本。基于UTF8,支持中文加解密。
PB BASE64加密和解密DEMO是一种在PowerBuilder(PB)环境中实现的基于BASE64编码技术的加密和解密方法。BASE64是一种常见的数据编码方式,它将二进制数据转换为可打印的ASCII字符,常用于在网络上传输包含二进制的...
LabVIEW实现Base64加密解密程序源码,可以作为子VI直接调用,非常方便,经过测试没有问题。base64是一种用64个字符来表示任意二进制数据的方法。base 64编码可以将任意一组字节转换为较长的常见文本字符序列,从而...
字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)
总的来说,Base64是一种在不同系统之间传输二进制数据的便捷手段,而“Base64 加密解密小工具”则为用户提供了一个方便快捷的实现这一功能的平台。通过理解和熟练运用这类工具,可以更好地处理各种涉及二进制数据...
总结而言,BASE64编码与解码是数据传输中的一项重要技术,尤其在保护数据完整性和隐私方面发挥着关键作用。通过了解其原理并掌握在Java中的实现方式,开发者可以更加灵活地应对不同场景下的数据处理需求。
JavaScript中的Base64编码是一种广泛使用的数据编码方式,它将任意二进制数据转换为可打印的ASCII字符串,便于在...了解和掌握Base64编码与解码的基本原理和实现方法,对于任何JavaScript开发者来说都是必备技能之一。
Base64加密&解密工具,可以用以验证咱编写Base64加密&解密程序的正确性。