etcimon / botan

Block & stream ciphers, public key crypto, hashing, KDF, MAC, PKCS, TLS, ASN.1, BER/DER, etc.
Other
85 stars 22 forks source link

AES sample ? #12

Closed Ogromny closed 1 year ago

Ogromny commented 8 years ago

Would it be possible for you to show a tiny AES sample ?

Thanks in advance ;)

vladimirgamalyan commented 8 years ago

Not sure if it is almost corect code, but I used it for my pet project.

import botan.block.aes;
import botan.libstate.lookup;

const int AES256_KEY_LEN = 32;
const int AES256_BLOCK_LEN = 16;

ubyte[] encrypt_aes256_cbc_pkcs7(const ubyte[] key, const ubyte[] iv, const ubyte[] input)
{
    assert(key.length == AES256_KEY_LEN);
    assert(iv.length == AES256_BLOCK_LEN);

    Unique!BlockCipher aes256 = retrieveBlockCipher("AES-256").clone();
    aes256.setKey(key.ptr, AES256_KEY_LEN);

    size_t blocks = (input.length / AES256_BLOCK_LEN) + 1;
    size_t padding = ((blocks * AES256_BLOCK_LEN) - input.length);

    ubyte[] padd = new ubyte[padding];
    padd[] = cast(ubyte)padding;
    ubyte[] buffer = input ~ padd;

    ubyte[AES256_BLOCK_LEN] _iv;
    _iv[] = iv[];

    for (size_t i = 0; i < blocks * AES256_BLOCK_LEN; i += AES256_BLOCK_LEN)
    {
        ubyte[] b = buffer[i .. i + AES256_BLOCK_LEN];
        b[] ^= _iv[];
        aes256.encrypt(b.ptr);
        _iv[] = b[];
    }

    return buffer;
}

ubyte[] decrypt_aes256_cbc_pkcs7(const ubyte[] key, const ubyte[] iv, const ubyte[] input)
{
    assert(key.length == AES256_KEY_LEN);
    assert(iv.length == AES256_BLOCK_LEN);
    assert(input.length > 0);
    assert((input.length % AES256_BLOCK_LEN) == 0);

    Unique!BlockCipher aes256 = retrieveBlockCipher("AES-256").clone();
    aes256.setKey(key.ptr, AES256_KEY_LEN);

    ubyte[] buffer = new ubyte[input.length];
    buffer[] = input[];

    ubyte[AES256_BLOCK_LEN] nextIv;
    ubyte[AES256_BLOCK_LEN] _iv;
    _iv[] = iv[];

    for (size_t i = 0; i < buffer.length; i += AES256_BLOCK_LEN)
    {
        ubyte[] b = buffer[i .. i + AES256_BLOCK_LEN];
        nextIv[] = b[];
        aes256.decrypt(b.ptr);
        b[] ^= _iv[];
        _iv[] = nextIv[];
    }

    size_t padding = buffer[$ - 1];
    assert(padding > 0);
    assert(padding <= buffer.length);

    return buffer[0..$ - padding];
}
etcimon commented 8 years ago

You should also make sure you call .destroy on your AES object to zeroise your key from memory as its destructor intends. You can also place it in a Unique!AES256. I would even create it with findBlockCipher to make sure it uses the available hardware optimizations like AES-NI or SSSE3.

Also, there's a (considerably more complex) example in source/botan/constructs/cryptobox_psk.d

etcimon commented 8 years ago

Sorry, that's retrieveBlockCipher from import botan.libstate.lookup

vladimirgamalyan commented 8 years ago

Update the code with your suggestions, thanks a lot!