分组密码模式: CBC模式(密码分组链接模式)

块加密

块加密,英文Block Cyper,又称分组加密,是一种常见的对称加密,具有代表性的块加密有DES,AES,3DES等。块加密的工作模式允许使用同一个分组密码密钥对多于一块的数据进行加密,并保证其安全性。

 

CBC模式是将前一个密文分组与当前明文分组的内容混合起来进行加密的,这样就可以避免ECB模式的弱点。

在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密,如下图所示:

c1

如果将一个分组的加密过程分离出来,我们就可以很容易地比较出ECB模式和CBC模式的区别,ECB模式只进行了加密,而CBC模式则在加密之前进行了一次XOR,如下图所示:

c2

 

当加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列称为初始化向量,通常缩写为IV。

 

CBC模式优点:

1. 不容易主动攻击, 安全性好于ECB, 适合传输长度长的报文, 是SSL、IPSec的标准

 

CBC模式缺点:

1. 不利于并行计算
2. 误差传递
3. 需要初始化向量IV

 

对CBC模式的攻击,截图来源自图解密码技术一书:

c3

 

c5

CBC模式的加密:

#include <STRING.H>

#define IN
#define OUT

//假设加密分组为4字节一组

/**************************************************************************
*功  能:    加密算法 (与Key异或)
*参  数:    lpszData        当前明文分组数据
*           lpszKey         Key    
*           lpszDeData      加密后的结果
*
*返回值:    
**************************************************************************/
void Encrypt(IN const char *lpszData, IN const char *lpszKey, OUT char *lpszEnData)
{
    int i = 0;
    for (i = 0; i < 4; i++)
    {
        lpszEnData[i] = lpszData[i] ^ lpszKey[i];
    }
}

/**************************************************************************
*功  能:    解密算法 (再次异或还原明文)
*参  数:    lpszData        当前密文分组数据
*           lpszKey         Key    
*           lpszDeData      解密后的结果
*
*返回值:    
**************************************************************************/
void Decrypt(IN const char *lpszData, IN const char *lpszKey, OUT char *lpszDeData)
{
    int i = 0;
    for (i = 0; i < 4; i++)
    {
        lpszDeData[i] = lpszData[i] ^ lpszKey[i];
    }
}

/**************************************************************************
*功  能:    与前一个密文分组进行xor
*参  数:    lpszData        当前明文分组数据
*           lpszPreEnData   前一个密文分组
*           lpszDeData      保存异或后的数据
*
*返回值:    
**************************************************************************/
void XorEnGroup(IN const char *lpszData, IN const char *lpszPreEnData, OUT char *lpszDeData)
{
    int i = 0;
    for (i = 0; i < 4; i++)
    {
        lpszDeData[i] = lpszData[i] ^ lpszPreEnData[i];
    }
}

int main(int argc, char* argv[])
{
    char szData[] = "Hello World!";
    char szEnData[16] = {0};
    char szDeData[16] = {0};
    char *lpszKey = "1234";
    int i = 0;
    char szIV[] = "9999";

    printf("原始数据: %s\r\n", szData);
    
    while (true)
    {
        if (strlen(szData + i) == 0)
        {
            break;
        }

        //首先需要与前一个密文分组进行xor
        XorEnGroup(szData + i, szIV, szData + i);

        //更新密文分组
        Encrypt(szData + i, lpszKey, szIV);

        memcpy(szEnData + i, szIV, 4);

        i += 4;
    }

    printf("加密后数据: %s\r\n", szEnData);

    memcpy(szIV, "9999", 4);

    i = 0;
    char szPreEnData[8] = {0};

    while (true)
    {
        if (strlen(szEnData + i) == 0)
        {
            break;
        }

        memcpy(szPreEnData, szEnData + i, 4);

        //先解密
        Decrypt(szEnData + i, lpszKey, szEnData + i);

        //再与前一个密文分组进行xor
        XorEnGroup(szData + i, szIV, szDeData + i);

        memcpy(szIV, szPreEnData, 4);

        i += 4;
    }

    printf("解密后数据: %s\r\n", szDeData);

    return 0;
}
来源:https://www.cnblogs.com/dacainiao/p/5521866.html
另外几种加密方式:

分组加密的模式(ECB、CBC、CFB、OFB)

加密一般分为对称加密(Symmetric Key Encryption)和非对称加密(Asymmetric Key Encryption)。

