【问题标题】:serpent encryption key schedule, how to padd the key to expand to 256bitsserpent 加密密钥调度,如何传递密钥扩展为 256 位
【发布时间】:2021-09-16 05:47:48
【问题描述】:

我试图从头开始实现蛇加密算法作为个人项目,现在我被它的密钥调度部分所困扰。根据唯一的文档,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

    
    
}

【问题讨论】:

  • 填充键不是个好主意,拒绝小键输入或使用 PBKDF2 导出完整的键大小。
  • @kelalaka 不,这是关于在键上执行的内部填充。
  • @MaartenBodewes 我知道这一点。为什么我们要垫一个键?有人对填充密钥进行安全分析吗?
  • @kelalaka 我的意思是蛇论文中指定的内部。他们执行填充的原因在其中指定。 128 位密钥不应与 192 位密钥相同,因为最终的关键字设置为零而不是 1。如果您放大字节,这适用于除 256 位密钥之外的任何密钥大小。顺便说一句,我并不是为这个设计决定辩护,这就是它的定义方式。

标签: c++ cryptography padding


【解决方案1】:

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

用户密钥长度是可变的,但出于此目的 提交我们将其固定为 128、192 或 256 位;少的短键 超过 256 位通过附加映射到 256 位的全长密钥 一个“1”位到 MSB 端,然后是所需数量的“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 *,但是好的,我们有一个由字节组成的新缓冲区。请注意,此调用不会初始化为零,请参阅here 了解更多信息。

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 个 int32_t 值的 padded_key 缓冲区;

  3. 将字节复制到padded_key 缓冲区(查看this answer,注意C++ 整数是未定义的混乱);

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

    一个。如果 2 个 int32_t 用于 128 位密钥,则将第 3 个 int32_t 设置为值 1,并将最后一个 int32_t 设置为零;

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

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

【讨论】:

  • 好吧,我忘记了蛇的方式。不错。
猜你喜欢
  • 1970-01-01
  • 2011-05-23
  • 2011-03-21
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
相关资源
最近更新 更多