You are viewing andreyvit

Oct. 7th, 2005 @ 05:51 pm Crypto++

(Posting in English in the hope this might be useful for someone else.) Crypto++ is one of the most complete and powerful cryptography libraries for C++. The only problem with it is a lack of a full introductory example. At least I could not figure out how to use it after an hour of searching and studying different resources. So, here is a full working example: 

#include <cryptopp/blowfish.h>
#include <cryptopp/base64.h>
#include <cryptopp/files.h>
#include <cryptopp/filters.h>
#include <cryptopp/modes.h>
#include <cryptopp/gzip.h>
#include <cryptopp/osrng.h>
#include <cryptopp/hex.h>

#include <wf/globals.hpp>
#include <iostream>
#include <exception>

using namespace CryptoPP;

void main () {
    byte key[CryptoPP::Blowfish::DEFAULT_KEYLENGTH], iv[CryptoPP::Blowfish::BLOCKSIZE];
    std::string plainText;

    plainText = "Hello, world!";
    for (int i = 0; i < 10; i++) {
        plainText = plainText + plainText;
    }

    CryptoPP::AutoSeededRandomPool rng (true);
    rng.GenerateBlock(key, sizeof (key));
    rng.GenerateBlock(iv, sizeof (iv));

    std::string cipher;
    {
        CryptoPP::StringSink* sink = new CryptoPP::StringSink(cipher);
        CryptoPP::Base64Encoder* base64_enc = new CryptoPP::Base64Encoder(sink);
        CryptoPP::CBC_Mode<CryptoPP::Blowfish>::Encryption twofish(key, CryptoPP::Blowfish::DEFAULT_KEYLENGTH, iv);
        CryptoPP::StreamTransformationFilter* enc = new CryptoPP::StreamTransformationFilter(twofish, base64_enc);
        CryptoPP::Gzip *zip = new CryptoPP::Gzip (enc);
        CryptoPP::StringSource source(plainText, true, zip);
    }

    std::cout << "Key length: " << (countof(key)*8) << std::endl;
    std::cout << "IV length: " << (countof(iv)*8) << std::endl;
    std::cout << "Encrypted text:\n" << cipher << std::endl;

    //rng.GenerateBlock(iv, sizeof (iv));
    //rng.GenerateBlock(key, sizeof (key));

    std::string decipher;
    try {
        CryptoPP::StringSink* sink = new CryptoPP::StringSink(decipher);
        CryptoPP::Gunzip *unzip = new CryptoPP::Gunzip (sink);
        CryptoPP::CBC_Mode<CryptoPP::Blowfish>::Decryption twofish(key, CryptoPP::Blowfish::DEFAULT_KEYLENGTH, iv);
        CryptoPP::StreamTransformationFilter* dec = new CryptoPP::StreamTransformationFilter(twofish, unzip);
        CryptoPP::Base64Decoder* base64_dec = new CryptoPP::Base64Decoder(dec);
        CryptoPP::StringSource source(cipher, true, base64_dec);
    } catch (const std::exception &e) {
        std::cout << "unsuccessful! caught " << "unknown" << ": " << e.what() << std::endl;
    } catch (...) {
        std::cout << "unsuccessful!" << std::endl;
    }
    std::cout << "Decrypted text:\n" << decipher.substr(0, 70) << "..." << std::endl;

    std::string skey;
    {
        CryptoPP::StringSink *sink = new CryptoPP::StringSink (skey);
        CryptoPP::HexEncoder enc (sink);
        enc.Put(key, sizeof(key));
    }
    std::cout << "Key: " << skey;
}

This code assumes you have Crypto++ installed in cryptopp subdirectory of some directory which is listed in include directories on your compiler's command line. E.g., if you invoke the compiler as "cl -Ic:/devel/src", then Crypto++ must be in "c:/devel/src/cryptopp".

Данная запись
[User Picture Icon]
From:dottedmag
Date:October 7th, 2005 10:56 am (UTC)
(Постоянная ссылка)
Первый вопрос - где умные указатели?
(Ответить) (Thread)
From:andreyvit
Date:October 7th, 2005 11:00 am (UTC)
(Постоянная ссылка)

