Twofish in C#

As one of the five AES competition finalists, Twofish algorithm is well known and appreciated. Yes, Rijndael ended up being AES at the end but, unlike other finalists, Twofish is still widely used.

As I tried to read some Twofish-encrypted files I've noticed one sad fact - C# support is severely lacking. Yes, there is one reasonably good free implementation on CodeProject but it doesn't really play nicely with CryptoStream due to lack of any padding support. So, since I had some free time on my hands, I've decided to roll my own implementation.

I won't go too much into the details - do check the code yourself. Suffice to say it can be inserted wherever SymmetricAlgorithm can be used. It supports CBC and ECB encryption modes with no, zero, or PKCS#7 padding. You can chose if you are going to deal with encryption yourself or decide to be at the mercy of CryptoStream.

Basis for this code was Twofish reference implementation in C. Yes, I am aware recommendation is to use the optimized version instead but I find reference code much more readable and it made porting so much easier. I did however use MDS table lookup from the optimized version as it pretty much doubles the speed. Some time in the future I might consider optimizing it further but, as I have no pressing need, it might be a while.

It should be reasonably easy to follow Twofish code and only confusion will probably arise from the use of DWord structure with the overlapping fields. Yes, you can have the exactly same functionality with bitwise operations but overlapping structure does help performance quite a bit (around 25%). As I am using unoptimized reference code, one might argue implementation is not a speed champ to start with. However I believe this actually makes code even a bit more readable so I saw no reason to resist the temptation.

Probably the same amount of time I've spent on code was spent on setting up the test environment. While the basic test cases for full block transformations were covered by the official test vectors, the more expansive test cases with padding were pretty much non-existent. And let's not even get into the Monte Carlo tests and all the insanity brewing within.

In any case, download is available (or check a GitHub link). Those a bit more interested in validity can check tests too.

7 thoughts to “Twofish in C#”

  1. static void Main()
    {

    string t = “l7878”;
    UnicodeEncoding ec = new UnicodeEncoding();
    byte[] bIn = ec.GetBytes(t);
    byte[] outBy = new byte[bIn.Length];
    TwofishManaged tm = new TwofishManaged();
    uint[] key={2,3,4,3,2,3,5,6};
    uint[] iv = {1,2,3,2,3,4,5,6};
    TwofishImplementation tf = new TwofishImplementation(key, iv, CipherMode.CBC);
    tf.BlockEncrypt(bIn, 0, outBy, 0);
    }

    But I got IndexOutOfBounfException at:
    internal DWord(byte[] buffer, int offset)
    : this()
    {
    this.B0 = buffer[offset + 0];
    this.B1 = buffer[offset + 1];
    this.B2 = buffer[offset + 2]; //this line
    this.B3 = buffer[offset + 3];
    }

    Can you give me a properly way to implement this?

    1. Your output array is too small to receive encrypted data (due to necessary padding). I would recommend using streams instead.

      Equivalent example to yours would be:

      string t = "l7878";
      byte[] bIn = Encoding.Unicode.GetBytes(t);
      byte[] outBy;
      byte[] key = { 2, 3, 4, 3, 2, 3, 5, 6, 2, 3, 4, 3, 2, 3, 5, 6 };
      byte[] iv = { 1, 2, 3, 2, 3, 4, 5, 6 , 1, 2, 3, 2, 3, 4, 5, 6 };
      
      using (var algorithm = new TwofishManaged() { KeySize = key.Length * 8, Mode = CipherMode.CBC }) {
          using (var ms = new MemoryStream()) {
              using (var transform = algorithm.CreateEncryptor(key, iv)) {
                  using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Write)) {
                      cs.Write(bIn, 0, bIn.Length);
                  }
              }
              outBy = ms.ToArray();
          }
      }
      
      1. Oh example listed above are not clear. pls clear example to encrypt and decrypt file using twofish algorithm ?? i am in urgent situation to do project on data security.

        1. Sorry, but I don’t have time to follow up on a freely given code. If this is for a school project, putting some effort into understanding topic will not hurt.

  2. Hello,
    I am poking around the version:
    //2017-08-15: Replacing ThreadStatic with Lazy.

    I found that the code always saves the last block of any chunk in TwofishManagedTransform.TransformBlock(…) for processing later. The following comments it:

    //save last block without processing because decryption otherwise cannot detect padding in CryptoStream

    I have turned off the delay of processing the block and it still functions find decrypting with a CrypoStream. Do you remember why the code is as it is?

    1. Yes, it depends on your padding. If you’re using None or Zeros, then it works without that too.

      However, if you’re using other paddings it won’t be correctly detected if it crosses block boundaries without this code.

Leave a Reply to Josip Medved Cancel reply

Your email address will not be published. Required fields are marked *