javabase64编码原理和解码,加密案例

javabase64编码原理和解码,加密案例javabase64编码原理和解码,加密案例

大家好,又见面了,我是你们的朋友全栈君。

博文转自: 

http://blog.csdn.net/zdqdj1/article/details/51760412点击打开链接

 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常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email、在XML中存储复杂数据。

原理:

在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。

        完整的base64定义可见RFC1421和RFC2045。编码后的数据比原始数据略长,为原来的4/3。在电子邮件中,根据RFC822规定,每76个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%。

        转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲器中剩下的bit用0补足。然后,每次取出6(因为2^6=64)个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。

        当原数据长度不是3的整数倍时,如果最后剩下一个输入数据,在编码结果后加2个“=”;如果最后剩下两个输入数据,编码结果后加1个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证数据还原的正确性。

原理理解:

上面提到编码后的数据长度约为原长的135.1%,算式为:1*(4/3)*((76+1)/76)≈1.351

        鉴于很多朋友不爱看大片枯燥文字,在下以个人理解将之总结为以下3点:

        将原始数据以先后顺序每3个字节分成一组*。在每一组中,把3个8bit的字节(3*8=24)按高低位顺序分为每段6bit的4段(4*6=24),将每段转为十进制得到0~63之间的数,以之为索引在Base64编码表中对照得到4个密文。重复以上操作。
       *若最后一组不足3个字节,则在其二进制位的低位上用尽量少的“0”补位,使二进制位的个数为6的倍数。

        ②密文每76个字符数据后加一个换行符*
       
*注意这里的换行符指CRLF(\r\n),而不是LF(\n),为什么?请看RFC2045下载完整PDF)。

        若原始数据字节长度除以3余1,则在输出数据末尾加2个“=”,若原始数据长度除以3余2,则在输出数据末尾加1个“=”

 规则

        1.ASCII编码表:

javabase64编码原理和解码,加密案例

  2.Base64编码表

javabase64编码原理和解码,加密案例
图解:

    我们还是来看下面这3个例子比较直观(例子下载)。

        例子1、假设我们的明文为“Base64”(数据长度为6,正好是3的倍数),则其编码计算方式如下:

javabase64编码原理和解码,加密案例

  例子2、假设我们的明文为“test”(数据长度为44%3=1),则其编码计算方式如下:

javabase64编码原理和解码,加密案例

  例子3、假设我们的明文为“JiaMi”(数据长度为55%3=2),则其编码计算方式如下:

javabase64编码原理和解码,加密案例

java案例1:

package com.dokio.base64;  
  
public class Base64 {  
      
    //Constructor  
    public Base64() {  
          
    }  
      
    private static String base64Code= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
      
    public static String encode(String srcStr) {  
        //有效值检查  
        if(srcStr == null || srcStr.length() == 0) {  
            return srcStr;  
        }  
        //将明文的ASCII码转为二进制位字串  
        char[] srcStrCh= srcStr.toCharArray();  
        StringBuilder asciiBinStrB= new StringBuilder();  
        String asciiBin= null;  
        for(int i= 0; i< srcStrCh.length; i++) {  
            asciiBin= Integer.toBinaryString((int)srcStrCh[i]);  
            while(asciiBin.length()< 8) {  
                asciiBin= "0"+ asciiBin;  
            }  
            asciiBinStrB.append(asciiBin);  
        }  
        //跟据明文长度在二进制位字串尾部补“0”  
        while(asciiBinStrB.length()% 6!= 0) {  
            asciiBinStrB.append("0");  
        }  
        String asciiBinStr= String.valueOf(asciiBinStrB);  
        //将上面得到的二进制位字串转为Value,再跟据Base64编码表将之转为Encoding  
        char[] codeCh= new char[asciiBinStr.length()/ 6];  
        int index= 0;  
        for(int i= 0; i< codeCh.length; i++) {  
            index= Integer.parseInt(asciiBinStr.substring(0, 6), 2);  
            asciiBinStr= asciiBinStr.substring(6);  
            codeCh[i]= base64Code.charAt(index);  
        }  
        StringBuilder code= new StringBuilder(String.valueOf(codeCh));  
        //跟据需要在尾部添加“=”  
        if(srcStr.length()% 3 == 1) {  
            code.append("==");  
        } else if(srcStr.length()% 3 == 2) {  
            code.append("=");  
        }  
        //每76个字符加一个回车换行符(CRLF)  
        int i= 76;  
        while(i< code.length()) {  
            code.insert(i, "\r\n");  
            i+= 76;  
        }  
        code.append("\r\n");  
        return String.valueOf(code);  
    }  
      
