OpenSSL 上的 AES CTR 256 加密操作模式 [英] AES CTR 256 Encryption Mode of operation on OpenSSL

查看:24
本文介绍了OpenSSL 上的 AES CTR 256 加密操作模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 OpenSSL 的新手,谁能给我一个关于如何从 C 文件初始化 AES CTR 模式的提示.我知道这是方法的签名,但是我遇到了参数问题,文档不多,也没有明确的示例如何进行简单的加密.如果有人可以举例说明对这种方法的调用,我将不胜感激.提前致谢!

Im new to OpenSSL, Can anybody give me a hint in how to initialize AES CTR mode from a C file. I know this is the method´s signature but I am having problems with the parameters, there´s not many documentation neither a clear example how to make a simple encryption. I would appreciate if somebody could exemplify a call to this method. Thanks in advance!

void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
    const unsigned long length, const AES_KEY *key,
    unsigned char ivec[AES_BLOCK_SIZE],
    unsigned char ecount_buf[AES_BLOCK_SIZE],
    unsigned int *num);

嗨 Caf 我真的很感谢你的快速回答它真的很有用,而且绝对是我在网上找到的最好的例子.我试图打开一个不确定长度的文件,对其进行加密并使用生成的密文写入另一个文件,然后打开加密文件并恢复明文.我需要使用大量 MB 的文件,因为我想对 CPU 的性能进行基准测试.但是我在解密时仍然遇到问题.不知何故,当解密相当多的 txt 文件 (1504KB) 时,它不会解密完成,我得到了一半的明文,另一半仍然是加密的.我认为这可能与 iv 的大小或我调用计数器的方式有关.这是我到目前为止所拥有的:

Hi Caf I really appreciate your quick answer it has been really useful, and defenetly the best example I have found on the web. I am trying to open a file with undetermined length, encrypt it and write another file with the ciphertext generated, then open the ciphered file and recover the plaintext. I need to use a file of a considerable amount of MB cause I would like to benchmark the performance of the CPU. However Im still having a problem while decrypting. Somehow when decrypting a considerable txt files (1504KB)it wont decrypt it complete, and I get half of it in plaintext and the other half still ciphered. I think this might be related to the size of the iv or the way I am calling the counter. Here is what I have so far:

#include <openssl/aes.h>
#include <stdio.h>
#include <string.h>

struct ctr_state { 
    unsigned char ivec[16];   
    unsigned int num; 
    unsigned char ecount[16]; 
}; 

FILE *fp;
FILE *rp;
FILE *op;
size_t count;   
char * buffer; 
AES_KEY key; 

int bytes_read, bytes_written;   
unsigned char indata[AES_BLOCK_SIZE]; 
unsigned char outdata[AES_BLOCK_SIZE];  
unsigned char ckey[] =  "thiskeyisverybad"; // It is 128bits though..
unsigned char iv[8] = {0};//This should be generated by RAND_Bytes I will take into    consideration your previous post
struct ctr_state state;   

int init_ctr(struct ctr_state *state, const unsigned char iv[8]){     
    state->num = 0; 
    memset(state->ecount, 0, 16);      
    memset(state->ivec + 8, 0, 8);  
    memcpy(state->ivec, iv, 8); 
} 

void encrypt(){ 
  //Opening files where text plain text is read and ciphertext stored      
  fp=fopen("input.txt","a+b");
  op=fopen("output.txt","w");
  if (fp==NULL) {fputs ("File error",stderr); exit (1);}   
  if (op==NULL) {fputs ("File error",stderr); exit (1);}      

  //Initializing the encryption KEY
  AES_set_encrypt_key(ckey, 128, &key); 

  //Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext  
 while (1) {     
    init_ctr(&state, iv); //Counter call
    bytes_read = fread(indata, 1, AES_BLOCK_SIZE, fp); 
    AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);    
    bytes_written = fwrite(outdata, 1, bytes_read, op); 
    if (bytes_read < AES_BLOCK_SIZE) 
    break; 
  }   

  fclose (fp); 
  fclose (op);
  free (buffer); 
}

void decrypt(){
  //Opening files where text cipher text is read and the plaintext recovered         
  rp=fopen("recovered.txt","w");
  op=fopen("output.txt","a+b");
  if (rp==NULL) {fputs ("File error",stderr); exit (1);}   
  if (op==NULL) {fputs ("File error",stderr); exit (1);} 

  //Initializing the encryption KEY
  AES_set_encrypt_key(ckey, 128, &key); 

  //Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext   
  while (1) {     
    init_ctr(&state, iv);//Counter call
    bytes_read = fread(indata, 1, AES_BLOCK_SIZE, op);  
    AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num); 
    bytes_written = fwrite(outdata, 1, bytes_read, rp); 
    if (bytes_read < AES_BLOCK_SIZE) 
    break; 
    }   
  fclose (rp); 
  fclose (op);
  free (buffer); 
}