对称加密又分为分组加密和序列密码。
分组密码,也叫块加密(block cyphers),一次加密明文中的一个块。是将明文按一定的位长分组,明文组经过加密运算得到密文组,密文组经过解密运算(加密运算的逆运算),还原成明文组。
序列密码,也叫流加密(stream cyphers),一次加密明文中的一个位。是指利用少量的密钥(制乱元素)通过某种复杂的运算(密码算法)产生大量的伪随机位流,用于对明文位流的加密。
解密是指用同样的密钥和密码算法及与加密相同的伪随机位流,用以还原明文位流。

分组加密算法中,有ECB,CBC,CFB,OFB这几种算法模式。

1)ECB(Electronic Code Book)/电码本模式

ecb1
ecb2

 

DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,按照需求补足8个字节进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。

特点:

1.简单,有利于并行计算,误差不会被传送;
2.不能隐藏明文的模式;
repetitions in message may show in cipher text/在密文中出现明文消息的重复
3.可能对明文进行主动攻击;
加密消息块相互独立成为被攻击的弱点/weakness due to encrypted message blocks being independent

2)CBC(Cipher Block Chaining)/密文分组链接方式

cbc1

cbc2

DES CBC(密文分组链接方式)有点麻烦,它的实现机制使加密的各段数据之间有了联系。其实现的机理如下:

加密步骤如下:

1)首先将数据按照8个字节一组进行分组得到D1D2......Dn(若数据不是8的整数倍,用指定的PADDING数据补位)

2)第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)

3)第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2

4)之后的数据以此类推,得到Cn

5)按顺序连为C1C2C3......Cn即为加密结果。

解密是加密的逆过程,步骤如下:

1)首先将数据按照8个字节一组进行分组得到C1C2C3......Cn

2)将第一组数据进行解密后与初始化向量I进行异或得到第一组明文D1(注意:一定是先解密再异或)

3)将第二组数据C2进行解密后与第一组密文数据进行异或得到第二组数据D2

4)之后依此类推,得到Dn

5)按顺序连为D1D2D3......Dn即为解密结果。

这里注意一点,解密的结果并不一定是我们原来的加密数据,可能还含有你补得位,一定要把补位去掉才是你的原来的数据。

特点:

1. 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
each ciphertext block depends on all message blocks/每个密文块依赖于所有的信息块
thus a change in the message affects all ciphertext blocks/明文消息中一个改变会影响所有密文块
2. need Initial Vector (IV) known to sender & receiver/发送方和接收方都需要知道初始化向量
3.加密过程是串行的,无法被并行化(在解密时,从两个邻接的密文块中即可得到一个平文块。因此,解密过程可以被并行化)。

PCBC

填充密码块链接(PCBC,Propagating cipher-block chaining)或称为明文密码块链接(Plaintext cipher-block chaining),是一种可以使密文中的微小更改在解密时导致明文大部分错误的模式,并在加密的时候也具有同样的特性。

p1

p2

对于使用PCBC加密的消息,互换两个邻接的密文块不会对后续块的解密造成影响。

3)Cipher Feedback (CFB)/密文反馈模式

cfb

密文反馈(CFB,Cipher feedback)模式类似于CBC,可以将块密码变为自同步的流密码;工作过程亦非常相似,CFB的解密过程几乎就是颠倒的CBC的加密过程:
需要使用一个与块的大小相同的移位寄存器,并用IV将寄存器初始化。然后,将寄存器内容使用块密码加密,然后将结果的最高x位与平文的x进行异或,以产生密文的x位。下一步将生成的x位密文移入寄存器中,并对下面的x位平文重复这一过程。解密过程与加密过程相似,以IV开始,对寄存器加密,将结果的高x与密文异或,产生x位平文,再将密文的下面x位移入寄存器。
与CBC相似,平文的改变会影响接下来所有的密文,因此加密过程不能并行化;而同样的,与CBC类似,解密过程是可以并行化的。

4)Output Feedback (OFB)/输出反馈模式

ofb

输出反馈模式(Output feedback, OFB)可以将块密码变成同步的流密码。它产生密钥流的块,然后将其与平文块进行异或,得到密文。与其它流密码一样,密文中一个位的翻转会使平文中同样位置的位也产生翻转。这种特性使得许多错误校正码,例如奇偶校验位,即使在加密前计算而在加密后进行校验也可以得出正确结果。
每个使用OFB的输出块与其前面所有的输出块相关,因此不能并行化处理。然而,由于平文和密文只在最终的异或过程中使用,因此可以事先对IV进行加密,最后并行的将平文或密文进行并行的异或处理。
可以利用输入全0的CBC模式产生OFB模式的密钥流。这种方法十分实用,因为可以利用快速的CBC硬件实现来加速OFB模式的加密过程。