Там само всё удаляется. Как видишь, последний объект из цепочки создаётся в стеке, остальных он удалит в деструкторе.

(Ответить) (Parent) (Thread)
[User Picture Icon]
From:dottedmag
Date:October 7th, 2005 12:38 pm (UTC)
(Постоянная ссылка)
На данный момент я заметил лишь утечку памяти, если в промежутке между созданием первого объекта из цепочки и последнего будет выброшено исключение.
(Ответить) (Parent) (Thread)
From:andreyvit
Date:October 7th, 2005 12:51 pm (UTC)
(Постоянная ссылка)

Это да. Но исправить это было бы очччень геморройно.

(Ответить) (Parent) (Thread)
[User Picture Icon]
From:dottedmag
Date:October 7th, 2005 12:53 pm (UTC)
(Постоянная ссылка)
auto_ptr и .release() для засовывания в следующий объект.
(Ответить) (Parent) (Thread)
From:andreyvit
Date:October 7th, 2005 12:55 pm (UTC)
(Постоянная ссылка)

Именно это я и имею в виду. Лениво. :) Кроме того, конструктор тоже может кинуть исключение. ;)

(Ответить) (Parent) (Thread)
[User Picture Icon]
From:dottedmag
Date:October 7th, 2005 12:58 pm (UTC)
(Постоянная ссылка)
Если библиотека не жопой написанаexception-aware, то это будет обработано нормально, за счет обыкновеннейшего RAII и правила разрушения созданных подобъектов в случае выброса исключения из конструктора.
(Ответить) (Parent) (Thread)
From:andreyvit
Date:October 7th, 2005 01:02 pm (UTC)
(Постоянная ссылка)

А если исключение выкинется при вычислении другого аргумента? ;) Не нравится мне release() передавать. Вообще, кривой дизайн, имхо.

Что такое RAII?

(Ответить) (Parent) (Thread)
[User Picture Icon]
From:dottedmag
Date:October 7th, 2005 01:14 pm (UTC)
(Постоянная ссылка)
Во, сам согласился, что дизайн кривой :)

RAII ты хорошо значешь - Resource Allocation Is Initialization.
(Ответить) (Parent) (Thread)
From:andreyvit
Date:October 7th, 2005 01:17 pm (UTC)
(Постоянная ссылка)

А, ну тогда и вправду знаю. :)

Что касается дизайна, то, по-моему, все передачи владения должны быть через std::auto_ptr (на тот случай, если другая сторона владение не приняла, или же заранее возникло исключение). По крайней мере, я всегда так делаю.

(Ответить) (Parent) (Thread)
[User Picture Icon]
From:dottedmag
Date:October 7th, 2005 01:44 pm (UTC)
(Постоянная ссылка)
Через умный указатель, в общем случае.
(Ответить) (Parent) (Thread)
[User Picture Icon]
From:w23
Date:October 20th, 2005 07:51 pm (UTC)
(Постоянная ссылка)
чем больше я вас, мальчики, читаю, тем больше понимаю, что не стоило мне даже и соваться в программисты.
хотя, конечно, и программистом я себя назвать не могу после прочтения этого треда %D.
(Ответить) (Parent) (Thread)
[User Picture Icon]
From:ler_do
Date:October 8th, 2005 01:08 pm (UTC)
(Постоянная ссылка)
Ох..Андрюша, Андрюша, такой хороший мальчик был лет 5 назад. Нужно научить тебя пить ;) тогда ты будешь ближе к земле.
(Ответить) (Thread)
From:(Anonymous)
Date:January 4th, 2007 05:03 pm (UTC)

_BLOCK_TYPE_IS_VALID

(Постоянная ссылка)
Привет.

Делаю всё по аналогии, но для ECB_Mode и без GZip
имею вот такую функцию для криптования

string encrypt(const string & src)
{
std::string cipher;

StringSink * sink = new StringSink(cipher);
Base64Encoder * base64_enc = new Base64Encoder(sink);
ECB_Mode::Encryption ecbEncryption(key, DES_EDE3::DEFAULT_KEYLENGTH);
StreamTransformationFilter * enc = new StreamTransformationFilter(ecbEncryption, base64_enc);
StringSource source(src, true, enc);

return cipher;
}