    public static String decode(String srcStr) {  
        //有效值检查  
        if(srcStr == null || srcStr.length() == 0) {  
            return srcStr;  
        }  
        //检测密文中“=”的个数后将之删除,同时删除换行符  
        int eqCounter= 0;  
        if(srcStr.endsWith("==")) {  
            eqCounter= 2;  
        } else if(srcStr.endsWith("=")) {  
            eqCounter= 1;  
        }  
        srcStr= srcStr.replaceAll("=", "");  
        srcStr= srcStr.replaceAll("\r\n", "");  
        //跟据Base64编码表将密文(Encoding)转为对应Value,然后转为二进制位字串  
        char[] srcStrCh= srcStr.toCharArray();  
        StringBuilder indexBinStr= new StringBuilder();  
        String indexBin= null;  
        for(int i= 0; i< srcStrCh.length; i++) {  
            indexBin= Integer.toBinaryString(base64Code.indexOf((int)srcStrCh[i]));  
            while(indexBin.length()< 6) {  
                indexBin= "0"+ indexBin;  
            }  
            indexBinStr.append(indexBin);  
        }  
        //删除因编码而在尾部补位的“0”后得到明文的ASCII码的二进制位字串  
        if(eqCounter == 1) {  
            indexBinStr.delete(indexBinStr.length()- 2, indexBinStr.length());  
        } else if(eqCounter == 2) {  
            indexBinStr.delete(indexBinStr.length()- 4, indexBinStr.length());  
        }  
        String asciiBinStr= String.valueOf(indexBinStr);  
        //将上面得到的二进制位字串分隔成字节后还原成明文  
        String asciiBin= null;  
        char[] ascii= new char[asciiBinStr.length()/ 8];  
        for(int i= 0; i< ascii.length; i++) {  
            asciiBin= asciiBinStr.substring(0, 8);  
            asciiBinStr= asciiBinStr.substring(8);  
            ascii[i]= (char)Integer.parseInt(asciiBin, 2);  
        }  
        return String.valueOf(ascii);  
    }  
      
    public static void main(String[] args) {  
        System.out.print(encode("I like your long long shadow.It just seems you are unhappy to say goodbye to me."));  
        System.out.print("\n------\n");  
        System.out.print(decode("SSBsaWtlIHlvdXIgbG9uZyBsb25nIHNoYWRvdy5JdCBqdXN0IHNlZW1zIHlvdSBhcmUgdW5oYXBweSB0byBzYXkgZ29vZGJ5ZSB0byBtZS4="));  
        System.out.print("\n------\n");  
        System.out.print(decode(encode("I like your long long shadow.It just seems you are unhappy to say goodbye to me.")));  
    }  
      
}


案例2:

加密 jquery代码:

// base64加密
		function encode64(input) {
		    var keyStr = "ABCDEFGHIJKLMNOP" + "QRSTUVWXYZabcdef" + "ghijklmnopqrstuv" + "wxyz0123456789+/" + "=";
		    var output = "";
		    var chr1, chr2, chr3 = "";
		    var enc1, enc2, enc3, enc4 = "";
		    var i = 0;
		    do {
	            chr1 = input.charCodeAt(i++);
	            chr2 = input.charCodeAt(i++);
	            chr3 = input.charCodeAt(i++);
	            enc1 = chr1 >> 2;
	            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
	            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
	            enc4 = chr3 & 63;
	            if (isNaN(chr2)) {
	               enc3 = enc4 = 64;
	            } else if (isNaN(chr3)) {
	               enc4 = 64;
	            }
	            output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
	            chr1 = chr2 = chr3 = "";
	            enc1 = enc2 = enc3 = enc4 = "";
	    	} while (i < input.length);
	   
	    	return output;
		}


