Threefish分组密码,ECB,.NET实现:加密和解密(初始明文)字符串的长度是不同的

时间:2014-11-16 19:40:10

标签: .net encryption cryptography block-cipher

我在.NET中加密和解密字符串,使用ECB密码模式和Threefish对称分组密码,我的项目作为.dll Here's the link to .NET implementation附加到我的项目

密钥大小等于块大小,在我的情况下是256位。

据我所知,输入字符串的长度明文必须等于密文的长度。或者必须吗?例如,在我的情况下,考虑到ASCII编码,明文被分成块,每个块包含32个字符,但每个块总共有12个密文字符,正如我已经想到的那样!也就是说,密文的长度=初始文本的长度+ 12 * n,其中n是文本块的数量,即str.Length / 32(str - 初始字符串,已经填充为32的倍数)

我的代码中是否有错误(如下)或我的理解仅对非常简单的分组密码有效,仅使用XOR操作进行加密,而对于复杂的.NET加密系统,此规则不符合要求?如果是后者,请告诉我实际上这些长度的不同!!!提前谢谢。

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;
        }

    }
}

1 个答案:

答案 0 :(得分:0)

如果明文可以通过块大小分割,那么如果使用PKCS#7填充,则为ECB模式加密添加完整的填充块。 Threefish的块大小为32,64或128字节,PKCS#7填充是.NET中的默认值。但是,base 64将结果扩展到大约1/3加上一些可能的舍入,所以12个基本的64个字符听起来是正确的。

块密码通常不应用明文的XOR进行加密。然而,流密码或使用诸如CTR 之类的流模式的分组密码。这种加密确实需要IV(或至少是一个nonce),否则如果密钥被重用,它就会发生灾难性的失败。

大家都这么说,你真的不应该使用ECB模式加密,而且Threefish还没有完全指定加密。我建议至少CBC模式加密和AES。经过验证的密码(如GCM或EAX)会更好。