Jan 052016
 

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.

  2 Responses to “Twofish in C#”

Comments (2)
  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?

    • 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();
          }
      }
      

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>