Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 错误:指定的密钥不是此算法的有效大小_C#_Algorithm_Encryption - Fatal编程技术网

C# 错误:指定的密钥不是此算法的有效大小

C# 错误:指定的密钥不是此算法的有效大小,c#,algorithm,encryption,C#,Algorithm,Encryption,我被一种加密方法困住了。我对加密或字节数组没有太多的知识,所以我很难解决这个问题 这是我的密码: public static class EncryptDecrypt { private static byte[] key = { }; private static string sEncryptionKey = "B@|@j!"; private static byte[] IV = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab}; pub

我被一种加密方法困住了。我对加密或字节数组没有太多的知识,所以我很难解决这个问题

这是我的密码:

 public static class EncryptDecrypt {
    private static byte[] key = { };
    private static string sEncryptionKey = "B@|@j!";
    private static byte[] IV = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab};

public static string Encrypt(string stringToEncrypt)
    {
        string returnstring = "";
        try
        {

            key = System.Text.Encoding.UTF8.GetBytes(sEncryptionKey);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            CryptoStream cs = new CryptoStream(ms,
                des.CreateEncryptor(key, IV), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();

            returnstring = Convert.ToBase64String(ms.ToArray());

            //URL Encryption Avoid Reserved Characters
            returnstring = returnstring.Replace("/", "-2F-");
            returnstring = returnstring.Replace("!", "-21-");
            returnstring = returnstring.Replace("#", "-23-");
            returnstring = returnstring.Replace("$", "-24-");
            returnstring = returnstring.Replace("&", "-26-");
            returnstring = returnstring.Replace("'", "-27-");
            returnstring = returnstring.Replace("(", "-28-");
            returnstring = returnstring.Replace(")", "-29-");
            returnstring = returnstring.Replace("*", "-2A-");
            returnstring = returnstring.Replace("+", "-2B-");
            returnstring = returnstring.Replace(",", "-2C-");
            returnstring = returnstring.Replace(":", "-3A-");
            returnstring = returnstring.Replace(";", "-3B-");
            returnstring = returnstring.Replace("=", "-3D-");
            returnstring = returnstring.Replace("?", "-3F-");
            returnstring = returnstring.Replace("@", "-40-");
            returnstring = returnstring.Replace("[", "-5B-");
            returnstring = returnstring.Replace("]", "-5D-");


            return returnstring;
        }
        catch (Exception e)
        {
            return e.Message;
        }
    }
}
但每当我以
stringencrypt=EncryptDecrypt.encrypt(“abcd”)的形式传递字符串时它提供了一个错误,指定的密钥不是此算法的有效大小。

如何解决这个问题,如何通过这个方法对任何字符串(主要是1-8个字符)进行加密

DES算法需要64位(8字节)密钥。您的
sEncryptionKey
的长度为6个字符,这就是为什么会出现“指定的密钥大小无效”错误

DES使用64位密钥,这些密钥不应该是像“SomePass”这样的人性化密码。它们应该是二进制键,涵盖64位键的所有可能种类(2^64个不同的组合)。否则,您的加密将比DES标准所暗示的要弱得多

这就是为什么在使用
System.Security.Cryptography
中的对称加密算法时,您不应将您的秘密视为用于加密的最终密钥,而应将其视为生成加密密钥的密码短语。您可以通过使用您的密码和一些salt(可以随机生成,但也应该在解密期间使用)构造
System.Security.Cryptography.Rfc2898DeriveBytes
的实例来执行此生成

代码的另一个问题是使用了长度为6字节的初始化向量(
IV
)。它的长度也应该是8字节,并且应该为每个加密使用随机初始化向量。您可以通过调用
DESCryptoServiceProvider.GenerateIV()
方法并访问
DESCryptoServiceProvider.IV
属性来生成IV

最后一点。由于将
returnstring
转换为Base64,因此无需替换所有这些特殊字符,如“&”和“$”。Base64字符集由数字、数字和“+”、“/”、“=”符号组成。您只能更换这3个字符

因此,以下是根据上述注释编辑代码:

public static class EncryptDecrypt
{
    private static string sEncryptionPassphrase = "B@|@j!";

