`
周凡杨
  • 浏览: 234543 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

加密与解密篇一之Base64

阅读更多

      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的编码都是按字符串长度,以每38bit的字符为一组,然后针对每组,首先获取每个字符的ASCII编码,然后将ASCII编码转换成8bit的二进制,得到一组3*8=24bit的字节,然后再将这24bit划分为46bit的字节,并在每个6bit的字节前面都填两个高位0,得到48bit的字节。然后将这48bit的字节转换成10进制,对照Base64编码表(下表),得到对应编码后的字符。(注:1. 要求被编码字符是8bit的,所以须在ASCII编码范围内,\u0000-\u00ff,中文就不行。  2. 如果被编码字符长度不是3的倍数的时候,则都用0代替,对应的输出字符为=

 1)字符长度为能被3整除时

比如“Tom” :
     T       o        m
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

 

 

 

 

 

 

 

 

  • 大小: 25.1 KB
  • 大小: 69.9 KB
0
1
分享到:
评论
2 楼 周凡杨 2014-01-17  
ahack 写道
base64算编码吧,不算加密。

是编码,但其编码过程可以看到是个简易加密的过程
1 楼 ahack 2014-01-15  
base64算编码吧,不算加密。

相关推荐

    BASE64加密解密

    【描述】中的"用过无问题,已经写了一份好详细的word文档"暗示了在实际Java开发中,BASE64加密解密已经被成功应用,并且有详细的文档记录了整个过程,这表明BASE64作为一种简单易用的编码手段,在处理二进制数据时...

    java 图片base64 加密解密

    在Java编程中,图片Base64加密解密是一种常见的数据处理技术,特别是在网络传输和存储时,由于Base64编码可以将二进制数据转换为可打印的ASCII字符,因此非常适用。`sun.misc.BASE64Encoder`和`sun.misc.BASE64...

    PB关于字符进制数转化及base64加密、解密,nvo_base64.sru

    在IT领域,尤其是在编程...理解并掌握字符进制转换和Base64加密解密对于提升软件的安全性和数据处理能力至关重要。在PowerBuilder这样的开发环境中,熟练运用这些技术能够帮助开发者更好地处理数据,保障系统的安全性。

    sqlserver2005的base64加密解密函数

    总结,虽然SQL Server 2005本身并不提供内置的Base64加密解密功能,但通过创建自定义函数,我们可以实现类似的功能。需要注意的是,上述函数仅适用于简单场景,对于更复杂的需求,可能需要更完善的Base64编码解码...

    C# Base64加密解密

    解密Base64字符串则需要用到`FromBase64String`方法,它接受Base64字符串并返回字节数组。解码后的字节数组可以保存为文件或者进一步处理。例如: ```csharp string encodedData = "your_base64_string"; byte[] ...

    Base64加密解密.zip

    以下是对Base64加密解密的详细讲解以及如何在C# WinForm应用中实现。 首先,理解Base64的基本原理。Base64使用64个不同的字符(包括大小写字母、数字以及"+"和"/")来表示二进制数据,每个字符代表6位二进制数。...

    Java Base64加密解密方法工具类

    Java Base64加密解密方法工具类

    c++实现base64算法加密解密

    c++实现base64算法加密解密,不需要修改,直接运行即可

    jquery-base64加密解密,支持中文

    标题"jquery-base64加密解密,支持中文"表明这个示例着重于使用`jQuery`进行Base64编码和解码,并且特别强调了对中文字符的支持。在Web开发中,中文字符的编码可能会引起问题,因为它们不在标准ASCII范围内。`jQuery...

    base64加密解密的hive udf函数

    以下是一个简单的Base64加密和解密UDF示例: 1. 创建一个Java项目,引入Hive相关的依赖库,如`hive-exec`和`hive-serde`。 2. 编写一个名为`Base64UDF`的类,继承`org.apache.hadoop.hive.ql.udf.generic....

    微信小程序 AES ECB base64 加密解密

    本篇将详细讲解微信小程序中使用AES(Advanced Encryption Standard)ECB(Electronic Codebook)模式进行Base64编码的加密与解密操作。 首先,AES是一种广泛使用的对称加密算法,它基于块密码,每个块大小为128位...

    Sql Server Base64加密解密角本

    非常实用的Base64加密,解密角本。基于UTF8,支持中文加解密。

    PB BASE64加密和解密DEMO

    PB BASE64加密和解密DEMO是一种在PowerBuilder(PB)环境中实现的基于BASE64编码技术的加密和解密方法。BASE64是一种常见的数据编码方式,它将二进制数据转换为可打印的ASCII字符,常用于在网络上传输包含二进制的...

    LabVIEW实现Base64加密解密程序源码

    LabVIEW实现Base64加密解密程序源码,可以作为子VI直接调用,非常方便,经过测试没有问题。base64是一种用64个字符来表示任意二进制数据的方法。base 64编码可以将任意一组字节转换为较长的常见文本字符序列,从而...

    字符串加密与解密(Base64)

    字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)字符串加密与解密(Base64)

    Base64 加密解密小工具

    总的来说,Base64是一种在不同系统之间传输二进制数据的便捷手段,而“Base64 加密解密小工具”则为用户提供了一个方便快捷的实现这一功能的平台。通过理解和熟练运用这类工具,可以更好地处理各种涉及二进制数据...

    BASE64Encoder加密与解密

    总结而言,BASE64编码与解码是数据传输中的一项重要技术,尤其在保护数据完整性和隐私方面发挥着关键作用。通过了解其原理并掌握在Java中的实现方式,开发者可以更加灵活地应对不同场景下的数据处理需求。

    js的base64加密解密

    JavaScript中的Base64编码是一种广泛使用的数据编码方式,它将任意二进制数据转换为可打印的ASCII字符串,便于在...了解和掌握Base64编码与解码的基本原理和实现方法,对于任何JavaScript开发者来说都是必备技能之一。

    Base64加密&解密工具

    Base64加密&解密工具,可以用以验证咱编写Base64加密&解密程序的正确性。

Global site tag (gtag.js) - Google Analytics