|
Boost Users : |
From: Pfligersdorffer, Christian (Christian.Pfligersdorffer_at_[hidden])
Date: 2006-09-22 10:41:44
Dear community,
I'm on my way to learn writing filters for the iostreams library and find it very hard. I want to compress and encrypt data, so I use the gzip-filters (that are already provided) and some self-tailored crypto-filter. Using a symmetric block cipher should be just fine with the framework, since data from a stream is usually fed in portions to the filter (128 Bytes by default).
Of course not when you use an aggregate_filter, which was my first attempt because it is so simple. Implementing a multichar_dual_use_filter seemed simple too but I am experiencing weird behaviour. Such as having runtime errors when reading an encrypted compressed file but not when reading compressed encrypted files. Also I am not entirely sure that I understood the documentation...
Here is what I do, perhaps you gurus instantly see what I'm doing wrong:
_________________________________________________________________________
class block_crypter : public boost::iostreams::multichar_dual_use_filter
{
const std::string pw;
char* buffer;
int length;
void reallocate_buffer(std::size_t n)
{
if (length < n) {
if (buffer) free(buffer);
buffer = (char*) malloc(n);
length = n;
}
}
public:
block_crypter(const char* password) : pw(password), buffer(NULL), length(0) {}
~block_crypter() { if (buffer) free(buffer); }
template<typename Source>
std::streamsize read(Source& src, char* s, std::streamsize n)
{
// Read up to n filtered characters into the buffer s,
// returning the number of characters read or -1 for EOF.
// Use src to access the unfiltered character sequence
reallocate_buffer(n);
std::streamsize count = boost::iostreams::read(src, buffer, n);
assert(count <= n);
if (count <= 0) return -1;
decrypt(pw, buffer, count, s);
return count;
}
template<typename Sink>
std::streamsize write(Sink& dest, const char* s, std::streamsize n)
{
// Consume up to n filtered characters from the buffer s,
// writing filtered characters to dest. Return the number
// of characters consumed.
reallocate_buffer(n);
encrypt(pw, s, n, buffer);
std::streamsize count = boost::iostreams::write(dest, buffer, n);
assert(count <= n);
return count;
}
};
BOOST_IOSTREAMS_PIPABLE(block_crypter, 0)
_________________________________________________________________________
The encrypt() and decrypt() functions produce a character sequence of the exact same length as the input sequence. All char values can occur which might be a problem but I don't know.
Runtime errors always occur at the end of the stream, i.e. on the last run of the filter. Perhaps I did not understand the EOF mechanics or am mixing up something. But then, it compiles and seems to behave properly if used alone. Only in read-mode preceding gzip-deflation there is an error.
I hope someone can help me there.
BTW: I did not even try to implement my filter as symmetric_filter. I cannot see how anyone would be able to do this given the present documentation or existing "examples".
Another thing that clearly arises is the block size issue n which has to be the same for writing and reading in order to produce the correct plain text again. Maybe the optimally_buffered_tag should be used instead of trusting in always the same default filter buffer size?
Thanks for your suggestions,
-- Christian Pfligersdorffer Dipl.-Ing. Bakk.rer.nat. Software Engineering EOS GmbH - Electro Optical Systems Robert-Stirling-Ring 1 D-82152 Krailling / Munich Phone +49 89 893 36-229 Fax +49 89 893 36-287 christian.pfligersdorffer_at_[hidden] http://www.eos.info
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net