首页 > 解决方案 > serpent 加密密钥调度,如何填充密钥以扩展为 256 位

问题描述

我试图从头开始实现蛇加密算法作为个人项目,现在我被它的密钥调度部分所困扰。根据唯一的文档,https://www.cl.cam.ac.uk/~rja14/Papers/serpent.pdf,我需要将密钥填充为 256,以便开始生成子密钥。

如何在不依赖外部库的情况下应用填充。

这是我写的代码,我不是 100% 肯定会引导我实现我想要实现的目标

void prekeyexpasion(unsigned char * key,unsigned char * expandedkeys){
    //padd the key to 256
    int originalkeylen = strlen((const char*)key);
    int lenOfPaddedkey = originalkeylen;
    if(lenOfPaddedkey % 32 !=0){
        lenOfPaddedkey = (lenOfPaddedkey / 32 + 1) * 32;
    }
    unsigned char * paddedkey = new unsigned char[lenOfPaddedkey];

    for (int i = 0; i < lenOfPaddedkey; i++){
        if ( i >= originalkeylen){
            paddedkey[i] = 1;
        }
        else{
            paddedkey[i] = key[i];
        }
        
    }
    //expand to 33 128bit subkeys
    //split per 128bit subkeys to 8 32 bit subsubkey

    
    
}

标签: c++cryptographypadding

解决方案


让我们看一下标准,假设本文开头指出的小端表示:

用户密钥长度是可变的,但出于本次提交的目的,我们将其固定为 128、192 或 256 位;少于 256 位的短密钥映射到 256 位的全长密钥,方法是在 MSB 端附加一个“1”位,后跟所需数量的“0”位以组成 256 位。


然后看看你的代码:

int originalkeylen = strlen((const char*)key);

首先,密钥不是密码。它是二进制字符串,而不是文本字符串。这意味着strlen不能在键上使用。相反,密钥的大小应该在提供时包含在密钥中(或者您应该使用更高级别的构造来传递密钥,毕竟这是 C++,而不是 C)。

int lenOfPaddedkey = originalkeylen;

一般来说,我永远不会为变量分配不正确的值,即使不是暂时的。

if(lenOfPaddedkey % 32 !=0){
    lenOfPaddedkey = (lenOfPaddedkey / 32 + 1) * 32;
}

您首先使用警卫检查密钥大小是否正确。在这种情况下% 32不需要,您不妨使用lenOfPaddedkey != 32. 除此之外,lenOfPaddedkey / 32将始终为零,因此整行也可能是int lenOfPaddedkey = 32,这应该是正确的。但是,如果它总是 32,为什么还需要一个变量呢?

unsigned char * paddedkey = new unsigned char[lenOfPaddedkey];

嗯,我不喜欢在char *这里使用,但是好的,我们有一个由字节组成的新缓冲区。请注意,此调用不会初始化为零,请参阅此处了解更多信息。

for (int i = 0; i < lenOfPaddedkey; i++){

好的,很好,虽然只是输入一个 32 字面量(作为常量 /#define可能会加快速度)。

    if ( i >= originalkeylen){
        paddedkey[i] = 1;
    }

这是不正确的,应该只添加一位/字节,然后添加零位/字节。

    else{
        paddedkey[i] = key[i];
    }

是的,仅使用库调用来复制字节可能会更快。


反而:

  1. 检查密钥的大小,应为 16、24 或 32 字节;

  2. 创建4 个值padded_key的缓冲区;int32_t

  3. 将字节复制到padded_key缓冲区中(看看这个答案,注意 C++ 整数是一个未定义的混乱);

  4. 如果需要,执行填充:

    一种。如果 2int32_t用于 128 位密钥,则将 3rd 设置int32_t为值 1 并将 finalint32_t设置为零;

    湾。如果 3int32_t用于 192 位密钥,则将第 4 个设置int32_t为值 1。

现在您可以根据 32 位字中的填充键继续进行键扩展(您可能首先需要更大的缓冲区吗?)。


推荐阅读