FBB:...ambuf(3bobcat)

πŸ“¦
version 5.09.01 Β· 2 versions
, in ubuntu jammy

πŸ’– FBB::ISymCryptStreambuf πŸ’–

okay bestie so this is FBB:...ambuf(3bobcat) β€” yes the man page name is truncated like that, it's giving ✨mysterious✨ β€” and it lives in the 3bobcat manual section. Buckle up, we're doing symmetric encryption and we're gonna understand it.


🌸 NAME 🌸

FBB::ISymCryptStreambuf β€” an input filtering stream buffer that does symmetric encryption. she filters, she encrypts, she slays. πŸ’…


✨ SYNOPSIS ✨

#include <bobcat/isymcryptstreambuf>
Linking option: -lbobcat -lcrypto

πŸ¦‹ DESCRIPTION πŸ¦‹

So the tea is this: everything an ISymCryptStreambuf object hands you has already been through symmetric encryption or decryption. Where does it get that info? From std::istream objects, obviously. You feed it a stream, it does its little crypto thing, and hands you the result. 🫢

ISymCryptStreambuf is a class template, and it takes an FBB::CryptType non-type template parameter. Translation, bestie:

  • FBB::ISymCryptStreambuf<FBB::ENCRYPT> β†’ encrypts whatever it receives πŸ”₯
  • FBB::ISymCryptStreambuf<FBB::DECRYPT> β†’ decrypts whatever it receives 🧊

