$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
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