SM4 CTS算法实现详解(四)

本文详细解释了SM4的CipherTextStealing(CTS)加密模式,包括数据分块、特殊处理步骤,以及解密过程。讨论了其优点(处理任意长度数据,保持数据长度不变)和局限性(依赖CBC模式,可能带来安全风险)。
摘要由CSDN通过智能技术生成

1、SM4 CTS 说明

SM4的CTS模式(Cipher Text Stealing)是一种特殊的加密模式,它主要用于处理数据长度不是加密算法块长度整数倍的情况。这种模式在保证数据安全性的同时,也保证了加密后的数据长度与原始数据长度一致,这在某些应用场景中非常重要,如文件加密。
CTS模式是建立在CBC(Cipher Block Chaining)模式之上的,它通过“窃取”(stealing)前一个密文块的一部分数据来解决最后一个数据块长度小于加密算法块长度的问题。

2、SM4 CTS 加密过程

在这里插入图片描述

2.1 数据分块

首先将数据分为若干块,块大小通常是加密算法的块大小(对于SM4来说是128位或16字节)。

2.2 处理最后两个块:

1)如果数据的总长度正好是块大小的整数倍,直接使用CBC模式进行加密。
2)如果最后一个数据块不足一个完整块的长度,那么取倒数第二个完整的数据块和最后一个不完整的数据块进行特殊处理。

2.3 特殊处理:

1)使用CBC模式加密除了最后两个块的所有块。
2)对倒数第二个块进行加密。
3)将不完整的最后一个块填充至完整块长,填充内容临时借用倒数第二个密文块的相应部分。
4)加密处理后的这个“合成的完整块”。
5)将加密后的结果中对应原始不足块长度的部分放回到倒数第二个密文块的末尾。

2.4 输出结果:

1)输出除了最后两个块外的所有已加密块。
2)按新的顺序输出最后两个处理过的块。

2.5 加密示例代码

int sm4_cts_encrypt(const uint8_t *plaintext, uint8_t *ciphertext, size_t length, const uint8_t key[16], const uint8_t iv[SM4_BLOCK_SIZE]) {
    unsigned char out_block[SM4_BLOCK_SIZE], iv_buf[SM4_BLOCK_SIZE];
    memcpy(iv_buf, iv, SM4_BLOCK_SIZE);
    int i=0;
    SM4_KEY ks={0};
    if (length <= 16)
        return 0;
    int ret = ossl_sm4_set_key(key,&ks);
    if(ret!=1)
    {
        printf("ossl_sm4_set_key err %08x\n",ret);
        return ret;
    }

    size_t residue = length % SM4_BLOCK_SIZE;
    if (residue == 0) residue = SM4_BLOCK_SIZE;

    // 按标准的CBC模式处理所有完整的块
    for (i = 0; i < length/SM4_BLOCK_SIZE; i++) {
        xor_blocks(plaintext + i * SM4_BLOCK_SIZE, iv_buf, out_block,SM4_BLOCK_SIZE);
        ossl_sm4_encrypt(out_block, ciphertext + i * SM4_BLOCK_SIZE, &ks);
        memcpy(iv_buf, ciphertext + i * SM4_BLOCK_SIZE, SM4_BLOCK_SIZE);
    }

    // 最后一个块处理
    memcpy(out_block,iv_buf,SM4_BLOCK_SIZE);
    xor_blocks(plaintext + i * SM4_BLOCK_SIZE, iv_buf, out_block,residue);
    ossl_sm4_encrypt(out_block, out_block, &ks);

    // 复制最后一个块并用倒数第二个块的加密结果进行填充
    memcpy(ciphertext +length - residue, ciphertext +length - SM4_BLOCK_SIZE - residue, residue);
    memcpy(ciphertext +length - residue - SM4_BLOCK_SIZE, out_block, SM4_BLOCK_SIZE);

    return length;
}

3、SM4 CTS 解密过程

CTS模式的解密过程需要逆向执行加密过程中的所有步骤,包括正确处理最后两个密文块的数据交换和恢复原始数据块。

