【问题标题】:Reading in 64 byte chunks from a file in C从 C 中的文件中读取 64 字节块
【发布时间】:2023-03-20 17:29:01
【问题描述】:

我似乎无法理解以 64 字节块读取然后使用河豚的概念,

BF_cfb64_encrypt(source, dest, sizeof(source), &bf_key, iv, &enc, BF_DECRYPT) 

函数加密?它。我知道如何使用 BF 函数,但是从 4096 字节的文件中读取 64 字节是我的困惑。任何提示或建议将不胜感激。我的理解是 1 char 是一个字节,这是否意味着我只是保持一个计数,当 char 计数为 8 时,这意味着我已经读取了 64 个字节,因此加密,然后写入文件,并重复直到整个文件被解析?

【问题讨论】:

    标签: c algorithm blowfish


    【解决方案1】:

    首先,您可能需要熟悉您的流密码。 Blowfish 使用 64 bits 的块大小进行加密/解密;不是字节。只要您了解您所指的 64 个“字节”是您的要求,而不是 Blowfish,而且 Blowfish 只需要 8 个字节的块。

    也就是说,循环传递一个大小是算法块大小的倍数的文件,一次提取一个 64 字节帧的解密数据当然是可行的。

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <openssl/blowfish.h>
    
    
    int main(int argc, char *argv[])
    {
        if (argc < 2)
            return EXIT_FAILURE;
    
        FILE * fp = fopen(argv[1], "rb");
        if (fp == NULL)
        {
            perror(argv[1]);
            return EXIT_FAILURE;
        }
    
        // your key bytes would be here (obviously).
        unsigned char key[16] = "1234567890123456";
        int key_len = sizeof(key)-1;
    
        // setup the key schedule.
        BF_KEY bf_key;
        BF_set_key(&bf_key, key_len, key);
    
        // and setup the initialization vector. normally the IV is
        //  randomly generated when encrypting, then stored as the
        //  lead 8 bytes of ciphertext output. this assumes you're
        //  iv is static (all zeros) similar to SSH
        unsigned char iv[8] = {0};
        int n = 0;
    
        // finally, begin reading the data in chunks of 64 bytes
        //  sending it through the blowfish algorithm
        unsigned char source[64];
        unsigned char dest[64];
        while (fread(source, sizeof(source), 1, fp) == 1)
        {
            BF_cfb64_encrypt(source, dest, sizeof(dest), &bf_key, iv, &n, BF_DECRYPT);
    
            // do something with your dest[] plaintext block
        }
        fclose(fp);
    
        return 0;
    }
    

    该示例相当简单,但它提出了一些您可能没有考虑的关于对称块算法和填充的内容(或者您可能已经考虑过,它与这个问题根本无关)。

    像 Blowfish 这样的对称块算法在块大小上运行。对于 Blowfish,块大小为 64 (8 字节)。这意味着加密/解密操作总是发生在 64 位大小的块中。如果您使用的是较低级别的 openssl api,则必须加密(和解密)不大于该数据的块中的数据。更高级别的 API(例如 BF_cfb64_encrypt)旨在允许“流模式”,这意味着您可以以更大的块提交数据,只要它们的大小是块大小的倍数。 并且在对 API 的连续调用之间保留 ivn 值。

    最后,我开始写这篇关于对称块算法和填充模式的相当长的文章,但意识到这并不适合这个问题,所以我只能建议你研究一下。我怀疑你在某个时候需要这样做。

    【讨论】:

      【解决方案2】:

      为什么不使用 read 系统调用?

      必需的包含文件

      #include <unistd.h>
      

      函数定义

      size_t read(int fildes, void *buf, size_t nbytes);
      

      参数

      int fildes :读取输入的文件描述符。您可以使用从 open 系统调用获得的文件描述符,也可以使用 0、1 或 2 来分别引用标准输入、标准输出或标准错误。

      const void *buf:将存储读取内容的字符数组。

      size_t nbytes :截断数据之前要读取的字节数。如果要读取的数据小于nbytes,则所有数据都保存在缓冲区中。

      返回值:返回已读取的字节数。如果值为负数,则系统调用返回错误。

      示例

      #include <unistd.h>
      int main()
      {
         char data[128];
      
         if(read(0, data, 128) < 0)
             write(2, "An error occurred in the read.\n", 31);
      
         exit(0);
      }
      

      ** 伪代码 **

      int no_byte_read = 0; // Will store number of byte read
      void *buffer; //temporary storage for read data   
      FILE *fp; //File pointer of the file to be read 
      
      buffer = (void*) malloc(64); //Allocate space to temporary buffer.
      
      fp = open file to be read;
      
      do{
            no_byte_read = read(fp, buffer, 64); // read 64 byte from file and store in buffer
            if(no_byte_read < 0){
                 printf("Error occoured in read");
                 break;
            }
         }while(no_byte_read == 64) //If this condition is true that means still some bytes
                                      remain in file which must be read.  
      

      【讨论】:

      • 假设一个文件有 500 个字节,它最终会全部读取吗?
      • 使用循环读取 64 字节块。并检查每次读取的返回值,如果返回值为 64,则一切正常。如果返回值小于 64,则表示已到达文件末尾。如果返回值为负,则读取错误。
      • if(read(0, data, 64)
      • 假设文件大小为 500 字节,那么在理想情况下读取将返回 64,ceil(500/64) 次,即 7 次。并且在第 8 次迭代中读取将返回 (500 - 7*64) 即 52。
      • 作为安全实践的一部分,您也必须检查负数,因为在读取失败的情况下读取返回负数(因此您必须中止)。但是直到你得到正数,读取是成功的。此外,第一个参数将是您正在读取的文件的文件描述符。
      猜你喜欢
      • 2018-07-17
      • 2020-09-05
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多