【问题标题】:Two-key triple DES encryption solution needed需要两密钥三重 DES 加密解决方案
【发布时间】:2011-10-04 07:28:19
【问题描述】:

这在 C# 中可行吗?我将如何做到这一点?

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

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

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

它接受A9993E364706816A,它必须使用的两个键是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 个字符。

【问题讨论】:

  • 这个算法是由某个标准指定的还是自制的?
  • 我不知道,因为我不太了解加密。请参阅更新后的程序流程。
  • 您可能只关心完成任务,但安全问题确实很难做好。所以我建议调查是否有一个描述算法的标准,并在此基础上编写你的实现。标准的措辞非常谨慎,通常还附带测试数据,因此您可以检查您的实施是否符合规范。如果该算法是自制的,它可能会损坏。除非需要与现有软件组件交互,否则请坚持切换到标准化算法。如果是:祝你好运! :-)
  • 谢谢。让我看看我能做什么。
  • @dtb:这就是我真正想要的,这可能吗? .NET 真的能满足这个需求吗?

标签: c# .net encryption


【解决方案1】:

这听起来你只是想为三重DES密钥设置一个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 - 如何确认您的消息未被篡改

【讨论】:

  • 谢谢。您还需要一个初始化委托人吗?我没有?我如何得到一个?你也使用 TripleDESCryptoServiceProvider 吗?
  • @BrendanVogt:更新了关于如何从您拥有的字符串格式中获取字节数组的帖子。
  • 我觉得我应该问你为什么要传输一个字符串的前 16 个字符来表示某物的哈希值?哈希类返回一个适合直接加密的字节数组。将其转换为字符串然后再转换回字节数组似乎有点愚蠢。另外,我不确定您为什么只想将计算的哈希的一部分安全地发送给某人。散列并不是真正的敏感数据,因为您无法从散列转到原始项目。至于你如何获取字节,并没有太大的区别,只要对方知道解密时如何处理就可以了。
  • 这些是给我的要求。我不会反对它。它目前的工作方式是我将散列字符串分成 3 部分。结果与 K1 和 K2 一起用于另一个 3DES,直到重复 3 次,直到我有一个 MAC。
【解决方案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);

注意,除了key,还需要一个初始化向量:

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

【讨论】:

  • 如果可以,请提供一个解决方案,您将如何在我正在寻找的三重 DES 加密中实现上述内容?
  • 请看我更新的帖子。这些是我的要求。
  • 我的初始化向量是什么?我的需求文档中没有指定任何内容?
  • +1 窥视,在继续提出请求之前,至少赞成一个显示如此出色和简洁示例代码的答案不是礼貌吗?必须感谢良好的答案才能使 SO 起作用
  • @sehe:假设你 +1 了原来的答案,我很高兴有人 +1 了你,但不是答案。 ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 2015-03-30
  • 1970-01-01
相关资源
最近更新 更多