Mercurial > public > ostc_companion
diff AES/rijndael.h @ 1:0b3630a29ad8
Initial version based on previous repository.
Project was ported to QT6 and in now cmake based.
| author | Ideenmodellierer <tiefenrauscher@web.de> |
|---|---|
| date | Thu, 27 Nov 2025 18:40:28 +0100 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AES/rijndael.h Thu Nov 27 18:40:28 2025 +0100 @@ -0,0 +1,296 @@ +////////////////////////////////////////////////////////////////////////////// +/// \file rijndael.h +/// \brief Public Domain AES encryption/decryption +/// \author Philip J. Erdelsky <pje@efgh.com>, JD Gascuel, and others. +/// +/// \copyright (c) 2015 JD Gascuel. All rights reserved. +/// $Id$ +////////////////////////////////////////////////////////////////////////////// +// +// BSD 2-Clause License: +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// +// HISTORY +// 2002-09-03 PJE: original source http://www.efgh.com/software/rijndael.htm +// 2015-03-14 jDG: Import into OSTC_Companion, major C++ rewrites to insure +// key length is not messed up. Added ECb and CFB modes. + +#ifndef RIJNDAEL_H +#define RIJNDAEL_H + +namespace Rijndael { + +#define KEYLENGTH(keybits) ((keybits)/8) +#define RKLENGTH(keybits) ((keybits)/8+28) +#define NROUNDS(keybits) ((keybits)/32+6) + +typedef unsigned long Word32; +typedef unsigned char Byte; +typedef Byte Block[16]; + +////////////////////////////////////////////////////////////////////////////// +/// \brief Public Domain AES encryption/decryption rewritten. +/// +/// The Rijndael encryption algorithm has been designed to replace the aging +/// DES algorithm. Like DES, it is a block cipher. It uses 128-bit, 192-bit +/// or 256-bit keys. This implementation encrypts 128-bit blocks. +/// (DES used 56-bit keys and 64-bit blocks.) +/// +/// The code in this package is a modified version of an implementation +/// placed in the public domain by the following persons: +/// + Vincent Rijmen vincent.rijmen@esat.kuleuven.ac.be +/// + Antoon Bosselaers antoon.bosselaers@esat.kuleuven.ac.be +/// + Paulo Barreto paulo.barreto@terra.com.br +/// +/// See details in http://www.efgh.com/software/rijndael.htm +/// +struct AES +{ + static void setupEncrypt(Word32* rk, const Byte *key, int keybits); + static void setupDecrypt(Word32* rk, const Byte *key, int keybits); + static void encrypt(Word32 *rk, int nrounds, const Block plaintext, Block ciphertext); + static void decrypt(Word32 *rk, int nrounds, const Block ciphertext, Block plaintext); + static Word32 get_random(Word32 *rk, int keybits); +}; + +////////////////////////////////////////////////////////////////////////////// +template<int keybits> +class ECB : private AES +{ + /// \brief Internal state + /// + /// storage for encryption buffer, required space: + /// keybits 32-bit words required + /// 128 44 + /// 192 52 + /// 256 60 + /// \sa RKLENGTH macro. + Word32 rk[RKLENGTH(keybits)]; + +public: + typedef Byte Key[KEYLENGTH(keybits)]; + + ECB(); + + //------------------------------------------------------------------------ + /// \brief Initialize encryption state + /// + /// + /// \param[in] key: AES key, where length is: + /// keybits number of bytes + /// 128 16 + /// 192 24 + /// 256 32 + /// \sa KEYLENGTH macro. + /// + /// \code + /// Rijndael::ECB<128>::Key key = "my big secret"; + /// Rijndael::ECB<128> enc; + /// enc.setupEncrypt(key); + /// ... + /// Rijndael::Block plain = "Hello World!"; + /// Rijndael::Block result; + /// enc.encrypt(plain, result); + /// \endcode + void setupEncrypt(const Key key); + + //------------------------------------------------------------------------ + /// \brief Encrypt a block of 16 bytes. + /// + /// \param[in] plaintext: The 16 bytes block to encrypt. + /// \param[out] ciphertext: Space to store the 16 bytes of encrypted data. + /// + void encrypt(const Block plaintext, Block ciphertext); + + //------------------------------------------------------------------------ + /// \brief Initialize decryption state. + /// + /// \param[in] key: AES key, where length is: + /// keybits number of bytes + /// 128 16 + /// 192 24 + /// 256 32 + /// \sa KEYLENGTH macro. + /// + /// \code + /// Rijndael::ECB<128>::Key key = "my big secret"; + /// Rijndael::ECB<128> dec; + /// dec.setupDecrypt(key); + /// ... + /// Rijndael::Block cipher = ...; + /// Rijndael::Block result; + /// Rijndael::decrypt(cipher, result); + /// \endcode + void setupDecrypt(const Key key); + + //------------------------------------------------------------------------ + /// \brief Decrypt a block of 16 bytes. + /// + /// \param[in] ciphertext: The 16 bytes block of data to decrypt. + /// \param[out] plaintext: Space to store the 16 bytes result block. + /// + void decrypt(const Block ciphertext, Block plaintext); + + //---------------------------------------------------------------------------- + /// \brief Crypto base PRNG + /// + /// Based on wall-clock value and current key, but should be a crypto-secure + /// generator. + Word32 get_random(); +}; + +////////////////////////////////////////////////////////////////////////////// +template<int keybits> +class CFB : public ECB<keybits> +{ + /// Initialization vector (salt), updated in CFB mode + /// for the next block of text. + Block iv; + +public: + typedef Byte Key[KEYLENGTH(keybits)]; + typedef Block IV; + + //------------------------------------------------------------------------ + /// \brief Initialize encryption/decription state + /// + /// + /// \param[in] key: AES key, where length is: + /// keybits number of bytes + /// 128 16 + /// 192 24 + /// 256 32 + /// \sa KEYLENGTH macro. + /// \param[in] iv: initialization vector. Some randomness needed to + /// enforce the sequence is non replayable. + /// + /// \code + /// Rijndael::CFB<128>::Key key = "my big secret"; + /// Rijndael::CFB<128> enc(key, iv); + /// ... + /// Rijndael::Block plain = "Hello World!"; + /// Rijndael::Block cipher, again; + /// enc.encrypt(plain, cipher); + /// enc.decrypt(cipher, again); + /// \endcode + CFB(const Key key, const IV iv); + + //------------------------------------------------------------------------ + /// \brief Encrypt a block of 16 bytes, with IV (CFB mode) + /// + /// \param[in] plaintext: The 16 bytes block to encrypt. + /// \param[out] ciphertext: Space to store the 16 bytes of encrypted data. + /// + void encrypt(const Block plaintext, Block ciphertext); + + //---------------------------------------------------------------------------- + /// \brief Decrypt a block of 16 bytes, with IV (CFB mode) + /// + /// \param[in] ciphertext: The 16 bytes block of data to decrypt. + /// \param[out] plaintext: Space to store the 16 bytes result block. + /// + void decrypt(const Block ciphertext, Block plaintext); +}; + +////////////////////////////////////////////////////////////////////////////// + +template<int keybits> +ECB<keybits>::ECB() +{ + for(int i=0; i<RKLENGTH(keybits); ++i) + rk[i] = 0; +} + +template<int keybits> +void ECB<keybits>::setupEncrypt(const Key key) +{ + AES::setupEncrypt(rk, key, keybits); +} + +template<int keybits> +void ECB<keybits>::encrypt(const Block plaintext, Block ciphertext) +{ + AES::encrypt(rk, NROUNDS(keybits), plaintext, ciphertext); +} + +////////////////////////////////////////////////////////////////////////////// + +template<int keybits> +void ECB<keybits>::setupDecrypt(const Key key) +{ + AES::setupDecrypt(rk, key, keybits); +} + +template<int keybits> +void ECB<keybits>::decrypt(const Block ciphertext, Block plaintext) +{ + AES::decrypt(rk, NROUNDS(keybits), ciphertext, plaintext); +} + +////////////////////////////////////////////////////////////////////////////// + +template<int keybits> +Word32 ECB<keybits>::get_random() +{ + return AES::get_random(rk, keybits); +} + +////////////////////////////////////////////////////////////////////////////// + +template<int keybits> +CFB<keybits>::CFB(const Key key, const IV _iv) +{ + ECB<keybits>::setupEncrypt(key); + for(int i=0; i<16; ++i) + iv[i] = _iv[i]; +} + +template<int keybits> +void CFB<keybits>::encrypt(const Block plaintext, Block ciphertext) +{ + Block tmp; + ECB<keybits>::encrypt(iv, tmp); + for(int i=0; i<16; ++i) + { + ciphertext[i] = plaintext[i] ^ tmp[i]; + iv[i] = ciphertext[i]; + } +} + +template<int keybits> +void CFB<keybits>::decrypt(const Block ciphertext, Block plaintext) +{ + Block tmp; + ECB<keybits>::encrypt(iv, tmp); + for(int i=0; i<16; ++i) + { + plaintext[i] = ciphertext[i] ^ tmp[i]; + iv[i] = ciphertext[i]; + } +} + +} +#endif // RIJNDAEL_H
