Algorithme de sécurité Java ☞ Résumé Algorithme - MD5, SHA1 Explication détaillée et mise en œuvre

concept:

Qu'est-ce qu'un algorithme de résumé ?

  • La principale caractéristique de l'algorithme de résumé de message est que le processus de cryptage ne nécessite pas de clé et que les données cryptées ne peuvent pas être décryptées.
  • Le même texte chiffré ne peut être obtenu qu'en saisissant les mêmes données en clair via le même algorithme de résumé de message
  • L'algorithme de résumé de message est principalement utilisé dans le domaine de la "signature numérique" comme algorithme de résumé pour le texte en clair
  • Les algorithmes de synthèse courants incluent l'algorithme MD5 et l'algorithme SHA-1 de RSA et un grand nombre de variantes

Quelles sont les caractéristiques de l'algorithme récapitulatif ?

  • Quelle que soit la longueur du message d'entrée, la longueur du résumé de message calculé est toujours fixe
  • Le résumé du message semble être "pseudo-aléatoire". C'est-à-dire que les résultats récapitulatifs pour les mêmes informations sont les mêmes
  • Des modifications mineures du message génèrent des résumés qui peuvent varier considérablement
  • Seul un résumé des informations positives peut être effectué, mais aucune nouvelle ne peut être récupérée à partir des résumés, et aucune information liée aux informations d'origine ne peut être trouvée.

scènes à utiliser

Les scénarios les plus couramment utilisés de l'algorithme de résumé de message sont la signature numérique et le chiffrement des données (mot de passe)

Qu'est-ce qu'une signature numérique

La signature numérique utilise principalement la technologie de cryptage à clé asymétrique et la technologie abstraite numérique. La technologie de signature numérique consiste à crypter les informations récapitulatives avec la clé privée de l'expéditeur et à les transmettre au destinataire avec le texte original. Le récepteur ne peut décrypter les informations récapitulatives cryptées qu'avec la clé publique de l'expéditeur, puis utiliser la fonction HASH pour générer des informations récapitulatives pour le texte original reçu et les comparer avec les informations récapitulatives décryptées. S'ils sont identiques, cela signifie que les informations reçues sont complètes et n'ont pas été modifiées lors de la transmission, sinon cela signifie que les informations ont été modifiées.

Par conséquent, les signatures numériques peuvent vérifier l'intégrité des informations. La signature numérique est un processus de cryptage et la vérification de la signature numérique est un processus de décryptage.

MD5

Qu'est-ce que MD5 ?

Le rôle de MD5 est de permettre aux informations de grande capacité d'être "compressées" dans un format confidentiel avant de signer la clé privée avec un logiciel de signature numérique (c'est-à-dire de convertir une chaîne d'octets de n'importe quelle longueur en une certaine longueur de chaîne de nombres hexadécimaux) .

MD5 a plusieurs caractéristiques :

  • Compressibilité : Pour les données de n'importe quelle longueur, la longueur de la valeur MD5 calculée est fixe.
  • Facile à calculer : Il est facile de calculer la valeur MD5 à partir des données d'origine.
  • Résistance à la modification : Toute modification des données d'origine, même si seulement 1 octet est modifié, entraînera une valeur MD5 très différente.
  • Anti-collision fort : Connaissant la donnée d'origine et sa valeur MD5, il est très difficile de trouver une donnée avec la même valeur MD5 (c'est-à-dire une donnée falsifiée).

Implémentation Java :

1. La classe java.security.MessageDigest implémente l'algorithme 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. Implémentez MD5 par écriture manuscrite :

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'est-ce que SHA1

Pour les messages plus courts que 2^64 bits, SHA1 produit un résumé de message de 160 bits (40 caractères). Lorsqu'un message est reçu, ce résumé de message peut être utilisé pour vérifier l'intégrité des données. Au cours du processus de transmission, les données sont susceptibles de changer, puis différents résumés de messages seront générés à ce moment

  • Il n'est pas possible de récupérer les informations des résumés de messages ;
  • Deux messages différents ne produiront pas le même résumé de message (mais il y aura 1x10^48 chances d'obtenir le même résumé de message, qui est généralement ignoré lorsqu'il est utilisé).

JDK est livré avec une implémentation d'algorithme :

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";
		
	}
}

ok, c'est à peu près tout

Je suppose que tu aimes

Origine blog.csdn.net/a619602087/article/details/130323589
conseillé
Classement