在这里插入图片描述

3.1 解密大部分块

1)使用标准的CBC模式解密所有除了最后两个块之外的密文块。

3.2 处理最后两个块

1)首先,需要确定最后两个块的特殊处理方式。这通常涉及到解析最后一个块,判断其长度是否等于标准块大小。
2)如果最后一个块不是完整的块,则从倒数第二个密文块中“窃取”足够的数据以补全这个块。

3.3 解密倒数第二个块

1)临时保存倒数第二个块的密文。
2)将这个块解密,得到明文。此时,解密得到的明文实际上包含了部分明文数据和用于填充最后一个块的数据。

3.4 解密合成的最后一个完整块

1)通过将最后一个不完整块和借用的数据合成一个完整块。
2)使用SM4解密这个合成的完整块,得到明文。

3.5 恢复最后两个块的正确数据

1)将解密得到的倒数第二个块的明文与最后一个块解密前合成的完整块中的原始数据进行必要的XOR操作,以恢复出原始的明文数据。
2)注意,这一步骤需要精确控制数据的交换和替换,确保明文的正确性。

3.6 输出所有明文块:

1)输出所有已解密的明文块,包括恢复的最后两个块。

3.7 解密示例代码

int sm4_cts_decrypt(const uint8_t *ciphertext, uint8_t *plaintext, size_t length, const uint8_t key[16], const uint8_t iv[SM4_BLOCK_SIZE]) {
    unsigned char out_block[SM4_BLOCK_SIZE];
    unsigned char iv_buf[SM4_BLOCK_SIZE];
    memcpy(iv_buf, iv, SM4_BLOCK_SIZE);
    size_t i;
    SM4_KEY ks={0};
    union {
        size_t align;
        unsigned char c[32];
    } tmp;

    if (length <= 16)
        return 0;

    size_t residue = length % SM4_BLOCK_SIZE;
    if (residue == 0) 
        residue = SM4_BLOCK_SIZE;

    length -= (16 + residue);

    int ret = ossl_sm4_set_key(key,&ks);
    if(ret!=1)
    {
        printf("ossl_sm4_set_key err %08x\n",ret);
        return ret;
    }

    // 解密除最后两块以外的所有块
    for ( i = 0; i < length; i += SM4_BLOCK_SIZE) {
        ossl_sm4_decrypt(ciphertext + i, out_block, &ks);
        xor_blocks(out_block, iv_buf, plaintext + i,SM4_BLOCK_SIZE);
        memcpy(iv_buf, ciphertext + i, SM4_BLOCK_SIZE);
    }

    //解密倒数第二个完整数据块
    ossl_sm4_decrypt(ciphertext + i, tmp.c+SM4_BLOCK_SIZE, &ks);
    memcpy(tmp.c, tmp.c + 16, 16);
    memcpy(tmp.c, ciphertext - residue, residue);

    ossl_sm4_decrypt(tmp.c, tmp.c, &ks);

    int n =0;
    for (n = 0; n < 16; ++n) {
        unsigned char c = ciphertext[length+n];
        plaintext[length+n] = tmp.c[n] ^ iv_buf[n];
        iv_buf[n] = c;
    }

    for (residue += 16; n < residue; ++n)
        plaintext[length+n] = tmp.c[n] ^ ciphertext[length+n];
    
    return length+16+residue;
}

4、优点与局限

1)优点:
	CTS模式能够处理任意长度的数据,且加密后的数据长度不变,这对于需要保持数据格式的应用非常有用。
2)局限:
	CTS模式依赖于CBC模式,因此它继承了CBC模式的所有缺点,包括对初始向量(IV)的依赖以及潜在的安全隐患(如如果使用不当,可能会有安全风险)。
	CTS模式适用于数据长度可能变动,且要求输出数据长度与输入相同的场合。在实际应用中,正确实现CTS模式需要仔细处理数据块的拆分和重组,确保在各种情况下都能安全、准确地加解密。
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值