Algoritmo de seguridad de Java ☞ Algoritmo de resumen - MD5, SHA1 Explicación detallada e implementación

concepto:

¿Qué es un algoritmo de resumen?

  • La característica principal del algoritmo de resumen de mensajes es que el proceso de cifrado no requiere una clave y los datos cifrados no se pueden descifrar.
  • El mismo texto cifrado solo se puede obtener ingresando los mismos datos de texto sin formato a través del mismo algoritmo de resumen de mensaje
  • El algoritmo de resumen de mensaje se utiliza principalmente en el campo de la "firma digital" como algoritmo de resumen para texto sin formato
  • Los algoritmos de resumen comunes incluyen el algoritmo MD5 de RSA y el algoritmo SHA-1 y una gran cantidad de variantes

¿Cuáles son las características del algoritmo de resumen?

  • No importa qué tan largo sea el mensaje de entrada, la longitud del resumen del mensaje calculado siempre es fija
  • El resumen del mensaje parece ser "pseudoaleatorio". Es decir, los resultados de resumen para la misma información son los mismos
  • Los cambios menores en el mensaje generan resúmenes que pueden variar mucho
  • Solo se puede realizar un resumen de información positiva, pero no se pueden recuperar noticias de los resúmenes y no se puede encontrar ninguna información relacionada con la información original.

Escenas a utilizar

Los escenarios más utilizados del algoritmo de resumen de mensajes son la firma digital y el cifrado de datos (contraseña).

que es una asignatura digital

La firma digital utiliza principalmente tecnología de cifrado de clave asimétrica y tecnología abstracta digital. La tecnología de firma digital consiste en cifrar la información resumida con la clave privada del remitente y transmitirla al receptor junto con el texto original. El destinatario solo puede descifrar la información de resumen cifrada con la clave pública del remitente y luego usar la función HASH para generar una información de resumen para el texto original recibido y compararla con la información de resumen descifrada. Si son iguales, significa que la información recibida está completa y no ha sido modificada durante la transmisión, de lo contrario, significa que la información ha sido modificada.

Por lo tanto, las firmas digitales pueden verificar la integridad de la información. La firma digital es un proceso de cifrado y la verificación de firma digital es un proceso de descifrado.

MD5

¿Qué es MD5?

La función de MD5 es permitir que la información de gran capacidad se "comprima" en un formato confidencial antes de firmar la clave privada con el software de firma digital (es decir, convertir una cadena de bytes de cualquier longitud en una cierta longitud de cadena de números hexadecimales) .

MD5 tiene varias características:

  • Compresibilidad : para datos de cualquier longitud, la longitud del valor MD5 calculado es fija.
  • Fácil de calcular : es fácil calcular el valor MD5 a partir de los datos originales.
  • Resistencia a la modificación : cualquier modificación de los datos originales, aunque solo se modifique 1 byte, dará como resultado un valor MD5 muy diferente.
  • Fuerte anticolisión : Conociendo los datos originales y su valor MD5, es muy difícil encontrar un dato con el mismo valor MD5 (es decir, datos falsificados).

Implementación Java:

1. La clase java.security.MessageDigest implementa el algoritmo MD5

package com.snailclimb.ks.securityAlgorithm;

import java.security.MessageDigest;

public class MD5Demo {

    // test
    public static void main(String[] args) {
        System.out.println(getMD5Code("hello,world"));
    }

    private MD5Demo() {
    }

    // md5加密
    public static String getMD5Code(String message) {
        String md5Str = "";
        try {
        	//创建MD5算法消息摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            //生成的哈希值的字节数组
            byte[] md5Bytes = md.digest(message.getBytes());
            md5Str = bytes2Hex(md5Bytes);
        }catch(Exception e) {
            e.printStackTrace();
        }
        return md5Str;
    }

    // 2进制转16进制
    public static String bytes2Hex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        int temp;
        try {
            for (int i = 0; i < bytes.length; i++) {
                temp = bytes[i];
                if(temp < 0) {
                    temp += 256;
                }
                if (temp < 16) {
                    result.append("0");
                }
                result.append(Integer.toHexString(temp));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
    }
}

2. Implemente MD5 a mano:

package com.snailclimb.ks.securityAlgorithm;

public class MD5{
    /*
    *四个链接变量
    */
    private final int A=0x67452301;
    private final int B=0xefcdab89;
    private final int C=0x98badcfe;
    private final int D=0x10325476;
    /*
    *ABCD的临时变量
    */
    private int Atemp,Btemp,Ctemp,Dtemp;
     