    public static string Encrypt(string stringToEncrypt)
    {
        try
        {
            string returnstring;
            var salt = GenerateSalt();
            using (var keyBytes = new Rfc2898DeriveBytes(sEncryptionPassphrase, salt))
            {
                var key = keyBytes.GetBytes(8);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.GenerateIV();
                byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(key, des.IV), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                returnstring = Convert.ToBase64String(ms.ToArray());
            }

            //URL Encryption Avoid Reserved Characters
            returnstring = returnstring.Replace("/", "-2F-");
            returnstring = returnstring.Replace("+", "-2B-");
            returnstring = returnstring.Replace("=", "-3D-");

            return returnstring;
        }
        catch (Exception e)
        {
            return e.Message;
        }
    }

    private static byte[] GenerateSalt()
    {
        var randomBytes = new byte[8];
        using (var rngCsp = new RNGCryptoServiceProvider())
        {
            rngCsp.GetBytes(randomBytes);
        }
        return randomBytes;
    }
}

DES算法需要64位(8字节)密钥。您的
sEncryptionKey
的长度为6个字符,这就是为什么会出现“指定的密钥大小无效”错误

DES使用64位密钥,这些密钥不应该是像“SomePass”这样的人性化密码。它们应该是二进制键,涵盖64位键的所有可能种类(2^64个不同的组合)。否则,您的加密将比DES标准所暗示的要弱得多

这就是为什么在使用
System.Security.Cryptography
中的对称加密算法时,您不应将您的秘密视为用于加密的最终密钥,而应将其视为生成加密密钥的密码短语。您可以通过使用您的密码和一些salt(可以随机生成,但也应该在解密期间使用)构造
System.Security.Cryptography.Rfc2898DeriveBytes
的实例来执行此生成

代码的另一个问题是使用了长度为6字节的初始化向量(
IV
)。它的长度也应该是8字节,并且应该为每个加密使用随机初始化向量。您可以通过调用
DESCryptoServiceProvider.GenerateIV()
方法并访问
DESCryptoServiceProvider.IV
属性来生成IV

最后一点。由于将
returnstring
转换为Base64,因此无需替换所有这些特殊字符,如“&”和“$”。Base64字符集由数字、数字和“+”、“/”、“=”符号组成。您只能更换这3个字符

因此,以下是根据上述注释编辑代码:

public static class EncryptDecrypt
{
    private static string sEncryptionPassphrase = "B@|@j!";

    public static string Encrypt(string stringToEncrypt)
    {
        try
        {
            string returnstring;
            var salt = GenerateSalt();
            using (var keyBytes = new Rfc2898DeriveBytes(sEncryptionPassphrase, salt))
            {
                var key = keyBytes.GetBytes(8);

                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.GenerateIV();
                byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(key, des.IV), CryptoStreamMode.Write);
                cs.Write(inputByteArray, 0, inputByteArray.Length);
                cs.FlushFinalBlock();
                returnstring = Convert.ToBase64String(ms.ToArray());
            }

            //URL Encryption Avoid Reserved Characters
            returnstring = returnstring.Replace("/", "-2F-");
            returnstring = returnstring.Replace("+", "-2B-");
            returnstring = returnstring.Replace("=", "-3D-");

            return returnstring;
        }
        catch (Exception e)
        {
            return e.Message;
        }
    }

    private static byte[] GenerateSalt()
    {
        var randomBytes = new byte[8];
        using (var rngCsp = new RNGCryptoServiceProvider())
        {
            rngCsp.GetBytes(randomBytes);
        }
        return randomBytes;
    }
}

“如何解决这个问题”——根据错误消息,似乎应该提供一个有效大小的键值。除此之外,请修复您的问题,以便包含一个重现问题的好代码,并解释为什么您认为用于
sEncryptionKey
的值应该有效。Base 64仅包含特殊字符
+
/
=
。因此,不需要替换任何其他字符。如果你真的更换了它们,你最好用它。密码和钥匙不是一回事,如果你生活在1970年,使用DES当然很好。尝试AES-GCM。“如何解决此问题”——根据错误消息,似乎应该提供一个有效大小的键值。除此之外,请修复您的问题,以便包含一个重现问题的好代码,并解释为什么您认为用于
sEncryptionKey
的值应该有效。Base 64仅包含特殊字符
+
/
=
。因此,不需要替换任何其他字符。如果你真的更换了它们,你最好用它。密码和钥匙不是一回事,如果你生活在1970年,使用DES当然很好。请尝试AES-GCM。谢谢你非常好的解释:)它有助于理解密码学…你能告诉我如何用你的方式解密字符串吗?谢谢你非常好的解释:)它有助于理解密码学…你能告诉我如何用你的方式解密字符串吗