20.3 OpenSSL symmetric AES encryption and decryption algorithm

The AES algorithm is a symmetric encryption algorithm, whose full name is Advanced Encryption Standard. It is a block cipher that uses 128 bits as a block for encryption. The key length can be 128 bits, 192 bits or 256bits, thus providing different levels of security. This algorithm uses techniques such as substitution, substitution and confusion, as well as mechanisms such as multi-round encryption and key expansion, making its encryption effect excellent and highly secure. It is widely used in various fields, such as data encryption, file encryption, network Security etc.

The AES algorithm uses the same key for encryption and decryption. This algorithm has fast encryption and decryption speeds and is suitable for scenarios where large amounts of data are encrypted and decrypted. In practical applications, a hybrid encryption method is usually used, that is, using the RSA algorithm to encrypt the key in the symmetric encryption algorithm, and then using the symmetric encryption algorithm to encrypt the data to ensure the confidentiality of the data and the efficiency of encryption and decryption.

There are two encryption modes commonly used in the AES algorithm, namely CBC and ECB modes, which have different advantages and disadvantages.

  • ECB (Electronic Codebook) mode is the simplest block cipher working mode. Each plaintext block is encrypted independently. The same ciphertext obtained by encrypting the same plaintext block with the same key is the same, so it is easy to be exploited by attackers. Repeated ciphertexts are analyzed and cracked. The ECB mode has high encryption efficiency and is suitable for short message encryption, but not suitable for long message encryption.

  • CBC (Cipher Block Chaining) mode is a block cipher working mode. The plaintext is first grouped, and then each group is encrypted. The previous block of ciphertext is used as input during encryption, so the same plaintext block is in different positions. The ciphertexts obtained are different, which can prevent attackers from using repeated ciphertexts for analysis and cracking. CBC mode encryption efficiency is low, but it is suitable for long message encryption because different plaintext blocks interact with each other, increasing security.

In practical applications, CBC mode is usually used for encryption because it is more secure than ECB mode, but the encryption efficiency is lower. In addition, there are other encryption modes, such as CFB, OFB, CTR, etc. Different encryption modes are suitable for different scenarios and need to be selected according to actual needs.

The OpenSSL library provides support for AES encryption, but readers still need to encapsulate some general encryption and decryption functions by themselves when using it. The following code snippets are a summary of some commonly used functions by the author, among which aes_cbc_encrypt function is used to encrypt a specific string using CBC mode, aes_cbc_decrypt uses CBC mode to decrypt the string, and the second function AES function uses OpenSSL library are implemented in secondary packaging.

#include <iostream>
#include <openssl/err.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/pem.h>

extern "C"
{<!-- -->
#include <openssl/applink.c>
}

#pragma comment(lib,"libssl_static.lib")
#pragma comment(lib,"libcrypto.lib")

//CBC mode encryption
int aes_cbc_encrypt(char* in, char* key, char* out)
{<!-- -->
    if (!in || !key || !out)
        return 0;

    unsigned char iv[AES_BLOCK_SIZE];
    for (int i = 0; i < AES_BLOCK_SIZE; + + i)
        iv[i] = 0;

    AES_KEY aes;
    if (AES_set_encrypt_key((unsigned char*)key, 128, & amp;aes) < 0)
    {<!-- -->
        return 0;
    }
    int len = strlen(in);
    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, & amp;aes, iv, AES_ENCRYPT);
    return 1;
}

//CBC mode decryption
int aes_cbc_decrypt(char* in, char* key, char* out)
{<!-- -->
    if (!in || !key || !out)
        return 0;

    // Encrypted initialization vector
    unsigned char iv[AES_BLOCK_SIZE];

    //IV is generally set to all 0s
    for (int i = 0; i < AES_BLOCK_SIZE; + + i)
        iv[i] = 0;

    AES_KEY aes;
    if (AES_set_decrypt_key((unsigned char*)key, 128, & amp;aes) < 0)
    {<!-- -->
        return 0;
    }
    int len = strlen(in);
    AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, len, & amp;aes, iv, AES_DECRYPT);
    return 1;
}

// Integrate encryption and decryption together
void AES(unsigned char* InBuff, unsigned char* OutBuff, unsigned char* key, char* Type)
{<!-- -->
    if (strcmp(Type, "encode") == 0)
    {<!-- -->
        AES_KEY AESEncryptKey;
        AES_set_encrypt_key(key, 256, & amp;AESEncryptKey);
        AES_encrypt(InBuff, OutBuff, &AESEncryptKey);
    }
    else if (strcmp(Type, "decode") == 0)
    {<!-- -->
        AES_KEY AESDecryptKey;
        AES_set_decrypt_key(key, 256, & amp;AESDecryptKey);
        AES_decrypt(InBuff, OutBuff, & amp;AESDecryptKey);
    }
}

With the above algorithm encapsulation, the author will next demonstrate how these different encryption functions are applied. First, we will briefly introduce the two functions aes_cbc_encrypt and aes_cbc_decrypt Both are self-encapsulated AES encryption and decryption algorithms. The parameter transfer of these two algorithms is consistent. The first parameter specifies the buffer that needs to be encrypted. The second parameter specifies the key used for encryption. The third parameter is Processed results.

int main(int argc, char* argv[])
{<!-- -->
  char szBuffer[1024] = "hello lyshark";
  char szDst[1024] = {<!-- --> 0 };
  char szSrc[1024] = {<!-- --> 0 };

  // Calculate a string of keys
  char key[AES_BLOCK_SIZE] = {<!-- --> 0 };
  for (int x = 0; x < AES_BLOCK_SIZE; x + + )
  {<!-- -->
    key[x] = 32 + x;
  }

  //AES encryption
  if (aes_cbc_encrypt(szBuffer, key, szDst) != 0)
  {<!-- -->
    std::cout << "Encrypted length: " << strlen(szDst) << std::endl;
  }

  //AES decryption
  if (aes_cbc_decrypt(szDst, key, szSrc) != 0)
  {<!-- -->
    std::cout << "Decrypted content: " << szSrc << std::endl;
  }

  system("pause");
  return 0;
}

The above code snippet implements the function of data encryption and decryption through AES. The following is the output effect of this code;

The second calling method is implemented using API, in which the AES function sets the encryption key through AES_set_encrypt_key and directly calls AES_encrypt Implement data encryption. On the contrary, set the decryption key through AES_set_decrypt_key and call AES_decrypt for decryption. The calling method of this code is as follows;

int main(int argc, char* argv[])
{<!-- -->
  unsigned char Buffer[1024] = "hello lyshark";
  unsigned char EncodeBuf[1024] = {<!-- --> 0 };
  unsigned char DecodeBuf[1024] = {<!-- --> 0 };
  unsigned char aes_key[32] = {<!-- --> 0 };

  // Randomly generate key
  for (int x = 0; x < 32; x + + )
  {<!-- -->
    int ch = rand() % 5;
    aes_key[x] = (char)ch;
  }

  AES(Buffer, EncodeBuf, (unsigned char *)aes_key, (char*)"encode");
  std::cout << "Encrypted data length: " << strlen((char *)EncodeBuf) << std::endl;

  AES(EncodeBuf, DecodeBuf, (unsigned char*)aes_key, (char*)"decode");
  std::cout << "Decrypted data: " << DecodeBuf << std::endl;

  system("pause");
  return 0;
}

As shown in the above code, when calling the AES function, pass in encode to implement data encryption, and pass in decode to implement data decryption, as shown in the figure below;

syntaxbug.com © 2021 All Rights Reserved.