view dcrypt/crypto/BlockCipherWrapper.d @ 11:02970e63257d

Fix stupid error with using uint instead of int in create*
author Thomas Dixon <reikon@reikon.us>
date Wed, 20 Aug 2008 23:33:02 -0400
parents cd376996cdb3
children
line wrap: on
line source

/**
 * This file is part of the dcrypt project.
 *
 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
 * License:   MIT
 * Authors:   Thomas Dixon
 */

module dcrypt.crypto.BlockCipherWrapper;

import dcrypt.crypto.BlockCipher;
import dcrypt.crypto.BlockCipherPadding;

/** 
 * Wraps a block cipher, enabling the encryption of a stream
 * whose length is a multiple of blockSize. Padding, if specified,
 * is to be applied otherwise and the result subsequently processed.
 */
class BlockCipherWrapper : BlockCipher {
    BlockCipher cipher;
    BlockCipherPadding padding;
    bool encrypt;
    
    this(BlockCipher c, BlockCipherPadding p=null) {
        cipher = c;
        padding = p; // null signifies no padding is to be applied
    }
    
    void init(bool encrypt, CipherParameters params) {
        this.encrypt = encrypt;
        cipher.init(encrypt, params);
    }
    
    char[] name() {
        if (padding !is null)
            return cipher.name~"/"~padding.name;
        return cipher.name;
    }
    
    uint blockSize() {
        return cipher.blockSize;
    }
    
    ubyte[] process(void[] input_) {
        ubyte[] input = cast(ubyte[]) input_;
        
        uint padLen = blockSize - (input.length % blockSize);
        if (padding !is null && !encrypt && padLen != blockSize)
            throw new ShortBufferError(
                    name()~": Encrypted padded block should be multiple of block size.");
        
        ubyte[] output = new ubyte[input.length];
        
        uint len = input.length,
             i = 0;
        while (len >= blockSize) {
            output[i..i+blockSize] = cipher.process(input[i..i+blockSize]);
            len -= blockSize;
            i += blockSize;
        }
                
        if (padding !is null) {
            if (encrypt) {
                output.length = output.length + padLen;
                ubyte[] t = new ubyte[blockSize];
                if (len > 0) {
                    t[0..len] = input[i..i+len];
                    t[len..blockSize] = padding.pad(padLen);
                } else
                    t[] = padding.pad(padLen);
                output[i..i+blockSize] = cipher.process(t);
            } else {
                output.length = output.length - padding.unpad(output);
            }
        } else
            if (len > 0)
                output[i..i+len] = cipher.process(input[i..i+len]);
            
        return output;
    }
    
    void reset() {
        cipher.reset();
    }
}