Java常见的加密解密

x33g5p2x  于2021-10-01 转载在 Java  
字(40.3k)|赞(0)|评价(0)|浏览(359)

不可逆加密

介绍

应用场景
一致性验证
MD5 可以为文件传输场景中,提供文件的一致性验证。

例如,文件服务器预先提供一个 MD5 校验值,用户下载完文件以后,用 MD5 算法计算下载文件的 MD5 校验值(如果任何人对文件做了任何改动,这个文件的MD5值就会发生变化),然后通过检查这两个校验值是否一致,就能判断下载的文件是否出错、或者下载的文件是否被篡改了。

现在,利用MD5算法进行文件校验的方法,已经广泛应用到软件下载站、论坛数据库、系统文件安全等方面了。

数字签名
MD5 的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止该段信息被篡改。

例如,在文件“readme.txt”中写入一些内容,并对这个文件进行MD5运算,产生一个MD5值并记录下来,然后可以将这个文件发送给别人,别人如果修改了“readme.txt”文件中的任何内容,我们对这个文件重新计算MD5时,就会发现两个MD5值不同。

在上述过程中,如果再有一个第三方的认证机构介入,那么使用 MD5 还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

安全访问认证
MD5 还广泛用于操作系统的登录认证中,如 Unix、各类BSD操作系统登录密码、数字签名等诸多方面。

例如,在Unix操作系统中,用户的密码是经MD5(或其它类似的算法)运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5运算,然后再与保存在文件系统中的MD5值进行比较,从而确定用户输入的密码是否正确。通过这些步骤,操作系统在并不知道用户密码的明文的情况下,就可以确定用户登录系统的合法性,这可以避免用户的密码被具有系统管理员权限的用户窃取。

MD5 将任意长度的“字符串”映射为一个128bit的“字符串”,并且通过该128bit的“字符串”反推原始字符串是困难的,换句话说,即使你看到源程序和算法描述,也很难将一个MD5的值转换回原始的字符串。

md5的用途
密码的加密存储,用户设置密码时,服务端只记录这个密码的MD5,而不记录密码本身,以后验证用户身份时,只需要将用户输入的密码再次做一下MD5后,与记录的MD5作一个比较即可验证其密码的合法性。
数字签名,比如发布一个程序,为了防止别人在你的程序里插入病毒或木马,你可以在发布这个程序的同时,公开这个程序文件的MD5码,这样别人只需要在任何地方下载这个程序后做一次MD5,然后跟公开的这个MD5作一个比较就知道这个程序是否被第三方修改过。
文件完整性验证,比如当下载一个文件时,服务器返回的信息中包括这个文件的md5,在本地下载完毕时进行md5,将两个md5值进行比较,如果一致则说明文件完整没有丢包现象。
文件上传,比如百度云实现的秒传,就是对比你上传的文件md5在百度服务器是否已经存在了,如果存在就不用上传了

MD5

public class MD5 {
    //存储小组
    long []groups = null;
    //存储结果
    String resultMessage="";

    //四个寄存器的初始向量IV,采用小端存储
    static final long A=0x67452301L;
    static final long B=0xefcdab89L;
    static final long C=0x98badcfeL;
    static final long D=0x10325476L;

    //java不支持无符号的基本数据(unsigned),所以选用long数据类型
    private long [] result={A,B,C,D};

    static final long T[][] = {
            {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
                    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
                    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
                    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821},

            {0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
                    0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
                    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
                    0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a},

            {0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
                    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
                    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
                    0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665},

            {0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
                    0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
                    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
                    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}};
    //表示X[k]中的的k取值,决定如何使用消息分组中的字
    static final int k[][] = {
            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
            {1, 6,11, 0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12},
            {5, 8,11,14, 1, 4, 7,10,13, 0, 3, 6, 9,12,15, 2},
            {0, 7,14, 5,12, 3,10, 1, 8,15, 6,13, 4,11, 2, 9}};

    //各次迭代中采用的做循环移位的s值
    static final int S[][] = {
            {7,12,17,22},
            {5,9,14,20},
            {4,11,16,23},
            {6,10,15,21}};

    //4轮循环中使用的生成函数(轮函数)g
    private static long g(int i, long b, long c, long d) {
        switch (i) {
            case 0:
                return (b & c) | ((~b) & d);
            case 1:
                return (b & d) | (c & (~d));
            case 2:
                return b ^ c ^ d;
            case 3:
                return c ^ (b | (~d));
            default:
                return 0;
        }
    }
    //开始使用MD5加密
    private String start(String message){
        //转化为字节数组
        byte [] inputBytes=message.getBytes();
        //6A 61 6E 6b 69 6e 67
        //获取字节数组的长度
        int byteLen = inputBytes.length;
        //得到K值(以bit作单位的message长度)
        long K = (long)(byteLen<<3);
        //完整小组(512bit)(64byte)的个数
        int groupCount = byteLen/64;

        //分块
        for(int i = 0;i < groupCount;i++){
            //每次取512bit
            //处理一个分组
            H(divide(inputBytes, i*64));
        }

        //填充
        int rest = byteLen % 64;
        //即将填充的一个分组
        byte [] paddingBytes=new byte[64];
        //原来的尾部数据
        for(int i=0;i<rest;i++)
            paddingBytes[i]=inputBytes[byteLen-rest+i];
        //即小于448bit的情况,先填充100...0再填充K值的低64位
        //此时只会新增一个分组
        if(rest <= 56){
            //填充100...0
            if(rest<56){
                //填充10000000
                paddingBytes[rest]=(byte)(1<<7);
                //填充00000000
                for(int i=1;i<56-rest;i++)
                    paddingBytes[rest+i]=0;
            }
            //填充K值低64位
            for(int i=0;i<8;i++){
                paddingBytes[56+i]=(byte)(K&0xFFL);
                K=K>>8;
            }
            //处理分组
            H(divide(paddingBytes,0));
            //即大于448bit的情况,先填充100...0再填充K值的低64位
            //此时会新增两个分组
        }else{
            //填充10000000
            paddingBytes[rest]=(byte)(1<<7);
            //填充00000000
            for(int i=rest+1;i<64;i++)
                paddingBytes[i]=0;
            //处理第一个尾部分组
            H(divide(paddingBytes,0));

            //填充00000000
            for(int i=0;i<56;i++)
                paddingBytes[i]=0;

            //填充低64位
            for(int i=0;i<8;i++){
                //这里很关键,使用小端方式,即Byte数组先存储len的低位数据,然后右移len
                paddingBytes[56+i]=(byte)(K&0xFFL);
                K=K>>8;
            }
            //处理第二个尾部分组
            H(divide(paddingBytes,0));
        }
        //将Hash值转换成十六进制的字符串
        //小端方式!
        for(int i=0;i<4;i++){
            resultMessage += Long.toHexString(result[i] & 0xFF) +
                    Long.toHexString((result[i] & 0xFF00) >> 8) +
                    Long.toHexString((result[i] & 0xFF0000) >> 16) +
                    Long.toHexString((result[i] & 0xFF000000) >> 24);

        }
        return resultMessage;
    }

