【问题标题】:How to use salsa20 (or ChaCha)?如何使用salsa20(或ChaCha)?
【发布时间】:2012-06-24 11:17:37
【问题描述】:

假设我们有一个大文件,可以读取 1024 字节左右的块,我如何使用 Salsa 或 Chacha 20 加密和解密每个块?

另外,我应该在哪里指定轮数(即 8、12 或 20)?

到目前为止,我还没有通过查看 eSTREAM 测试包来弄清楚:(

我已经通过eSTREAM 和Salsa20 homepage 下载了以下文件:

  • chacha.c
  • ecrypt-config.h
  • ecrypt-machine.h
  • ecrypt-portable.h
  • ecrypt-sync.h

我看到 encrypt-sync.h 中的 cmets 以这种顺序谈论调用函数:

  • ECRYPT_keysetup();
  • ECRYPT_ivsetup();
  • ECRYPT_encrypt_bytes();

但我完全不知道我应该提供什么作为参数来完成这项工作......

这是我迄今为止最好的尝试,从一小串明文开始(我的 C 已经生锈了……我可能犯了一些基本错误,虽然我看不到它):

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ecrypt-sync.h"

#define CHUNKSIZE 1024

void getRandomBytes(u8 **str, u32 len);
void showData(u8 *data, u8 *header);

int main(int argc, char** argv)
{
    char plaintext[CHUNKSIZE] = "THIS IS A TEST";
    ECRYPT_ctx ctx;
    u8 *key, *IV, *ciphertext, *result;

    /*
    Don't use random values till we get it working with zeroes at least
    getRandomBytes(&key, ECRYPT_MAXKEYSIZE/8);
    getRandomBytes(&IV, ECRYPT_MAXIVSIZE/8);
    */

    key = (u8 *)calloc((size_t)ECRYPT_MAXKEYSIZE/8, sizeof(u8));
    IV = (u8 *)calloc((size_t)ECRYPT_MAXIVSIZE/8, sizeof(u8));

    printf("Encrypting [%s] using random %d bit key and %d bit IV:\n", plaintext, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);

    ECRYPT_init();
    ECRYPT_keysetup(&ctx, key, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);
    ECRYPT_ivsetup(&ctx, IV);

    ciphertext = (u8 *)calloc((size_t)CHUNKSIZE, sizeof(u8));

    ECRYPT_encrypt_bytes(&ctx, plaintext, ciphertext, CHUNKSIZE);

    //showData(ciphertext, "CIPHERTEXT");

    result = (u8 *)calloc((size_t)CHUNKSIZE, sizeof(u8));

    ECRYPT_decrypt_bytes(&ctx, ciphertext, result, CHUNKSIZE);
    printf("And now decrypting back: [%s]\n", result);

    return 0;
}

void showData(u8 *data, u8 *header) {
    printf("\n-----BEGIN %s-----\n%s\n-----END %s-----\n", header, data, header);

}

void getRandomBytes(u8 **str, u32 len) {
    int fd = open("/dev/random", O_RDONLY);
    char *ptr = malloc((size_t) + 1);

    read(fd, ptr, len);
    close(fd);

    ptr[len] = '\0';
    *str = ptr; 
}

结果如下:

使用随机 256 位密钥和 64 位 IV 加密 [这是一个测试]: 现在解密回来:[(一堆随机字符)]

它应该在哪里:

现在解密回来:[这是一个测试]

欢迎使用 C 或 C++ 提供您的解决方案

谢谢!

【问题讨论】:

  • 如果您的 C 知识生疏,您打算如何在 C/C++ 中实现这样的应用程序?您是否尝试过查找任何示例代码?您一般尝试过什么?这是转发吗?我似乎想起了另一个关于 Salsa20 的问题,我再也找不到了。
  • 关于 C 的第一个提示:它不是 C++。
  • 谢谢!我已经编辑了这个问题以提供一些我到目前为止编写的示例代码,直到我遇到了死胡同。你可以看到,我的 C 生锈了——但并非完全不存在。我猜这就像骑自行车一样:) 不幸的是,我在网上找到了复杂的示例(例如 eSTREAM 测试套件)和其他语言的示例……但在 C 中没有直接的简单实现(可能是因为我只是缺少一些基本的这里的概念应该是不言而喻的)。我还没有看到另一篇提出这个确切问题的帖子。
  • DeadMG:eSTREAM 提供的salsa20.c 文件是否无效C++?

标签: c++ c cryptography


【解决方案1】:

如果您打算在实际代码中使用 Salsa20 并且您提出这样的问题,您可能希望使用带有友好 C++ 包装器的 NaCl 库。

见The NaCl website。

要回答您的实际问题:您需要再次设置 IV 以进行解密操作。 IV 由您的随机数和块偏移量组成。加密/解密函数会增加偏移量,从而为您的代码提供不同的加密和解密函数 IV。

【讨论】:

  • 感谢 janm-添加 ECRYPT_ivsetup(&ctx, IV);就在 ECRYPT_decrypt_bytes() 成功之前。当我启用 getRandomBytes() 东西时也可以工作:) 感谢您提供指向 NaCl 的链接-太好了!问题-现在我让它使用一个 1024 字节的块,假设我现在想从一个更大的文件读取/写入....我可以使用相同的 nonce 每次重新初始化 IV(对在每次调用 ECRYPT_encrypt_bytes()) 之前,还是必须更改每次读/写的随机数?
  • @davidkomer:Salsa20 有 64 字节块,因此您需要向加密/解密函数提供 64 字节的倍数,直到最后一个块。使用唯一的 64 位消息编号作为 nonce,并让库增加块编号。您只需要在消息开始时设置 IV,而不是在每个块之前。在每个块之前设置 IV 会通过重复使用块号来削弱安全性,所以不要这样做。
  • 知道了,谢谢 :) 如果最后一个块小于 64 字节,我可以用 NULL 填充对吗?
  • IV 可以安全地以明文形式传输,即直接附加到输出的前面,是吗?
  • 图书馆会为您服务,但您也可以这样做。是的,IV 可以安全地以明文形式传输。
猜你喜欢
  • 2016-04-29
  • 1970-01-01
  • 2015-12-16
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多