基于Java的SHA-1算法原生不调库实现

1 sha-1的核心计算类

package com.encryption.presentationTool.encryptionTool;

import java.util.Arrays;

public class SHA1 {
    private static final boolean hexcase = false;

    private static final String b64pad = "=";

    private static final int chrsz = 8;

// 得到字符串SHA-1值的方法

    public  String hex_sha1(String s) {
        s = (s == null) ? "" : s;
        int[][] result = core_sha1(str2binb(s), s.length() * chrsz);
        int[] final_result = new int[5];
        for (int i = 0; i <5 ; i++){
            final_result[i] = result[0][i];
        }
        return binb2hex(final_result);
    }

    public  String binb2b64(int[] binarray) {
        String tab = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789+/";
        StringBuilder str = new StringBuilder();
        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.append(b64pad);
                } else {
                    str.append(tab.charAt((triplet >> 6 * (3 - j)) & 0x3f));
                }
            }
        }
        return cleanb64str(str.toString());
    }

    public String binb2hex(int[] binarray) {
        String hex_tab = hexcase ? "0123456789abcdef" : "0123456789abcdef";
        StringBuilder str = new StringBuilder();
        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.append(Character.toString(a)).append(Character.toString(b));
        }

        return str.toString();
    }


    public String cleanb64str(String str) {
        str = (str == null) ? "" : str;
        int len = str.length();
        if (len <= 1) {
            return str;
        }
        char trailchar = str.charAt(len - 1);
        StringBuilder trailstr = new StringBuilder();
        for (int i = len - 1; i >= 0 && str.charAt(i) == trailchar; i--) {
            trailstr.append(str.charAt(i));
        }
        return str.substring(0, str.indexOf(trailstr.toString()));
    }

    /**
     * 原文填充为完整的512bit分组长度的16进制字符串
     * @param x
     * @param len
     * @return
     */
    public String getInputStretchHexStr(int[] x, int len){
        System.out.println("x:"+ Arrays.toString(x)+"len:"+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); // 原文尾部加1
        x[((len + 64 >> 9) << 4) + 15] = len; // 分组末尾加上原文bit长度
        return binb2hex(x);
    }

    /**
     * 执行哈希算法的核心调度类
     * @param x
     * @param len
     * @return retval[0][0-4]:散列结果。10进制,retval[1][0-4]为80轮操作的第一轮结果
     */
    public  int[][] core_sha1(int[] x, int len) {
        int[][] retval = new int[2][5];
        System.out.println("x:"+ Arrays.toString(x)+"len:"+len);
        int size = (len >> 5);
        x = strechbinarray(x, size); //填充
//        System.out.println("填充后的x = strechbinarray(x, size):"+ Arrays.toString(x)+"  size:"+size);
        x[len >> 5] |= 0x80 << (24 - len % 32);
        size = ((len + 64 >> 9) << 4) + 15;
//        System.out.println("x[len >> 5] |= 0x80 << (24 - len % 32):"+ x[len >> 5]+"  size:"+size);
        x = strechbinarray(x, size); // 原文尾部加1
//        System.out.println("x = strechbinarray(x, size):"+ Arrays.toString(x)+"  x.len:"+x.length);
        x[((len + 64 >> 9) << 4) + 15] = len; // 分组末尾加上原文bit长度
//        System.out.println("完整填充的x:"+ Arrays.toString(x)+"  x.len:"+x.length);
//        System.out.println("完整填充的x:"+ binb2hex(x) +"  x.len:"+x.length);
        //初始IV变量,共160bit
        int[] w = new int[80];
//        int a = 1732584193; //10进制
//        int b = -271733879;
//        int c = -1732584194;
//        int d = 271733878;
//        int e = -1009589776;
        int a = 0x67452301;
        int b = 0xEFCDAB89;
        int c = 0x98BADCFE;
        int d = 0x10325476;
        int e = 0xC3D2E1F0;
        //512bit分组,每32bit一组,共16组
        for (int i = 0; i < x.length; i += 16) {
            int olda = a;
            int oldb = b;
            int oldc = c;
            int oldd = d;
            int olde = e;
            //每512bit的处理流程
            for (int j = 0; j < 80; j++) {
                //数据扩展:[0,15]  [16,79]
                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;
                retval[1][0] = a;
                retval[1][1] = b;
                retval[1][2] = c;
                retval[1][3] = d;
                retval[1][4] = e;
            }
            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);
        }
        //返回散列的结果,10进制
        retval[0][0] = a;
        retval[0][1] = b;
        retval[0][2] = c;
        retval[0][3] = d;
        retval[0][4] = e;
        return retval;
    }


    //32位二进制数循环左移
    public  int rol(int num, int cnt) {
        return (num << cnt) | (num >>> (32 - cnt));
    }

    //将32位数拆成高16位和低16位分别进行相加,从而实现 mod 2^32 的加法
    public  int safe_add(int x, int y) {
        int lsw = (int) (x & 0xffff) + (int) (y & 0xffff);
        System.out.println("lsw:" + lsw);
        int msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        System.out.println("msw:" + msw);
        return (msw << 16) | (lsw & 0xffff);
    }
    //分块处理中的4个基本逻辑函数:[0,19]  [20,39]  [40,59]  [60,79]
    //返回对应F函数的值
    public  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;
    }
    //返回对应的Kt值
    public  int sha1_kt(int t) {
        return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
    }

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

    }

    //字符串转为二进制数组,只返回有效值,填充的为0的部分不做返回,且返回的值为10进制数
    public  int[] str2binb(String str) {
        str = (str == null) ? "" : str; //判断str是否为空
        int[] tmp = new int[str.length() * chrsz];
        int mask = (1 << chrsz) - 1; //二进制左移8位 ,结果为255
        for (int i = 0; i < str.length() * chrsz; i += chrsz) {
            System.out.println("tmp:"+ Arrays.toString(tmp));
            tmp[i >> 5] |= ((int) (str.charAt(i / chrsz)) & mask) << (24 - i % 32);

        }
        int len = 0;
        System.out.println("tmp.length:"+ tmp.length);
        for (int i = 0; i < tmp.length && tmp[i] != 0; i++, len++); //满足第二个条件时,len++
        System.out.println("tmp:"+ Arrays.toString(tmp));
        System.out.println("len:"+len);
        int[] bin = new int[len];
        for (int i = 0; i < len; i++) {
            bin[i] = tmp[i];
        }
        return bin;
    }

    public  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) {
        SHA1 sha1 = new SHA1();
        System.out.println(sha1.hex_sha1("123456"));
//        int lsw = (int) (12345678 & 0xffff) + (int) (98765432 & 0xffff);
//        System.out.println("12345678 & 0xffff:" + (12345678 & 0xffff));
//        System.out.println("(98765432 & 0xffff):" + (98765432 & 0xffff));
//        System.out.println("(lsw):" + (lsw));
//        int msw = (12345678 >> 16) + (98765432 >> 16) + (lsw >> 16);
//        System.out.println("(12345678 >> 16):" + (12345678 >> 16));
//        System.out.println("(98765432 >> 16):" + (98765432 >> 16));
//        System.out.println("(lsw >> 16):" + (lsw >> 16));
//        System.out.println("msw:" + msw);
//        System.out.println( (msw << 16) | (lsw & 0xffff));
//        System.out.println("(msw << 16):" + (msw << 16));
//        System.out.println("(lsw & 0xffff):" + (lsw & 0xffff));
//        System.out.println("xxxxxxxx:" + ( (msw << 16) | (lsw & 0xffff)));

    }

}