    //从inputBytes的index开始取512位,作为新的512bit的分组
    private static long[] divide(byte[] inputBytes,int start){
        //存储一整个分组,就是512bit,数组里每个是32bit,就是4字节,为了消除符号位的影响,所以使用long
        long [] group=new long[16];
        for(int i=0;i<16;i++){
            //每个32bit由4个字节拼接而来
            //小端的从byte数组到bit恢复方法
            group[i]=byte2unsign(inputBytes[4*i+start])|
                    (byte2unsign(inputBytes[4*i+1+start]))<<8|
                    (byte2unsign(inputBytes[4*i+2+start]))<<16|
                    (byte2unsign(inputBytes[4*i+3+start]))<<24;
        }
        return group;
    }

    //其实byte相当于一个字节的有符号整数,这里不需要符号位,所以把符号位去掉
    public static long byte2unsign(byte b){
        return b < 0 ? b & 0x7F + 128 : b;
    }

    // groups[] 中每一个分组512位(64字节)
    // MD5压缩函数
    private void H(long[] groups) {
        //缓冲区(寄存器)数组
        long a = result[0], b = result[1], c = result[2], d = result[3];
        //四轮循环
        for(int n = 0; n < 4; n++) {
            //16轮迭代
            for(int i = 0; i < 16; i++) {
                result[0] += (g(n, result[1], result[2], result[3])&0xFFFFFFFFL) + groups[k[n][i]] + T[n][i];
                result[0] = result[1] + ((result[0]&0xFFFFFFFFL)<< S[n][i % 4] | ((result[0]&0xFFFFFFFFL) >>> (32 - S[n][i % 4])));
                //循环轮换
                long temp = result[3];
                result[3] = result[2];
                result[2] = result[1];
                result[1] = result[0];
                result[0] = temp;
            }
        }
        //加入之前计算的结果
        result[0] += a;
        result[1] += b;
        result[2] += c;
        result[3] += d;
        //防止溢出
        for(int n = 0; n < 4 ; n++) {
            result[n] &=0xFFFFFFFFL;
        }
    }

    public static void main(String []args){
        MD5 md=new MD5();
        String message = "helloMD5";
        System.out.println("明文:" + message);
        System.out.println("小写的密文:" + md.start(message));
        System.out.println("大写的密文: " + md.resultMessage.toUpperCase());
        //F0F99260B5A02508C71F6D81C15E9A44
        //3ED9E5F6855DBCDBCD95AC6C4FE0C0A5
    }
}

前端MD5

jQuery.md5.js