    /*
    *常量ti
    *公式:floor(abs(sin(i+1))×(2pow32)
    */
    private final int K[]={
        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};
    /*
    *向左位移数,计算方法未知
    */
    private final int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
        12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
        4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
        15,21,6,10,15,21,6,10,15,21,6,10,15,21};
     
     
    /*
    *初始化函数
    */
    private void init(){
        Atemp=A;
        Btemp=B;
        Ctemp=C;
        Dtemp=D;
    }
    /*
    *移动一定位数
    */
    private    int    shift(int a,int s){
        return(a<<s)|(a>>>(32-s));//右移的时候,高位一定要补零,而不是补充符号位
    }
    /*
    *主循环
    */
    private void MainLoop(int M[]){
        int F,g;
        int a=Atemp;
        int b=Btemp;
        int c=Ctemp;
        int d=Dtemp;
        for(int i = 0; i < 64; i ++){
            if(i<16){
                F=(b&c)|((~b)&d);
                g=i;
            }else if(i<32){
                F=(d&b)|((~d)&c);
                g=(5*i+1)%16;
            }else if(i<48){
                F=b^c^d;
                g=(3*i+5)%16;
            }else{
                F=c^(b|(~d));
                g=(7*i)%16;
            }
            int tmp=d;
            d=c;
            c=b;
            b=b+shift(a+F+K[i]+M[g],s[i]);
            a=tmp;
        }
        Atemp=a+Atemp;
        Btemp=b+Btemp;
        Ctemp=c+Ctemp;
        Dtemp=d+Dtemp;
     
    }
    /*
    *填充函数
    *处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
    *填充方式为先加一个0,其它位补零
    *最后加上64位的原来长度
    */
    private int[] add(String str){
        int num=((str.length()+8)/64)+1;//以512位,64个字节为一组
        int strByte[]=new int[num*16];//64/4=16,所以有16个整数
        for(int i=0;i<num*16;i++){//全部初始化0
            strByte[i]=0;
        }
        int    i;
        for(i=0;i<str.length();i++){
            strByte[i>>2]|=str.charAt(i)<<((i%4)*8);//一个整数存储四个字节,小端序
        }
        strByte[i>>2]|=0x80<<((i%4)*8);//尾部添加1
        /*
        *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
        */
        strByte[num*16-2]=str.length()*8;
            return strByte;
    }
    /*
    *调用函数
    */
    public String getMD5(String source){
        init();
        int strByte[]=add(source);
        for(int i=0;i<strByte.length/16;i++){
        int num[]=new int[16];
        for(int j=0;j<16;j++){
            num[j]=strByte[i*16+j];
        }
        MainLoop(num);
        }
        return changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);
     
    }
    /*
    *整数变成16进制字符串
    */
    private String changeHex(int a){
        String str="";
        for(int i=0;i<4;i++){
            str+=String.format("%2s", Integer.toHexString(((a>>i*8)%(1<<8))&0xff)).replace(' ', '0');
 
        }
        return str;
    }
    /*
    *单例
    */
    private static MD5 instance;
    public static MD5 getInstance(){
        if(instance==null){
            instance=new MD5();
        }
        return instance;
    }
     
    private MD5(){};
     
    public static void main(String[] args){
        String str=MD5.getInstance().getMD5("hello,world");
        System.out.println(str);
    }
}

SHA1

¿Qué es SHA1?

Para mensajes de menos de 2^64 bits, SHA1 produce un resumen de mensaje de 160 bits (40 caracteres). Cuando se recibe un mensaje, este resumen de mensaje se puede utilizar para verificar la integridad de los datos. En el proceso de transmisión, es probable que los datos cambien, luego se generarán diferentes resúmenes de mensajes en este momento

  • No es posible recuperar información de resúmenes de mensajes;
  • Dos mensajes diferentes no producirán el mismo resumen de mensaje (pero habrá una posibilidad de 1x10^48 de tener el mismo resumen de mensaje, que generalmente se ignora cuando se usa).

JDK viene con implementación de algoritmo:

package com.snailclimb.ks.securityAlgorithm;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA1Demo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(getSha1("hello,world"));
	
	}

	public static String getSha1(String str) {
		if (null == str || 0 == str.length()) {
			return null;
		}
		char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			//创建SHA1算法消息摘要对象
			MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
			//使用指定的字节数组更新摘要。
			mdTemp.update(str.getBytes("UTF-8"));
			//生成的哈希值的字节数组
			byte[] md = mdTemp.digest();
			//SHA1算法生成信息摘要关键过程
			int j = md.length;
		    char[] buf = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
				buf[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(buf);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "0";
		
	}
}

bien, eso es todo

Supongo que te gusta

Origin blog.csdn.net/a619602087/article/details/130323589
Recomendado
Clasificación