2 直接运行hex_sha1()方法

在这里插入图片描述

3 获得算法的中间过程

3.1 视图(VO)封装类

package com.encryption.presentationTool.VO;

import java.util.Arrays;

/**
 * sha-1散列函数的视图映射
 */
public class SHA1VO {
    //80轮寄存器处理的第一轮结果
    private int[] first_80;

    //80轮寄存器处理的第一轮结果,数组内是int[] first_80对应的16进制
    private String[] first_80_hex;

    //最终的10进制的哈希结果,160bit = 32 * 5
    private int[] retval;

    //最终的base64的哈希结果
    private String retval_base64Str;

    //最终的string[],哈希结果,数组内是int[] retval对应的16进制结果
    private String[] retval_hex;

    //原文
    private String input;

    //原文字符串转为ASCII码16进制字符串
    private String input_hexStr ;

    //原文填充为完整的512bit分组长度的16进制字符串
    private String input_stretch_hexStr;

    public int[] getFirst_80() {
        return first_80;
    }

    public void setFirst_80(int[] first_80) {
        this.first_80 = first_80;
    }

    public String[] getFirst_80_hex() {
        return first_80_hex;
    }

    public void setFirst_80_hex(String[] first_80_hex) {
        this.first_80_hex = first_80_hex;
    }

