AES with padding pkcs7 c++ code

后端 未结 2 1033
南笙
南笙 2021-01-07 03:59

I need an example of string encryption (in C++ -> I\'m working on linux-Ubuntu) with aes-cbc256 and a padding: PKCS7 Please help.


For the following code how ca

相关标签:
2条回答
  • 2021-01-07 04:32

    OpenSSL uses PKCS7 padding by default. This padding means when your data is not a multiple of the block size, you pad n bytes of the value n, where n is however many bytes you need to get to the block size. AES's block size is 16.

    Here's an example on how to encrypt a string using AES256-cbc with OpenSSL. The OpenSSL documentation also has examples, although they use different ciphers. This example does no error checking.

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <vector>
    #include <cassert>
    
    #include <openssl/evp.h>
    
    int main()
    {
        // ctx holds the state of the encryption algorithm so that it doesn't
        // reset back to its initial state while encrypting more than 1 block.
        EVP_CIPHER_CTX ctx;
        EVP_CIPHER_CTX_init(&ctx);
    
        unsigned char key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
        unsigned char iv[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        assert(sizeof(key) == 32);  // AES256 key size
        assert(sizeof(iv) == 16);   // IV is always the AES block size
    
        // If data isn't a multiple of 16, the default behavior is to pad with
        // n bytes of value n, where n is the number of padding bytes required
        // to make data a multiple of the block size.  This is PKCS7 padding.
        // The output then will be a multiple of the block size.
        std::string plain("encrypt me");
        std::vector<unsigned char> encrypted;
        size_t max_output_len = plain.length() + 16 - (plain.length() % 16);
        encrypted.resize(max_output_len);
    
        // Enc is 1 to encrypt, 0 to decrypt, or -1 (see documentation).
        EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv, 1);
    
        // EVP_CipherUpdate can encrypt all your data at once, or you can do
        // small chunks at a time.
        int actual_size = 0;
        EVP_CipherUpdate(&ctx,
                 &encrypted[0], &actual_size,
                 reinterpret_cast<unsigned char *>(&plain[0]), plain.size());
    
        // EVP_CipherFinal_ex is what applies the padding.  If your data is
        // a multiple of the block size, you'll get an extra AES block filled
        // with nothing but padding.
        int final_size;
        EVP_CipherFinal_ex(&ctx, &encrypted[actual_size], &final_size);
        actual_size += final_size;
    
        encrypted.resize(actual_size);
    
        for( size_t index = 0; index < encrypted.size(); ++index )
        {
            std::cout << std::hex << std::setw(2) << std::setfill('0') <<
                static_cast<unsigned int>(encrypted[index]);
        }
        std::cout << "\n";
    
        EVP_CIPHER_CTX_cleanup(&ctx);
    
        return 0;
    }
    

    Name it encrypt.cpp and compile with:

    g++ encrypt.cpp -o encrypt -lcrypto -lssl -Wall
    

    You'll get this output:

    338d2a9e28208cad84c457eb9bd91c81
    

    You can verify correctness by running the OpenSSL command-line utility from the command prompt:

    $ echo -n "encrypt me" > to_encrypt
    $ openssl enc -in to_encrypt -out encrypted -e -aes-256-cbc \
    -K 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \
    -iv 00000000000000000000000000000000
    $ hexdump -C encrypted
    

    And the hexdump will show the same bytes as the c++ program.

    00000000  33 8d 2a 9e 28 20 8c ad  84 c4 57 eb 9b d9 1c 81  |3.*.( ....W.....|
    
    0 讨论(0)
  • 2021-01-07 04:34

    look also at my answer to this question

    I suggest checking out cryptopp. Here's a code sample:

    CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor;
    byte* key;
    size_t keylen;
    // ... acquire key
    
    encryptor.SetKey( key, keylen );
    
    std::string input;
    std::string result;
    // read input ...
    
    StringSource( input, true,
           new StreamTransformationFilter( encryptor, new StringSink( result ),
         StreamTransformationFilter::PKCS_PADDING));
    

    The values for padding mode in StreamTransformationFilter can be:

    BlockPaddingScheme { 
      NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, 
      DEFAULT_PADDING 
    }
    

    EDIT: replaced the padding mode in the sample to pkcs

    0 讨论(0)
提交回复
热议问题