(it says "see also section ENUMERATION below" β€” that's coming in the next part, don't worry, we're getting there πŸ‘€)

Every symmetric encryption method that the OpenSSL library defines, and that can be picked by name, works with EncryptBuf objects. To choose your method you pass an identifier to the constructor. Like "aes-128-cbc" β€” that's the AES (Rijndael) method, 128 bit sized keys, blocks, and it's using cbc mode. We explain modes below, keep reading. ⭐

If you hand it a shorter key than the method expects, the key gets extended by adding however many 0-bytes are needed. That's zero valued bytes, not the character '0'. Big difference, don't play yourself. 😭

Most modes use an initialization vector, and you gotta hand it over at construction time. Here's the catch: the matching decrypting object needs to know the exact initialization vector that was used when encrypting the data. So it's on the application to make sure the decryption object receives the same initialization vector that was given to the encryption object. Fumbled that handoff? That's on you. πŸ™ˆ

Good news though: initialization vectors are not security sensitive in the sense that they can totally be sent in the clear to the decryption object. What is important is that they contain random data when used "for real". And if you specify an initialization vector that's shorter than the method expects, it gets extended with the required number of 0-bytes. Same energy as the key thing above. πŸ’œ


πŸ” the four block cipher encryption modes πŸ”

Block ciphers use one of these four, periodt:

  • CBC (Cipher Block Chaining): the first block is XOR-ed by the initialization vector and then encrypted using the specified method. Every subsequent block gets XOR-ed by the encrypted version of the block before it. And because of the initialization vector, dictionary attacks are infeasible β€” as long as the initialization vector is truly random. random or it doesn't count, bestie. πŸŽ€
  • ECB (Electronic Code Book): every block is encrypted all by itself using the specified encryption method. You can specify an initialization vector but it is not used, so don't bother. This method is susceptible to dictionary attacks and should therefore be avoided, unless you know what you're doing. ⚠️ lowkey a red flag. and it's spelled out as a warning in the original so I'm not softening it for you.
  • CFB (Cipher Feednack): this one lets a block cipher be used as a stream cipher. It uses an initialization vector, which should be unique and random for each new stream of data that's encrypted with the method. Also, encryption can only start after the first data block has been received. patience is a virtue. πŸ¦‹
  • OFB (Output Feednack): another 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, and again it should be unique and random for each new stream of data that's encrypted. ✨

πŸ‘‘ the method table πŸ‘‘

Here's the whole rundown of methods that are currently available. If the block size says N.A. it's a stream cipher; everything else is a block cipher:

────────────────────────────────────────────────────────────────
method      keysize    blocksize    mode    identifier
            (bytes)    (bytes)
────────────────────────────────────────────────────────────────
AES         16         8            CBC     "aes-128-cbc"
                                    EBC     "aes-128-ecb"
                                    CFB     "aes-128-cfb"
                                    OFB     "aes-128-ofb"
            24         24           CBC     "aes-192-cbc"
                                    EBC     "aes-192-ecb"
                                    CFB     "aes-192-cfb"
                                    OFB     "aes-192-ofb"
            32         32           CBC     "aes-256-cbc"
                                    EBC     "aes-256-ecb"
                                    CFB     "aes-256-cfb"
                                    OFB     "aes-256-ofb"
────────────────────────────────────────────────────────────────
BLOWFISH    16         8            CBC     "bf-cbc"
                                    EBC     "bf-ecb"
                                    CFB     "bf-cfb"
                                    OFB     "bf-ofb"
max key length is 56 bytes, 16 generally used
────────────────────────────────────────────────────────────────
CAMELLIA    16         16           CBC     "camellia-128-cbc"
                                    EBC     "camellia-128-ecb"
                                    CFB     "camellia-128-cfb"
                                    OFB     "camellia-128-ofb"
            24                      CBC     "camellia-192-cbc"
                                    EBC     "camellia-192-ecb"
                                    CFB     "camellia-192-cfb"
                                    OFB     "camellia-192-ofb"
            32                      CBC     "camellia-256-cbc"
                                    EBC     "camellia-256-ecb"
                                    CFB     "camellia-256-cfb"
                                    OFB     "camellia-256-ofb"
────────────────────────────────────────────────────────────────
CAST        16         8            CBC     "cast-cbc"
                                    EBC     "cast-ecb"
                                    CFB     "cast-cfb"
                                    OFB     "cast-ofb"
min key length is 5 bytes, max is shown
────────────────────────────────────────────────────────────────
DES         8          8            CBC     "des-cbc"
                                    EBC     "des-ebc"
                                    CFB     "des-cfb"
                                    OFB     "des-ofb"
────────────────────────────────────────────────────────────────
DESX        8          8            CBC     "desx-cbc"
────────────────────────────────────────────────────────────────
3DES        16         8            CBC     "des-ede-cbc"
                                    EBC     "des-ede"
                                    CFB     "des-ede-cfb"
                                    OFB     "des-ede-ofb"
────────────────────────────────────────────────────────────────
3DES        24         8            CBC     "des-ede3-cbc"
                                    EBC     "des-ede3"
                                    CFB     "des-ede3-cfb"
                                    OFB     "des-ede3-ofb"
Key bytes 9-16 define the 2nd key, bytes 17-24
define the 3rd key
────────────────────────────────────────────────────────────────
RC2         16         8            CBC     "rc2-cbc"
                                    EBC     "rc2-ecb"
                                    CFB     "rc2-cfb"
                                    OFB     "rc2-ofb"
Key length variable, max. 128 bytes, default length is shown
────────────────────────────────────────────────────────────────
RC2-40      5          8                    "rc2-40-cbc"
obsolete: avoid
────────────────────────────────────────────────────────────────
RC2-64      8          8                    "rc2-64-cbc"
obsolete: avoid
────────────────────────────────────────────────────────────────
RC4         16         N.A.                 "rc4"
Key length is variable, max. 256 bytes. default length is shown
Encrypt again to decrypt. Don’t use DecryptBuf
────────────────────────────────────────────────────────────────
RC4-40      5          N.A.                 "rc4-40"
obsolete: avoid
────────────────────────────────────────────────────────────────
RC5         16         8            CBC     "rc5-cbc"
                                    EBC     "rc5-ecb"
                                    CFB     "rc5-cfb"
                                    OFB     "rc5-ofb"
Key length variable, max. 256 bytes, rounds 8, 12 or 16,
default # rounds is 12
────────────────────────────────────────────────────────────────

a few things I need to scream at you from that table, since they're literally written there:

  • BLOWFISH: max key length is 56 bytes, 16 generally used.
  • CAST: min key length is 5 bytes, max is shown.
  • 3DES (24-byte one): key bytes 9-16 define the 2nd key, bytes 17-24 define the 3rd key.
  • RC2: key length variable, max. 128 bytes, default length is shown.
  • RC2-40 and RC2-64: obsolete: avoid πŸ’€
  • RC4: key length is variable, max. 256 bytes, default length is shown. And β€” iconic, honestly β€” encrypt again to decrypt, and don't use DecryptBuf. 🀯
  • RC4-40: obsolete: avoid πŸ’€
  • RC5: key length variable, max. 256 bytes, rounds 8, 12 or 16, and the default number of rounds is 12.

😭 the RC4 of it all 😭

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 initial 256 bytes produced by the cipher are discarded.

so like. if you're not throwing away those first 256 bytes, the attackers are eating. throw them away. πŸ™

🌸 NAMESPACE 🌸

FBB β€” literally every single constructor, member, operator and manipulator mentioned in this man-page lives in the namespace FBB. No cap. πŸ’…


πŸ¦‹ INHERITS FROM πŸ¦‹

FBB::IFilterBuf


πŸ‘‘ MEMBER FUNCTIONS πŸ‘‘

Okay bestie so the thing is, every single member of FBB::IFilterBuf is available to you, because ISymCryptStreambuf inherits from that class. Free real estate. 🫢

Heads up though: the overloaded move and/or copy assignment operators are not available. Not a thing. Don't go looking. πŸ’€

πŸ”₯ ENUMERATION πŸ”₯

ISymCryptStreambuf objects are doing exactly one of two jobs: they either encrypt or decrypt the info that comes their way.

  • FBB::ISymCryptStreambuf<FBB::ENCRYPT> β€” these ones encrypt the data they receive ✨
  • FBB::ISymCryptStreambuf<FBB::DECRYPT> β€” these ones decrypt the data they receive πŸ•΅οΈ

And the values ENCRYPT and DECRYPT? They're defined in the enum CryptType, which lives in the FBB namespace. Periodt. πŸ’œ


πŸŽ€ CONSTRUCTOR πŸŽ€

  • ISymCryptStreambuf<CryptType>( std::istream &in, char const *type, std::string const &key, std::string const &iv, size_t bufSize = 100, size_t filterBufSize = 1000, ENGINE *engine = 0 ) β€” this constructor initializes the streambuf, and it's giving so many options, let me break it down:
    • ISymCryptStreambuf<ENCRYPT> objects perform encryption; ISymCryptStreambuf<DECRYPT> objects perform decryption πŸ”
    • ISymCryptStreambuf<CryptType> objects obtain the bytes they're gonna encrypt or decrypt from std::istream &in πŸ“₯
    • The encryption method to use is specified by the type parameter. So like, "bf-cbc" selects the Blowfish Cipher Block Chaining method. iykyk 🐑
    • The symmetric key to use is specified by the key parameter πŸ”‘
    • The initialization vector is specified by the iv parameter 🧭
    • The FBB::ISymCryptStreambuf internally used buffer will contain bufSize characters. The default value is the smallest value that is used. And if you specify a smaller bufSize value? Then the default value gets used instead. It's giving "we'll decide for you" πŸ™ˆ
    • FBB::ISymCryptStreambuf's IFilterBuf base class is initialized with a buffer of size filterBufSize, using a lower bound of 100 🧱
    • The parameter ENGINE can be used to specify a hardware acceleration engine, as supported by the encryption/decryption method you're using. Its default argument value indicates that no hardware acceleration is available ⚑
Also: copy and move constructors (and assignment operators) are not available. None of them. Sorry bestie. πŸ’€

⭐ EXAMPLE ⭐

So this example shows the construction of an ISymCryptStreambuf<ENCRYPT> object ebuf, which is used to initialize a std::istream object. The info read from this istream gets encrypted using the Blowfish CBC method. Then an ISymCryptStreambuf<DECRYPT> object (dbuf reads the information from that stream and decrypts it again). The std::istream din object is initialized with the ISymCryptStreambuf<DECRYPT> object, and its content is sent to std::cout. The information that's presented at std::cin and that appears at std::cout should be identical. Full circle moment. 🌈

#include <iostream>

#include <bobcat/isymcryptstreambuf>

using namespace std;
using namespace FBB;

int main()
{
    ISymCryptStreambuf<ENCRYPT> ebuf(cin, "bf-cbc",
                                    "1234567890", "1234567890");
    istream ein(&ebuf);

    ISymCryptStreambuf<DECRYPT> dbuf(ein, "bf-cbc",
                                    "1234567890", "1234567890");
    istream din(&dbuf);

    cout << din.rdbuf();
}

πŸ“ FILES πŸ“

  • bobcat/isymcryptstreambuf β€” defines the class interface

πŸ‘€ SEE ALSO πŸ‘€

bobcat(7), encryptbuf(3bobcat), isymcryptstream(3bobcat), ibase64buf(3bobcat), ifilterbuf(3bobcat), ofilterbuf(3bobcat), std::streambuf.

Go read those too, bestie, they're all part of the lore πŸ“š


πŸ’€ BUGS πŸ’€

Sep/Oct 2013: due to a change in library handling by the linker (cf. http://fedoraproject.org/wiki/UnderstandingDSOLinkChange and https://wiki.debian.org/ToolChain/DSOLinking) libraries that are indirectly required are no longer automatically linked to your program. With BigInt this is libcrypto, which requires programs to link to both bobcat and crypto. Yeah. Annoying. Not our fault but you gotta deal with it 😭


🧚 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 name, iconic origin story πŸ’…


This is free software, distributed under the terms of the GNU General Public License (GPL). Slay. πŸŽ€


🌸 AUTHOR 🌸

Frank B. Brokken (f.b.brokken@rug.nl). Legend behaviour, honestly. πŸ‘‘


And that's the whole thing bestie!! ✨ This page came from libbobcat-dev_5.09.01, it's dated 2005-2021, and it's the FBB:...ambuf(3bobcat) page. Go encrypt something cute πŸ¦‹πŸ’œ

πŸ“¦ where this page comes from