CTR

CTR模式(Counter mode,CM)也被称为ICM模式(Integer Counter Mode,整数计数模式)和SIC模式(Segmented Integer Counter),与OFB相似,CTR将块密码变为流密码。它通过递增一个加密计数器以产生连续的密钥流,其中,计数器可以是任意保证长时间不产生重复输出的函数,但使用一个普通的计数器是最简单和最常见的做法。

CTR模式的特征类似于OFB,但它允许在解密时进行随机存取。由于加密和解密过程均可以进行并行处理,CTR适合运用于多处理器的硬件上。
注意图中的“nonce”与其它图中的IV(初始化向量)相同。IV、随机数和计数器均可以通过连接,相加或异或使得相同明文产生不同的密文。

p5

 来源: https://blog.csdn.net/includeiostream123/article/details/51066799
               https://blog.csdn.net/jerry81333/article/details/78336616

Java 加解密技术系列之 PBE

前边的几篇文章,已经讲了几个对称加密的算法了,今天这篇文章再介绍最后一种对称加密算法 — — PBE,这种加密算法,对我的认知来说,并没有 DES、3DES、AES 那么流行,也不尽然,其实是我之前并没有这方面的需求,当然接触他的机会也就很少了,因此,可想而知,没听过显然在正常不过了。
概念
PBE,全称为“Password Base Encryption”,中文名“基于口令加密”,是一种基于密码的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。
PBE算法没有密钥的概念,把口令当做密钥了。因为密钥长短影响算法安全性,还不方便记忆,这里我们直接换成我们自己常用的口令就大大不同了,便于我们的记忆。但是单纯的口令很容易被字典法给穷举出来,所以我们这里给口令加了点“盐”,这个盐和口令组合,想破解就难了。同时我们将盐和口令合并后用消息摘要算法进行迭代很多次来构建密钥初始化向量的基本材料,使破译更加难了。

原理

首先,是基于口令的加密原理图
pp1
然后,是基于口令的解密原理图
pp2
由于这种加密方式的口令容易记忆,不用放在物理媒体上,因此增加了口令的安全性。密钥空间较小,安全性不高,用字典法比较容易破译。攻击者可产生一套密钥列表,用所有可能的密钥进行查找。
常用算法有
  • PBEWithSHAAndDES
  • PBEWithSHAAndBlowfish
  • PBEWithSHAAnd128BitRC4
  • PBEWithSHAAndIDEA-CBC
  • PBEWithSHAAnd3-KeyTripleDES-CBC
其次,是基于口令和盐的加密原理图
pp3
最后,是基于口令和盐的解密原理图
pp6
当然,这种加密方式也具有口令容易记忆的特点,不用放在物理媒体上,因此增加了口令的安全性。可防止攻击者用事先产生的密钥列表进行查找。通过增加消息摘要的计算次数增加了攻击者测试口令的时间。
常用算法有
  • PBEWithSHAAndDES
  • PBEWithSHAAndBlowfish
  • PBEWithSHAAnd128BitRC4
  • PBEWithSHAAndIDEA-CBC
  • PBEWithSHAAnd3-KeyTripleDES-CBC

代码实现

代码实现, 还是参考  https://www.bouncycastle.org/documentation.html
这个是 一个开源的 加密库, 算法齐全, 相对可靠稳定
例子代码:beg_crypto_examples
源代码的原始地址:  http://media.wiley.com/product_ancillary/30/07645963/DOWNLOAD/beg_crypto_examples.zip

结束语

到这里,对称加密算法就算是结束了,其实回想起来,PBE 并不算是一种新算法,他只不过是把密钥概念转变成了“口令 + 盐”的方式而已,至于加解密的原理,还是用到常用的对称加密算法,比如 DES 和 AES 等,因此说,没有什么新东西。
对称加密总算是告一段落了,我打算下次讲几个非对称加密的算法,之后这个系列的文章就要画上句号了。好的,小伙伴们,下次再见喽,欢迎大家与我交流,我们共同学习、共同进步。