где const byte key[24] инициализирована моим ключем, но на выходе из фунции неизменно получаю

---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!

Program: ...
File: dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------

при длине исходного текста более 8 символов.

не знаю что происходит внутри CryptoPP библиотеки, но валюсь...
Но cipher расчитывается верно.
(Ответить) (Thread)
From:andreyvit
Date:January 5th, 2007 04:48 am (UTC)
(Постоянная ссылка)

Привет. Crypto++ нужно выкинуть на помойку, о чем я с тех пор написал другой пост, http://andreyvit-old.blogspot.com/2006/03/blog-post.html.

Честно говоря, я не понимаю отличие между CBC, ECB и другими вариантами, ибо в криптографии не разбираюсь. Наверное, стоить взять какой-нибудь BoundsChecker (тьфу, DevPartner) и посмотреть, что творится.

(Ответить) (Parent) (Thread)
From:korostelev
Date:March 16th, 2007 07:33 pm (UTC)
(Постоянная ссылка)
А что тогда юзать?
(Ответить) (Parent) (Thread)
From:(Anonymous)
Date:October 25th, 2008 08:34 pm (UTC)

Не компилит

(Постоянная ссылка)
Доброго времени суток. Код, представленный в топе страницы не хочет компилиться. Если конкретнее, то компилер не опознает функцию "countof": пишет: error C3861: 'countof': identifier not found. Есть варианты решения?

ЗЫ. перед этим удалил строку с
[Error: Irreparable invalid markup ('<wf/globals.hpp>') in entry. Owner must fix manually. Raw contents below.]

Доброго времени суток. Код, представленный в топе страницы не хочет компилиться. Если конкретнее, то компилер не опознает функцию "countof": пишет: error C3861: 'countof': identifier not found. Есть варианты решения?

ЗЫ. перед этим удалил строку с <wf/globals.hpp>, т.к. файл не находило.
(Ответить) (Parent) (Thread)
From:andreyvit
Date:October 26th, 2008 05:31 am (UTC)

Re: Не компилит

(Постоянная ссылка)

Я часто делаю #define countof(x) (sizeof(x)/sizeof((x)[0])).

(Ответить) (Parent) (Thread)
From:(Anonymous)
Date:October 27th, 2008 04:39 pm (UTC)

Re: Не компилит

(Постоянная ссылка)
Ого! Компиляция сразу прошла успешно, но непосредственно при запуске (F7) выдает 92 ошибки типа

test_example_crypopp.obj : error LNK2019: unresolved external symbol "public: __thiscall CryptoPP::Gunzip::Gunzip(class CryptoPP::BufferedTransformation *,bool,int)" (??0Gunzip@CryptoPP@@QAE@PAVBufferedTransformation@1@_NH@Z) referenced in function _main

Отчего может такое быть?

ЗЫ. Пути к библиотеке прописал вроде правильно, ибо при компиляции пустого проекта с ее подключением ошибок не возникает.
(Ответить) (Parent) (Thread)
From:andreyvit
Date:October 29th, 2008 07:10 pm (UTC)

Re: Не компилит

(Постоянная ссылка)

Это значит, что скомпилилось, но не слинковалось (т.е. нифига это не запуск). Надо настроить пути линкеру. Если ты не знаешь, что такое линковщик (по-старосоветски "редактор связей"), то предварительно нужно изучить сию крайне важную вещь.

А Crypto++, как я уже писал выше, дерьмо, и место ему на помойке.

(Ответить) (Parent) (Thread)
From:(Anonymous)
Date:October 25th, 2009 11:12 pm (UTC)

Kino-Get - скачать кино фильм на высокой скорости одним фай

(Постоянная ссылка)
да бывает (http://kino-get.ru)и такое
(Ответить) (Thread)
From:(Anonymous)
Date:January 10th, 2011 05:21 am (UTC)

Путь к Истине

(Постоянная ссылка)
Путь к Истине находится по адресу: truenewworld.ru
(внимание, это не реклама сайта - это "реклама" Истины).
(Ответить) (Thread)