openssl 对称/非对称加密 AES CBC模式加解密

openssl 对称/非对称加密 AES CBC模式加解密

对称加密: 在加密和解密过程中使用相同的密钥, 或是两个可以简单地相互推算的密钥的加密算法.

非对称加密: 也称为公开加密, 它需要一个密钥对, 一个是公钥, 一个是私钥, 一个负责加密, 一个负责解密.

对称加密在性能上要优于非对称加密, 但是安全性低于非对称加密.

主流的对称加密方式有 DES, AES. 这两种加密方式都属于分组加密, 先将明文分成多个等长的模块 ( block ), 然后进行加密.

  • DES 加密

  • AES 加密

非对称加密

RSA 也是一种分组加密方式, 但明文的分组长度根据选择的填充方式的不同而不同.

openssl AES 加密/解密

AES 加密

img

1)ECB模式

img

####2)CBC模式

img

AES 加密的分组长度是 128 位, 即每个分组为 16 个字节 ( 每个字节 8 位 ). 密钥的长度根据加密方式的不同可以是 128 位, 192 位, 256 位. 与 DES 加密一样. 密钥长度超过指定长度时, 超出部分无效. 密钥长度不足时, 会自动以\0补充到指定长度.

AES 密钥长度 ( 位 ) 分组长度 ( 位 )
AES-128 128 128
AES-192 192 128
AES-256 256 128

https://www.openssl.org/docs/man1.1.0/man3/EVP_DecryptInit_ex.html

/*__owur*/ int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,
                                  const EVP_CIPHER *cipher, ENGINE *impl,
                                  const unsigned char *key,
                                  const unsigned char *iv);

type is normally supplied by a function such as EVP_aes_256_cbc(). If impl is NULL then the default implementation is used. key is the symmetric key to use and iv(非空的初始化向量) is the IV to use (if necessary), the actual number of bytes used for the key and IV depends on the cipher. It is possible to set all parameters to NULL except type in an initial call and supply the remaining parameters in subsequent calls, all of which have type set to NULL. This is done when the default cipher parameters are not appropriate.
    
/*__owur*/ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                 int *outl, const unsigned char *in, int inl);

EVP_EncryptUpdate() encrypts inl bytes from the buffer in and writes the encrypted version to out. This function can be called multiple times to encrypt successive blocks of data. The amount of data written depends on the block alignment of the encrypted data: as a result the amount of data written may be anything from zero bytes to (inl + cipher_block_size - 1) so out should contain sufficient room. The actual number of bytes written is placed in outl. It also checks if in and out are partially overlapping, and if they are 0 is returned to indicate failure.
    
/*__owur*/ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                   int *outl);

/*__owur*/ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,
                                  const EVP_CIPHER *cipher, ENGINE *impl,
                                  const unsigned char *key,
                                  const unsigned char *iv);
/*__owur*/ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                 int *outl, const unsigned char *in, int inl);
/*__owur*/ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
                                   int *outl);

Encrypt

EVP_CIPHER_CTX* ctx = NULL;
uint8_t const key[] = "key";
uint8_t const iv[]  = "iv";
int written = 0;
uint32_t bytes = 0;
//1.create the cipher context
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
{
	goto CommonReturn;
}
//2.sets up cipher context ctx for encryption
if (EVP_EncryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv) != 1)
{
	goto CommonReturn;
}
written = 0;
3.encrypts inl bytes from the buffer in and writes the encrypted version to out.
if (EVP_EncryptUpdate(ctx, OutCipher, &written, Plain, PlainLen) != 1)
{
	goto CommonReturn;
}
bytes = written;
written = 0;
4.If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the "final" data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding) as described in the NOTES section, below. The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.
if (EVP_EncryptFinal_ex(ctx, OutCipher + bytes, &written) != 1)
{
    goto CommonReturn;
}
bytes += written;

Decrypt

EVP_DecryptInit_ex(), EVP_DecryptUpdate() and EVP_DecryptFinal_ex() are the corresponding decryption operations. EVP_DecryptFinal() will return an error code if padding is enabled and the final block is not correctly formatted. The parameters and restrictions are identical to the encryption operations except that if padding is enabled the decrypted data buffer out passed to EVP_DecryptUpdate() should have sufficient room for (inl + cipher_block_size) bytes unless the cipher block size is 1 in which case inl bytes is sufficient.

EVP_CIPHER_CTX* ctx = NULL;
uint8_t const key[] = "key";
uint8_t const iv[]  = "iv";
int written = 0;
uint32_t bytes = 0;
//1.create the cipher context
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
{
	goto CommonReturn;
}
//2.sets up cipher context ctx for decryption
if (EVP_DecryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv) != 1)
{
	goto CommonReturn;
}
written = 0;
3.decrypts inl bytes from the buffer in and writes the encrypted version to out.
if (EVP_DecryptUpdate(ctx, OutPlain, &written, Cipher, CipherLen) != 1)
{
	goto CommonReturn;
}
bytes = written;
written = 0;
4.decrypts the "final" data
if (EVP_DecryptFinal_ex(ctx, OutPlain + bytes, &written) != 1)
{
    goto CommonReturn;
}
bytes += written;

猜你喜欢

转载自blog.csdn.net/vegeta852/article/details/111484192