I am encrypting and decrypting a string in .NET, using ECB cipher mode and Threefish symmetric block cipher, whose implementation I've attached to my project as a .dll Here's the link to .NET implementation
Key size is equal to block size and is 256 bits in my case.
The thing is, as far as I understand, the length of input string, plaintext, must be equal to the length of ciphertext. Or must it? For example, in my case, considering ASCII encoding, plaintext is divided into blocks with each block containing 32 characters, but there always are 12 additional characters of ciphertext for each block, as I've figured out! That is, the length of ciphertext = the length of initial text + 12*n, where n is the number of blocks of text, that is str.Length/32 (str - initial string, already padded for being a multiple of 32).
Is there an error in my code (below) or is my understanding valid only for the case of very simple block cipher, using only XOR operation for encryption, while for complex .NET encryption system this rule doesn't fulfill? If the latter is the case, than please explain me what actually makes these lengths different!!! Thank you in advance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using SkeinFish;
using System.Security.Cryptography;
namespace ComputerSecurity_Threefish
{
class Program
{
static void Main(string[] args)
{
string plainText = inputProperString(), decryptedText, cipherText;
Threefish th = new Threefish();
th.GenerateIV();
th.GenerateKey();
cipherText = EncryptWithThreefish(plainText, th);
Console.WriteLine("\nThis is how your encrypted string looks like:\n" + cipherText + "\n\nNow it will be decrypted...");
Console.WriteLine(cipherText.Length);
decryptedText = DecryptWithThreefish(cipherText, th);
Console.WriteLine("\nAnd here is your initial string decrypted:\n" + decryptedText);
Console.Read();
}
public static string inputProperString()
{
Console.Write("Enter a string for encryption: ");
string str = Console.ReadLine();
int remainder = str.Length % 32;
if (remainder != 0)
{
Console.WriteLine("\nYour string's length is not a multiple of 32, which is the equivalent of Threefish-256 blocksize for the length of ASCII string. The string will be padded with spaces.");
for (int i = 0; i < 32 - remainder; i++)
str += " ";
}
return str;
}
public static string EncryptWithThreefish(string plainText, Threefish th)
{
MemoryStream memoryStream = new MemoryStream();
ICryptoTransform threefishEncryptor = th.CreateEncryptor();
CryptoStream cryptoStream = new CryptoStream(memoryStream, threefishEncryptor, CryptoStreamMode.Write);
byte[] plainBytes = Encoding.ASCII.GetBytes(plainText);
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
}
public static string DecryptWithThreefish(string cipherText, Threefish th)
{
MemoryStream memoryStream = new MemoryStream();
ICryptoTransform threefishDecryptor = th.CreateDecryptor();
CryptoStream cryptoStream = new CryptoStream(memoryStream, threefishDecryptor, CryptoStreamMode.Write);
string decryptedText = String.Empty;
try
{
byte[] cipherBytes = Convert.FromBase64String(cipherText);
cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] plainBytes = memoryStream.ToArray();
decryptedText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
}
finally
{
memoryStream.Close();
cryptoStream.Close();
}
return decryptedText;
}
}
}