实战篇-OpenSSL之TripleDES加密算法-ECB模式

  • 一、TripleDES简介
  • 二、ECB模式
  • 1、命令行操作
  • 2、函数说明
  • 3、编程实现
  • (1)特别注意
  • (2)实现ECB模式加解密
  • (3)测试代码


一、TripleDES简介

3DES又称Triple DES,是DES加密算法的一种模式,它使用2条不同的56位的密钥对数据进行三次加密。

数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法,并于1981年被ANSI组织规范为ANSI X.3.92。

DES使用56位密钥和密码块的方法,而在密码块的方法中,文本被分成64位大小的文本块然后再进行加密。比起最初的DES,3DES更为安全。

3DES(即Triple DES)是DES向AES过渡的加密算法,它使用3条56位的密钥对数据进行三次加密。是DES的一个更安全的变形。
它以DES为基本模块,通过组合分组方法设计出分组加密算法。比起最初的DES,3DES更为安全。

Triple DES属于对称加密算法,加解密使用同一个秘钥。

对称加密算法,一般有至少4种模式,即ECB、CBC、CFB、OFB等。

具体的加密原理,就不进行介绍了,本文主要从使用角度,进行说明。

以下命令行和编程实现,均基于OpenSSL开源库。在命令行中,我们可以使用命令实现对文件加解密,以验证我们的编程实现,是否正确。

二、ECB模式

电子密码本模式 Electronic Code Book(ECB)。这种模式是最早采用和最简单的模式,它将加密的数据分成若干组,每组的大小跟加密 密钥长度相同,然后每组都用相同的密钥进行加密。

1、命令行操作

使用des-ede3-ecb对hello.txt加密,密钥为8cc72b05705d5c46f412af8cbed55aad8cc72b05705d5c46,密文为hello.en。

openssl enc -e -des-ede3-ecb -in hello.txt -out hello.en -K 8cc72b05705d5c46f412af8cbed55aad8cc72b05705d5c46

使用des-ede3-ecb对hello.en解密,密钥为8cc72b05705d5c46f412af8cbed55aad8cc72b05705d5c46,解密后的文件为hello.de。

openssl enc -d -des-ede3-ecb -in hello.en -out hello.de -K 8cc72b05705d5c46f412af8cbed55aad8cc72b05705d5c46

2、函数说明

ECB模式加密/解密:

void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
                      DES_key_schedule *ks1, DES_key_schedule *ks2,
                      DES_key_schedule *ks3, int enc);

参数名称

含义

input

输入数据,长度固定为8字节

output

输出数据,长度与输入数据一致,固定为8字节。

ks1

使用DES_set_key_unchecked生成的Key

ks2

使用DES_set_key_unchecked生成的Key

ks3

使用DES_set_key_unchecked生成的Key

enc

DES_ENCRYPT代表加密, DES_DECRYPT代表解密

3、编程实现

(1)特别注意

由于ECB模式,每次只能处理一个块的数据,即8字节,所以如果需要处理任意长度的数据,那么需要在原始数据末尾,先进行填充,使得数据长度为8的整数倍,随后再分块进行加密。解密时,也需要分块解密,最后将解密后的数据,进行取消填充。

故,建议将输入数据进行PKCS7填充后,再进行加密,以便解密时,正确还原明文数据。关于PKCS7填充,可参考《实战篇-OpenSSL之AES加密算法-ECB模式》中有介绍。

(2)实现ECB模式加解密

下面,函数已经封装完毕,如下:

/**
 * @brief TripleDES::ecb_encrypt
 * ECB模式加解密,支持对任意长度明文进行加解密。
 * @param in 输入数据
 * @param out 输出结果
 * @param key 密钥,长度必须是24字节,否则加密失败
 * @param enc true-加密,false-解密
 */
void TripleDES::ecb_encrypt(const QByteArray &in, QByteArray &out, const QByteArray &key, bool enc)
{
    // 检查密钥合法性(只能是24字节)
    Q_ASSERT(key.size() == 24);

    // 设置key
    DES_key_schedule sch1, sch2, sch3;
    setKey(key, sch1, sch2, sch3);

    // 进行加解密
    if (enc)
    {
        // 进行PKCS7Padding填充
        QByteArray inTemp = Padding::PKCS7Padding(in, DES_BLOCK_SIZE);

        // 执行加密
        out.resize(inTemp.size()); // 调整输出buf大小
        for (int i = 0; i < inTemp.size() / DES_BLOCK_SIZE; i++)
        {
            DES_ecb3_encrypt((const_DES_cblock*)(inTemp.constData() + i * DES_BLOCK_SIZE),
                             (DES_cblock *)(out.data() + i * DES_BLOCK_SIZE),
                             &sch1, &sch2, &sch3, DES_ENCRYPT);
        }
    }
    else
    {
        // 执行解密
        out.resize(in.size()); // 调整输出buf大小
        for (int i = 0; i < in.size() / DES_BLOCK_SIZE; i++)
        {
            DES_ecb3_encrypt((const_DES_cblock*)(in.constData() + i * DES_BLOCK_SIZE),
                             (DES_cblock *)(out.data() + i * DES_BLOCK_SIZE),
                             &sch1, &sch2, &sch3, DES_DECRYPT);
        }

        // 解除PKCS7Padding填充
        out = Padding::PKCS7UnPadding(out);
    }
}

加密过程:

  • 生成key
  • 进行PKCS7Padding填充
  • 执行加密

解密过程:

  • 生成key
  • 执行解密
  • 去除PKCS7Padding填充

经测试,本函数支持对任意长度输入数据进行加解密。

(3)测试代码

void createTestData(QByteArray& data, int size)
{
    data.resize(size);
    for (int i = 0; i < size; i++)
    {
        data[i] = i % 128;
    }
}

void testTripleDES(const QByteArray& data)
{
    QByteArray plainText = data;
    QByteArray encryptText;
    QByteArray decryptText;

    QByteArray key = QByteArray::fromHex("8cc72b05705d5c46f412af8cbed55aad8cc72b05705d5c46");
    QByteArray ivec = QByteArray::fromHex("667b02a85c61c786");

    // TripleDES ecb模式加密验证
    TripleDES tripleDES;
    tripleDES.ecb_encrypt(plainText, encryptText, key, true);    // 加密
    tripleDES.ecb_encrypt(encryptText, decryptText, key, false); // 解密
    qDebug() << "TripleDES ecb encrypt verify" << ((decryptText == plainText) ? "succeeded" : "failed");
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 产生1MB+3B的测试数据,为了使该测试数据长度,不为8或16的整数倍
    QByteArray data;
    createTestData(data, 1*1024*1024+3);

    // 测试TripleDES
    testTripleDES(data);

    return a.exec();
}

执行结果:

Java实现 openssl加密 openssl des加密_TripleDES加密