int main(int argc, char *argv[]){  
  encrypt();  
  //decrypt(); 
  system("PAUSE");  
  return 0;
}

每个加密和解密函数在不同的运行中被调用,所以所有的东西总是用相同的值初始化.再次感谢您可以提前为我提供的提示 &问候!!!

Each encrypt and decrypt function are called in different runs so everything is initialized always with the same values. Thanks again for the hints you can provide me in advance & Regards!!!

推荐答案

通常,您会打算重复调用 AES_ctr128_encrypt() 以发送多条具有相同密钥和 IV 的消息,并且递增柜台.这意味着您需要跟踪调用之间的 'ivec'、'num' 和 'ecount' 值 - 因此创建一个 struct 来保存这些值,以及一个初始化函数:

Usually, you will be intending to call AES_ctr128_encrypt() repeatedly to send several messages with the same key and IV, and an incrementing counter. This means you need to keep track of the 'ivec', 'num' and 'ecount' values between calls - so create a struct to hold these, and an initialisation function:

struct ctr_state {
    unsigned char ivec[16];  /* ivec[0..7] is the IV, ivec[8..15] is the big-endian counter */
    unsigned int num;
    unsigned char ecount[16];
};

int init_ctr(struct ctr_state *state, const unsigned char iv[8])
{
    /* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the
     * first call. */
    state->num = 0;
    memset(state->ecount, 0, 16);

    /* Initialise counter in 'ivec' to 0 */
    memset(state->ivec + 8, 0, 8);

    /* Copy IV into 'ivec' */
    memcpy(state->ivec, iv, 8);
}

现在,当您开始与目的地通信时,您需要生成一个 IV 以使用和初始化计数器:

Now, when you start communicating with the destination, you'll need to generate an IV to use and initialise the counter:

unsigned char iv[8];
struct ctr_state state;

if (!RAND_bytes(iv, 8))
    /* Handle the error */;

init_ctr(&state, iv);

然后您需要将 8 字节的 IV 发送到目的地.您还需要从原始密钥字节初始化 AES_KEY:

You will then need to send the 8 byte IV to the destination. You'll also need to initialise an AES_KEY from your raw key bytes:

AES_KEY aes_key;

if (AES_set_encrypt_key(key, 128, &aes_key))
    /* Handle the error */;

您现在可以开始加密数据并将其发送到目的地,重复调用 AES_ctr128_encrypt() 如下:

You can now start encrypting data and sending it to the destination, with repeated calls to AES_ctr128_encrypt() like this:

AES_ctr128_encrypt(msg_in, msg_out, msg_len, &aes_key, state->ivec, state->ecount, &state->num);

(msg_in 是指向包含明文消息的缓冲区的指针,msg_out 是指向加密消息所在缓冲区的指针,msg_len 是消息长度).

(msg_in is a pointer to a buffer containing the plaintext message, msg_out is a pointer to a buffer where the encrypted message should go, and msg_len is the message length).

解密完全一样,只是你没有用RAND_bytes()生成IV——而是取另一方给你的值.

Decryption is exactly the same, except that you do not generate the IV with RAND_bytes() - instead, you take the value given to you by the other side.

重要提示:

  1. 不要不要在加密过程中多次调用init_ctr().计数器和 IV 必须在开始加密之前仅初始化一次.

  1. Do not call init_ctr() more than once during the encryption process. The counter and IV must be initialised once only prior to the start of encryption.

在任何情况下都不要试图从加密端的 RAND_bytes() 以外的任何地方获取 IV.不要将其设置为固定值;不要使用哈希函数;不要使用收件人的姓名;不要从磁盘读取它.使用 RAND_bytes() 生成它并将其发送到目的地.每当您从零计数器开始时,必须从一个您以前从未使用过的全新 IV 开始.

Under no circumstances be tempted to get the IV anywhere other than from RAND_bytes() on the encryption side. Don't set it to a fixed value; don't use a hash function; don't use the recipient's name; don't read it from disk. Generate it with RAND_bytes() and send it to the destination. Whenever you start with a zero counter, you must start with a completely fresh IV that you have never used before.

如果您有可能在不更改 IV 和/或密钥的情况下发送 2**64 字节,您将需要测试计数器是否溢出.

If it is at all possible that you will be sending 2**64 bytes without changing the IV and/or key, you will need to test for the counter overflowing.

不要省略错误检查.如果某个功能失败而您忽略它,则您的系统很可能(甚至很可能)看起来运行正常,但实际上运行起来完全不安全.

Do not omit error-checking. If a function fails and you ignore it, it's quite possible (even likely) that your system will appear to be functioning normally, but will actually be operating completely insecurely.

这篇关于OpenSSL 上的 AES CTR 256 加密操作模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