/** * jQuery MD5 hash algorithm function * * <code> * Calculate the md5 hash of a String * String $.md5 ( String str ) * </code> * * Calculates the MD5 hash of str using the » RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash. * MD5 (Message-Digest algorithm 5) is a widely-used cryptographic hash function with a 128-bit hash value. MD5 has been employed in a wide variety of security applications, and is also commonly used to check the integrity of data. The generated hash is also non-reversable. Data cannot be retrieved from the message digest, the digest uniquely identifies the data. * MD5 was developed by Professor Ronald L. Rivest in 1994. Its 128 bit (16 byte) message digest makes it a faster implementation than SHA-1. * This script is used to process a variable length message into a fixed-length output of 128 bits using the MD5 algorithm. It is fully compatible with UTF-8 encoding. It is very useful when u want to transfer encrypted passwords over the internet. If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag). * This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin. * * Example * Code * <code> * $.md5("I'm Persian."); * </code> * Result * <code> * "b8c901d0f02223f9761016cfff9d68df" * </code> * * @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com > * @link http://www.semnanweb.com/jquery-plugin/md5.html * @see http://www.webtoolkit.info/ * @license http://www.gnu.org/licenses/gpl.html [GNU General Public License] * @param {jQuery} {md5:function(string)) * @return string */
(function($){
    var rotateLeft = function(lValue, iShiftBits) {
        return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
    }
    var addUnsigned = function(lX, lY) {
        var lX4, lY4, lX8, lY8, lResult;
        lX8 = (lX & 0x80000000);
        lY8 = (lY & 0x80000000);
        lX4 = (lX & 0x40000000);
        lY4 = (lY & 0x40000000);
        lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
        if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
        if (lX4 | lY4) {
            if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
            else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
        } else {
            return (lResult ^ lX8 ^ lY8);
        }
    }
    var F = function(x, y, z) {
        return (x & y) | ((~ x) & z);
    }
    var G = function(x, y, z) {
        return (x & z) | (y & (~ z));
    }
    var H = function(x, y, z) {
        return (x ^ y ^ z);
    }
    var I = function(x, y, z) {
        return (y ^ (x | (~ z)));
    }
    var FF = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    var GG = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    var HH = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    var II = function(a, b, c, d, x, s, ac) {
        a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
        return addUnsigned(rotateLeft(a, s), b);
    };
    var convertToWordArray = function(string) {
        var lWordCount;
        var lMessageLength = string.length;
        var lNumberOfWordsTempOne = lMessageLength + 8;
        var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
        var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
        var lWordArray = Array(lNumberOfWords - 1);
        var lBytePosition = 0;
        var lByteCount = 0;
        while (lByteCount < lMessageLength) {
            lWordCount = (lByteCount - (lByteCount % 4)) / 4;
            lBytePosition = (lByteCount % 4) * 8;
            lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
            lByteCount++;
        }
        lWordCount = (lByteCount - (lByteCount % 4)) / 4;
        lBytePosition = (lByteCount % 4) * 8;
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
        lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
        lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
        return lWordArray;
    };
    var wordToHex = function(lValue) {
        var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount;
        for (lCount = 0; lCount <= 3; lCount++) {
            lByte = (lValue >>> (lCount * 8)) & 255;
            WordToHexValueTemp = "0" + lByte.toString(16);
            WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
        }
        return WordToHexValue;
    };
    var uTF8Encode = function(string) {
        string = string.replace(/\x0d\x0a/g, "\x0a");
        var output = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                output += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
                output += String.fromCharCode((c >> 6) | 192);
                output += String.fromCharCode((c & 63) | 128);
            } else {
                output += String.fromCharCode((c >> 12) | 224);
                output += String.fromCharCode(((c >> 6) & 63) | 128);
                output += String.fromCharCode((c & 63) | 128);
            }
        }
        return output;
    };
    $.extend({
        md5: function(string) {
            var x = Array();
            var k, AA, BB, CC, DD, a, b, c, d;
            var S11=7, S12=12, S13=17, S14=22;
            var S21=5, S22=9 , S23=14, S24=20;
            var S31=4, S32=11, S33=16, S34=23;
            var S41=6, S42=10, S43=15, S44=21;
            string = uTF8Encode(string);
            x = convertToWordArray(string);
            a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
            for (k = 0; k < x.length; k += 16) {
                AA = a; BB = b; CC = c; DD = d;
                a = FF(a, b, c, d, x[k+0],  S11, 0xD76AA478);
                d = FF(d, a, b, c, x[k+1],  S12, 0xE8C7B756);
                c = FF(c, d, a, b, x[k+2],  S13, 0x242070DB);
                b = FF(b, c, d, a, x[k+3],  S14, 0xC1BDCEEE);
                a = FF(a, b, c, d, x[k+4],  S11, 0xF57C0FAF);
                d = FF(d, a, b, c, x[k+5],  S12, 0x4787C62A);
                c = FF(c, d, a, b, x[k+6],  S13, 0xA8304613);
                b = FF(b, c, d, a, x[k+7],  S14, 0xFD469501);
                a = FF(a, b, c, d, x[k+8],  S11, 0x698098D8);
                d = FF(d, a, b, c, x[k+9],  S12, 0x8B44F7AF);
                c = FF(c, d, a, b, x[k+10], S13, 0xFFFF5BB1);
                b = FF(b, c, d, a, x[k+11], S14, 0x895CD7BE);
                a = FF(a, b, c, d, x[k+12], S11, 0x6B901122);
                d = FF(d, a, b, c, x[k+13], S12, 0xFD987193);
                c = FF(c, d, a, b, x[k+14], S13, 0xA679438E);
                b = FF(b, c, d, a, x[k+15], S14, 0x49B40821);
                a = GG(a, b, c, d, x[k+1],  S21, 0xF61E2562);
                d = GG(d, a, b, c, x[k+6],  S22, 0xC040B340);
                c = GG(c, d, a, b, x[k+11], S23, 0x265E5A51);
                b = GG(b, c, d, a, x[k+0],  S24, 0xE9B6C7AA);
                a = GG(a, b, c, d, x[k+5],  S21, 0xD62F105D);
                d = GG(d, a, b, c, x[k+10], S22, 0x2441453);
                c = GG(c, d, a, b, x[k+15], S23, 0xD8A1E681);
                b = GG(b, c, d, a, x[k+4],  S24, 0xE7D3FBC8);
                a = GG(a, b, c, d, x[k+9],  S21, 0x21E1CDE6);
                d = GG(d, a, b, c, x[k+14], S22, 0xC33707D6);
                c = GG(c, d, a, b, x[k+3],  S23, 0xF4D50D87);
                b = GG(b, c, d, a, x[k+8],  S24, 0x455A14ED);
                a = GG(a, b, c, d, x[k+13], S21, 0xA9E3E905);
                d = GG(d, a, b, c, x[k+2],  S22, 0xFCEFA3F8);
                c = GG(c, d, a, b, x[k+7],  S23, 0x676F02D9);
                b = GG(b, c, d, a, x[k+12], S24, 0x8D2A4C8A);
                a = HH(a, b, c, d, x[k+5],  S31, 0xFFFA3942);
                d = HH(d, a, b, c, x[k+8],  S32, 0x8771F681);
                c = HH(c, d, a, b, x[k+11], S33, 0x6D9D6122);
                b = HH(b, c, d, a, x[k+14], S34, 0xFDE5380C);
                a = HH(a, b, c, d, x[k+1],  S31, 0xA4BEEA44);
                d = HH(d, a, b, c, x[k+4],  S32, 0x4BDECFA9);
                c = HH(c, d, a, b, x[k+7],  S33, 0xF6BB4B60);
                b = HH(b, c, d, a, x[k+10], S34, 0xBEBFBC70);
                a = HH(a, b, c, d, x[k+13], S31, 0x289B7EC6);
                d = HH(d, a, b, c, x[k+0],  S32, 0xEAA127FA);
                c = HH(c, d, a, b, x[k+3],  S33, 0xD4EF3085);
                b = HH(b, c, d, a, x[k+6],  S34, 0x4881D05);
                a = HH(a, b, c, d, x[k+9],  S31, 0xD9D4D039);
                d = HH(d, a, b, c, x[k+12], S32, 0xE6DB99E5);
                c = HH(c, d, a, b, x[k+15], S33, 0x1FA27CF8);
                b = HH(b, c, d, a, x[k+2],  S34, 0xC4AC5665);
                a = II(a, b, c, d, x[k+0],  S41, 0xF4292244);
                d = II(d, a, b, c, x[k+7],  S42, 0x432AFF97);
                c = II(c, d, a, b, x[k+14], S43, 0xAB9423A7);
                b = II(b, c, d, a, x[k+5],  S44, 0xFC93A039);
                a = II(a, b, c, d, x[k+12], S41, 0x655B59C3);
                d = II(d, a, b, c, x[k+3],  S42, 0x8F0CCC92);
                c = II(c, d, a, b, x[k+10], S43, 0xFFEFF47D);
                b = II(b, c, d, a, x[k+1],  S44, 0x85845DD1);
                a = II(a, b, c, d, x[k+8],  S41, 0x6FA87E4F);
                d = II(d, a, b, c, x[k+15], S42, 0xFE2CE6E0);
                c = II(c, d, a, b, x[k+6],  S43, 0xA3014314);
                b = II(b, c, d, a, x[k+13], S44, 0x4E0811A1);
                a = II(a, b, c, d, x[k+4],  S41, 0xF7537E82);
                d = II(d, a, b, c, x[k+11], S42, 0xBD3AF235);
                c = II(c, d, a, b, x[k+2],  S43, 0x2AD7D2BB);
                b = II(b, c, d, a, x[k+9],  S44, 0xEB86D391);
                a = addUnsigned(a, AA);
                b = addUnsigned(b, BB);
                c = addUnsigned(c, CC);
                d = addUnsigned(d, DD);
            }
            var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
            return tempValue.toLowerCase();
        }
    });
})(jQuery);
<script src="jquery-3.4.1.js"></script>
<script src="jQuery.md5.js"></script>
<script>
    //加密
    alert($.md5("1234"))