解密 java代码:

/**
 * 
 */
package com.allinfinance.aps.biz.util;

import java.io.ByteArrayOutputStream;

public class Base64Util {

	    private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
	        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	        -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
	        60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
	        10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
	        -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
	        38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
	        -1, -1 };
	    
	    /**
	    * 解密
	    * @param str
	    * @return
	    */
	    public static byte[] decode(String str) {
            byte[] data = str.getBytes();
            int len = data.length;
            ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
            int i = 0;
            int b1, b2, b3, b4;

            while (i < len) {
                do {
                        b1 = base64DecodeChars[data[i++]];
                } while (i < len && b1 == -1);
                if (b1 == -1) {
                        break;
                }

                do {
                        b2 = base64DecodeChars[data[i++]];
                } while (i < len && b2 == -1);
                if (b2 == -1) {
                        break;
                }
                buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4)));

                do {
                        b3 = data[i++];
                        if (b3 == 61) {
                                return buf.toByteArray();
                        }
                        b3 = base64DecodeChars[b3];
                } while (i < len && b3 == -1);
                if (b3 == -1) {
                        break;
                }
                buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

                do {
                        b4 = data[i++];
                        if (b4 == 61) {
                                return buf.toByteArray();
                        }
                        b4 = base64DecodeChars[b4];
                } while (i < len && b4 == -1);
                if (b4 == -1) {
                        break;
                }
                buf.write((int) (((b3 & 0x03) << 6) | b4));
            }
            return buf.toByteArray();
	    }
	    
	    /**
	     * 返回解密结果
	     */
	    
	    public static String decodeToString(String param){
	        return new String(decode(param));
	    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/106230.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 久坐提醒电脑软件_久坐提醒app哪个好

    久坐提醒电脑软件_久坐提醒app哪个好下载废话不多说,先直接给出下载地址介绍久坐的危害不必多言,但工作起来很多时候总是不知不觉一坐几个小时不动地方。去年毕业前闲来无事写了个桌面端的久坐提醒小工具,放到github就没再管过,前些天发现这个仓库有了20个star了,虽然很少,但也蛮有成就感的。于是又有了更新的动力,根据issues里使用者提的建议,做了些小修改,提高了一些使用体验。截图展示…

  • bootstrap实现分页(实例)「建议收藏」

    bootstrap实现分页(实例)「建议收藏」写前端都会面临的一个问题就是分页,如果是纯js分页也是可以的,只是可能代码量比较大,所以今天写一个关于用bootstrap框架分页的例子,希望以后可以帮助到一些对这方面比较头疼的码农。首先需要明确的一点是,哪些数据是需要分页的,单从数据显示上其实是没有必要分页的,因为页面是可以显示的出来的,但是作为一个相对比较合格的前端,你首先要考虑的不仅仅是这个功能是不是可以实现,而是要考虑用户体验是不是好的,…

  • Javaweb 后端框架总结

    Javaweb 后端框架总结REST方法       Spring核心  IOC(InversionofController)-面向对象的一个准则,对象的控制(创建和管理)由容器或者框架来实现,而不是开发者直接调用,开发者只需要实现接口或者放入自己的类就可以依赖注入(DependencyInjectionDI)每个方法都有一个独立的对象,通过接口去调用其他的对…

  • 网站优化网络推广怎么做_网站推广公司

    网站优化网络推广怎么做_网站推广公司如何优化网站,网站推广优化一般流程

  • 在线词云制作生成 tagxedo

    在线词云制作生成 tagxedo在线词云制作生成tagxedo在线词云10行Python代码的词云待办在线词云原博文地址和详细使用方法介绍在线词云制作tagxedo在线网址http://www.tagxedo.com/注意点:直接访问http://www.tagxedo.com/app.html可能会超时,先进主页再点击右上角的create按钮进入创作页面会加载更快;需要下载一个软件,使用IE浏览器可加载上述软件,谷歌和EDGE实测都无法加载;导出的词云图片:10行Python代码的词云原博客地址:1

    2022年10月26日
  • 【面试】面试中经常遇到的Git 操作命令

    【面试】面试中经常遇到的Git 操作命令

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号