需要双键三重DES加密解决方案

时间:2011-10-04 07:28:20

标签: c# .net encryption

这在C#中是否可行?我该如何做到这一点?

双键三重DES是我们用K1加密的地方,然后用K2解密,最后用K1再次加密。因此,密钥空间是2×56 = 112比特。

例如,使用K1=0x0123456789ABCDEFK2=0xFEDCBA9876543210,您可以将三重DES密钥设置为0x0123456789ABCDEFFEDCBA98765432100123456789ABCDEF

0123456789ABCDEF FEDCBA9876543210 0123456789ABCDEF
|<------K1------>|<------K2------>|<------K3------>|

它接受A9993E364706816A,并且必须使用的2个密钥是K1 = 0123456789ABCDEFK2 = FEDCBA9876543210。最终结果必须是:6E5271A3F3F5C418我没有得到。

更新

我正在尝试创建我需要使用的连接密钥。上面使用的2个密钥转换为字节数组,似乎每个长度为16。当2连接时,长度为32.然后我的代码炸弹了。密钥的长度必须为16或24.在这种情况下我需要做什么?

UTF8Encoding characterEncoding = new UTF8Encoding();
byte[] accessKey1ByteArray = characterEncoding.GetBytes(accessKey1);
byte[] accessKey2ByteArray = characterEncoding.GetBytes(accessKey2);
byte[] accessKeysArray = accessKey1ByteArray.Concat(accessKey2ByteArray).ToArray();

这是我尝试设置值的地方:

public byte[] ComputeTripleDesEncryption(byte[] plainText, byte[] key)
{
     TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();

     des.Key = key;
     des.GenerateIV();
     des.Mode = CipherMode.ECB;
     des.Padding = PaddingMode.None;

     ICryptoTransform ic = des.CreateEncryptor();

     byte[] enc = ic.TransformFinalBlock(plainText, 0, plainText.Length);

     return enc;
}

更新2

我需要设置尺寸吗?我发送的字节数组键是K1 + K2 + K1。

我发送的文字,我是否需要将此转换为字母,就像您推荐的那样,或者以下也可以做到这一点?

UTF8Encoding characterEncoding = new UTF8Encoding();
byte[] block1ByteArray = characterEncoding.GetBytes(block1);

block1的值为:A9993E364706816A

我如何得到A9993E364706816A来自我的SHA-1哈希结果。我想要编码的字符串的散列结果的前16个字符。

2 个答案:

答案 0 :(得分:2)

这听起来好像你只想为三重密钥设置一个128位密钥。

我相信在这种情况下,如果你提供一个128位密钥,它会将它分成两个64位密钥,并将第一个用作K1和K3,第二个用作K2,这正是你想要的。

不幸的是我找不到引用这个的来源,但是我最近在实现一些加密内容并找到关键长度时对这个主题进行了大量阅读,这就是我发现的内容。

如果您已经将K1和K2作为字节数组,那么您应该能够使用一个漂亮的小linq扩展方法并执行:

SymmetricAlgorithm cryptoService = new TripleDESCryptoServiceProvider();
byte[] myKey = K1.Concat(K2).ToArray();
cryptoService.Key = mKey;

那样就可以随心所欲。

在回答问题的更新部分时,您拥有的两个键是字节序列的十六进制表示。 0x0123456789ABCDEF是十六进制的16个字符,但这相当于8个字节的信息,因为它在每个字符中是4位 - 两个构成一个字节。

要将该字符串转换为字节数组,可以使用以下函数:

public static byte[] StringToByteArray(String hex)
{
    if (hex.Substring(0,2)=="0x")
    hex = hex.Substring(2);
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];
    for (int i = 0; i < NumberChars; i += 2)
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    return bytes;
}

(来自How do you convert Byte Array to Hexadecimal String, and vice versa?

然后将这样使用:

string K1="0x0123456789ABCDEF";
string K2="0xFEDCBA9876543210";
byte[] key = StringToByteArray(K1).Concat(StringToByteArray(K2)).ToArray();

实施TDES时,您需要同意密钥,分组密码模式,填充方法,在大多数阻止模式下,您将需要初始化向量。您可能还想使用消息验证码。

要获得初始化向量,您需要执行以下操作:

cryptoService.GenerateIV();
byte[] iv = cryptoService.IV;

我强烈建议阅读有关加密的页面,以便更好地了解您正在做的各种事情,而不仅仅是编写代码。它会让您对自己的安全更有信心,让您在与他人打交道时更有信心。我冒昧地包含了一些链接,其中大部分都可以通过谷歌搜索找到。

有用的链接:

http://en.wikipedia.org/wiki/Initialization_vector - 所有关于初始化向量

http://en.wikipedia.org/wiki/Triple_DES - 关于TDES算法

http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation - 连续的数据块如何相互作用。

http://en.wikipedia.org/wiki/Padding_%28cryptography%29 - 除了填充方式不同以外,双方都需要使用相同的方法(当然),这一点并不重要。

http://chargen.matasano.com/chargen/2009/7/22/if-youre-typing-the-letters-a-e-s-into-your-code-youre-doing.html - 关于加密使用的优秀且有趣的评论,以及存在弱点和加密可以做什么和不能做什么的评论。

http://en.wikipedia.org/wiki/Message_authentication_code - 如何确认您的邮件未被篡改

答案 1 :(得分:2)

要使用TripleDES算法加密/解密数据,您可以使用TripleDESCryptoServiceProvider Class。该算法支持从128位到192位的密钥长度,增量为64位。

如果您有两个64位密钥

byte[] k1 = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
byte[] k2 = new byte[] { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 };

并希望将k1,k2和k1再次连接到192位密钥,您可以按如下方式执行此操作:

byte[] key = new byte[K1.Length + K2.Length + K1.Length];
Buffer.BlockCopy(k1, 0, result,  0, 8);
Buffer.BlockCopy(k2, 0, result,  8, 8);
Buffer.BlockCopy(k1, 0, result, 16, 8);

请注意,除了密钥之外,还需要一个初始化向量:

byte[] iv = // ...

示例:

byte[] data = new byte[] { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A };

using (var csp    = new TripleDESCryptoServiceProvider())
using (var enc    = csp.CreateEncryptor(key, iv))
using (var stream = new MemoryStream())
using (var crypto = new CryptoStream(stream, enc, CryptoStreamMode.Write))
{
    crypto.Write(data, 0, data.Length);
}