</script>

SHA1

public class SHA1 {

    private static final boolean hexcase = false;
    private static final String b64pad = "=";
    private static final int chrsz = 8;

    // 得到字符串SHA-1值的方法
    public static String hex_sha1(String s) {
        s = (s == null) ? "" : s;
        return binb2hex(core_sha1(str2binb(s), s.length() * chrsz));
    }

    public static String b64_hmac_sha1(String key, String data) {
        return binb2b64(core_hmac_sha1(key, data));
    }

    public static String b64_sha1(String s) {
        s = (s == null) ? "" : s;
        return binb2b64(core_sha1(str2binb(s), s.length() * chrsz));
    }

    private static String binb2b64(int[] binarray) {
        String tab = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/";
        String str = "";
        binarray = strechbinarray(binarray, binarray.length * 4);

        for (int i = 0; i < binarray.length * 4; i += 3) {
            int triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xff) << 16)
                    | (((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xff) << 8)
                    | ((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xff);

            for (int j = 0; j < 4; j++) {
                if (i * 8 + j * 6 > binarray.length * 32) {
                    str += b64pad;
                } else {
                    str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3f);
                }
            }
        }

        return cleanb64str(str);
    }

    private static String binb2hex(int[] binarray) {
        String hex_tab = hexcase ? "0123456789abcdef" : "0123456789abcdef";
        String str = "";

        for (int i = 0; i < binarray.length * 4; i++) {
            char a = (char) hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xf);
            char b = (char) hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xf);
            str += (new Character(a).toString() + new Character(b).toString());
        }

        return str;
    }

    private static String binb2str(int[] bin) {
        String str = "";
        int mask = (1 << chrsz) - 1;

        for (int i = 0; i < bin.length * 32; i += chrsz) {
            str += (char) ((bin[i >> 5] >>> (24 - i % 32)) & mask);
        }

        return str;
    }

    private static int bit_rol(int num, int cnt) {
        return (num << cnt) | (num >>> (32 - cnt));
    }

    private static String cleanb64str(String str) {
        str = (str == null) ? "" : str;
        int len = str.length();

        if (len <= 1) {
            return str;
        }

        char trailchar = str.charAt(len - 1);
        String trailstr = "";

        for (int i = len - 1; i >= 0 && str.charAt(i) == trailchar; i--) {
            trailstr += str.charAt(i);
        }

        return str.substring(0, str.indexOf(trailstr));
    }

    private static int[] complete216(int[] oldbin) {
        if (oldbin.length >= 16) {
            return oldbin;
        }

        int[] newbin = new int[16 - oldbin.length];

        for (int i = 0; i < newbin.length; newbin[i] = 0, i++)
            ;

        return concat(oldbin, newbin);
    }

    private static int[] concat(int[] oldbin, int[] newbin) {
        int[] retval = new int[oldbin.length + newbin.length];

        for (int i = 0; i < (oldbin.length + newbin.length); i++) {
            if (i < oldbin.length) {
                retval[i] = oldbin[i];
            } else {
                retval[i] = newbin[i - oldbin.length];
            }
        }

        return retval;
    }

    private static int[] core_hmac_sha1(String key, String data) {
        key = (key == null) ? "" : key;
        data = (data == null) ? "" : data;
        int[] bkey = complete216(str2binb(key));

        if (bkey.length > 16) {
            bkey = core_sha1(bkey, key.length() * chrsz);
        }

        int[] ipad = new int[16];
        int[] opad = new int[16];

        for (int i = 0; i < 16; ipad[i] = 0, opad[i] = 0, i++)
            ;

        for (int i = 0; i < 16; i++) {
            ipad[i] = bkey[i] ^ 0x36363636;
            opad[i] = bkey[i] ^ 0x5c5c5c5c;
        }

        int[] hash = core_sha1(concat(ipad, str2binb(data)), 512 + data.length() * chrsz);

        return core_sha1(concat(opad, hash), 512 + 160);
    }

    private static int[] core_sha1(int[] x, int len) {
        int size = (len >> 5);
        x = strechbinarray(x, size);
        x[len >> 5] |= 0x80 << (24 - len % 32);
        size = ((len + 64 >> 9) << 4) + 15;
        x = strechbinarray(x, size);
        x[((len + 64 >> 9) << 4) + 15] = len;

        int[] w = new int[80];
        int a = 1732584193;
        int b = -271733879;
        int c = -1732584194;
        int d = 271733878;
        int e = -1009589776;

        for (int i = 0; i < x.length; i += 16) {
            int olda = a;
            int oldb = b;
            int oldc = c;
            int oldd = d;
            int olde = e;

            for (int j = 0; j < 80; j++) {
                if (j < 16) {
                    w[j] = x[i + j];
                } else {
                    w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
                }

                int t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));

                e = d;
                d = c;
                c = rol(b, 30);
                b = a;
                a = t;
            }

            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd);
            e = safe_add(e, olde);
        }

        int[] retval = new int[5];

        retval[0] = a;
        retval[1] = b;
        retval[2] = c;
        retval[3] = d;
        retval[4] = e;

        return retval;
    }

    private static void dotest() {
        String key = "key";
        String data = "data";
        System.out.println("hex_sha1(" + data + ")=" + hex_sha1(data));
        System.out.println("b64_sha1(" + data + ")=" + b64_sha1(data));
        System.out.println("str_sha1(" + data + ")=" + str_sha1(data));
        System.out.println("hex_hmac_sha1(" + key + "," + data + ")=" + hex_hmac_sha1(key, data));
        System.out.println("b64_hmac_sha1(" + key + "," + data + ")=" + b64_hmac_sha1(key, data));
        System.out.println("str_hmac_sha1(" + key + "," + data + ")=" + str_hmac_sha1(key, data));
    }

    public static String hex_hmac_sha1(String key, String data) {
        return binb2hex(core_hmac_sha1(key, data));
    }

    private static int rol(int num, int cnt) {
        return (num << cnt) | (num >>> (32 - cnt));
    }

    private static int safe_add(int x, int y) {
        int lsw = (int) (x & 0xffff) + (int) (y & 0xffff);
        int msw = (x >> 16) + (y >> 16) + (lsw >> 16);

        return (msw << 16) | (lsw & 0xffff);
    }

    private static int sha1_ft(int t, int b, int c, int d) {
        if (t < 20)
            return (b & c) | ((~b) & d);

        if (t < 40)
            return b ^ c ^ d;

        if (t < 60)
            return (b & c) | (b & d) | (c & d);

        return b ^ c ^ d;
    }

    private static int sha1_kt(int t) {
        return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
    }

    private static boolean sha1_vm_test() {
        return hexcase ? hex_sha1("abc").equals("a9993e364706816aba3e25717850c26c9cd0d89d") : hex_sha1("abc").equals(
                "a9993e364706816aba3e25717850c26c9cd0d89d");
    }

    public static String str_hmac_sha1(String key, String data) {
        return binb2str(core_hmac_sha1(key, data));
    }

    public static String str_sha1(String s) {
        s = (s == null) ? "" : s;

        return binb2str(core_sha1(str2binb(s), s.length() * chrsz));
    }

    private static int[] str2binb(String str) {
        str = (str == null) ? "" : str;

        int[] tmp = new int[str.length() * chrsz];
        int mask = (1 << chrsz) - 1;

        for (int i = 0; i < str.length() * chrsz; i += chrsz) {
            tmp[i >> 5] |= ((int) (str.charAt(i / chrsz)) & mask) << (24 - i % 32);
        }

        int len = 0;
        for (int i = 0; i < tmp.length && tmp[i] != 0; i++, len++)
            ;

        int[] bin = new int[len];

        for (int i = 0; i < len; i++) {
            bin[i] = tmp[i];
        }

        return bin;
    }

    private static int[] strechbinarray(int[] oldbin, int size) {
        int currlen = oldbin.length;

        if (currlen >= size + 1) {
            return oldbin;
        }

        int[] newbin = new int[size + 1];
        for (int i = 0; i < size; newbin[i] = 0, i++)
            ;

        for (int i = 0; i < currlen; i++) {
            newbin[i] = oldbin[i];
        }

        return newbin;
    }

    public static void main(String[] args) {
        System.out.println("admin的SHA1的值为:" + hex_sha1("123") + ",length=" + hex_sha1("admin").length());
    }
}
比较依据MD5SHA1
代表信息摘要安全哈希算法
信息摘要的长度128位160位
识别原始消息将需要2 的128次幂操作2的160次幂操作
查找两条生成相同消息摘要的消息需要2的64次幂操作需要2的80次幂操作
安全较差的中等
速度快速