    public int[] getRetval() {
        return retval;
    }

    public void setRetval(int[] retval) {
        this.retval = retval;
    }

    public String getRetval_base64Str() {
        return retval_base64Str;
    }

    public void setRetval_base64Str(String retval_base64Str) {
        this.retval_base64Str = retval_base64Str;
    }

    public String[] getRetval_hex() {
        return retval_hex;
    }

    public void setRetval_hex(String[] retval_hex) {
        this.retval_hex = retval_hex;
    }

    public String getInput_hexStr() {
        return input_hexStr;
    }

    public void setInput_hexStr(String input_hexStr) {
        this.input_hexStr = input_hexStr;
    }

    public String getInput_stretch_hexStr() {
        return input_stretch_hexStr;
    }

    public void setInput_stretch_hexStr(String input_stretch_hexStr) {
        this.input_stretch_hexStr = input_stretch_hexStr;
    }

    public String getInput() {
        return input;
    }

    public void setInput(String input) {
        this.input = input;
    }

    @Override
    public String toString() {
        return "SHA1VO{" +
                "first_80=" + Arrays.toString(first_80) +
                ", first_80_hex=" + Arrays.toString(first_80_hex) +
                ", retval=" + Arrays.toString(retval) +
                ", retval_base64Str='" + retval_base64Str + '\'' +
                ", retval_hex=" + Arrays.toString(retval_hex) +
                ", input='" + input + '\'' +
                ", input_hexStr='" + input_hexStr + '\'' +
                ", input_stretch_hexStr='" + input_stretch_hexStr + '\'' +
                '}';
    }
}

3.2 调用VO封装计算过程

SHA1VO sha1VO = new SHA1VO();
            //1.原文
            sha1VO.setInput(input);
            //2.原文字符串转为ASCII码16进制字符串
            codeTool codeTool = new codeTool();
            sha1VO.setInput_hexStr(codeTool.strToAsciiHexStr(input));
            //3.原文填充为完整的512bit分组长度的16进制字符串
            SHA1 sha1 = new SHA1();
            sha1VO.setInput_stretch_hexStr(sha1.getInputStretchHexStr(sha1.str2binb(input),input.length() * 8));
            //4.80轮寄存器处理的第一轮结果
            int[][] result = sha1.core_sha1(sha1.str2binb(input),input.length() * 8);
            sha1VO.setFirst_80(result[1]);
            //5.80轮寄存器处理的第一轮结果,数组内是int[] first_80对应的16进制字符串
            sha1VO.setFirst_80_hex(codeTool.intToAsciiHexStr(result[1]));
            //6.最终的10进制的哈希结果,160bit = 32 * 5
            sha1VO.setRetval(result[0]);
            //7.最终的base64的哈希结果
            sha1VO.setRetval_base64Str(sha1.binb2b64(result[0]));
            //8.最终的string[],哈希结果,数组内是int[] retval对应的16进制结果
            sha1VO.setRetval_hex(codeTool.intToAsciiHexStr(result[0]));

3.3 结合前端页面的测试结果

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值