对称加密算法

-- TOC --

对称加密在消息通信的两端共享相同密钥,加解密相对速度更快,一般用来对明文内容进行加解密操作。

对称加密算法一般分为两种类型:

其中块加密的块大小与具体加密算法的实现有关,常见的块大小有128、256位等。

Stream Ciphers

流加密会逐字节加密数据,最常见的流加密算法就是SSL中用到的RC4算法了。其本质上是以密钥为种子(seed)产生的随机数来对明文进行逐字节异或。流加密本质上依赖于随机数生成器的随机性,其随机性越强,加密强度就越大。

RC4

RC4加密算法是大名鼎鼎的RSA三人组中的头号人物Ron Rivest在1987年设计的密钥长度可变的流加密算法簇,之所以称其为簇,是由于其核心部分的S-box长度可为任意,但一般为256字节。

在密码学中,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。所谓对称加密,就是加密和解密的过程是一样的。RC4已经成为一些常用的协议和标准的一部分,如1997年的WEP和2003/2004年无线卡的WPA和1995年的SSL,以及后来1999年的TLS。让它如此广泛分布和使用的主要因素是它不可思议的简单和速度,不管是软件还是硬件,实现起来都十分容易。

RC4的基本原理,就是两次XOR,一次得到密文,再来一次解密。用来做XOR操作的,是一个KeyStream,这个stream来自一个伪随机数生成算法。

RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特),在如今技术支持的前提下,当密钥长度为128比特时,用暴力法搜索密钥已经不太可行,所以可以预见RC4的密钥范围任然可以在今后相当长的时间里抵御暴力搜索密钥的攻击。实际上,如今也没有找到对于128bit密钥长度的RC4加密算法的有效攻击方法。

首先利用key生成一个sbox,这部分叫做 The Key-scheduling algorithm(KSA),然后利用sbox不断地生成伪随机数,这个伪随机数就是用来XOR的值,The pseudo-random generation algorithm(PRGA)

加密解密的两端,使用相同的key,以及相同的计算方式得到相同的伪随机数,因此实现简单的XOR加解密。

下面代码是个示意实现:

$ cat rc4.c
#include <stdio.h>
#include <string.h>


void rc4_init(unsigned char *s, char *key, int keylen)
{
    int i;
    unsigned char j;
    unsigned char t[256] = {0};
    unsigned char tmp;

    for(i=0; i<256; i++) {
        s[i] = i;
        t[i] = key[i%keylen];
    }
    for(i=0; i<256; i++) {
        j = (j+s[i]+t[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}


void rc4_crypt(unsigned char *s, char *data, int datalen)
{
    int i=0,j=0,t=0;
    int k=0;
    unsigned char tmp;

    for(k=0; k<datalen; k++)
    {
        i = (i+1) % 256;
        j = (j+s[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
        t = (s[i]+s[j]) % 256;
        data[k] ^= s[t];
    }
}


int main(void) {
    char data[] = "abcdefg123456789";
    char key[] = "cs.pynote.net";

    unsigned char sbox[256] = {0};
    rc4_init(sbox, key, strlen(key));
    /* encrypt */
    rc4_crypt(sbox, data, strlen(data));

    memset(sbox, 0, 256);
    rc4_init(sbox, key, strlen(key));
    /* decrypt */
    rc4_crypt(sbox, data, strlen(data));
    printf("data: %s\n", data);
    return 0;
}
$ gcc -Wall -Wextra rc4.c -o rc4
$ ./rc4
data: abcdefg

在对stream加解密的时候,不能提前知道stream的长度,因此上面的代码只是原理示意。另外,stream cipher的加密流程和解密流程,是一样的。

rc4.png

命令行使用openssl rc4算法

Block Ciphers

块加密也称为分组加密,也是大多数人比较熟悉的。AES、DES、3DES、Towfish等常见的加密算法都是块加密。在块加密中,原始数据会被分割成若干个大小为N的块,并分别对这些块进行加密。由于我们不能保证数据是N的倍数,因此需要对数据进行填充(Padding),这增加了实现的复杂度。一般来说,与流加密相反,块加密的解密流程和加密流程往往是不同的。

Padding

一种常见的填充方式是不论数据大小是否对齐块边界,都进行填充,而填充的内容为填充的字节数。比如块大小为8字节,那么可能有以下填充:

    'AAAAAAA' + '\x01'
    'AAAAAA' + '\x02\x02'
    …
    'AA' + 'x06' * 6
    'A' + '\x07' * 7
    '\x08' * 8   # 对齐也padding

这就是PKCS#7中所定义的填充方式。

In cryptography, PKCS stands for Public Key Cryptography Standards. These are a group of public-key cryptography standards devised and published by RSA Security LLC, starting in the early 1990s. The company published the standards to promote the use of the cryptography techniques to which they had patents, such as the RSA algorithm, the Schnorr signature algorithm and several others. Though not industry standards (because the company retained control over them), some of the standards in recent years have begun to move into the "standards-track" processes of relevant standards organizations such as the IETF and the PKIX working-group. (more info https://en.wikipedia.org/wiki/PKCS)

ECB

ECB全称为Electronic CodeBook,是块加密中比较简单的加密模式。

在ECB模式中,每一块明文数据都被独立地进行加密来生成加密块。这意味着如果你发现两个加密块有相同的内容,那么就可以确定这两个加密块的原文也是相同的。

这看起来好像没什么大不了的,但我们可以考虑这么一种情况,比如要加密的对象是一张图像,我们使用ECB加密算法,并且设置块大小为8字节(DES),加密后的图像如下:

ecb_demo.jpg

虽然和原图有所区别,但也足以明显地看出原图的大致内容。

ECB块重排攻击

由于ECB模式下,对每个block的加密是独立的,攻击者可以在不知道秘钥的情况下,通过重新排列加密后的block,来达到重新排列明文的效果,而且这些重排列后的block,能够被正确解密,解开后的内容,就是攻击者重排block后的明文。

CBC

CBC全称为Cipher-Block Chaining,算是最常见的块加密模式了。在CBC模式中,每个明文块都会在加密前用前一个明文块的秘文进行异或;解密过程则正好相反。其中第一个明文块会被使用IV即初始化向量进行异或。

cbc_demo.png

本文链接:https://cs.pynote.net/se/jjm/202206271/

-- EOF --

-- MORE --