可逆加密

介绍

对称加密解密

非对称加密解密

非对称 就是 商家 生成 公钥 和私钥
公钥 给用户 让用户进行加密 后将加密后的 密文 发给商家
商家在利用私钥进行解密 (有效防止窃取)

对称加密:双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密。

优点:速度快,对称性加密通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。

缺点:在数据传送前,发送方和接收方必须商定好秘钥,然后 使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘 钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。

在对称加密算法中常用的算法有:DES、AES等。

AES:密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节

DES:密钥的长度64位,8个字节。

非对称加密:一对密钥由公钥和私钥组成(可以使用很多对密钥)。私钥解密公钥加密数据,公钥解密私钥加密数据(私钥公钥可以互相加密解密)。

私钥只能由一方保管,不能外泄。公钥可以交给任何请求方。

在非对称加密算法中常用的算法有:

RSA、Elgamal、背包算法、Rabin、Diffie-Hellman、ECC(椭圆曲线加密算法)。
使用最广泛的是RSA算法,Elgamal是另一种常用的非对称加密算法。

缺点:速度较慢

优点:安全

对称加密解密

AES
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AESUtil {
    public static final String AES = "AES";
    public static final String charset = "UTF-8"; // 编码格式
    public static final int keysizeAES = 128;

    private static AESUtil instance;

    private AESUtil() {
    }

    // 单例
    public static AESUtil getInstance() {
        if (instance == null) {
            synchronized (AESUtil.class) {
                if (instance == null) {
                    instance = new AESUtil();
                }
            }
        }
        return instance;
    }

    /** * 使用 AES 进行加密 */
    public String encode(String res, String key) {
        return keyGeneratorES(res, AES, key, keysizeAES, true);
    }

    /** * 使用 AES 进行解密 */
    public String decode(String res, String key) {
        return keyGeneratorES(res, AES, key, keysizeAES, false);
    }

    // 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错
    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(algorithm);
            if (keysize == 0) {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(new SecureRandom(keyBytes));
            } else if (key == null) {
                kg.init(keysize);
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(keysize, new SecureRandom(keyBytes));
            }
            SecretKey sk = kg.generateKey();
            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            if (isEncode) {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
                return parseByte2HexStr(cipher.doFinal(resBytes));
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
                return new String(cipher.doFinal(parseHexStr2Byte(res)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 将二进制转换成16进制
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // 将16进制转换为二进制
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) {
        AESUtil instance = AESUtil.getInstance();
        //加密
        String jiami = instance.encode("hu867682752", "aaa");
        System.out.println(jiami);
        //解密
        String jiemi= instance.decode(jiami, "aaa");
        System.out.println(jiemi);

    }
}
DES
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class DESUtil {
    public static final String DES = "DES";
    public static final String charset = "UTF-8"; // 编码格式;默认null为GBK
    public static final int keysizeDES = 0;

    private static DESUtil instance;

    private DESUtil() {
    }

    // 单例
    public static DESUtil getInstance() {
        if (instance == null) {
            synchronized (DESUtil.class) {
                if (instance == null) {
                    instance = new DESUtil();
                }
            }
        }
        return instance;
    }

    /** * 使用 DES 进行加密 */
    public String encode(String res, String key) {
        return keyGeneratorES(res, DES, key, keysizeDES, true);
    }

    /** * 使用 DES 进行解密 */
    public String decode(String res, String key) {
        return keyGeneratorES(res, DES, key, keysizeDES, false);
    }

    // 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错
    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {
        try {
            KeyGenerator kg = KeyGenerator.getInstance(algorithm);
            if (keysize == 0) {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(new SecureRandom(keyBytes));
            } else if (key == null) {
                kg.init(keysize);
            } else {
                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);
                kg.init(keysize, new SecureRandom(keyBytes));
            }
            SecretKey sk = kg.generateKey();
            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            if (isEncode) {
                cipher.init(Cipher.ENCRYPT_MODE, sks);
                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);
                return parseByte2HexStr(cipher.doFinal(resBytes));
            } else {
                cipher.init(Cipher.DECRYPT_MODE, sks);
                return new String(cipher.doFinal(parseHexStr2Byte(res)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 将二进制转换成16进制
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // 将16进制转换为二进制
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) {
        DESUtil instance= DESUtil.getInstance();
          String jiami=  instance.encode("12345abc67","abc");
          System.out.println(jiami);
          String jiemi=instance.decode(jiami,"abc");
          System.out.println(jiemi);

    }
}
XOR
public class XORUtil {
    private static XORUtil instance;

    private XORUtil() {
    }

    // 单例
    public static XORUtil getInstance() {
        if (instance == null) {
            synchronized (XORUtil.class) {
                if (instance == null) {
                    instance = new XORUtil();
                }
            }
        }
        return instance;
    }

    /** * 对一个数字进行异或加解密 */
    public int code(int res, String key) {
        return res ^ key.hashCode();
    }

    /** * 异或加密 */
    public String encode(String res, String key) {
        byte[] bs = res.getBytes();
        for (int i = 0; i < bs.length; i++) {
            bs[i] = (byte) ((bs[i]) ^ key.hashCode());
        }
        return parseByte2HexStr(bs);
    }

    /** * 异或解密 */
    public String decode(String res, String key) {
        byte[] bs = parseHexStr2Byte(res);
        for (int i = 0; i < bs.length; i++) {
            bs[i] = (byte) ((bs[i]) ^ key.hashCode());
        }
        return new String(bs);
    }

    // 将二进制转换成16进制
    private String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    // 将16进制转换为二进制
    private byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) {

        XORUtil  instance=  XORUtil.getInstance();
       String jiami= instance.encode("124ff","abc");
        System.out.println(jiami);
        String jiemi = instance.decode(jiami,"abc");
        System.out.println(jiemi);
//针对 纯数字 进行加密 和解密
        int num_jiami= instance.code(543,"abv");
        System.out.println(num_jiami);
        int num_jiemi= instance.code(num_jiami,"abv");
        System.out.println(num_jiemi);

    }
}

非对称

RSA后端工具
import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/** * @author yihur * @description RSA加密 * @date 2019/4/3 */
public class RSAUtils {

//前端使用方法
//<script src="js/jsencrypt.js"></script>
// function encryptRequest( text) {
// var encrypt=new JSEncrypt();
// encrypt.setPrivateKey("公秘钥");
			//生成密文
// alert(encrypt.encrypt(text))
// }

    /** * 用于封装随机产生的公钥与私钥 * * @author yihur * @date 2019/4/4 * @param * @return */
    private static Map<Integer, String> keyMap = new HashMap<>();



    /** * 随机生成密钥对 * * @param * @return void * @author yihur * @date 2019/4/4 */
    public static void genKeyPair() {
        // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        KeyPairGenerator keyPairGen = null;
        try {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();

        }
        // 初始化密钥对生成器,密钥大小为96-1024位
        assert keyPairGen != null;
        keyPairGen.initialize(1024, new SecureRandom());
        // 生成一个密钥对,保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私钥字符串
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        // 将公钥和私钥保存到Map
        keyMap.put(0, publicKeyString);  //0表示公钥
        keyMap.put(1, privateKeyString);  //1表示私钥
    }

    /** * RSA公钥加密 * * @param str 加密字符串 * @param publicKey 公钥 * @return 密文 */
    public static String encrypt(String str, String publicKey) {
        //base64编码的公钥
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = null;
        String outStr = null;
        try {
            pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
        } catch (InvalidKeySpecException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException | NoSuchPaddingException | NoSuchAlgorithmException e) {
            e.printStackTrace();

        }
        //RSA加密
        return outStr;
    }

    /** * RSA私钥解密 * * @param str 加密字符串 * @param privateKey 私钥 * @return 铭文 */
    public static String decrypt(String str, String privateKey) {
        //64位解码加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        //base64编码的私钥
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = null;
        //RSA解密
        Cipher cipher = null;
        String outStr = null;
        try {
            priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            outStr = new String(cipher.doFinal(inputByte));
        } catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
            e.printStackTrace();

        }
        return outStr;
    }

    public static void main(String[] args) {
        //生成公钥和私钥
        genKeyPair();
        String  publicKey=keyMap.get(0);
        String  privateKey=keyMap.get(1);
        //加密字符串
        String message = "df723820";
        System.out.println("随机生成的公钥为:" + publicKey);
        System.out.println("随机生成的私钥为:" + privateKey);
        //加密 生成密文
        String messageEn = encrypt(message, publicKey);
        System.out.println("加密后的字符串为:" + messageEn);
        //解密
        String messageDe = decrypt(messageEn, privateKey);
        System.out.println("还原后的字符串为:" + messageDe);
    }

}
RSA 前端工具

jsencrypt.js

链接:https://pan.baidu.com/s/1p4bTF8w_nw5pBieIr_EFyA
提取码:1234

前端-后端 使用RSA

使用步骤
后端 生成公钥和私秘钥
前端 利用公秘钥 生成密文 传递给后端
后端在 利用私秘钥 解析密文

当然前端也是可以生成公钥和私秘钥 但是不安全 一般都是交给后端

公秘钥和私密钥生成

前端
生成公秘钥和私密钥 和使用

var encrypt=new JSEncrypt();
    var  publicKey = encrypt.getPublicKey();
    var privateKey = encrypt.getPrivateKey();
    alert("公钥\n"+publicKey)
    alert("私钥\n"+privateKey)

//前端使用方法
<script src="js/jsencrypt.js"></script>
	<script>
       function encryptRequest( text) {
        var encrypt=new JSEncrypt();
       encrypt.setPrivateKey("公秘钥");
			//生成密文
       alert(encrypt.encrypt(text))
    }
    
    </script>

后端

生成公秘钥和私密钥 和使用

//生成公钥和私钥
   public static void main(String[] args) {
        //生成公钥和私钥
        genKeyPair();
        String  publicKey=keyMap.get(0);
        String  privateKey=keyMap.get(1);
        //加密字符串
        String message = "df723820";
        System.out.println("随机生成的公钥为:" + publicKey);
        System.out.println("随机生成的私钥为:" + privateKey);
        //利用公秘钥加密 生成密文 (这一步可以放到前端 )
        String messageEn = encrypt(message, publicKey);
        System.out.println("加密后的字符串为:" + messageEn);
        //解密 (传来的密文 利用私钥 解析出来 )
        String messageDe = decrypt(messageEn, privateKey);
        System.out.println("还原后的字符串为:" + messageDe);
    }

使用对称AES加密文件案例

文本类型加密-和解密(快速)

需要导入AESUtil工具类

然后添加以下内容

package com.bda.www.aa;

import java.beans.beancontext.BeanContext;
import java.io.*;
import java.util.*;

public class file_jia_mi__jie_mi_Wen_ben {

/* * 注意事项 加密后 会将原文件 删除 可以修改 * 解密后也会将 原文件删除 可以修改 * */
                //缓存大小
                private static final int HUAN_CHUN=10000;

    private static AESUtil instance = AESUtil.getInstance();

    public static boolean jiami(String fileName, String key) {
        long startTime = System.currentTimeMillis();
        int b = fileName.lastIndexOf(".");
        String b2 = fileName.substring(0,b); //获取.前面内容

        int bf = fileName.lastIndexOf(".");
        String bf1 = fileName.substring(bf); //获取后缀

        String file_luj=b2+"_encrypt_"+bf1;
        try(
                BufferedReader   br = new BufferedReader(new InputStreamReader(new FileInputStream(
                        new File(fileName))));
                BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(new File(file_luj))));

        ) {
            StringBuilder stringBuilder=new StringBuilder();
            String line=br.readLine();
            int i=0;
            boolean pd=false;
            int num=0;
            while(true) {
                stringBuilder.append(line+"\n");
                if(i==HUAN_CHUN){
                    bw.write(instance.encode(stringBuilder.toString(),key)+"\n");  //写入
                    i=0;
                    stringBuilder=new StringBuilder();
                    pd=true;
                    num++;
                }
                i++;

                line=br.readLine();//循环每次读取一行数据
                if (line==null){
                    if (!pd){
                        bw.write(instance.encode(stringBuilder.toString(),key)+"\n");  //写入
                        num++;
                    }
                    break;
                }
                pd=false;
            }
            System.out.println("一共写入了几次"+num);

        } catch (IOException e) {
            e.printStackTrace();
         return false;
        }
        //删除加密前文件
        File file1 = new File(fileName);
        file1.delete();

        //想命名的原文件的路径
        File file = new File(file_luj);
        String rootPath = file.getParent();
        String a=rootPath + File.separator + "_encrypt_"+Name_tuP()+bf1;
        System.out.println(a);
        //将原文件更改为f:\a\b.xlsx,其中路径是必要的。注意
        file.renameTo(new File( a));
        file.delete();  //删除原文件
        long endTime = System.currentTimeMillis();
        System.out.println("加密花费时间为:" + (endTime - startTime));
        return true;

    }

    public static boolean jiemi(String fileName, String key) {
        //将二进制转换为 字符
        // 然后 解密
        // 在 二进制写入
        long startTime = System.currentTimeMillis();
        int b = fileName.lastIndexOf(".");
        String b2 = fileName.substring(0,b); //获取.前面内容

        int bf = fileName.lastIndexOf(".");
        String bf1 = fileName.substring(bf); //获取后缀

        String file_luj=b2+"_decode_"+bf1;
        try(
                BufferedReader   br = new BufferedReader(new InputStreamReader(new FileInputStream(
                        new File(fileName))));
                BufferedWriter   bw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(new File(file_luj))));
        ) {
            StringBuilder stringBuilder=new StringBuilder();
            String line=br.readLine();
            int i=0;
            boolean pd=false;
            int num=0;
            while(true) {
                stringBuilder.append(instance.decode(line,key));
                if(i==HUAN_CHUN/10){
                    bw.write(stringBuilder.toString());  //写入
                    i=0;
                    stringBuilder=new StringBuilder();
                    pd=true;
                    num++;
                }
                i++;

                line=br.readLine();//循环每次读取一行数据
                if (line==null){
                    if (!pd){
                        bw.write(stringBuilder.toString());  //写入
                        num++;
                    }
                    break;
                }
                pd=false;
            }
            System.out.println("一共写入了几次"+num);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

        //删除加密文件
        File file1 = new File(fileName);
        file1.delete();

        //想命名的原文件的路径
        File file = new File(file_luj);
        String rootPath = file.getParent();
        String a=rootPath + File.separator + "_decode_"+Name_tuP()+bf1;
        System.out.println(a);
        //将原文件更改为f:\a\b.xlsx,其中路径是必要的。注意
        file.renameTo(new File( a));
        file.delete();  //删除原文件

        long endTime = System.currentTimeMillis();
        System.out.println("解密花费时间为:" + (endTime - startTime));
        return true;

    }

    public static String Name_tuP(){
        char[] ch={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
        char[] Ch={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
        Calendar cal = Calendar.getInstance();
        Random sun=new Random();

        int num1=sun.nextInt(1000);//0-1000随机数
        StringBuilder time=new StringBuilder();
        time.append(num1+"-");//随机数
        time.append(cal.get(Calendar.YEAR)); //年
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.MONTH) + 1);//月
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.DAY_OF_MONTH));//日
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.HOUR_OF_DAY));//时
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.MINUTE));//分
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.SECOND));//秒
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]+"-");
        int num=sun.nextInt(1000);//0-1000随机数
        time.append(num);//随机数
        return time.toString();
    }
}

