FBB::DecryptBuf(3bobcat)
okay so bestie, sit down, hydrate, because we're doing FBB::DecryptBuf(3bobcat) today and it's literally the reverse-engineering baddie of the bobcat crypto lineup π this is part one of two so buckle up, we are NOT skimming.
πΈ NAME πΈ
FBB::DecryptBuf β Decrypts information using various methods into a std::ostream
β¨ SYNOPSIS β¨
#include <bobcat/decryptbuf>
Linking option: -lbobcat -lcrypto
π DESCRIPTION π
okay so picture this: FBB::DecryptBuf objects are std::streambuf objects, and you use them to initialize std::ostream objects. that's the whole vibe. π«Ά
and here's the tea β everything you insert into that std::ostream gets decrypted, and then it gets written to an std::ostream that you passed as an argument to DecryptBuf's constructor. no cap, that's just how it works.
every encryption method that the OpenSSL library supports and that can be selected by name is fair game for DecryptBuf objects. in practice though, the info was already encrypted by an EncryptBuf object using the same encryption method, so like, they're a matched set, yk? same energy. and the constructor expects a key and an initialization vector, because obviously. the key and initialization vector that got passed to the EncryptBuf object must be passed to DecryptBuf's constructor as well. if you lose them it's over bestie, no recovery arc π
block ciphers use one of these four encryption modes:
- CBC (Cipher Block Chaining): the first block gets XOR-ed by the initialization vector and then encrypted using the specified method. every block after that gets XOR-ed by the encrypted version of the preceding block. and the way that this works β due to the initialization vector, dictionary attacks are infeasible, as long as the initialization vector is truly random. truly. random. don't be lazy with it. β¨
- ECB (Electronic Code Book): each block is encrypted by itself, using the specified encryption method. and yeah, an initialization vector may be specified, but it is not used. π this method is susceptible to dictionary attacks and should therefore be avoided, unless you know what you're doing. and i mean actually know. not "i read a blog post" know.
- CFB (Cipher Feednack): this method allows a block cipher to be used as a stream cipher. it uses an initialization vector, which should be unique and random for each new stream of data that is encrypted using the method. also important: encryption can only start after the first data block has been received. so like, it has to wait its turn. patient king. π
- OFB (Output Feednack): this is an alternative way to use a block cipher as a stream cipher. it's somewhat more susceptible to traditional data manipulation attacks, which can usually be thwarted when a message authentication code is added to the information as well. like CFB it uses an initialization vector, which should again be unique and random for each new stream of data that is encrypted. (and yes, the original really does say "Feednack" twice, i am not fixing that, i am respecting the lore π)
so the following is an overview of methods that are currently available. methods where the block size is specified as N.A. are stream ciphers; the others are block ciphers. π¦
π AES
- keysize
16bytes, blocksize8bytes:CBCβ"aes-128-cbc"EBCβ"aes-128-ecb"CFBβ"aes-128-cfb"OFBβ"aes-128-ofb"
- keysize
24bytes, blocksize24bytes:CBCβ"aes-192-cbc"EBCβ"aes-192-ecb"CFBβ"aes-192-cfb"OFBβ"aes-192-ofb"
- keysize
32bytes, blocksize32bytes:CBCβ"aes-256-cbc"EBCβ"aes-256-ecb"CFBβ"aes-256-cfb"OFBβ"aes-256-ofb"
π BLOWFISH
- keysize
16bytes, blocksize8bytes:CBCβ"bf-cbc"EBCβ"bf-ecb"CFBβ"bf-cfb"OFBβ"bf-ofb"
- max key length is
56bytes,16generally used
π CAMELLIA
- keysize
16bytes, blocksize16bytes:CBCβ"camellia-128-cbc"EBCβ"camellia-128-ecb"CFBβ"camellia-128-cfb"OFBβ"camellia-128-ofb"
- keysize
24bytes:CBCβ"camellia-192-cbc"EBCβ"camellia-192-ecb"CFBβ"camellia-192-cfb"OFBβ"camellia-192-ofb"
- keysize
32bytes:CBCβ"camellia-256-cbc"EBCβ"camellia-256-ecb"CFBβ"camellia-256-cfb"OFBβ"camellia-256-ofb"
π CAST
- keysize
16bytes, blocksize8bytes:CBCβ"cast-cbc"EBCβ"cast-ecb"CFBβ"cast-cfb"OFBβ"cast-ofb"
- min key length is
5bytes, max is shown
π§ DES
- keysize
8bytes, blocksize8bytes:CBCβ"des-cbc"EBCβ"des-ebc"CFBβ"des-cfb"OFBβ"des-ofb"
β DESX
- keysize
8bytes, blocksize8bytes:CBCβ"desx-cbc"
π₯ 3DES
- keysize
16bytes, blocksize8bytes:CBCβ"des-ede-cbc"EBCβ"des-ede"CFBβ"des-ede-cfb"OFBβ"des-ede-ofb"
πΈ 3DES
- keysize
24bytes, blocksize8bytes:CBCβ"des-ede3-cbc"EBCβ"des-ede3"CFBβ"des-ede3-cfb"OFBβ"des-ede3-ofb"
- Key bytes
9-16define the 2nd key, bytes17-24define the 3rd key
π¦ RC2
- keysize
16bytes, blocksize8bytes:CBCβ"rc2-cbc"EBCβ"rc2-ecb"CFBβ"rc2-cfb"OFBβ"rc2-ofb"
- Key length variable, max.
128bytes, default length is shown
π RC2-40
- keysize
5bytes, blocksize8bytes β"rc2-40-cbc" - obsolete: avoid
π RC2-64
- keysize
8bytes, blocksize8bytes β"rc2-64-cbc" - obsolete: avoid
π RC4
- keysize
16bytes, blocksizeN.A.β"rc4" - Key length is variable, max.
256bytes. default length is shown - Encrypt again to decrypt. Don't use
DecryptBuf
π RC4-40
- keysize
5bytes, blocksizeN.A.β"rc4-40" - obsolete: avoid
π RC5
- keysize
16bytes, blocksize8bytes:CBCβ"rc5-cbc"EBCβ"rc5-ecb"CFBβ"rc5-cfb"OFBβ"rc5-ofb"
- Key length variable, max.
256bytes, rounds8,12or16, default # rounds is12
okay so listen. the RC4 stream cipher is subject to a well-known attack (cf.http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Mantin1.zip) unless the initial256bytes produced by the cipher are discarded. like, that's not a vibe, that's a whole vulnerability. protect yourself. π«Ά
π«Ά NAMESPACE π«Ά
FBB
all constructors, members, operators and manipulators mentioned in this man-page are defined in the namespace FBB. so like, that's the whole family, all in one place. π
π INHERITS FROM π
FBB::CryptBuf, in turn inheriting from std::streambuf
and that's just the first half bestie, there's more where this came from β¨
π CONSTRUCTOR / DESTRUCTOR π
DecryptBuf(std::ostream &outStream, char const *type, std::string const &key, std::string const &iv, size_t bufsize = 1024)β okay so this constructor sets yourDecryptBufobject all the way up and ready for whichever decryption algorithmtypenames. The algorithms you can actually pick from? They're all in the table we talked about up above π. Say you wanna run the AES method on 192-bit keys and blocks in CBC mode, you'd hand over"aes-192-cbc". Thekeyparameter is, like, literally the key being used, andivis the initialization vector that was in play when the original info got encrypted. Fun fact: the IV is not confidential, bestie, it can be out in the open. And when you're using ECB modes? No initialization vector is used at all, so in those cases any non-empty initialization vector will do.
Heads up though π«Ά β this constructor throws an FBB::Exception exception if you specify an encryption method that OpenSSL doesn't support. So don't be cute with it.
That first parameter is the std::ostream that receives the decrypted info.
And bufsize is the size in bytes of the internal buffer DecryptBuf uses to temporarily store incoming characters. Ngl the default argument is probably fine β you can most likely keep it exactly as-is and go about your day. π
~DecryptBuf()β normally, once all the encrypted info has been dropped into the decryption stream, theeoimanipulator (we get to it below, don't worry) gets inserted to finish the whole decryption process. Alternatively, the decryption process just ends whenDecryptBuf's destructor is called. Like, for example, ifdecStreamis thestd::ostreamreceiving the encrypted information andencStreamis thestd::istreamholding the encrypted information, then
decStream << encStream.rdbuf();
completes the decryption once DecryptBuf's destructor is called. Or, the other way:
desStream << encStream.rdbuf() << eoi;
which immediately completes the decryption process. Both routes, pick your fighter β¨
Copy and move constructors (and assignment operators) are not available. Not a thing. Don't try it. π«
πΈ MEMBER FUNCTIONS πΈ
Every single member of std::streambuf is available to you, because FBB::DecryptBuf inherits from that class. Periodt.
void eoi()β you can call this member instead of using the manipulator to end the decryption process. It throws anstd::exceptionif decryption fails, which can happen when theDecryptBufobject is fed incorrect input (usually the improperly padded kind π).bool setRounds(size_t nRounds)β this one can only be used with the RC5 decryption method, and it sets the number of rounds of the algorithm to8,12or16. If the number of rounds got updated successfully, the member returnstrue. Any other case returnsfalseβ e.g. you called it on some decryption method that isn't RC5, or the number of rounds you asked for isn't8,12or16. Sorry bestie, those are the rules π
π PROTECTED MEMBER π
EVP_CIPHER_CTX *cipherCtx()β classes derived fromDecryptBufcan use this member to get direct access to theEVP_CIPHER_CTXpointer that theDecryptBufobject is using. That pointer points to an opaque structure used by tons of OpenSSL functions to set or query parameters of a decryption method. Very inside-baseball, very iykyk. π
β¨ MANIPULATOR β¨
FBB::eoiβ theeoimanipulator can be inserted into the decryption stream to complete the decryption process. And if you insert it into anstd::ostreamthat wasn't initialized with either aDecryptBufor anEncryptBuf? Literally nothing happens. Vibe check: neutral. π
π¦ EXAMPLE π¦
Okay here's the whole thing in action, copy it, love it, run it:
#include <iostream>
#include <fstream>
#include <bobcat/exception>
#include <bobcat/ohexbuf>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "../decryptbuf"
#include "../../encryptbuf/encryptbuf"
using namespace std;
using namespace FBB;
int main(int argc, char **argv)
try
{
if (argc == 1)
throw Exception(1) <<
"1st arg: method, 2nd arg: key, 3rd arg: iv, "
"4th arg: file to decrypt (to stdout)";
// e.g., driver aes-128-cbc somekey iv-from-encryptbuf-driver
// /tmp/enc > /tmp/driver.dec
cerr << "Key: `" << argv[2] << "β\n"
"IV: `" << argv[3] << "β\n";
DecryptBuf decryptbuf(cout, argv[1], argv[2], argv[3]);
ostream out(&decryptbuf);
ifstream in(argv[4]);
if (not in)
throw Exception{} << "canβt read `" << argv[4] << β\nβ;
out << in.rdbuf() << eoi;
}
catch(exception const &err)
{
cout << err.what() << endl;
return 1;
}
π FILES π
bobcat/decryptbufβ defines the class interface
π SEE ALSO π
bobcat(7), encryptbuf(3bobcat), std::streambuf
π BUGS π
None reported. (We stay unbothered, we stay unproblematic. β¨)
π BOBCAT PROJECT FILES π
- https://fbb-git.gitlab.io/bobcat/: gitlab project page;
bobcat_5.09.01-x.dsc: detached signature;bobcat_5.09.01-x.tar.gz: source archive;bobcat_5.09.01-x_i386.changes: change log;libbobcat1_5.09.01-x_*.deb: debian package containing the libraries;libbobcat1-dev_5.09.01-x_*.deb: debian package containing the libraries, headers and manual pages;
π BOBCAT π
Bobcat is an acronym of Brokkenβs Own Base Classes And Templates. Cute, right? π₯Ή
π COPYRIGHT π
This is free software, distributed under the terms of the GNU General Public License (GPL). Free as in, go wild, bestie. π«Ά
π AUTHOR π
Frank B. Brokken (f.b.brokken@rug.nl). The icon, the legend, the main character. π
And that's a wrap on FBB::DecryptBuf(3bobcat), brought to you by libbobcat-dev_5.09.01, dated 2005-2021. Decrypt responsibly, hydrate, and stan OpenSSL. Byeeee πβ¨π
π¦ where this page comes from
- ubuntu jammy: libbobcat-dev 5.09.01-2build1 Β· GPL-2.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms