精华内容
下载资源
问答
  • DES算法设计

    2021-03-21 15:16:07
    文章目录一、DES算法介绍1、历史背景2、算法描述3、具体实现3.1、密钥处理3.2、明文加密过程3.2.1、IP置换3.2.2、16轮迭代运算3.2.2.1、E扩展置换函数表和与子密钥异或3.2.2.2、S盒变换3.2.2.3、P盒变换3.2.3、IP-1...

    DES算法设计与问题解决

    山东大学网络空间安全学院

    一、DES算法介绍

    1、历史背景

       数据加密标准DES( data encryption standard)是美国国家标准局(现美国国家标准和技术协会NST)为了满足计算机通信网络的发展对安全保密的要求,实现同一水平的安全性和兼容性,降低数据加密产品的生产成本,推广使用密码算法而公开征集的一种用于政府部门及民间进行计算机数据加密的密码算法。
      NBS最初于1973年5月13日向社会公开发起征集,IBM公司提出的一种称为Lucifer的加密算法,被选为数据加密标准。1977年1月15日DES被正式批准作为美国联邦信息处理标准,即FIP-46,同年7月15日生效。1994年1月NSA(美国国家保密局)对DS进行评估后,決定1998年12月以后将不再使用DES,同时征集新的加密标准AES。

    2、算法描述

       DES是一个16轮的Feistel型结构密码,它的分组长度为64比特,用一个56比特的密钥来加密一个64比特的明文串,输出一个64比特的密文串。其中,使用密钥为64比特,实用56比特,另8位用作奇偶校验。加密的过程是先对64位明文分组进行初始置换,然后分左、右两部分分别经过16轮迭代,然后再进行循环移位与变换,最后进行逆变换得出密文。加密与解密使用相同的密钥,因而它属于对称密码体制。

      图1-1给出了DES过程框图。假设输入的明文数据是64比特。首先经过初始置换IP后把其左半部分32比特记为L0,右半部分32比特记为R0,即成了置换后的输入;然后把R0与密钥产生器产生的子密钥k1进行运算,其结果计为f (R0,k1);再与L0进行摸2加得到L0 \bigoplusf (R0 , k1), 把R0记为L1放在左边,而把L0 \bigoplusf (R0 , k1)记为R1放在右边,从而完成了第一轮迭代运算。在此基础上,重复上述的迭代过程,一直迭代至第16轮。所得的第16轮迭代结果左右不交换,即L15 \bigoplusf (R15 , k16)记为R16,放在左边,而R15记为L16放在右边,成为预输出,最后经过初始置换的逆置换IP-1运算后得到密文。

    在这里插入图片描述

    1-1

    3、具体实现

    3.1、密钥处理

       DES算法共需进行16轮迭代运算,每轮迭代运算使用一个子密钥,共需要16个子密钥。
      首先输入的密码K为64位,但有8位是校验位(8,16,24,32,40,48,56,64),故实际的有效位为56位。
      其次根据PC_1置换表进行第一次的变换生成新的56位比特串,变换表如下所示代码:

    PC_1=[
        57,49,41,33,25,17,9,
        1,58,50,42,34,26,18,
        10,2,59,51,43,35,27,
        19,11,3,60,52,44,36,
        63,55,47,39,31,23,15,
        7,62,54,46,38,30,22,
        14,6,61,53,45,37,29,
        21,13,5,28,20,12,4
    ]
    

       然后再将新得到的比特串分为左右两部分(C1和D1),C1左移k1位,C2左移k2位,其余根据left表的值一次左移相应的位数,同理Di也依次进行相同的变换,得到Ci和Di两组值。

    left = [1, 1, 2, 2, 2, 2, 2, 
            2, 1, 2, 2, 2, 2, 2, 2, 1]
    

      最后将得到的Ci和Di拼接成CDi,然后再将CDi经过PC_2置换表置换得到F函数中使用的16个轮密钥Ki

    PC_2=[14,17,11,24,1,5,
          3,28,15,6,21,10,
          23,19,12,4,26,8,
          16,7,27,20,13,2,
          41,52,31,37,47,55,
          30,40,51,45,33,48,
          44,49,39,56,34,53,
          46,42,50,36,29,32
        ]
    

      密钥生成代码如下:

    ef Subkey(key):    #生成子密钥
        keyresult = []
        key0 = [0 for i in range(56)]
        for i in range(len(key_table1)):
        for i in range(MaxTime):
            key1 = [0 for i in range(48)]
            #确定每次左移的步数
            if (i == 0 or i == 1 or i == 8 or i == 15):
               step = 1
            else:
           key0[i] = key[key_table1[i]-1]
    
       #生成16个密钥
                step = 2
            #分成两组
            tmp1 = key0[0:28]
            tmp2 = key0[28:56]
             #循环左移
            tmp1 = Listmove(tmp1, step)
            tmp2 = Listmove(tmp2, step)
            #左右连接
            key0 = tmp1 + tmp2
           #置换选择
            for i in range(len(key_table2)):
                key1[i] = key0[key_table2[i]-1]
            #生成密钥
            keyresult.append(key1)
        #返回的是一个集合包含了每次的密钥
        return keyresult
    

      生成密钥结果:

    Ki = ['7833C320DA70', '2B1A74CA48D8', 
     '8C78D881D31D', '1667789316A0', 
     'CE5D01D80B25', '4BAB4D126A9C', 
     '09F48B713191', '710DEAA3202B', 
     '129AB83347C3', '9C38661E8103', 
     'A26E4CC66544', '48772468A3C8', 
     'C09D79F0D40B', 'C5E2634E162A',
     'A3DF829C7968', 'A6120B4D4C25']
    

    3.2、明文加密过程

    3.2.1、IP置换

      IP置换又称初始置换,在迭代运算之前,需要将输入的64位明文数据进行初始置换,将次序打乱。

    IP = [
            58, 50, 42, 34, 26, 18, 10, 2, 
            60, 52, 44, 36, 28, 20, 12, 4,
            62, 54, 46, 38, 30, 22, 14, 6, 
            64, 56, 48, 40, 32, 24, 16, 8,
            57, 49, 41, 33, 25, 17, 9, 1, 
            59, 51, 43, 35, 27, 19, 11, 3,
            61, 53, 45, 37, 29, 21, 13, 5, 
            63, 55, 47, 39, 31, 23, 15, 7
    ]
    

    3.2.2、16轮迭代运算

       在每一迭代中,每个64位的中结果被分成左右两部分,而且左右两部分作为相互独立的32位数据进行处理。每轮迭代的输入是上轮的结果Li-1和Ri-1
       Ri-1先由32位扩展到48位,扩展后的48位结果与48位的密钥位的Ki进行异或,得到的结果经过一个S盒替代产生32位的输出,然后再经过一个P盒置换再将得到的结果与Li-1进行简单异或,最后的输出结果作为Ri,而是不经过变换的Ri-1直接得到的。
       Li = Ri -1
       Ri = Li -1\bigoplusF(Ri-1,ki)
       下面将具体介绍迭代运算的各个部分。

    3.2.2.1、E扩展置换函数表和与子密钥异或

      扩展置换将前一轮迭代的结果Ri-1作为输入,根据扩展函数E将32位扩展到48位,扩展函数E将32位的明文每4位分成组,共有8组。每个分组由4位扩展为6位,扩展方法为:每个分组的4位作为6位输出分组的中间4位,6位输出分组中的第1位和第6位分别由相邻的两个4位小分组的最外面两位散进入到本分组产生,其中第1个小分组的左侧相邻分组位最后一个小分组。如E扩展置换表所示

    E = [	32,1,2,3,4,5,4,5,6,7,8,9,
            8,9,10,11,12,13,12,13,14,15,16,17,
            16,17,18,19,20,21,20,21,22,23,24,25,
            24,25,26,27,28,29,28,29,30,31,32,1,
         ]
    

      随机经过E盒扩展置换得到的48位输出与子密钥Ki-1进行异或运算。

    3.2.2.2、S盒变换

      S盒变换是将与子密钥异或得到的结果作为S盒变换的输入,经过变换得到32位的输出,DES加密函数中共有8个S盒每个S盒有4行16列。
      S盒变换的过程为:将与子密钥异或得到48位,每6比特一组,共分成8组,分别作为8个S盒的输入;每一个分组将对应于一个S盒进行变换运算:分组1由S盒1进行变换操作,分组2由盒2操作。。。。。。而且8个S盒所表示的变换运算各不相同。
      如果第i个盒的输入为:Bi=b1b2b3b4b5b6,则S盒变换得到4位输出的过程为:将b1b6和b2b3b4b5作为二进制数,令r=b1b6和c=b2b3b4b5,设第i个S盒中的第r行、c列对应的整数为N,则N的二进制表示就是该s盒在输入为Bi=b1b2b3b4b5b6时对应的4位输出。

    S=[
        14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
        0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
        4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
        15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13
    ]
    
    3.2.2.3、P盒变换

      P盒变换是将输出的32位比特串根据固定的置换p置换到相应的位置。P盒变换运算后得到的输出即为函数F(Ri-1,Ki)的最终结果。

    P=[
        16,7,20,21,29,12,28,17,
        1,15,23,26,5,18,31,10,
        2,8,24,14,32,27,3,9,
        19,13,30,6,22,11,4,25
    ]
    

    3.2.3、IP-1置换

      IP-1置换又称为逆初始置换,结果这一步骤的置换过程即为DES加密算法的密文输出。

    IP_1=[
            40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,
            38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,
            36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,
            34,2,42,10,50,18,58,26,33,1,41, 9,49,17,57,25
    ]
    

    3.2.4、DES代码以及测试运行时间

      IP置换与IP-1置换:

    def IP(text, op):   ##打乱顺序,op=0时为正,op=1时为逆
         tmp = [0 for i in range(64)]
         if op == 0:
             for i in range(64):
                 tmp[i] = text[IP_table[i]-1]
             return tmp
         if op == 1:
             for i in range(64):
                 tmp[i] = text[Inv_IP_table[i]-1]
             return tmp
    

      E扩展:

    def Extend(text):   ##将32位扩展成48位
         extend = [0 for i in range(48)]
         for i in range(48):
             extend[i] = text[extend_table[i] - 1]
         return extend
    

      异或运算:

    def XOR(bit1, bit2):    ##异或运算
         XORresult = [0 for i in range(len(bit1))]
         for i in range(len(bit1)):
             XORresult[i] = str(int(bit1[i]) ^ int(bit2[i]))
         return XORresult
    

      S盒变换:

    def S_replace(text):       ##根据表将48bit->32bit   S盒变换
         Sresult = [0 for k in range(32)]
         for k in range(8):
             row = 2*int(text[k*6]) + int(text[k*6+5])
             column = 8*int(text[k*6+1]) + 4*int(text[k*6+2]) + 2*int(text[k*6+3]) + int(text[k*6+4])
             tmp = S[k][row*16+column]
             for i in range(4):
                 Sresult[4*k + i] = int2bit(tmp)[i]
         return Sresult
    

      P盒变换:

    def P_replace(text):
         Presult = [0 for i in range(32)]
         for i in range(32):
             Presult[i] = text[P_table[i]-1]
         return Presult
    

      经过多次运行代码,得到平均运行速度为0.00606536865234375s,对比之下,加密效率较高。

    4、体会混乱、扩散的概念

    4.1、问题1:DES原轮函数

    在这里插入图片描述
      在原轮函数下,明文1bit的变化,在6轮加密之后,导致了密文将近32位的变化(这无疑是最好的可以隐藏改变的位数的我们所期待的数据),并且这些变化基本上都是均匀分布的,所以DES加密的扩散和混淆是很好的。
      注:为了更加清晰展示32为变化的来源,附加代码如下:

    def bchange(a):
        if(a==1):
            a=0
        else:
            a=1
        return a
    def randomchange(st): #随机更改
        b=bin(int(st,16))[2:]
        slist=list(b)
        le=len(slist)
        x=int(random.random()*le)
        slist[x]=bchange(slist[x])
        fst=" ".join('%s' %i for i in slist)
        fst = ''.join(fst.split())
        return fst
    def count(b1,b2):
        list1=list(b1)
        list2=list(b2)
        num=0
        l=min(len(list2),len(list1))
        for i in range(l):
          if(list1[i]!=list2[i]):
            num=num+1
        return (num)
    ptext=input('请输入明文:')
    x1=bin(int(DES(ptext),16))[2:]
    sumnum=0
    for i in range (10000):
        chtext=randomchange(ptext)
        ctext=bin(int(DES(chtext),16))[2:]
        sumnum=sumnum+count(x1,ctext)
    print(sumnum/10000)
    
    

    4.2、问题2:删除E扩散

    在这里插入图片描述

      在删除E扩散的情况下,明文1bit的变化,在6轮加密之后,导致了密文将近32位的变化,但是这些变化看上去像是均匀分布的,所以在删除E扩散的情况下,扩散效应保持的不错,混淆做的也不差,但是有了E扩散,虽然扩散和混淆的作用并没有显著的提高,但是这加强了我们加密过程的安全性。

    4.3、问题3:删除S-box

    在这里插入图片描述

      在删除S盒之后,明文1bit的变化,在6轮加密之后,导致了密文很少位数的变化,很明显,在删除了S盒之后,DES加密的扩散功能受到了很大的削弱,由于变化的位数过少,我们也不能很容易地判断混淆的作用是否有所影响。换而言之,S盒在DES加密中,对于扩散有着必不可少的作用。

    4.4、问题4:删除P置换

    在这里插入图片描述
      在删除P置换之后,明文1bit的变化,在6轮加密之后,导致了密文将近32位的变化,但是我们通过图可以发现变化的密文位数集中在了明文改变的位数的附近,这样就代表了在删除P置换之后,DES加密混淆效果并不好。换而言之,P置换在DES加密中能够起到很大的混淆作用。

    展开全文
  • 有界面,可以运行,能看出时间对比,支持文本文件
  • 不过其中存在Jni底层资源释放的问题,长时间运行会导致JNI报错使得程序闪退。这一版修改了此Bug。压缩文件内包含编译后的lib3DES.so文件,3DES加密算法的JNI C语言源码,Android的makefile文件等。希望能够帮助到有...
  • 为了得出更真实的运行时间,这里的明文和密钥均为8字节(实际加密解密中多于或者少于8字节都是无关的,明文、密文多了会进行分组,密钥多了会裁切,明文、密文、密钥少于会自动补),经过多次统计平均运行时间,了解...

    1.使用说明

    本程序使用eclipse Java编写。使用该程序可利用eclipse打开源代码文件夹,然后运行MainBody.java即可根据默认的明文和密钥输出加密、解密结果。

    2.运行分析

    为了得出更真实的运行时间,这里的明文和密钥均为8字节(实际加密解密中多于或者少于8字节都是无关的,明文、密文多了会进行分组,密钥多了会裁切,明文、密文、密钥少于会自动补),经过多次统计平均运行时间,了解到加解密所需时间分别是3毫秒和1毫秒。运行截图如下所示。
    在这里插入图片描述

    3.总体设计

    3.1类及函数

    MainBody.java,算法主体部分。构造函数public MainBody(byte[] text, String key, int flag) throws UnsupportedEncodingException,传入明文(密文)、密钥、标识解密或解密。主要用于调用函数产生16个子密钥和对明文(密文)进行分组。main函数用于初始化对象和调用mainbody函数进行加密解密。public byte[] mainBody() throws UnsupportedEncodingException是算法主体部分,主要是对DES算法的各个部分进行实现,返回加密解密后的byte型结果数组。public void eachRound(int[] IP_result, int roundNum)为16轮加密解密中的每一轮的函数,参数分别为IP置换后的结果(也是后一轮的输入)、轮次。
    GenerateSubkeys.java,产生子密钥的类。public static int[][] generateSubkeys(String key) throws UnsupportedEncodingException传入String类型密钥,返回保存16个48位子密钥,用int型二维数组进行保存,形参为密钥。
    GroupText.java,对明文(密文)进行分组的类。public static int[][] groupText(byte[] text_byte) throws UnsupportedEncodingException对传入的明文(密文)分组,以64bit为一组,最后一组不足64bit则补全,以二进制int型数组形式返回分组结果,形参分别是明文(密文)、分组结果。
    FFunction.java,F轮函数类。public static int[] fFuction(int[] r_text, int[] subkey) 输入32bit明文(密文)右半部分、48bit子密钥, 返回32bit结果,形参分别是明文(密文)右半部分、子密钥、输出结果。
    Table.java,存储DES算法所需要的全部置换、压缩、扩展和S盒表。

    3.2结构说明

    在这里插入图片描述

    如上图所示为DES算法的基本流程,根据此流程图结合本实例来说明一下流程。在MainBody构造函数中调用GroupText.groupText()对明文(密文)进行分组,同时根据GenerateSubkeys.generateSubkeys()产生子密钥。利用MainBody.mainBody函数对整体流程进行包装,先是IP置换,然后利用MainBody.eachRound函数实现16轮加密、解密,其中在这16轮加密、解密中对调用轮函数FFunction.fFuction(),最后在MainBody.mainBody函数中进行IP-1逆置换输出加密解密结果。

    4.详细设计

    Table.java类存储置换、压缩、扩展和S盒表。类中的表均为final型,使其成为常量,除了S盒表采用三维int型数组保存(维度分别是盒号、行号、列号),其他表均是采用一维int型数组保存。类中包含的表有PC-1密钥压缩置换表PC_1(用于将64位密钥压缩置换为56位)、PC-2密钥压缩置换表PC_2(用于将56位密钥压缩置换为48位)、左移位数表LEFT_SHIFT(用于生成每轮所需的子密钥时左移的位数)、IP初始置换表IP(将输入的64位数据块按位重新组合)、E扩展表E(目标是IP置换后获得的右半部分R0,将32位输入扩展为48位)、8个S盒表S_BOX(输入的是压缩后的密钥与扩展分组异或以后得到48位的数据,输出32位数据)、P置换表P(用于置换S盒输出的32位)、IP-1逆初始置换表IP_1(用于DES最后一轮的置换)。
    GroupText.java类用于对明文(密文)进行分组。函数groupText通过形参传入byte数组型的明文(密文),先是计算出byte数组的长度,由于DES算法输入的明文(密文)需要是64bit,也就是8byte,因此传入的数据应该是8的整数倍。这里需要先计算要补充字节数,如果需要补充,则新建一个长度为原来的长度加上要补充的字节的长度的byte数组,利用System.arraycopy函数将原来的数据复制到新建的数组,然后利用循环for (int i = 0; i < padding_num; i++) {text_padding[text_byte_length + i] = (byte) padding_num;}在其后面补充数据,补充的数据可任选,这里补充的数据为将补充的字节数转化为byte型进行补充。
    补充完成后以8byte为一组计算出共有几组数据,new一个以维度分别是组数和64的二维数组int型数组用于保存每组的二进制数据。如以下代码所示,

    for (int i = 0; i < group_num; i++) {// 将每组的byte型转化为二进制int型数组返回
    for (int j = 0; j < 8; j++) {// 组内8个字节转为string型二进制数据
    		text_bit_tmp = Integer.toBinaryString(text_padding[i * 8 + j] & 0xff);
    		while (text_bit_tmp.length() % 8 != 0) {
    			text_bit_tmp = "0" + text_bit_tmp;
    		}
    		text_bit += text_bit_tmp;
    	}
    	for (int z = 0; z < 64; z++) {// string型二进制数据转为int型二进制数据
    		int p_t = Integer.valueOf(text_bit.charAt(z));
    		if (p_t == 48) {
    			p_t = 0;
    		} else {// p_t== 49
    			p_t = 1;
    		}
    		group_result_int[i][z] = p_t;
    	}
    
    	text_bit = "";
    	text_bit_tmp = "";
    }
    

    以组数为大循环,逐组进行byte转化为二进制int数据的操作,首先分别将组内的8个byte型数据和0xff(16进制255表示)进行与操作之后利用Integer.toBinaryString()函数将它们的结果转为二进制字符串,也就是byte型的二进制形式,然后检查转化后的长度是否为8位,如果不是则需要在其前面补充0字符串,这样的操作后每组就会生成64长度的string类型的二进制数据。之后再利用64次循环,利用Integer.valueOf检查其中的数据,如果是48则为0,49则为1,然后将0或1保存到之前初始化的int型数组。以同样的操作对每组进行转化后返回结果即可。
    GenerateSubkeys.java类用于产生子密钥。形参传入string类型的密钥,转化为byte数组之后检查其长度是否到8字节,如果不足则上相同的密钥,直到足8字节为止。以类似于明文(密文)分组的步骤,将其转化为二进制int数组存储,这里就不再说明,最后的结果是将这8字节byte数组的密钥转化为64长度的int型二进制数组,接着利用PC_1压缩置换表进行压缩置换,利用System.arraycopy函数将56位的数据平分为左右两部分,在16次循环中逐个产生16个子密钥,根据左移位数表左右两部部分进行移位。
    如果移动1位,则将后27位复制到新的数组,在将原数组的第一个放到新数组的最后一位即可;如果移动两位则类似。然后利用数组复制函数将新的数组组合成新的数组,再对此数组进行PC_2压缩置换成48位数据,保存在subkeys二维数组中。而移位后的左右两部分作为下一个子密钥生成的左右两部分进行同样的16次操作即可生成16个48位的子密钥,最后再返回结果即可。
    FFunction.java类是DES算法对应的F轮函数。形参传入明文(密文)右半部分、子密钥,for (int i = 0; i < 48; i++) {e_output[i] = r_text[Table.E[i] - 1] ^ subkey[i];}利用E扩展之后的数据和子密钥进行异化输出48位二进制型int数据。然后在循环当以6位为一组中分别送入8个S盒,利用左移运算符生成S盒行和列,如int r = (e_output[i * 6] << 1) + e_output[i * 6 + 5];生成行号,之后利用S和表找出对用的数据并生成4位二进制数据,保存到int型数组,经过8个S盒之后数据由48位变成32位后接着进行P置换后就以二进制int一维数组型数据返回结果。
    MainBody.java类为算法主体部分。类中有3个变量,分别是分组后的明文(密文)groupText、16个子密钥subkeys,标识加密还是解密flag(1表示加密,0表示解密)。构造函数传入byte数组型的明文(密文)、String类型的key、int类型的标识flag。构造函数里面如果是加密,则在获取明文byte数组的长度之后再将长度和@符号一起转化为byte数据添加到byte数组前面,方便在解密时确定明文长度从而去掉明文后面的乱码。然后再利用分组函数对此进行分组,若是解密则直接进行分组即可,之后再利用密钥生成16个子密钥。
    MainBody.eachRound函数为16轮加密(解密)的每一轮。形参传入每组加密(解密)IP置换后的int数组保存的二进制数据、加密(解密)轮数。利用数组复制函数将明文(密文)分割为左右两部分,右半部分做为下一轮的左半部分,然后将右半部分和该轮对应的子密钥传入F轮函数返回32位结果后和左半部分进行异或操作并作为下一轮的右半部分。然后需要判断该轮数是否为最后一轮,如果是,则不需要交换左右两边的数据否则交换。
    MainBody.mainBody为算法主体部分。以对明文(密文)分组后的的组数为已循环,逐组8字节进行解密,先是利用IP置换表对其进行置换,如果是加密,则顺者调用eachRound函数利用子密钥进行加密,解密则反之。这个完成之后便对其进行IP-1逆置换,这里得到的还是int数组型的二进制数据,然后利用左移操作符和强制类型将它们转化为byte型数组数据再复制到结果数组返回即可。如果是解密,这里还要进行最后一步,就是找出原先添加到明文前面的数据长度,然后根据明文长度对其进行截取再返回,如果是加密则直接返回。
    主函数利用默认明文(密文)和密钥进行加密(解密),通过构造函数传入,然后调用mainBody函数返回加密(解密)的byte型数组结果,然后利用String的构造函数转化为string类型的数据输出,其中还利用System.currrentTimeMillis时间戳计算加密(解密的时间),平均时间分别是3ms、1ms。

    5.源码

    https://gitee.com/zhz000/des
    https://github.com/zhz000/des

    展开全文
  • 由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数...
  • 由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数...

    原文来源:http://www.nowamagic.net/librarys/veda/detail/1953,新浪的文档编辑太差劲了,哎,无语

     

    由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数,对密文进行解密,从中解读出项目的使用到期时间。

    之前,自己有先试着写了下,主要是base64+md5+反转字符串。算法太过简单,很容易被破解,而且也没有能过做到“密钥”在加解密中的重要性,故而舍之。

    后来,查找了相关资料,发现,原来PHP中内置了一个功能强大的函数库,即Mcrypt。

    其实,mcrypt本身就提供了强大的加密解密方法,并且支持很多流行的公开的加密算法,如DES,  TripleDES, Blowfish (默认), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2 and GOST in CBC, OFB, CFB and ECB。

    这里简单的引用下百度百科关于“加密算法”的解释:

    数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。

    加密技术通常分为两大类:“对称式”和“非对称式”。

    对称式加密就是加密和解密使用同一个密钥,通常称之为“Session Key ”这种加密技术目前被广泛采用,如美国政府所采用的DES加密标准就是一种典型的“对称式”加密法,它的Session Key长度为56Bits。

    非对称式加密就是加密和解密所使用的不是同一个密钥,通常有两个密钥,称为“公钥”和“私钥”,它们两个必需配对使用,否则不能打开加密文件。这里的“公钥”是指可以对外公布的,“私钥”则不能,只能由持有人一个人知道。它的优越性就在这里,因为对称式的加密方法如果是在网络上传输加密文件就很难把密钥告诉对方,不管用什么方法都有可能被别窃听到。而非对称式的加密方法有两个密钥,且其中的“公钥”是可以公开的,也就不怕别人知道,收件人解密时只要用自己的私钥即可以,这样就很好地避免了密钥的传输安全性问题。

    前面提到过,mcrypt支持多种国际公开的算法,我在这次的项目中使用的是DES算法,DES(Data Encryption Standard),这是一个对称算法,速度较快,适用于加密大量数据的场合。

    用到的几个加密函数介绍

    接下来我简要的说明下加密类中会使用到的几个函数。

    1. resource mcrypt_module_open ( string $algorithm , string $algorithm_directory , string $mode , string $mode_directory )

    参数$algorithm:要使用的算法,可以通过函数mcrypt_list_algorithms()来查看所有支持的算法名称
    参数$ mode:要使用哪种模式,同样,可以内置函数mcrypt_list_algorithms()来查看所有支持的模式
    2. int mcrypt_enc_get_iv_size ( resource $td )

    该函数将返回使用的算法的初始化向量(IV)的大小(看着有点抽象),如果IV在算法中被忽略的话讲返回0。
    参数$td就是使用mcrypt_module_open函数的返回值。
    3. string mcrypt_create_iv ( int $size [, int $source = MCRYPT_DEV_RANDOM ] )

    该函数会创建一个初始化向量(IV)

    参数:$source可以使MCRYPT_RAND,MCRYPT_DEV_RANDOM,MCRYPT_DEV_URANDOM

    注意:PHP5.3.0以上的版本,只支持MCRYPT_RAND

    返回值:成功,则返回一个字符串型的初始向量,失败,则返回False

    4. int mcrypt_enc_get_key_size ( resource $td )

    该函数能够取得当前算法所支持的最大的密钥长度(以字节计算)

    int mcrypt_generic_init ( resource $td , string $key , string $iv )

    调用mcrypt_generic() or mdecrypt_generic()之前,首先需要调用该函数,该函数能够帮我们初始化缓冲区,用以存放加密数据。

    参数$key:密钥长度,记住,当前$key的值,要比函数mcrypt_enc_get_key_size()返回的值小

    问题:$key的值,越大越好吗?有同学会的,帮忙解答下。

    5. string mcrypt_generic ( resource $td , string $data )

    完成了前面的工作之后,就可以调用该函数用以加密数据了。

    参数$data:要加密的数据内容
    返回值:返回加密后的密文
    6. bool mcrypt_generic_deinit ( resource $td )

    该函数能够帮我们卸载当前使用的加密模块。

    返回值:成功时返回 TRUE, 或者在失败时返回 FALSE.

    7. string mdecrypt_generic ( resource $td , string $data )

    该函数能够用来解密数据。

    注意:解密后的数据可能比实际上的更长,可能会有后续的\0,需去掉

    8. bool mcrypt_module_close ( resource $td )

    关闭指定的加密模块资源句柄

    返回值:成功时返回 TRUE, 或者在失败时返回 FALSE.

    参考代码

        class authCode {
            public $ttl;//到期时间 时间格式:20120101(年月日)
            public $key_1;//密钥1
            public $key_2;//密钥2
            public $td;
            public $ks;//密钥的长度
            public $iv;//初始向量
            public $salt;//盐值(某个特定的字符串)
            public $encode;//加密后的信息
            public $return_array = array(); // 返回带有MAC地址的字串数组
            public $mac_addr;//mac地址
            public $filepath;//保存密文的文件路径
            public function __construct(){
                //获取物理地址
                $this->mac_addr=$this->getmac(PHP_OS);
                $this->filepath="./licence.txt";
                $this->ttl="20120619";//到期时间
                $this->salt="~!@#$";//盐值,用以提高密文的安全性
    //            echo "

    ".print_r(mcrypt_list_algorithms ())."
    
    ";
    //            echo "
    ".print_r(mcrypt_list_modes())."
    
    ";
            }
           
            public function encode($key) {
                $this->td = mcrypt_module_open(MCRYPT_DES,'','ecb',''); //使用MCRYPT_DES算法,ecb模式
                $size=mcrypt_enc_get_iv_size($this->td);//设置初始向量的大小
                $this->iv = mcrypt_create_iv($size, MCRYPT_RAND);//创建初始向量
                $this->ks = mcrypt_enc_get_key_size($this->td);//返回所支持的最大的密钥长度(以字节计算)
                $this->key_1 = substr(md5(md5($key).$this->salt),0,$this->ks);
                mcrypt_generic_init($this->td, $this->key_1, $this->iv); //初始处理
                //要保存到明文
                $con=$this->mac_addr.$this->ttl;
                //加密
                $this->encode = mcrypt_generic($this->td, $con);  
                //结束处理
                mcrypt_generic_deinit($this->td);
                //将密文保存到文件中
                $this->savetofile();
            }
           
            public function decode($key) {
                try {
                    if (!file_exists($this->filepath)){
                       
    展开全文
  • 由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数...

         由于项目的需要,要写一个能生成“授权码”的类(授权码主要包含项目使用的到期时间),生成的授权码将会写入到一个文件当中,每当项目运行的时候,会自动读取出文件中的密文,然后使用唯一的“密钥”来调用某个函数,对密文进行解密,从中解读出项目的使用到期时间。

        之前,自己有先试着写了下,主要是base64+md5+反转字符串。算法太过简单,很容易被破解,而且也没有能过做到“密钥”在加解密中的重要性,故而舍之。

        后来,查找了相关资料,发现,原来PHP中内置了一个功能强大的函数库,即Mcrypt。

        其实,mcrypt本身就提供了强大的加密解密方法,并且支持很多流行的公开的加密算法,如DES,  TripleDES, Blowfish (默认), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2 and GOST in CBC, OFB, CFB and ECB。

      这里简单的引用下百度百科关于“加密算法”的解释:

      数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。

      加密技术通常分为两大类:对称式非对称式

      对称式加密就是加密和解密使用同一个密钥,通常称之为“Session Key ”这种加密技术目前被广泛采用,如美国政府所采用的DES加密标准就是一种典型的“对称式”加密法,它的Session Key长度为56Bits。

      非对称式加密就是加密和解密所使用的不是同一个密钥,通常有两个密钥,称为“公钥”和“私钥”,它们两个必需配对使用,否则不能打开加密文件。这里的“公钥”是指可以对外公布的,“私钥”则不能,只能由持有人一个人知道。它的优越性就在这里,因为对称式的加密方法如果是在网络上传输加密文件就很难把密钥告诉对方,不管用什么方法都有可能被别窃听到。而非对称式的加密方法有两个密钥,且其中的“公钥”是可以公开的,也就不怕别人知道,收件人解密时只要用自己的私钥即可以,这样就很好地避免了密钥的传输安全性问题。

      前面提到过,mcrypt支持多种国际公开的算法,我在这次的项目中使用的是DES算法,DES(Data Encryption Standard),这是一个对称算法,速度较快,适用于加密大量数据的场合。

    接下来我简要的说明下加密类中会使用到的几个函数。


     resource mcrypt_module_open ( string $algorithm , string $algorithm_directory , string $mode , string $mode_directory )

    参数$algorithm:要使用的算法,可以通过函数mcrypt_list_algorithms()来查看所有支持的算法名称

    参数$ mode:要使用哪种模式,同样,可以内置函数mcrypt_list_algorithms()来查看所有支持的模式


    int mcrypt_enc_get_iv_size ( resource $td )

    该函数将返回使用的算法的初始化向量(IV)的大小(看着有点抽象),如果IV在算法中被忽略的话讲返回0。

    参数$td就是使用mcrypt_module_open函数的返回值。


    string mcrypt_create_iv ( int $size [, int $source = MCRYPT_DEV_RANDOM ] )

    该函数会创建一个初始化向量(IV)

    参数:

    $source可以使MCRYPT_RAND,MCRYPT_DEV_RANDOM

    MCRYPT_DEV_URANDOM

    注意:PHP5.3.0以上的版本,只支持MCRYPT_RAND

    返回值:

    成功,则返回一个字符串型的初始向量,失败,则返回False


    int mcrypt_enc_get_key_size ( resource $td )

    该函数能够取得当前算法所支持的最大的密钥长度(以字节计算)

    int mcrypt_generic_init ( resource $td , string $key , string $iv )

    调用mcrypt_generic() or mdecrypt_generic()之前,首先需要调用该函数,该函数能够帮我们初始化缓冲区,用以存放加密数据。

    参数$key:密钥长度,记住,当前$key的值,要比函数mcrypt_enc_get_key_size()返回的值小

    问题:$key的值,越大越好吗?有同学会的,帮忙解答下。


    string mcrypt_generic ( resource $td , string $data )

    完成了前面的工作之后,就可以调用该函数用以加密数据了。

    参数$data:要加密的数据内容

    返回值:返回加密后的密文


    bool mcrypt_generic_deinit ( resource $td )

    该函数能够帮我们卸载当前使用的加密模块。

    返回值

    成功时返回 TRUE, 或者在失败时返回 FALSE.


    string mdecrypt_generic ( resource $td , string $data )

    该函数能够用来解密数据。

    注意:解密后的数据可能比实际上的更长,可能会有后续的\0,需去掉


    bool mcrypt_module_close ( resource $td )

    关闭指定的加密模块资源句柄

    返回值

    成功时返回 TRUE, 或者在失败时返回 FALSE.


    贴上代码:

    <?php
        class authCode {
            public $ttl;//到期时间 时间格式:20120101(年月日)
            public $key_1;//密钥1
            public $key_2;//密钥2
            public $td;
            public $ks;//密钥的长度
            public $iv;//初始向量
            public $salt;//盐值(某个特定的字符串)
            public $encode;//加密后的信息
            public $return_array = array(); // 返回带有MAC地址的字串数组 
            public $mac_addr;//mac地址
            public $filepath;//保存密文的文件路径
            public function __construct(){
                //获取物理地址
                $this->mac_addr=$this->getmac(PHP_OS);
                $this->filepath="./licence.txt";
                $this->ttl="20120619";//到期时间
                $this->salt="~!@#$";//盐值,用以提高密文的安全性
    //            echo "<pre>".print_r(mcrypt_list_algorithms ())."</pre>";
    //            echo "<pre>".print_r(mcrypt_list_modes())."</pre>";
            }
            /**
             * 对明文信息进行加密
             * @param $key 密钥
             */
            public function encode($key) {
                $this->td = mcrypt_module_open(MCRYPT_DES,'','ecb',''); //使用MCRYPT_DES算法,ecb模式
                $size=mcrypt_enc_get_iv_size($this->td);//设置初始向量的大小
                $this->iv = mcrypt_create_iv($size, MCRYPT_RAND);//创建初始向量
                $this->ks = mcrypt_enc_get_key_size($this->td);//返回所支持的最大的密钥长度(以字节计算)
                $this->key_1 = substr(md5(md5($key).$this->salt),0,$this->ks);
                mcrypt_generic_init($this->td, $this->key_1, $this->iv); //初始处理
                //要保存到明文
                $con=$this->mac_addr.$this->ttl;
                //加密
                $this->encode = mcrypt_generic($this->td, $con);   
                //结束处理
                mcrypt_generic_deinit($this->td);
                //将密文保存到文件中
                $this->savetofile();
            }
            /**
             * 对密文进行解密
             * @param $key 密钥
             */
            public function decode($key) {
                try {
                    if (!file_exists($this->filepath)){
                        throw new Exception("授权文件不存在");
                    }else{//如果授权文件存在的话,则读取授权文件中的密文
                        $fp=fopen($this->filepath,'r');
                        $secret=fread($fp,filesize($this->filepath)); 
                        $this->key_2 = substr(md5(md5($key).$this->salt),0,$this->ks);
                        //初始解密处理
                        mcrypt_generic_init($this->td, $this->key_2, $this->iv);
                        //解密
                        $decrypted = mdecrypt_generic($this->td, $secret);
                        //解密后,可能会有后续的\0,需去掉   
                        $decrypted=trim($decrypted) . "\n";   
                        //结束
                        mcrypt_generic_deinit($this->td);   
                        mcrypt_module_close($this->td);
                        return $decrypted;        
                    }
                }catch (Exception $e){
                    echo $e->getMessage();
                }
            }
            /**
             * 将密文保存到文件中
             */
            public function savetofile(){
                try {
                    $fp=fopen($this->filepath,'w+');
                    if (!$fp){
                        throw new Exception("文件操作失败");
                    }
                    fwrite($fp,$this->encode);
                    fclose($fp);
                }catch (Exception $e){
                    echo $e->getMessage();
                }
            }
            /**
             * 取得服务器的MAC地址
             */
            public function getmac($os_type){ 
                 switch ( strtolower($os_type) ){ 
                          case "linux": 
                                    $this->forLinux(); 
                                    break; 
                          case "solaris": 
                                    break; 
                          case "unix": 
                                     break; 
                           case "aix": 
                                     break; 
                           default: 
                                   $this->forWindows(); 
                                   break; 
                  }
                  $temp_array = array(); 
                  foreach( $this->return_array as $value ){
                            if (preg_match("/[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f][:-]"."[0-9a-f][0-9a-f]/i",$value,$temp_array )){
                                $mac_addr = $temp_array[0]; 
                                break; 
                           }
                  }
                  unset($temp_array); 
                  return $mac_addr; 
             }
             /**
              * windows服务器下执行ipconfig命令
              */
             public function forWindows(){ 
                  @exec("ipconfig /all", $this->return_array); 
                  if ( $this->return_array ) 
                           return $this->return_array; 
                  else{ 
                           $ipconfig = $_SERVER["WINDIR"]."\system32\ipconfig.exe"; 
                           if ( is_file($ipconfig) ) 
                              @exec($ipconfig." /all", $this->return_array); 
                           else 
                              @exec($_SERVER["WINDIR"]."\system\ipconfig.exe /all", $this->return_array); 
                           return $this->return_array; 
                  }
             }
             /**
              * Linux服务器下执行ifconfig命令
              */
             public function forLinux(){ 
                  @exec("ifconfig -a", $this->return_array); 
                  return $this->return_array; 
             }
        }
        $code=new authCode();
        //加密
        $code->encode("~!@#$%^");
        //解密
        echo $code->decode("~!@#$%^");
    ?>

    原创文章:WEB开发_小飞

    转载请注明出处:http://www.cnblogs.com/hongfei/archive/2012/06/19/2555504.html

    转载于:https://www.cnblogs.com/hongfei/archive/2012/06/19/2555504.html

    展开全文
  • 在ARM系统中,有时需要精确的时间测量。通常,取时间的C函数(如gettime()等)不仅通用性差(必须...笔者在移植DES算法到ARM系统的实验过程中,便遇到过要定量评估加密算法耗时多少的问题,发现的确不能用上述常规的C函
  • 现如今窃取隐私信息太简单了,为了让自己脑海里形成一种保密意识,今天花了大概半个小时的时间写了一个用SOCKET实现的DES加密全双工聊天程序,程序的内容也比较简单,并且DES算法的实现也使用了pydes这个库,具体的...
  • 运行于微控制器(AT89C52)中的DES密码算法插入随机时延来模拟信号的未对齐,用该方式进行旁路攻击实验。结果表明,当各信号在相同操作时间点未对齐程度略有增加时,敌手直接进行DPA攻击破解算法密钥时所需的信号...
  • 新的项目我们想用ASP.NET Core来开发,但是苦于我们历史的遗产很多,比如《使用 JavaScriptService 在.NET Core 里实现DES加密算法》,我们要估计等到.NET Core 1.2我们才会有大部分的API,通过NodeJs方式有点曲线...
  • 可以在不到一天的时间内,在一台具有128 Gb RAM和32个处理器的计算机上运行完整的四年DES调查数据。 安装 您可以使用 cd fgcm python setup.py install 文献资料 (文档不完整。) 在数据集上运行FGCM校准分为三个...
  • Java,C#加密方法小结

    2011-11-07 12:00:15
    方案三 编写加密算法 DES jni 加密软件也多是采用加密算法 但独立开发耗费时间长 效果不确定  其他: Proguard DES加密器 其他加密软件 选择加密方式前,确认要保护的文件运行的平台,如果是
  • BCArchive 中文版是一款使用简单的高速加密工具。它具有简单明了的使用界面,用户还可以通过鼠标右键快速对文件进行...在此后任何时间你或你的收件人可以运行任何计算机上的程序,并提取数据,而无需安装任何特殊软件。
  • AES和RSA:加密解密

    2019-07-18 21:00:57
    最近生活乱七八糟,什么都懒上了天。...AES又叫Rijndael算法,是DES升级的加密标准,运行要求低,不需计算机有非常高的处理能力和大的内存; 操作可以很容易的抵御时间和空间的攻击,在不同的运行环...
  • 使用了DES加密算法,部署后正常。隔段再打开页面居然 加密报错。 一直以为是IIS部署后的目录权限造成读不到。 又以为是代码问题不停的修改检查加密方式和位子 最后发现是Temporary ASP.NET Files里缓存...
  • 使用了DES加密算法,部署后正常。隔段再打开页面居然 加密报错。 一直以为是IIS部署后的目录权限造成读不到。 又以为是代码问题不停的修改检查加密方式和位子 最后发现是Temporary ASP.NET Files里缓存...
  • 特点:多种加密方式:256位元AES,TwoFish,Triple DES加密算法,保障您的数据安全。自动化备份:支持一个任务多种时间备份,最具弹性备份计划。强大的应用支持:支持Oracle,Mysql,MsSql等大型数据库的备份还原。...
  • 计算机系统的可靠性是指从它开始运行(t=0)到某时刻t这段时间内能正常运行的概率,用R(t)表示。所谓失效率是指单位时间内失效的元件数与元件总数的比例,以表示,当为常数时,可靠性与失效率的关系为: R(t)=e-λ...
  • \DES.......................DES算法示例 \2DES......................双重DES算法示例 \3DES......................两个密钥的三重DES算法示例 \3DES3.....................三个密钥的三重DES算法示例 \Blow...
  • \DES.......................DES算法示例 \2DES......................双重DES算法示例 \3DES......................两个密钥的三重DES算法示例 \3DES3.....................三个密钥的三重DES算法示例 \Blow...
  • \DES.......................DES算法示例 \2DES......................双重DES算法示例 \3DES......................两个密钥的三重DES算法示例 \3DES3.....................三个密钥的三重DES算法示例 \Blow...
  • \DES.......................DES算法示例 \2DES......................双重DES算法示例 \3DES......................两个密钥的三重DES算法示例 \3DES3.....................三个密钥的三重DES算法示例 \Blow...
  • \DES.......................DES算法示例 \2DES......................双重DES算法示例 \3DES......................两个密钥的三重DES算法示例 \3DES3.....................三个密钥的三重DES算法示例 \Blow...
  • 在普通PC机上,用纯软件实现DES加密算法的速度超过200K字节/秒,如果对一篇一万汉字的文章进行加密,其加/脱密时间仅需1/10秒,这种时间延迟用户几乎无感觉。目前,加密卡的加/脱密速度一般为1M位/ 秒,对中小型...
  • 4. $encrypt_type: 加密使用的算法(支持:BEAST_ENCRYPT_TYPE_DES、BEAST_ENCRYPT_TYPE_AES) 制定自己的php-beast php-beast 有多个地方可以定制的,以下一一列出: 1. 使用 header.c 文件可以修改 php-beast ...
  • des24 采用DES算法加密或解密一个字符串,长度为24位 EnDeString 双向加密解密字符串的函数 Encrypt 双向加密解密字符串 RSACalc RSA计算函数 RSAGen 生成随机RSA密钥函数 RSACmp 比较两个十六进制值是否...

空空如也

空空如也

1 2 3 4 5
收藏数 83
精华内容 33
关键字:

des运行时间算法