使用

import org.junit.Test;

public class test {

//必须是txt文件

    @Test
    public void tes(){
        //filename 路径 key 秘钥
        boolean pd= file_jia_mi__jie_mi_Wen_ben.jiami("加密的文件","aaa");
        if(pd){
            System.out.println("加密成功");
        }else{
            System.out.println("加密失败");
        }
    }

//解密
   @Test
    public void ss(){
             //filename 文件路径 key秘钥(要和加密的秘钥对应) 
        boolean pd1= file_jia_mi__jie_mi_Wen_ben.jiemi("解密的文件","aaa");

            if(pd1){
                System.out.println("解密成功");
            }else{
                System.out.println("解密失败");
            }
   }
}

加密视频图片等大型文件和解密(慢)

需要导入AESUtil工具类

然后添加以下内容

import java.io.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;

public class file_jia_mi__jie_mi_erjinzhi {
    private static AESUtil instance = AESUtil.getInstance();

    public static boolean jiami(String fileName, String key) {

        int b = fileName.lastIndexOf(".");
        String b2 = fileName.substring(0,b); //获取.前面内容
        String file_luj=b2+"_"+Name_tuP()+".txt";

        List<String> str = new ArrayList<>();
        try (
                FileInputStream fileInputStream = new FileInputStream(fileName);
                DataInputStream dataInputStream = new DataInputStream(fileInputStream);
                FileWriter fileWriter = new FileWriter(file_luj);
                BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        ) {

            int data;
            while ((data = dataInputStream.read()) != -1) {
                bufferedWriter.write(instance.encode(String.valueOf(data),key)+"\n");
            }

            return true;
        } catch (IOException e) {
            return false;
        }finally {
            File file = new File(fileName);
            file.delete();
        }

    }

