加密算法 订阅
数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码为“密文”,使其只能在输入相应的密钥之后才能显示出原容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。通过修改文件的md5值,可以绕过某些网盘的"违规文件扫描机制",这是因为网盘服务器内存储着已知违规文件的md5值,当上传文件时会自动与服务器md5数据库匹配以判断是否违规。 [1] 展开全文
数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码为“密文”,使其只能在输入相应的密钥之后才能显示出原容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。通过修改文件的md5值,可以绕过某些网盘的"违规文件扫描机制",这是因为网盘服务器内存储着已知违规文件的md5值,当上传文件时会自动与服务器md5数据库匹配以判断是否违规。 [1]
信息
别    称
密文
作    用
加密数据 [2]
解    锁
密钥
中文名
加密算法
外文名
Encryption algorithm
加密算法相关简介
据记载,公元前400年,古希腊人发明了置换密码。1881年世界上的第一个电话保密专利出现。在第二次世界大战期间,德国军方启用“恩尼格玛”密码机,密码学在战争中起着非常重要的作用。随着信息化和数字化社会的发展,人们对信息安全和保密的重要性认识不断提高,于是在1997年,美国国家标准局公布实施了“美国数据加密标准(DES)”,民间力量开始全面介入密码学的研究和应用中,采用的加密算法有DES、RSA、SHA等。随着对加密强度需求的不断提高,近期又出现了AES、ECC等。使用密码学可以达到以下目的:保密性:防止用户的标识或数据被读取。数据完整性:防止数据被更改。身份验证:确保数据发自特定的一方。
收起全文
精华内容
下载资源
问答
  • 加密算法

    2021-01-08 05:52:24
    文章目录加密和解密对称加密算法非对称加密算法散列加密算法对比各种加密算法加密算法选择 加密和解密 加密:数据加密的基本过程,就是对原来为 明文 的文件或数据按 某种算法 进行处理,使其成为 不可读 的一段代码...
  • AES 加密算法的原理详解

    万次阅读 多人点赞 2018-07-23 22:18:49
    高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图: 下面简单介绍下各个部分的....

    本教程摘选自 https://blog.csdn.net/qq_28205153/article/details/55798628 的原理部分。

    AES简介

    高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图: 
    加密流程图
    下面简单介绍下各个部分的作用与意义:

    • 明文P

      没有经过加密的数据。

    • 密钥K

      用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

    • AES加密函数

      设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。

    • 密文C

      经加密函数处理后的数据

    • AES解密函数

      设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

    在这里简单介绍下对称加密算法与非对称加密算法的区别。

    • 对称加密算法

      加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

    • 非对称加密算法

      加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

    实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

    本文下面AES原理的介绍参考自《现代密码学教程》,AES的实现在介绍完原理后开始。

    AES的基本结构

    AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

    AES密钥长度(32位比特字)分组长度(32位比特字)加密轮数
    AES-1284410
    AES-1926412
    AES-2568414

    轮数在下面介绍,这里实现的是AES-128,也就是密钥的长度为128位,加密轮数为10轮。 
    上面说到,AES的加密公式为C = E(K,P),在加密函数E中,会执行一个轮函数,并且执行10次这个轮函数,这个轮函数的前9次执行的操作是一样的,只有第10次有所不同。也就是说,一个明文分组会被加密10轮。AES的核心就是实现一轮中的所有操作。

    AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。如,明文分组为P = abcdefghijklmnop,其中的字符a对应P0,p对应P15。一般地,明文分组用字节为单位的正方形矩阵描述,称为状态矩阵。在算法的每一轮中,状态矩阵的内容不断发生变化,最后的结果作为密文输出。该矩阵中字节的排列顺序为从上到下、从左至右依次排列,如下图所示: 
    state

    现在假设明文分组P为”abcdefghijklmnop”,则对应上面生成的状态矩阵图如下: 
    state2
    上图中,0x61为字符a的十六进制表示。可以看到,明文经过AES加密后,已经面目全非。

    类似地,128位密钥也是用字节为单位的矩阵表示,矩阵的每一列被称为1个32位比特字。通过密钥编排函数该密钥矩阵被扩展成一个44个字组成的序列W[0],W[1], … ,W[43],该序列的前4个元素W[0],W[1],W[2],W[3]是原始密钥,用于加密运算中的初始密钥加(下面介绍);后面40个字分为10组,每组4个字(128比特)分别用于10轮加密运算中的轮密钥加,如下图所示: 
    keystate
    上图中,设K = “abcdefghijklmnop”,则K0 = a, K15 = p, W[0] = K0 K1 K2 K3 = “abcd”。

    AES的整体结构如下图所示,其中的W[0,3]是指W[0]、W[1]、W[2]和W[3]串联组成的128位密钥。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。另外,在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作。 
    aes_struct
    上图也展示了AES解密过程,解密过程仍为10轮,每一轮的操作是加密操作的逆操作。由于AES的4个轮操作都是可逆的,因此,解密操作的一轮就是顺序执行逆行移位、逆字节代换、轮密钥加和逆列混合。同加密操作类似,最后一轮不执行逆列混合,在第1轮解密之前,要执行1次密钥加操作。

    下面分别介绍AES中一轮的4个操作阶段,这4分操作阶段使输入位得到充分的混淆。

    一、字节代换

    1.字节代换操作

    AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。 
    AES的S盒:

    行/列0123456789ABCDEF
    00x630x7c0x770x7b0xf20x6b0x6f0xc50x300x010x670x2b0xfe0xd70xab0x76
    10xca0x820xc90x7d0xfa0x590x470xf00xad0xd40xa20xaf0x9c0xa40x720xc0
    20xb70xfd0x930x260x360x3f0xf70xcc0x340xa50xe50xf10x710xd80x310x15
    30x040xc70x230xc30x180x960x050x9a0x070x120x800xe20xeb0x270xb20x75
    40x090x830x2c0x1a0x1b0x6e0x5a0xa00x520x3b0xd60xb30x290xe30x2f0x84
    50x530xd10x000xed0x200xfc0xb10x5b0x6a0xcb0xbe0x390x4a0x4c0x580xcf
    60xd00xef0xaa0xfb0x430x4d0x330x850x450xf90x020x7f0x500x3c0x9f0xa8
    70x510xa30x400x8f0x920x9d0x380xf50xbc0xb60xda0x210x100xff0xf30xd2
    80xcd0x0c0x130xec0x5f0x970x440x170xc40xa70x7e0x3d0x640x5d0x190x73
    90x600x810x4f0xdc0x220x2a0x900x880x460xee0xb80x140xde0x5e0x0b0xdb
    A0xe00x320x3a0x0a0x490x060x240x5c0xc20xd30xac0x620x910x950xe40x79
    B0xe70xc80x370x6d0x8d0xd50x4e0xa90x6c0x560xf40xea0x650x7a0xae0x08
    C0xba0x780x250x2e0x1c0xa60xb40xc60xe80xdd0x740x1f0x4b0xbd0x8b0x8a
    D0x700x3e0xb50x660x480x030xf60x0e0x610x350x570xb90x860xc10x1d0x9e
    E0xe10xf80x980x110x690xd90x8e0x940x9b0x1e0x870xe90xce0x550x280xdf
    F0x8c0xa10x890x0d0xbf0xe60x420x680x410x990x2d0x0f0xb00x540xbb0x16

    状态矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。例如,加密时,输出的字节S1为0x12,则查S盒的第0x01行和0x02列,得到值0xc9,然后替换S1原有的0x12为0xc9。状态矩阵经字节代换后的图如下: 
    (第二个字符0xAB查表后应该是转换成0x62的,感谢细心的朋友指出,有空再重新画图更正了) 
    byte

    2.字节代换逆操作

    逆字节代换也就是查逆S盒来变换,逆S盒如下:

    行/列0123456789ABCDEF
    00x520x090x6a0xd50x300x360xa50x380xbf0x400xa30x9e0x810xf30xd70xfb
    10x7c0xe30x390x820x9b0x2f0xff0x870x340x8e0x430x440xc40xde0xe90xcb
    20x540x7b0x940x320xa60xc20x230x3d0xee0x4c0x950x0b0x420xfa0xc30x4e
    30x080x2e0xa10x660x280xd90x240xb20x760x5b0xa20x490x6d0x8b0xd10x25
    40x720xf80xf60x640x860x680x980x160xd40xa40x5c0xcc0x5d0x650xb60x92
    50x6c0x700x480x500xfd0xed0xb90xda0x5e0x150x460x570xa70x8d0x9d0x84
    60x900xd80xab0x000x8c0xbc0xd30x0a0xf70xe40x580x050xb80xb30x450x06
    70xd00x2c0x1e0x8f0xca0x3f0x0f0x020xc10xaf0xbd0x030x010x130x8a0x6b
    80x3a0x910x110x410x4f0x670xdc0xea0x970xf20xcf0xce0xf00xb40xe60x73
    90x960xac0x740x220xe70xad0x350x850xe20xf90x370xe80x1c0x750xdf0x6e
    A0x470xf10x1a0x710x1d0x290xc50x890x6f0xb70x620x0e0xaa0x180xbe0x1b
    B0xfc0x560x3e0x4b0xc60xd20x790x200x9a0xdb0xc00xfe0x780xcd0x5a0xf4
    C0x1f0xdd0xa80x330x880x070xc70x310xb10x120x100x590x270x800xec0x5f
    D0x600x510x7f0xa90x190xb50x4a0x0d0x2d0xe50x7a0x9f0x930xc90x9c0xef
    E0xa00xe00x3b0x4d0xae0x2a0xf50xb00xc80xeb0xbb0x3c0x830x530x990x61
    F0x170x2b0x040x7e0xba0x770xd60x260xe10x690x140x630x550x210x0c0x7d

    二、行移位

    1.行移位操作

    行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,如下图所示: 
    shiftRows

    2.行移位的逆变换

    行移位的逆变换是将状态矩阵中的每一行执行相反的移位操作,例如AES-128中,状态矩阵的第0行右移0字节,第1行右移1字节,第2行右移2字节,第3行右移3字节。

    三、列混合

    1.列混合操作

    列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵,如下图的公式所示: 
    col

    状态矩阵中的第j列(0 ≤j≤3)的列混合可以表示为下图所示: 
    col2

    其中,矩阵元素的乘法和加法都是定义在基于GF(2^8)上的二元运算,并不是通常意义上的乘法和加法。这里涉及到一些信息安全上的数学知识,不过不懂这些知识也行。其实这种二元运算的加法等价于两个字节的异或,乘法则复杂一点。对于一个8位的二进制数来说,使用域上的乘法乘以(00000010)等价于左移1位(低位补0)后,再根据情况同(00011011)进行异或运算,设S1 = (a7 a6 a5 a4 a3 a2 a1 a0),刚0x02 * S1如下图所示: 
    col3 
    也就是说,如果a7为1,则进行异或运算,否则不进行。 
    类似地,乘以(00000100)可以拆分成两次乘以(00000010)的运算: 
    col4 
    乘以(0000 0011)可以拆分成先分别乘以(0000 0001)和(0000 0010),再将两个乘积异或: 
    col5
    因此,我们只需要实现乘以2的函数,其他数值的乘法都可以通过组合来实现。 
    下面举个具体的例子,输入的状态矩阵如下:

        
    C9E5FD2B
    7AF2786E
    639C2667
    B0A782E5

    下面,进行列混合运算: 
    以第一列的运算为例: 
    col7 
    其它列的计算就不列举了,列混合后生成的新状态矩阵如下:

        
    D4E7CD66
    2802E5BB
    BEC6D6BF
    220FDFA5

    2.列混合逆运算

    逆向列混合变换可由下图的矩阵乘法定义: 
    col6 
    可以验证,逆变换矩阵同正变换矩阵的乘积恰好为单位矩阵。

    四、轮密钥加

    轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作,如下图所示。其中,密钥Ki中每个字W[4i],W[4i+1],W[4i+2],W[4i+3]为32位比特字,包含4个字节,他们的生成算法下面在下面介绍。轮密钥加过程可以看成是字逐位异或的结果,也可以看成字节级别或者位级别的操作。也就是说,可以看成S0 S1 S2 S3 组成的32位字与W[4i]的异或运算。 
    roundadd
    轮密钥加的逆运算同正向的轮密钥加运算完全一致,这是因为异或的逆操作是其自身。轮密钥加非常简单,但却能够影响S数组中的每一位。

    密钥扩展

    AES首先将初始密钥输入到一个4*4的状态矩阵中,如下图所示。 
    keyextends
    这个4*4矩阵的每一列的4个字节组成一个字,矩阵4列的4个字依次命名为W[0]、W[1]、W[2]和W[3],它们构成一个以字为单位的数组W。例如,设密钥K为”abcdefghijklmnop”,则K0 = ‘a’,K1 = ‘b’, K2 = ‘c’,K3 = ‘d’,W[0] = “abcd”。 
    接着,对W数组扩充40个新列,构成总共44列的扩展密钥数组。新列以如下的递归方式产生: 
    1.如果i不是4的倍数,那么第i列由如下等式确定: 
    W[i]=W[i-4]⨁W[i-1] 
    2.如果i是4的倍数,那么第i列由如下等式确定: 
    W[i]=W[i-4]⨁T(W[i-1]) 
    其中,T是一个有点复杂的函数。 
    函数T由3部分组成:字循环、字节代换和轮常量异或,这3部分的作用分别如下。 
    a.字循环:将1个字中的4个字节循环左移1个字节。即将输入字[b0, b1, b2, b3]变换成[b1,b2,b3,b0]。 
    b.字节代换:对字循环的结果使用S盒进行字节代换。 
    c.轮常量异或:将前两步的结果同轮常量Rcon[j]进行异或,其中j表示轮数。 
    轮常量Rcon[j]是一个字,其值见下表。

    j12345
    Rcon[j]01 00 00 0002 00 00 0004 00 00 0008 00 00 0010 00 00 00
    j678910
    Rcon[j]20 00 00 0040 00 00 0080 00 00 001B 00 00 0036 00 00 00

    下面举个例子: 
    设初始的128位密钥为: 
    3C A1 0B 21 57 F0 19 16 90 2E 13 80 AC C1 07 BD 
    那么4个初始值为: 
    W[0] = 3C A1 0B 21 
    W[1] = 57 F0 19 16 
    W[2] = 90 2E 13 80 
    W[3] = AC C1 07 BD 
    下面求扩展的第1轮的子密钥(W[4],W[5],W[6],W[7])。 
    由于4是4的倍数,所以: 
    W[4] = W[0] ⨁ T(W[3]) 
    T(W[3])的计算步骤如下: 
    1. 循环地将W[3]的元素移位:AC C1 07 BD变成C1 07 BD AC; 
    2. 将 C1 07 BD AC 作为S盒的输入,输出为78 C5 7A 91; 
    3. 将78 C5 7A 91与第一轮轮常量Rcon[1]进行异或运算,将得到79 C5 7A 91,因此,T(W[3])=79 C5 7A 91,故 
    W[4] = 3C A1 0B 21 ⨁ 79 C5 7A 91 = 45 64 71 B0 
    其余的3个子密钥段的计算如下: 
    W[5] = W[1] ⨁ W[4] = 57 F0 19 16 ⨁ 45 64 71 B0 = 12 94 68 A6 
    W[6] = W[2] ⨁ W[5] =90 2E 13 80 ⨁ 12 94 68 A6 = 82 BA 7B 26 
    W[7] = W[3] ⨁ W[6] = AC C1 07 BD ⨁ 82 BA 7B 26 = 2E 7B 7C 9B 
    所以,第一轮的密钥为 45 64 71 B0 12 94 68 A6 82 BA 7B 26 2E 7B 7C 9B。

    AES解密

    在文章开始的图中,有AES解密的流程图,可以对应那个流程图来进行解密。下面介绍的是另一种等价的解密模式,流程图如下图所示。这种等价的解密模式使得解密过程各个变换的使用顺序同加密过程的顺序一致,只是用逆变换取代原来的变换。 
    deaes

    AES原理到这里就结束了。实际开发中都是直接使用第三方已经封装好的库,这时候就需要根据使用的编程语言直接加载第三方库,来实现。所以省去了原文的C的代码实现部分,愿意深度了解代码实现的请移步到文章开头标明的原文出处。

    个人博客里面也有如何用 Java、JavaScript(含两者的跨语言加密解密) 去实现的文章,感兴趣的可以在我的个人博客里面找一下。

    其他加密算法相关参考:

    RSA 加密算法原理简述:https://blog.csdn.net/gulang03/article/details/81176133

    Java 实现 AES 和 RSA 算法:https://blog.csdn.net/gulang03/article/details/81771341

    JS 与 JAVA 跨语言实现 RSA 和 AES 加密算法:https://blog.csdn.net/gulang03/article/details/82230408

    展开全文
  • md5加密算法详解md5加密算法详解md5加密算法详解md5加密算法详解md5加密算法详解md5加密算法详解md5加密算法详解md5加密算法详解
  • DES加密算法

    2018-04-24 15:04:14
    DES加密算法DES加密算法DES加密算法DES加密算法DES加密算法DES加密算法
  • 加密算法------DES加密算法详解

    万次阅读 多人点赞 2018-04-13 21:15:59
    一、加密算法的分类1.对称加解密算法a.通信双方同时掌握一个密钥,加密解密都是由一个密钥完成的(即加密密钥等于解密密钥,加解密密钥可以相互推倒出来)。b.双方通信前共同拟定一个密钥,不对第三方公开。c.不具有...

    一、加密算法的分类

    1.对称加解密算法

    a.通信双方同时掌握一个密钥,加密解密都是由一个密钥完成的(即加密密钥等于解密密钥,加解密密钥可以相互推倒出来)。

    b.双方通信前共同拟定一个密钥,不对第三方公开。

    c.不具有个体原子性,一个密钥被共享,泄漏几率增大

    2.公私钥加解密算法

    a.通信双方掌握不同的密钥,不同方向的加解密由不同的密钥完成。

    二、对称加密算法的代表----DES加密算法

    原理:该算法是一个利用56+8奇偶校验位(第8,16,24,32,40,48,56,64)=64位的密钥对以64位为单位的块数据进行加解密。

    具体过程:

        有明文M(64位) = 0123456789ABCDEF

            即M(64位) = 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

                L(32位) = 0000 0001 0010 0011 0100 0101 0110 0111

                R(32位) = 1000 1001 1010 1011 1100 1101 1110 1111

        有密钥64位:133457799BBCDFF1

            即K(64位) = 00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001

                注:其中红色为奇偶校验位,即实际密钥为56位

    第一步:按照下表中的规则对各个位进行交换,生成16个子钥(48位)

    交换规则表(8*7):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

    交换方法:第一行第一列的数为57,那么就将K中第一位上的数换成K中第57位上的数(将0换为了57位上的1),依次类推。

    那么原K(64位) = 00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001

    去掉奇偶校验位,再经过上表的转换就变为了:

         K + (56位) =  1111000  0110011  0010101  0101111  0101010   1011001    1001111  0001111

    因此:C0(28位) = 1111000  0110011  0010101  0101111

              D0(28位) = 0101010   1011001    1001111  0001111

    下来依次是C1,D1为C0,D0左移一位,C2,D2为C1,D1左移一位,C3,D3为C2,D2左移两位.......


    所以,可以得到C1D1----C16D16的结果为:

    C1 = 1110000 1100110 01010101011111

    D1 = 1010101011001100111100011110

    C2 = 1100001100110010101010111111

    D2 = 0101010110011001111000111101

    C3 = 0000110011001010101011111111

    D3 = 0101011001100111100011110101

    ................

    .................

    C15 = 1111100001100110010101010111

    D15 = 1010101010110011001111000111

    C16 = 1111000011001100101010101111

    D16 = 0101010101100101101110001111


    Kn(48位) = PC-2(CnDn(56位))

    PC-2(8*6)----为一个8*6的矩阵,将上面得到的16个子钥按照下表的规律进行位的交换

    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

    因此,通过上面公式的计算可以得到:

    K1 = 000110 110000 001011 101111 111111 000111 000001 110010

    Eg:C1D1 = 1110000 1100110 0101010 1011111  1010101 0110011 0011110 0011110

    红色部分为奇偶校验位,那么通过上表对C1D1进行位的变换:将14位上的0放到第一位,将17位上的0放到第二位,将11位上的0放到第三位,将24位上的1放到第四位,将1位上的一放到第五位,将5位上的0放到第六位;则最后的前6位的结果·就·变为000110,剩下的做法同上

    ****************以下做法都同K1*********************************

    K2 = 011110 011010 111011 011001 110110 111100 100111 100101

    K3 = 010101 011111 110010 001010 010000 101100 111110 011001

    K4 = 011100 101010 110111 010110 110110 110011 010100 011101

    K5 = 011111 001110 110000 000111 111010 110101 001110 101000

    K6 = 011000 111010 010100 111110 010100 000111 101100 101111

    K7 = 111011 001000 010010 110111 111101 100001 100010 111100

    K8 = 111101 111000 101000 111010 110000 010011 101111 111011

    K9 = 111000 001101 101111 101011 111011 011110 011110 000001

    K10 = 101100 011111 001101 000111 101110 100100 011001 001111

    K11 = 001000 010101 111111 010011 110111 101101 001110 000110 

    K12 = 011101 010111 000111 110101 100101 000110 011111 101001

    K13 = 100101 111100 010111 010001 111110 101011 101001 000001

    K14 = 010111 110100 001110 110111 111100 101110 011100 111010

    K15 = 101111 111001 000110 001101 001111 010011 111100 001010

    K16 = 110010 110011 110110 001011 000011 100001 011111 110101

    因此,最终就得到了如上的16个子密钥,每个48位

    第二步:用得到的子密钥对64位数据加密

    对明文M使用IP(8*8)

    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

    因为: M(64位) = 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

    对M进行IP操作可以得到:

                IP(64位) = 1100 1100 0000 0000 1100 1100 1111 1111 11111 0000 1010 1010 1111 0000 1010 1010

                IP(64位) = L0(32位)+ R0(32位)

                 L0(32位) = 1100 1100 0000 0000 1100 1100 1111 1111

                 R0(32位) = 11111 0000 1010 1010 1111 0000 1010 1010

    接下来,从L0和R0开始,循环16次根据递推公式


    得出L1R1到L16R16。其中除了Kn为48位,其它变量及函数均为32位。

    得到L1R1到L16R16的具体过程如下:

    1.将数据的右半部分R0通过扩展置换E从32位扩展到48位

        通过将原32位数据中的某些位重复出现达到扩展的目的。扩展置换也称位选择函数,俗称E盒,扩展置换E通过将第32,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29共16位分别放置在两个位置,从而将32位的数据扩展为48位。


    根据上面的E表则扩展之后的R0为:

     原来的: R0(32位) = 1111 0000 1010 1010 1111 0000 1010 1010

     扩展后: R0(64位) = 011110 100001 010101 010101 011110 100001 010101 010101

    然后将R0(64位)与

                    K1(64位) =  000110 110000 001011 101111 111111 000111 000001 110010做异或运算

    得到结果为:E(R(n-1)异或K1) = 011000 010001 011110 111010 100001 100110 010100  100111

    (2).将异或后的结果通过S盒子转换为32位

        将异或运算得到的48位结果数据分成8个6位的块,将每一块通过对应的一个S盒产生一个4位的输出,S盒接收6位的输入,经过置换输出4位的数据,具体置换过程为:

        将6位的输入中的第一位和第六位取出来1形成一个两位的二进制数X,将其转换为十进制作为行数,然后将中间4位构成另一个二进制数Y,并将其转换为十进制数作为列,然后查出S的X行Y列所对应的整数,将该整数置换为一个4位的二进制数,即S盒的输出。(eg:输入数据中的第一个6位数据块位010111,则需要通过查S1盒,先取出010111的第一位和第六位,则X=01,其对应的十进制为1。然后取出中间4位的1011,则Y = 1011,其对应的十进制为11,在S1盒中第1行11列的数为11,将其转换为二进制位1011,则输出1011)



     将第一步得到的结果: 011000 010001 011110 111010 100001 100110 010100  100111

    进行S盒置换得到的十进制为:5 10 7 10 15 8 6 2

    转换为相应的二进制位:0101 1010 0111 1010 1111 1000 0110 0010

    3.进行P盒置换

        将S盒输出结果再通过一个P盒置换产生一个32位输出


    上步得到的结果使用P盒置换后得到的结果为:

                                         0111 0101 0101 1111 1000 0100 1100 0110

    将此结果与 L0(32位) = 1100 1100 0000 0000 1100 1100 1111 1111

    进行异或运算得到结果为:1011 1001 1010 0000 0100 1000 0011 1001

    4.左右交换位置

    将上步的结果赋给R1

        即R1 = 1011 1001 1010 0000 0100 1000 0011 1001

    R0则原封不动的赋给L1

        即L1 =  R0(32位) = 1111 0000 1010 1010 1111 0000 1010 1010

    之后进入下一轮迭代。最后生成L16和R16,其中R16为L15与P盒置换结果做异或运算的结果,L16是R15的直接赋值

    5.密文的生成

        经过16次的迭代,我们得到了16对32位的数据块,即L1R1,L2R2,......L16R16;

        最后一对L16R16就是我们需要的。然后将L16与R16的位置交换,继续对R16L16(64位)运用一次IP-1排列


    即在:L16(32位) = 0100 0011 0100 0010 0011 0010 0011 0100

              R16(32位) = 0000 1010 0100 1100 1101 1001 1001 0101

         R16L16(64位) = 00001010 01001100 11011001 10010101 01000011  01000010 00110010 00110100

    时,对R16L16运用IP-1,得

    IP-1(64位) = 10000101 11101000 00010011 01010100 00001111 00001010 10110100 00000101

                        =85E813540F0AB405

    至此,我们就得到了明文M的密文。


    以上为加密过程,要解密,依次反向计算即可。




    参考博客:https://blog.csdn.net/yxtxiaotian/article/details/52025653

                     http://www.doc88.com/p-9909383710144.html



    展开全文
  • 加密算法大全

    2018-12-14 21:26:20
    加密算法 1 2 加密算法 1 3 加密算法介绍 2 3.1 密码学简介 2 3.2 加密算法介绍 3 3.2.1 对称加密算法 3 3.2.2 非对称算法 4 3.2.3 散列算法 5 3.2.4 对称与非对称算法比较 6 3.3 加密算法的选择 7 3.4 密码学在现代...
  • DES加密算法源码 DES加密算法源码

    热门讨论 2009-06-10 12:05:56
    DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码 DES加密算法源码DES加密...
  • 如题,请教NTLM加密算法NTLM 密码加密算法NTLM 密码加密算法NTLM 密码加密算法
  • AES128加密算法完整实现

    万次阅读 多人点赞 2019-02-26 22:38:02
    原本想把自己AES加密算法的整个实现过程给详细复述下来,分享给想学习的同学,也方便自己复习,但后来发现该工作量太大,加上作业太多没有过多的时间去写。所以就想把自己在学习的过程中多遇到的好的文章进行汇总,...

          概述

    原本想把自己AES加密算法的整个实现过程给详细复述下来,分享给想学习的同学,也方便自己复习,但后来发现该工作量太大,加上作业太多没有过多的时间去写。所以就想把自己在学习的过程中多遇到的好的文章进行汇总,避免重复性的工作,因为我感觉有的文章的介绍和配图写的非常好,再次重复也没有意义。本文里我会将文章的链接附上,如有侵权,敬请告知!

    因为最近要完成课程作业,实现AES128加解密,本以为就是一个简单的算法实现,后来发现AES加密的每一步都挺难,而且都涉及到我没听过的概念,所以最近看了很多帖子、资料。最终终于能够解决这个问题。关于AES算法的介绍,网上有很多的帖子,所以我就不进行赘述了,我只是希望将我遇到的一些比较难以理解的点进行详细的叙述。

    实现AES算法主要包括以下学习步骤:

    1. GF(2^8)域上的多项式运算
    2. 扩展的欧几里德算法
    3. 生成S盒
    4. 生成逆S盒
    5. S盒置换
    6. 行移位
    7. 列混合
    8. 生成秘钥
    9. 循环加密

    其中1、2、3、4步都跟S盒生成有关,根据我所看的一些博客,S盒的生成涉及到数论的基础知识。如果没有基础的话,1、2是要专门去学习的,我在这两步上花费了很多时间。但是在网上也可以找到很多AES算法,他们用的是现成的S盒,没有前4步,直接用现成的S盒置换,这样相对会容易一些。但是本着刨根问底和多学习知识的原则,我还是去学习了S盒的生成方式。第5步就是将每一个字符进行查表替换,没有什么难以理解的地方,所以相对而言比较容易。第6步应该是整个过程当中最简单的一步了,就是进行一个循环移位。第7步列混合涉及到矩阵和多项式的乘法,所以还是有一定难度,。。。

    如果想从整体上了解AES加密的完整过程,那么下面几篇文章不管从叙述还是插图上来看都是很不错的,几篇文章介绍的方式不同,但是原理都是一样的,对比结合着看会更有帮助:

    AES加密 - block2016 - 博客园

    AES算法简介_Jimmy.li的博客-CSDN博客_aes算法

    密码算法详解——AES - ReadingLover - 博客园

    http://www.alonemonkey.com/2016/05/25/aes-and-des/

    但是仅从这几篇文章来看的话,对于像我这样的小白而言还是没有办法实现的,因为各个步骤介绍的并不具体,尤其是对于缺少基本数学知识学习的同学很难理解。所以这几篇文章可以作为整体进度的把控,接下来看怎么一步步学习实现。

         S盒

    我在学习这个算法的时候,在S盒的生成及置换上花费的时间是最多的。可能是因为基础较差,所以需要学习的东西比较多,所以我将这一部分进行了逐项的划分。关于S盒的生成及置换,这篇博客进行了非常详细的介绍,但是有一些东西我还是没明白,所以又参考了很多其他文章,才把这一部分搞明白。建议初学者以这篇博客为基础进行学习:

    AES128加密-S盒和逆S盒构造推导及代码实现_u011516178的博客-CSDN博客

    下面进行分步的介绍。

          GF(2^8)域上的多项式计算

    因为整个过程很多,所以我决定分为多个文章分别进行叙述,首先是GF(2^8)域上的多项式计算,因为以前也没有学过相关知识,很多概念都是第一次见到,所以这部分花了很长时间去学习。在学习这个之前,我们需要知道为什么去学习这个东西,AES加密中的哪一步用到了该知识点呢?

    S盒的置换就是将0~2^8中的任意一个字节置换为另外一个,置换的原则是将该元素置换为在GF(2^8)域上的乘法逆元,什么是GF(2^8)域?什么又是逆元呢?这些定义的准确数学描述我不太懂,根据本次应用,我可以给出粗略说明,GF(2^8)有限域大概就是指定义在该域中的数值经过定义在该域上的函数运算,其结果也都在该域内, 借用网上的一个例子进行说明:

    那什么又是乘法逆元呢,形如:

    (a\cdot a_{-1} ) \% p=1

    其中p为有限域的范围,这里按理说应该为2^8,但是却不能取这个数,因为2^8并不与其内的每一个数互质,所以只能选一个更大的质数(具体原因请参考扩展的欧几里德算法),AES算法中p的值选的是0x11B, 我也不知道为什么,可能是约定俗成的吧,因为如果想找一个稍微比255大的质数,不知道为什么要取293(0x11B)。a 为有限域内的整数,那么 a_{-1} 即为 a 在有限域上的逆元。至此,我们知道逆元是什么,但是具体怎么去求解还不太清楚,这一部分请参照扩展的欧几里德算法

    我接下来继续说GF(2^8)域上的多项式运算,因为把基本的运算搞清楚是计算GF(2^8)域上乘法逆元的前提,该域上的加减乘除运算是与传统的运算所不同的,具体的多项式运算请参考GF(2^8)域上的多项式运算。当然,也可以先学习扩展的欧几里德算法,然后再学习该部分,实现的时候将欧几里德算法中的四则运算换成GF(2^8)域上的多项式运算就行了。关于GF(2^8)域的计算介绍参考以下几篇博客介绍:

    有限域GF(2^8)的四则运算及拉格朗日插值_luotuo44的专栏-CSDN博客

    伽罗华域(Galois Field)上的四则运算_shelldon的专栏-CSDN博客_伽罗华域

    伽罗华域(Galois Field)上的四则运算 - kk Blog —— 通用基础

    在四则运算中,加减运算就是简单的异或运算,很简单。而乘除运算则是以乘法运算为基础,所以四则运算中最主要的是理解乘法的运算,这篇有限域GF(2^8)内乘法代码实现以及原理_bupt073114的专栏-CSDN博客_有限域乘法文章详细介绍了乘法运算,以及其实现。

    拓展的欧几里得算法

    待掌握了GF(2^8)域的运算知识后,应该去学一下拓展的欧几里得算法,对于该算法,上面所给出的关于S盒生成的综述博文里已经参考相关教材进行了非常详细的论述,所以关于这部分知识可以同样参考这篇博文(参考文献10),

    还可以参考以下这篇博客:

    欧几里德与扩展欧几里德算法 - jumpingfrog0 - 博客园

    如果还不明白,也可以自行查找其他关于拓展欧几里得算法的介绍。

    S盒生成及置换

    关于S盒的生成及置换,同样参考文献10,该文章已经进行了非常详尽的描述与代码实现。待自己完成后也可以参考博客中的结果进行检验。

    行移位

    行移位就是对每行数据进行相应的循环移位,没有难以理解的地方,应该是整个加密过程最简单的部分,关于移位的规则,可以参考文献1、2、3、4,均有详细的图示介绍。下图来源于文献4:

    列混合

    列混合就是将数据矩阵乘上一个矩阵,解密的时候乘上原矩阵的逆矩阵进行解密,秩序要按照步骤一步步来即可,同样没有难以理解的地方,按照参考文献1、2、3、4的介绍进行操作就没有问题。关于列混合还可以参照这篇专门介绍的文章[11],其对于列混合又专门的介绍与实现,而且还有检验数据。下图参照文献4中图片:

    密钥生成

    密钥的生成过程稍微有些麻烦,需要仔细参考规则,避免搞错,但是只需要理解操作规则即可,不需要理论理解,还好参考文献3、4中都有非常生动的图示。下图来源于文献4:

    循环加密

    循环加密就是对上述过程重复进行若干次。具体实现参照文献1、2、3、4。

    解密

    解密过程就是将上述的过程反过来执行一遍,原本置换的就置换过来;原本移位的就反向移过来;原本乘上矩阵的就乘上她的逆矩阵。。。上面关于每个加密过程的参考文献都有相应的解密过程。

    实现

    关于AES128的加密完整实现,可以参照代码https://github.com/xinyu-yang/AES128-CBC,此代码的实现几乎都是参照上文的介绍,唯一不同的是在加密的时候采用了CBC模式,具体什么是CBC加密模式,如果不清楚的可以自行百度。如果有时间我也会把这部分补全。

    最后:本文如有帮助,请关注最新站点麋鹿博客,非常感谢

    参考文献:

    1、扩展欧几里德算法详解_蛤蛤~-CSDN博客_扩展欧几里得算法

    2、AES加密 - block2016 - 博客园

    3、AES算法简介_Jimmy.li的博客-CSDN博客_aes算法

    4、密码算法详解——AES - ReadingLover - 博客园

    5、http://www.alonemonkey.com/2016/05/25/aes-and-des/

    6、有限域GF(2^8)的四则运算及拉格朗日插值_luotuo44的专栏-CSDN博客

    7、伽罗华域(Galois Field)上的四则运算_shelldon的专栏-CSDN博客_伽罗华域

    8、伽罗华域(Galois Field)上的四则运算 - kk Blog —— 通用基础

    9、有限域GF(2^8)内乘法代码实现以及原理_bupt073114的专栏-CSDN博客_有限域乘法

    10、AES128加密-S盒和逆S盒构造推导及代码实现_u011516178的博客-CSDN博客

    11、AES加密算法之列混合变换_﹎厡.唻-CSDN博客_aes列混合

    12、欧几里德与扩展欧几里德算法 - jumpingfrog0 - 博客园

    展开全文
  • SVN Password加密算法(httpd加密算法

    热门讨论 2012-02-22 14:05:22
    SVN Password加密算法(httpd加密算法) C#代码
  • 常用加密算法之非对称加密算法

    万次阅读 2018-03-16 21:44:45
    非对称加密算法 非对称加密算法是一种密钥的保密方法。非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有...

    非对称加密算法

     
    对称加密算法是一种密钥的保密方法。
    非对称加密算法需要两个密钥: 公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对 密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。
    另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。
    甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。 非 对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。
    非对称 密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。


    工作原理


    1.A要向B发送信息,A和B都要产生一对用于加密
    非对称加密算法 非对称加密算法
    和解密的 公钥私钥
    2.A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。
    3.A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。
    4.A将这个消息发给B(已经用B的公钥加密消息)。
    5.B收到这个消息后,B用自己的私钥解密A的消息。其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。



    主要应用


    非对称加密(公钥加密):指加密和解密使用不同 密钥的加密算法,也称为公 私钥加密。假设两个用户要加密交换数据,双方交换 公钥,使用时一方用对方的公钥加密,另一方即可用自己的私钥解密。如果企业中有n个用户,企业需要生成n对密钥,并分发n个公钥。假设A用B的公钥加密消息,用A的私钥签名,B接到消息后,首先用A的公钥验证签名,确认后用自己的私钥解密消息。由于公钥是可以公开的,用户只要保管好自己的私钥即可,因此加密密钥的分发将变得 十分简单。同时,由于每个用户的私钥是唯一的,其他用户除了可以通过信息发送者的公钥来验证信息的来源是否真实,还可以通过数字签名确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比对称加密慢上1000倍。

    主要功能


    非对称加密体系不要求通信双方事先传递 密钥或有任何约定就能完成 保密通信,并且 密钥管理方便,可实现防止假冒和抵赖,因此,更适合网络通信中的保密通信要求。

    主要算法


    RSAElgamal、背包算法、Rabin、D-H、 ECC(椭圆曲线加密算法)。
    使用最广泛的是RSA算法,Elgamal是另一种常用的非 对称加密算法

    算法区别


    对称加密算法与对称加密算法的区别[1] 
    首先,用于消息解密的密钥值与用于消息加密的密钥值不同;
    其次,非对称加密算法比对称加密算法慢数千倍,但在保护通信安全方面,非对称加密算法却具有对称密码难以企及的优势。
    为说明这种优势,使用对称加密算法的例子来强调:
    Alice使用 密钥K加密消息并将其发送给Bob,Bob收到加密的消息后,使用密钥K对其解密以恢复原始消息。这里存在一个问题,即Alice如何将用于加密消息的密钥值发送给 Bob?答案是,Alice发送密钥值给Bob时必须通过独立的安全通信信道(即没人能监听到该信道中的通信)。
    这种使用独立安全信道来交换 对称加密算法密钥的需求会带来更多问题:
    首先,有独立的安全信道,但是安全信道的带宽有限,不能直接用它发送原始消息。
    其次,Alice和Bob不能确定他们的密钥值可以保持多久而不泄露(即不被其他人知道)以及何时交换新的密钥值
    当然,这些问题不只Alice会遇到,Bob和其他每个人都会遇到,他们都需要交换密钥并处理这些 密钥管理问题(事实上,X9.17是一项DES密钥管理ANSI标准[ANSIX9.17])。如果Alice要给数百人发送消息,那么事情将更麻烦,她必须使用不同的 密钥值来加密每条消息。例如,要给
    非对称加密算法 非对称加密算法
    200个人发送通知,Alice需要加密消息200次,对每个接收方加密一次消息。显然,在这种情况下,使用 对称加密算法来进行安全通信的开销相当大。
    非对称加密算法的主要优势就是使用两个而不是一个密钥值:一个密钥值用来加密消息,另一个密钥值用来解密消息。这两个密钥值在同一个过程中生成,称为密钥对。用来加密消息的密钥称为 公钥,用来解密消息的密钥称为 私钥。用公钥加密的消息只能用与之对应的私钥来解密,私钥除了持有者外无人知道,而公钥却可通过非安全管道来发送或在目录中发布。
    Alice需要通过电子邮件给Bob发送一个机密文档。首先,Bob使用电子邮件将自己的公钥发送给Alice。然后Alice用Bob的公钥对 文档加密并通过电子邮件将加密消息发送给Bob。由于任何用Bob 的公钥加密的消息只能用Bob的私钥解密,因此即使窥探者知道Bob的公钥,消息也仍是安全的。Bob在收到加密消息后,用自己的私钥进行解密从而恢复原始文档。

    说了这么多概念性东西,都是方便大家加深理解,想要理解的更仔细可以自行百度。

    下面我会以实战的方式实现常用的非对称加密算法的加密和解密。


    一:DH实现非对称加密算法:

    方式一:jdk的方式实现DH


          // jdk实现:
    public static void jdkDH()
    {
    try 
    {
    // 1.初始化发送方密钥
    KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
    senderKeyPairGenerator.initialize(512);
    KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
    // 发送方公钥,发送给接收方(网络、文件。。。)
    byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();

    // 2.初始化接收方密钥
    KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
    PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
    DHParameterSpec dhParameterSpec = ((DHPublicKey) receiverPublicKey).getParams();
    KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
    receiverKeyPairGenerator.initialize(dhParameterSpec);
    KeyPair receiverKeypair = receiverKeyPairGenerator.generateKeyPair();
    PrivateKey receiverPrivateKey = receiverKeypair.getPrivate();
    byte[] receiverPublicKeyEnc = receiverKeypair.getPublic().getEncoded();

    // 3.密钥构建
    KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
    receiverKeyAgreement.init(receiverPrivateKey);
    receiverKeyAgreement.doPhase(receiverPublicKey, true);
    SecretKey receiverDesKey = receiverKeyAgreement.generateSecret("DES");

    KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
    x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
    PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
    KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
    senderKeyAgreement.init(senderKeyPair.getPrivate());
    senderKeyAgreement.doPhase(senderPublicKey, true);
    SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
    if(Objects.equals(receiverDesKey, senderDesKey))
    {
    System.out.println("双方密钥相同。");
    }

    // 4.加密
    Cipher cipher = Cipher.getInstance("DES");
    cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
    byte[] result = cipher.doFinal(src.getBytes());
    System.out.println("bc dh encrypt:" + Base64.encodeBase64String(result));

    // 5.解密
    cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
    result = cipher.doFinal(result);
    System.out.println("bc dh decrypt:" + new String(result));

    } catch (Exception e) {

    e.printStackTrace();
    }

    }

    方式二:elgamal方式实现:

    // jdk实现:“私钥解密、公钥加密” , 对于:“私钥加密、公钥解密”有问题,因为Elgamal不支持
    public static void jdkElgamal()
    {
    try 
    {
    // 加入对BouncyCastle支持  
    Security.addProvider(new BouncyCastleProvider());

    // 1.初始化发送方密钥
    AlgorithmParameterGenerato algorithmParameterGenerator=        AlgorithmParameterGenerator.getInstance("Elgamal");
    // 初始化参数生成器
    algorithmParameterGenerator.init(256);
    // 生成算法参数
    AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
    // 构建参数材料
    DHParameterSpec dhParameterSpec = (DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class);
    // 实例化密钥生成器
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("Elgamal");
    // 初始化密钥对生成器  
    keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    // 公钥
    PublicKey elGamalPublicKey = keyPair.getPublic();
    // 私钥 
    PrivateKey elGamalPrivateKey = keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));


    // 2.私钥解密、公钥加密 ---- 加密
    // 初始化公钥  
            // 密钥材料转换
    X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
    // 实例化密钥工厂
    KeyFactory keyFactory2 = KeyFactory.getInstance("Elgamal");
    // 产生公钥
    PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
    // 数据加密 
    // Cipher cipher2 = Cipher.getInstance("Elgamal");
    Cipher cipher2 = Cipher.getInstance(keyFactory2.getAlgorithm()); 
    cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
    byte[] result2 = cipher2.doFinal(src.getBytes());
    System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result2));

    // 3.私钥解密、公钥加密 ---- 解密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
    KeyFactory keyFactory5 = KeyFactory.getInstance("Elgamal");
    PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
    // Cipher cipher5 = Cipher.getInstance("Elgamal");
    Cipher cipher5 = Cipher.getInstance(keyFactory5.getAlgorithm()); 
    cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
    byte[] result5 = cipher5.doFinal(result2);
    System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result5));




    /*
    // 私钥加密、公钥解密: 有问题
    // 4.私钥加密、公钥解密 ---- 加密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());
    KeyFactory keyFactory = KeyFactory.getInstance("Elgamal");
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    Cipher cipher = Cipher.getInstance("Elgamal");
    cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    byte[] result = cipher.doFinal(src.getBytes());
    System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));

    // 5.私钥加密、公钥解密 ---- 解密
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());
    keyFactory = KeyFactory.getInstance("Elgamal");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    cipher = Cipher.getInstance("Elgamal");
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    result = cipher.doFinal(result);
    System.out.println("Elgamal 私钥加密、公钥解密 ---- 解密:" + new String(result));
    */

    } catch (Exception e) {

    e.printStackTrace();
    }

    }


    方式二:

    //非对称密钥算法
    public static final String KEY_ALGORITHM="ElGamal";


    /**
    * 密钥长度,DH算法的默认密钥长度是1024
    * 密钥长度必须是8的倍数,在160到16384位之间
    * */
    private static final int KEY_SIZE=256;
    //公钥
    private static final String PUBLIC_KEY="ElGamalPublicKey";

    //私钥
    private static final String PRIVATE_KEY="ElGamalPrivateKey";

    /**
    * 初始化密钥对
    * @return Map 甲方密钥的Map
    * */
    public static Map<String,Object> initKey() throws Exception{
    //加入对BouncyCastle支持
    Security.addProvider(new BouncyCastleProvider());
    AlgorithmParameterGenerator apg=AlgorithmParameterGenerator.getInstance(KEY_ALGORITHM);
    //初始化参数生成器
    apg.init(KEY_SIZE);
    //生成算法参数
    AlgorithmParameters params=apg.generateParameters();
    //构建参数材料
    DHParameterSpec elParams=(DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);

    //实例化密钥生成器
    KeyPairGenerator kpg=KeyPairGenerator.getInstance(KEY_ALGORITHM) ;

    //初始化密钥对生成器
    kpg.initialize(elParams,new SecureRandom());

    KeyPair keyPair=kpg.generateKeyPair();
    //甲方公钥
    PublicKey publicKey= keyPair.getPublic();
    //甲方私钥
    PrivateKey privateKey= keyPair.getPrivate();
    //将密钥存储在map中
    Map<String,Object> keyMap=new HashMap<String,Object>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;

    }


    /**
    * 公钥加密
    * @param data待加密数据
    * @param key 密钥
    * @return byte[] 加密数据
    * */
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{

    //实例化密钥工厂
    KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
    //初始化公钥
    //密钥材料转换
    X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
    //产生公钥
    PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);

    //数据加密
    Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    return cipher.doFinal(data);
    }
    /**
    * 私钥解密
    * @param data 待解密数据
    * @param key 密钥
    * @return byte[] 解密数据
    * */
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
    //取得私钥
    PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
    KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
    //生成私钥
    PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
    //数据解密
    Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    return cipher.doFinal(data);
    }

    /**
    * 取得私钥
    * @param keyMap 密钥map
    * @return byte[] 私钥
    * */
    public static byte[] getPrivateKey(Map<String,Object> keyMap){
    Key key=(Key)keyMap.get(PRIVATE_KEY);
    return key.getEncoded();
    }
    /**
    * 取得公钥
    * @param keyMap 密钥map
    * @return byte[] 公钥
    * */
    public static byte[] getPublicKey(Map<String,Object> keyMap) throws Exception{
    Key key=(Key) keyMap.get(PUBLIC_KEY);
    return key.getEncoded();
    }
    /**
    * @param args
    * @throws Exception 
    */
    public static void main(String[] args) throws Exception {
    //初始化密钥
    //生成密钥对
    Map<String,Object> keyMap=ElGamalTest2.initKey();
    //公钥
    byte[] publicKey=ElGamalTest2.getPublicKey(keyMap);

    //私钥
    byte[] privateKey=ElGamalTest2.getPrivateKey(keyMap);
    System.out.println("公钥:/n"+Base64.encodeBase64String(publicKey));
    System.out.println("私钥:/n"+Base64.encodeBase64String(privateKey));

    System.out.println("================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输=============");
    String str="ElGamal密码交换算法";
    System.out.println("/n===========甲方向乙方发送加密数据==============");
    System.out.println("原文:"+str);

    //乙方使用公钥对数据进行加密
    byte[] code2=ElGamalTest2.encryptByPublicKey(str.getBytes(), publicKey);
    System.out.println("===========乙方使用公钥对数据进行加密==============");
    System.out.println("加密后的数据:"+Base64.encodeBase64String(code2));


    //甲方使用私钥对数据进行解密
    byte[] decode2=ElGamalTest2.decryptByPrivateKey(code2, privateKey);

    System.out.println("甲方解密后的数据:"+new String(decode2));
    }


    方式三:RSA实现非对称加密算法:

    RSA实现非对称也有俩种方式,具体的实现和区别见代码注释:

           方式一:jdk实现

           // jdk实现:私钥加密、公钥解密: 并发时间测试
    public static void RSA()
    {
    try 
    {
    long startTimes = System.currentTimeMillis();


    // 1.初始化发送方密钥
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
    final RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));




    // 2.公钥加密、私钥解密 ---- 加密
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    result = cipher.doFinal(src.getBytes());
    System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result));

    long endEncryptTime = System.currentTimeMillis();
    System.out.println("公钥加密、私钥解密 ---- 加密1个时间(单位毫秒):" + (endEncryptTime - startTimes));

    int decryptTimes = 200000;  // 并发解密的个数
    //创建一个可重用固定线程数的线程池
            ExecutorService pool =  Executors.newCachedThreadPool(); // Executors.newFixedThreadPool(1000);
            
    for(int i=0; i<decryptTimes;i++)
    {
    pool.execute(new Thread(new Runnable() {

    @Override
    public void run() {
    try {
    // 3.私钥解密、公钥加密 ---- 解密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec2 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
    KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");

    PrivateKey privateKey2 = keyFactory2.generatePrivate(pkcs8EncodedKeySpec2);
    Cipher cipher2 = Cipher.getInstance("RSA");
    cipher2.init(Cipher.DECRYPT_MODE, privateKey2);
    byte[] result2 = cipher2.doFinal(result);
    // System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result2));
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }));
      
    }

    pool.shutdown();

    while (true) {  
                if (pool.isTerminated()) {  
                    System.out.println("结束了!"); 
                    long endDencryptTime = System.currentTimeMillis() ;
                    long totalTimes = (endDencryptTime - endEncryptTime) / 1000;
                    System.out.println("公钥加密、私钥解密 ---- 并发:" + decryptTimes + "个解密时间(单位秒):" + totalTimes);
                    break;  
                }  
                Thread.sleep(200);  
            }


    } catch (Exception e) {

    e.printStackTrace();
    }

    }


    方式二:

    // jdk实现:
    public static void jdkRSA()
    {
    try 
    {
    // 1.初始化发送方密钥
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(512);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
    System.out.println("Public Key:" + Base64.encodeBase64String(rsaPublicKey.getEncoded()));
    System.out.println("Private Key:" + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));

    // 2.私钥加密、公钥解密 ---- 加密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    byte[] result = cipher.doFinal(src.getBytes());
    System.out.println("私钥加密、公钥解密 ---- 加密:" + Base64.encodeBase64String(result));

    // 3.私钥加密、公钥解密 ---- 解密
    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
    keyFactory = KeyFactory.getInstance("RSA");
    PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
    cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, publicKey);
    result = cipher.doFinal(result);
    System.out.println("私钥加密、公钥解密 ---- 解密:" + new String(result));



    // 4.公钥加密、私钥解密 ---- 加密
    X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
    KeyFactory keyFactory2 = KeyFactory.getInstance("RSA");
    PublicKey publicKey2 = keyFactory2.generatePublic(x509EncodedKeySpec2);
    Cipher cipher2 = Cipher.getInstance("RSA");
    cipher2.init(Cipher.ENCRYPT_MODE, publicKey2);
    byte[] result2 = cipher2.doFinal(src.getBytes());
    System.out.println("公钥加密、私钥解密 ---- 加密:" + Base64.encodeBase64String(result2));

    // 5.私钥解密、公钥加密 ---- 解密
    PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
    KeyFactory keyFactory5 = KeyFactory.getInstance("RSA");
    PrivateKey privateKey5 = keyFactory5.generatePrivate(pkcs8EncodedKeySpec5);
    Cipher cipher5 = Cipher.getInstance("RSA");
    cipher5.init(Cipher.DECRYPT_MODE, privateKey5);
    byte[] result5 = cipher5.doFinal(result2);
    System.out.println("公钥加密、私钥解密 ---- 解密:" + new String(result5));

    } catch (Exception e) {

    e.printStackTrace();
    }

    }


    好了,对称加密算法就总结到这里了,在下一篇中,我将会总结常用的对称加密算法。

    展开全文
  • des加密算法 des加密算法 des加密算法 des加密算法 des加密算法 des加密算法
  • 加密算法及工具类

    2018-07-25 18:44:57
    加密算法加密算法加密算法加密算法加密算法加密算法加密算法加密算法
  • 对称加密算法和非对称加密算法的区别 1.对称加密算法加密和解密使用的密钥的是相同的,也就是只有一个密钥,而非对称加密算法有两个密钥,也就是加密和解密所使用的密钥是不同的 2.各自算法不同 3.对称加密算法加密...
  • 浅谈常见的七种加密算法及实现

    万次阅读 多人点赞 2018-09-10 18:38:26
    数字签名、信息加密 是前后端开发都经常需要使用到的技术,应用场景包括了用户登入、交易、信息通讯、oauth 等等,不同的应用场景也会需要使用到不同的签名加密算法,或者需要搭配不一样的 签名加密算法 来达到业务...
  • 常见加密算法及常见加密算法原理

    万次阅读 2018-08-09 17:16:11
    加密算法和协议 对称加密 简介:加密和解密使用同一个密钥 常见的算法: - DES:Data Encryption Standard; - 3DES:Triple DES; - AES:Advanced Encryption Standard; (128bits, 192bits, 256bits, 384...
  • RSA加密算法原理

    万次阅读 多人点赞 2019-10-08 00:58:01
    RSA加密算法是一种非对称加密算法,所谓非对称,就是指该算法加密和解密使用不同的密钥,即使用加密密钥进行加密、解密密钥进行解密。在RAS算法中,加密密钥(即公开密钥)PK是公开信息,而解...
  • 四种加密算法

    千次阅读 2021-05-27 17:35:16
    加密算法 AES 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传 输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图: RSA RSA ...
  • 对称加密算法

    千次阅读 2017-01-22 09:33:23
    对称加密算法由古典加密算法演化而来,解密和加密互为逆运算,加密和解密秘钥相同,因而称为对称加密算法,具有代表性的有DES、3DES、AES、PBE、IDEA。DES由IBM提出堪称经典对称加密算法,不仅应用在软件行业,甚至...
  • 对称加密算法和非对称加密算法

    千次阅读 2017-06-16 18:47:36
    (一)对称加密(Symmetric Cryptography)对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key),这种方法在密码学中叫做对称加密算法。对称加密有很多...
  • 在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。常用的对称加密算法:AES,RC4,3DES传输的示意图如下所示:如上图所示,此种...
  • 数据加密算法2010

    2010-03-04 10:45:10
    加密算法加密算法加密算法加密算法加密算法加密算法加密算法加密算法加密算法
  • 对称加密算法与非对称加密算法的区别 对称加密算法 对称加密算法是应用较早的加密算法,技术成熟。在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文...
  • RSA加密算法MFC

    热门讨论 2011-03-23 10:02:53
    RSA加密算法MFCRSA加密算法MFCRSA加密算法MFCRSA加密算法MFC
  • DES,DES加密算法,DES算法源码。用C写的DES加密算法。 DES,DES加密算法,DES算法源码。 DES加密算法(c语言实现) (本程序可以直接使用)
  • 对称加密算法之DES介绍

    万次阅读 2014-12-30 21:15:04
    对称加密算法之DES介绍!
  • 通信加密算法

    千次阅读 2018-03-10 23:39:41
    1. 加密算法分类加密算法通常分为对称性加密算法和非对称性加密算法。对于对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行加解密了。非对称算法与之不同,发送双方A...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 338,289
精华内容 135,315
关键字:

加密算法