如何使用 DES 实现 CBC-MAC?

Posted

技术标签:

【中文标题】如何使用 DES 实现 CBC-MAC?【英文标题】:How can I implement CBC-MAC with DES? 【发布时间】:2011-10-03 07:11:06 【问题描述】:

我应该在 C# 中实现一个 MAC-CBC 生成方法,其中包含一些关于加密算法的信息。这是我所拥有的:

我应该使用 DES。 密钥是byte[] 11, 11, 11, 11, 11, 11, 11, 11 数据(16 字节)应以 8 字节部分加密。前 8 个字节使用 Instance Vector = new byte[8] 加密(8 个字节,值为 0)。 (CBC?) 应将加密值的最后 8 个字节转换为十六进制字符串。这是我应该发送的结果。

有了这些信息,我实现了以下方法:

public static string Encrypt(byte[] data)

    var IV = new byte[8];
    var key = new byte[]  11, 11, 11, 11, 11, 11, 11, 11 ;
    var result = new byte[16];

    // Create DES and encrypt.
    var des = DES.Create();
    des.Key = key;
    des.IV = IV;
    des.Padding = PaddingMode.None;
    des.Mode = CipherMode.CBC;
    ICryptoTransform cryptoTransform = des.CreateEncryptor(key, IV);
    cryptoTransform.TransformBlock(data, 0, 16, result, 0);

    // Get the last eight bytes of the encrypted data.
    var lastEightBytes = new byte[8];
    Array.Copy(result, 8, lastEightBytes, 0, 8);

    // Convert to hex.
    var hexResult = string.Empty;
    foreach (byte ascii in lastEightBytes)
    
        int n = (int)ascii;
        hexResult += n.ToString("X").PadLeft(2, '0');
    

    return hexResult;

他们提供给我的示例原始数据是:input=byte[] 0, 6, 4, 1, 6, 4, 1, 7, E, E, F, F, F, F, B, B),它应该返回值的输出:A7CBFB3C730B059C。这意味着加密数据的最后八个字节应该是:byte[] 167, 203, 251, 60, 115, 11, 05, 156

但不幸的是使用上述方法,我得到:32D91200D0007632。意味着我的加密数据不正确。 (我的方法生成的加密值的最后八个字节是byte[] 50, 207, 18, 0, 208, 0, 118, 50)。

有什么方法可以让我知道我应该怎么做才能到达 A7CB...?我做错了吗?

【问题讨论】:

CBC-MAC 对于应用了填充的消息是不安全的。这意味着消息必须是 DES 块的大小,否则您已经失去了相当多的安全性。您应该使用 CMAC 或 HMAC。 CMAC 是正确的 CBC-MAC。 DES 几年前就被弃用了,因为它不安全。您可能应该改用现代分组密码,例如 3-key Triple DES、AES 或 Cameilla。 【参考方案1】:

CBC-MAC 需要一个零初始化向量。明确指定 IV 要好得多:

var IV = new byte[]  0, 0, 0, 0, 0, 0, 0, 0 ;  

您说您的密钥是byte[] 11, 11, 11, 11, 11, 11, 11, 11 这些字节是十六进制还是基数 10?您可能想尝试:

var key = new byte[]  0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 ;

看看是否效果更好。

【讨论】:

谢谢。虽然我无法得到正确的结果。但这是我没有尝试过的一种方法。 @Kaymar:再看看这个问题,你是把纯文本 0, 6, 4, 1, 6, 4, 1, 7, E, E, F, F, F, F, B, B 当作十六进制还是十进制?你确定这是正确的明文,所有值都低于 16? 这个字节数组是通过使用自定义算法将 PAN 号码与 PIN 码进行异或运算来计算的。这个字节数组是银行提供给我的。我确定0, 6, 4, 1, ... 是正确的数组。并使用Encoding.ASCII.GetBytes 获取字符串的字节数组:“06416417EEFFFFBB`。您是否建议我应该使用另一种方法将它们转换为字节数组? 你的字符串在我看来像十六进制。您应该尝试 8 个十六进制字节,而不是 16 个 ASCII 字节/半字节。【参考方案2】:

Mono 项目有一个通用的 MAC-CBC 实现,它应该适用于任何 SymmetricAlgorithm - 即使它在内部被用于实现 MACTripleDES。 p>

您可以找到 MIT.X11 许可源代码here。 按原样使用或将其与您自己的代码进行比较。

【讨论】:

以上是关于如何使用 DES 实现 CBC-MAC?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用JAVA实现对字符串的DES加密和解密

如何使用 DES3 解密密文?

如何在netbeans java中使用充气城堡(DES)加密和解密文件?

如何实现C语言的DES加密算法实现,请关注

Golang:如何使用 DES、CBC 和 PKCS7 解密?

如何在 python 3 中使用 pycrypto 库使用 DES 加密和解密图像?