    public static boolean jiemi(String fileName,String key,String  suffix){
        int bf = fileName.lastIndexOf(".");
        String bf1 = fileName.substring(bf+1); //获取后缀
        if (!bf1.equals("txt")){
            System.out.println("不能解密此类型文件,只能解密 加密后的txt文本文件");
            return  false;
        }

        int b = fileName.lastIndexOf(".");
        String b2 = fileName.substring(0,b); //获取.前面内容路径
        String file_luj=b2+"_"+Name_tuP()+"."+suffix;
        //解密 将文件内的加密信息读取出来 然后解密完 在覆盖回去

        try(
                FileReader fr=new FileReader(fileName);
                BufferedReader br=new BufferedReader(fr);
                FileOutputStream fileOutputStream=new FileOutputStream(file_luj);
                DataOutputStream dataOutputStream=new DataOutputStream(fileOutputStream);
        ) {

            String line=br.readLine();
            while(line!=null) {
                dataOutputStream.write(Integer.parseInt( instance.decode(line.toString(), key)));
                line=br.readLine();//循环每次读取一行数据
            }

            //删除原文件

            return true;

        } catch (IOException e) {
            return false;
        }finally {
            File file = new File(fileName);
            file.delete();
        }



    }
    public static String Name_tuP(){
        char[] ch={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
        char[] Ch={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
        Calendar cal = Calendar.getInstance();
        Random sun=new Random();

        int num1=sun.nextInt(1000);//0-1000随机数
        StringBuilder time=new StringBuilder();
        time.append(num1+"-");//随机数
        time.append(cal.get(Calendar.YEAR)); //年
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.MONTH) + 1);//月
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.DAY_OF_MONTH));//日
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.HOUR_OF_DAY));//时
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.MINUTE));//分
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]);
        time.append(cal.get(Calendar.SECOND));//秒
        time.append(ch[sun.nextInt(ch.length)]);
        time.append(Ch[sun.nextInt(ch.length)]+"-");
        int num=sun.nextInt(1000);//0-1000随机数
        time.append(num);//随机数
        return time.toString();
    }


}
import org.junit.Test;

public class test {

//12.3mb的视频加密后 的文件大小 400mb左右 大约在32倍左右
//148kb 图片加密后 的文件大小 4.79 mb左右 大约在32倍左右
    //可以看出来 加密文件的大小会是 原文件的 32倍大小
    public static void main(String[] args) {
        //filename 路径 key 秘钥
      boolean pd= file_jia_mi__jie_mi_erjinzhi.jiami("加密文件","aaa");

            if(pd){
                System.out.println("加密成功");
            }else{
                System.out.println("加密失败");
            }
   }

    @Test
    public void jiemi(){
        // filename 文件路径 key秘钥(要和加密的秘钥对应) suffix 生成的文件的后缀名(也就是文件类型)
        // //这里注意的是别瞎搞 加密前的文件是什么类型 解密后也进量是什么类型 比如png(加密前)=png(解密后) 否则有可能出现生成失败的情况
        boolean pd= file_jia_mi__jie_mi_erjinzhi.jiemi("解密文件","aaa","png");

        if(pd){
            System.out.println("解密成功");
        }else{
            System.out.println("解密失败");
        }
   }

}

相关文章