使用用户输入密码使用 DES 加密

Posted

技术标签:

【中文标题】使用用户输入密码使用 DES 加密【英文标题】:Encrypting with DES with user input password 【发布时间】:2016-11-15 15:23:21 【问题描述】:

我还在学习密码学。我正在尝试在 C# 中创建一个简单的静态函数,将字符串加密为 DES(使用 Base64 输出)。我了解到 DES 使用 8 字节作为其密钥。我希望用户输入任意长度的字符串,将其作为密钥加密消息,然后将其转换为 Base64。示例在此site。

public static string EncryptDES(string phrase, string key)

    string encrypted = "";

    byte[] phraseBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(phrase);
    byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(key);

    System.Security.Cryptography.MD5CryptoServiceProvider hashMD5Provider 
                                = new System.Security.Cryptography.MD5CryptoServiceProvider();
    System.Security.Cryptography.DESCryptoServiceProvider provider 
                                = new System.Security.Cryptography.DESCryptoServiceProvider();

    provider.Mode = System.Security.Cryptography.CipherMode.CBC;

    System.Security.Cryptography.ICryptoTransform transform 
                                = provider.CreateEncryptor(keyBytes, keyBytes);
    System.Security.Cryptography.CryptoStreamMode mode 
                                = System.Security.Cryptography.CryptoStreamMode.Write;



    System.IO.MemoryStream memStream = new System.IO.MemoryStream();
    System.Security.Cryptography.CryptoStream cryptoStream 
                                = new System.Security.Cryptography.CryptoStream(memStream, transform, mode);
    cryptoStream.Write(phraseBytes, 0, phraseBytes.Length);
    cryptoStream.FlushFinalBlock();

    byte[] encryptedMessageBytes = new byte[memStream.Length];
    memStream.Position = 0;
    memStream.Read(encryptedMessageBytes, 0, encryptedMessageBytes.Length);

    encrypted = System.Convert.ToBase64String(encryptedMessageBytes);

    return (encrypted);
 // private static string EncryptDES(string phrase, string key)  

然后在 Main 中这样调用它:

SimpleEncryption.EncryptDES("A message regarding some secure 512-bit  encryption", "AnUltimatelyVeryVeryLongPassword");

当用户输入一个随机数的字符串长度(大于或小于 8 个字符)时,此行总是发生密码学异常:

System.Security.Cryptography.ICryptoTransform transform = provider.CreateEncryptor(keyBytes, keyBytes);

上面写着Specified key is not a valid size for this algorithm.

删除部分密钥以适应 8 个字符的长度(带或不带散列)似乎不是一个安全的解决方案(可能存在很高的冲突率)。

如何使用用户输入字符串实现 DES(不是 3DES)?

【问题讨论】:

你看过LegalKeySizes属性吗? msdn.microsoft.com/en-us/library/… 是的。我知道 DES 使用 64 位长密钥,但我们如何让用户输入的密码与用于加密字符串的密钥相匹配? DESCryptoServiceProvider des = new DESCryptoServiceProvider(); Console.WriteLine("DESCryptoServiceProvider"); ks = des.LegalKeySizes; foreach (KeySizes k in ks) Console.WriteLine("\tLegal min key size = " + k.MinSize); Console.WriteLine("\tLegal 最大密钥大小 = " + k.MaxSize); 其实我用的是CodeProject网站上的一个库。 【参考方案1】:

您需要从用户的密码生成一个哈希,并且只需要 8 个字节作为您的密钥。

var fullHash = hashMD5Provider.ComputeHash(System.Text.Encoding.ASCII.GetBytes(key));
var keyBytes = new byte[8];
Array.Copy(fullHash , keyBytes, 8);

您的问题表达了对丢弃部分散列的散列冲突的担忧;是的,这确实增加了风险,但是(假设你的哈希算法很好)你的情况并不比你只使用一开始只产生 8 个字节的哈希算法更糟。一个好的哈希算法应该均匀地分配熵。

【讨论】:

MD5 是一个非常弱的密钥派生函数,不适合生产使用。相反,iIterate over an HMAC with a random salt for about 100ms duration and save the salt with the hash.使用PBKDF2password_hashBcrypt等函数和类似函数。关键是让攻击者花费大量时间通过蛮力寻找密码。保护您的用户很重要,请使用安全的密码方法。 @zaph OP 已经在他发布的代码中使用了 MD5 哈希算法。我只是想展示最少量的代码来让它工作,而不是支持他选择的哈希算法。 喜欢帮助一些人跳下桥?哦等等,这也不是一个好主意。事情是这样的,它不是关于 OP 的代码,而是关于将应用程序的用户置于风险之中。 PBKDF2(基于密码的密钥派生函数 2)确实用于从密码中派生加密密钥,这正是 OP 正在做的事情。为了暴力破解加密,被攻击的不是密钥而是密码。解密速度很快,尤其是在只需要解密少量以确定密钥是否正确的情况下。这就是为什么需要一个慢速函数来从密码中获取密钥,MD5 速度很快,PBKDF2 通常与迭代计数一起使用,因此它需要大约 100 毫秒。 IMO 它有助于指出什么是安全的,什么不是,并促进安全的解决方案。是安全性差的用户松动。

以上是关于使用用户输入密码使用 DES 加密的主要内容,如果未能解决你的问题,请参考以下文章

DES加密解密问题,java 和 C#

FineReport中如何对cpt模板加密

jmu-python-凯撒密码加密算法,谢谢

密码加密

DES加密算法详细原理以及Java代码实现

plsql实现DES对称加密