一种基于MD5和Base64的简单算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36143023/article/details/80622763

一、介绍

这是一次信息系统防护课程的作业,老师是邹海涛老师。要求是自己设计一个加密算法,我们小组设计的算法如下。

二、背景知识

(1)算法的提出

        在信息系统防护的课程上,讲了MD5加密算法,MD5是计算机安全领域广泛使用的一种散列函数,可以产生信息摘要,可以提供消息的完整性保护,同时MD5也是不可逆的单向加密算法。MD5用来进行文件校验的方案大量用于软件下载站、论坛数据库、系统文件安全等方面。

        然而,随着快速MD5碰撞生成器的产生,单纯的MD5其实并不可靠。

        因此,我们组设计出一种将MD5产生的摘要做二次处理,以增强安全性形成新的算法,解决了单纯MD5加密易被破解的问题。

        设计并没有就此结束。在加密的最后阶段,明文与最终的密码表之间如果用简单的数值对应实则不够安全。在这里,我们再次设计了一个类似于Base64的加密算法。Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,是二进制到字符的过程,可用于在HTTP环境下传递较长的信息标识。

        准确的说,我们参考Base64设计的加密方式严格来讲并不是一种真正的加密算法,而是一种改进版的更具安全性的自定义的对应法则,这也加强了安全性。

(2)关于MD5

        MD5算法的全名是Message DigestAlgorithm MD5,中文名为消息摘要算法第五版。是为计算机安全领域广泛使用的一种散列函数,用以提高消息的完整性保护。MD5是MD4算法的增强版,1991年由Rivest开发。MD5提供一致性验证、数字签名、安全访问认证。是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。不管是MD2、MD4还是MD5,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但MD2的设计与MD4和MD5完全不同,那是因为MD2是为8位机器做过设计优化的,而MD4和MD5却是面向32位的电脑。这三个算法的描述和C语言源代码在Internet RFCs 1321中有详细的描述,这是一份最权威的文档,由Ronald L. Rivest在1992年8月向IETF提交。

        但是MD5的弱点也被发现。2004年8月17日的美国加州圣巴巴拉的国际密码学会议(Crypto’2004)上,来自中国山东大学的王小云教授做了破译MD5、HAVAL-128、 MD4和RIPEMD算法的报告,公布了MD系列算法的破解结果。宣告了固若金汤的世界通行密码标准MD5的堡垒轰然倒塌,引发了密码学界的轩然大波。(注意:并非是真正的破解,只是加速了杂凑冲撞)

        在实际应用当中,MD5凭借其方便存储、文件完整性验证、不可逆、加密损耗低等优点,广泛被应用于用户加密、请求参数校验、文件校验等场景中发挥着重要作用,在日常的开发中MD5校验技术能有效地避免一些安全问题。

(3)关于Base64

        Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,需要解码后才能阅读。

        Base64是用64个可打印字符表示二进制所有数据方法。由于2的6次方等于64,所以可以用每6个位元为一个单元,对应某个可打印字符。我们知道三个字节有24个位元,就可以刚好对应于4个Base64单元,即3个字节需要用4个Base64的可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中一般有所不同。但是,我们经常所说的Base64另外2个字符是:“+/”。这64个字符。


        另外,在 转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。如果数据不足3byte的话,缓冲区中剩下的bit用0来补足。

三、流程简介

(1)先设计一个原始密码表和一个密钥

(2)用MD5对密钥进行加密,hash出一个32位字符串的MD5

(3)再用这个32位的MD5字符串对原来的密码表进行加密,其中的加密规则是我们组自行设计的

(4)最后得到一个全新的密码表

(5)将待加密的明文转ASCII,然后将每个字节的二进制位拼接,不足的位数从左侧补0,再每5位分隔得到十进制的数字

(6)用刚才得到的数字作为下标从(4)中的密码表中取出对应字符即完成了对明文的加密

四、 程序

# 初始化密码表

原始密码表为


abcdefghijklmnop 
qrstuvwxyzABCDEF  


将密钥通过md5生成32位的hash,然后每4位为一组  
第一排密码表的第1位和第2位交换  
第二排密码表的第3位和第4位交换

# 加密
将明文转ASCII,然后将每个字节的二进制位拼接,再每5位分隔得到数字,不足的位数从左侧补0
形如  
abc->110000111000101100011
->00110 00010 11000 10011 00011
->6 2 24 19 3

用刚才得到的数字作为下标从密码表中取出对应字符即可

# 解密
同理生成密码表后通过密文找到下标,然后转成二进制拼接,再从右向左每8位合成字符即可

py3代码:

	import hashlib
	


	# Create Table
	def CT(key):
	    oritable = [i for i in "abcdefghijklmnopqrstuvwxyzABCDEF"]
	    h = hashlib.md5(key).digest().hex()
	    for i in range(len(h)//2):
	        p = int(h[i], 16) + i%2*16
	        q = int(h[i+1], 16) + i%2*16
	        oritable[p], oritable[q] = oritable[q], oritable[p]
	    table = "".join(oritable)
	    print("table: ", table)
	    return table
	


	# Encrypt
	def encrypt(text, key):
	    table = CT(key)
	    c = ""
	
	    f = bin(int(text.hex(), 16))[2:]
	    print(f)
	    f = (5-len(f)%5)*'0' + f
	    print(f)
	    for i in range(len(f)//5):
	        p = f[5*i:5*i+5]
	        print(p, end='\t')
	        p = int(p, 2)
	        print(p, end='\t')
	        print(table[p])
	        c += table[p]
	    print("cipher: ", c)
	    return c
	
	
	# Decrypt
	def find(x, table):
	    return table.index(x)
	
	
	def decrypt(c, key):
	    table = CT(key)
	    p = ""
	    for i in c:
	        p += bin(find(i, table))[2:].zfill(5)
	    print(p)
	    return bytes.fromhex(hex(int(p, 2))[2:])
	
	# Example
	text = b"this is plain"
	key = b"this is key"
	c = encrypt(text, key)
	print("decrypt: ", decrypt(c, key))


猜你喜欢

转载自blog.csdn.net/qq_36143023/article/details/80622763