/* Copright 2001/2002 by Markus Hahn All rights reserved. */ using System; namespace Blowfish_NET { /// /// helper class to enable CBCB for Blowfish /// /// /// Use this class to encrypt or decrypt byte arrays or a single /// block with Blowfish in the CBC (Cipher Block Block Chaining) mode. /// public class BlowfishCBC : Blowfish { uint m_unIvHi; uint m_unIvLo; /// /// the current IV, Blowfish.BLOCKSIZE bytes large /// public byte[] Iv { set { m_unIvHi = (((uint)value[0]) << 24) | (((uint)value[1]) << 16) | (((uint)value[2]) << 8) | ((uint)value[3]); m_unIvLo = (((uint)value[4]) << 24) | (((uint)value[5]) << 16) | (((uint)value[6]) << 8) | ((uint)value[7]); } get { byte[] result = new byte[Blowfish.BLOCKSIZE]; result[0] = (byte)(m_unIvHi >> 24); result[1] = (byte)(m_unIvHi >> 16); result[2] = (byte)(m_unIvHi >> 8); result[3] = (byte)m_unIvHi; result[4] = (byte)(m_unIvLo >> 24); result[5] = (byte)(m_unIvLo >> 16); result[6] = (byte)(m_unIvLo >> 8); result[7] = (byte)m_unIvLo; return result; } } /// /// standard constructor /// /// /// the key material, up to MAXKYELENGTH bytes, oversized material is ignored /// /// /// the initialization vector as a byte array of Blowfish.BLOCKSIZE length, /// no range checking, oversized data is ignored /// public BlowfishCBC (byte[] key, byte[] iv) : base(key) { m_unIvHi = (((uint)iv[0]) << 24) | (((uint)iv[1]) << 16) | (((uint)iv[2]) << 8) | ((uint)iv[3]); m_unIvLo = (((uint)iv[4]) << 24) | (((uint)iv[5]) << 16) | (((uint)iv[6]) << 8) | ((uint)iv[7]); } /// /// deletes all internal data structures and invalidates this instance /// /// /// Call this method as soon as the work with a particular instance is /// done. By this no sensitive translated key material remains. The /// instance is invalid after this call and usage can lead to unexpected /// results. /// /// /// self reference /// public new BlowfishCBC Burn() { base.Burn(); m_unIvHi = m_unIvLo = 0; return this; } /// /// encrypts a single block /// /// /// Use this method to encrypt one logical block, which is passed /// as two 32bit halves. If you extract the block from a sequence /// of bytes you have to do it in the network byte order. /// /// /// reference to the high 32 bits of the block /// /// /// reference to the low 32 bits of the block /// public new BlowfishCBC Encrypt (ref uint unHiRef, ref uint unLoRef) { unHiRef ^= m_unIvHi; unLoRef ^= m_unIvLo; base.Encrypt(ref unHiRef, ref unLoRef); m_unIvHi = unHiRef; m_unIvLo = unLoRef; return this; } /// /// decrypts a single block /// /// /// Use this method to decrypt one logical block, which is passed /// as two 32bit halves. If you extract the block from a sequence /// of bytes you have to do it in the network byte order. /// /// /// reference to the high 32 bits of the block /// /// /// reference to the low 32 bits of the block /// /// /// self reference /// public new BlowfishCBC Decrypt (ref uint unHiRef, ref uint unLoRef) { uint unBakHi = unHiRef; uint unBakLo = unLoRef; base.Decrypt(ref unHiRef, ref unLoRef); unHiRef ^= m_unIvHi; unLoRef ^= m_unIvLo; m_unIvHi = unBakHi; m_unIvLo = unBakLo; return this; } } } // (end of namespace)