65.9K
CodeProject 正在变化。 阅读更多。
Home

VB.NET 中的 DES 和三重 DES 实现

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (5投票s)

2010年1月27日

GPL3

2分钟阅读

viewsIcon

54565

downloadIcon

3992

一个简单的 VB.NET DES/三重 DES 实现,没有实例化开销。

引言

我正在一个慢速 CPU 上执行大量的加密操作,对性能不满意。由于我只处理几十个字节的数据,我怀疑问题在于 .NET 加密服务实例化的开销,事实也确实如此。

与其学习 CryptoAPI 并希望它没有相同的开销,我移植了 Christophe Devine 的 C++ 实现(包含在 zip 文件中),该实现没有开销。

Using the Code

我包含了一个演示,它使用 DES 类和 .NET 加密类。它显示输出是相同的。还有几个基准测试按钮。

使用该类非常简单。首先,创建该类

Dim myDes As New DES()

然后调用子程序

myDes.encrypt_des(key8, input, input.Length, output, outputLength)

模式为 CBC(密码块链接)。

为了演示,在加密后将输出复制回输入以进行解密。输入必须是 8 的倍数(不为您添加填充)。

DES 类不执行任何异常处理。如果没有错误,将不会有异常,并且它会将处理的字节数放入 outputLength 整数中,这将与 input.Length 相同。

对于我的目的,未使用 TransformFinalBlock

DES 类在 Compact Framework 上也能正常工作。

演示截图

关注点

如基准测试所示,在发布配置中,实例化基准测试(大量小操作)比 .NET 快约 14 倍(在某些系统上快 25 倍),但数据基准测试(16 兆字节)慢约 4 倍,因此该类仅适用于大量小操作。

VB.NET 使所有数学运算都显得很笨拙,因为强制执行了空格,并且从十六进制常量中删除了前导 0。(更新:在 Visual Studio 中找到了一个选项来删除自动格式化(工具 > 选项 > 文本编辑器 > Basic > VB 特定)。)

两个主要问题困扰了我

  • 为什么 &HFFFFFFFF 不是有效的 UInt32?因为十六进制常量默认被视为 Int32,除非你在末尾添加 UI:&HFFFFFFFFUI。
  • 我需要将字节转换为 UInt32,然后将它们左移到 UInt32 中(GET_UINT32 子程序)。这个 CUInt 错误让我花费了大约 4 个小时。

由于 VB.NET 没有 #define 的概念,我修改了这些转换后的子程序,以接受另一个变量作为继承的变量。并且由于处理数组的不同方式,我添加了一个 nSK 枚举器到一些子程序中。

这是 GPL,因为 Christophe 的许可证是 GPL。

移植示例

对移植 C++ 到 VB.NET 感兴趣的人也应该觉得这段代码有用。我不太擅长写 C++,但我可以理解它。

这里有一些移植示例

/* DES round macro */

#define DES_ROUND(X,Y)                          \
{                                               \
    T = *SK++ ^ X;                              \
    Y ^= SB8[ (T      ) & 0x3F ] ^              \
         SB6[ (T >>  8) & 0x3F ] ^              \
         SB4[ (T >> 16) & 0x3F ] ^              \
         SB2[ (T >> 24) & 0x3F ];               \
                                                \
    T = *SK++ ^ ((X << 28) | (X >> 4));         \
    Y ^= SB7[ (T      ) & 0x3F ] ^              \
         SB5[ (T >>  8) & 0x3F ] ^              \
         SB3[ (T >> 16) & 0x3F ] ^              \
         SB1[ (T >> 24) & 0x3F ];               \
}
'DES round macro
'init nSK as -1
Private Sub DES_ROUND(ByRef X As UInt32, ByRef Y As UInt32, _
	ByRef T As UInt32, ByRef SK() As UInt32, ByRef nSK As Integer)
    nSK += 1
    T = SK(nSK) Xor X
    Y = Y Xor SB8((T      ) And &H3FUI) Xor _
              SB6((T >>  8) And &H3FUI) Xor _
              SB4((T >> 16) And &H3FUI) Xor _
              SB2((T >> 24) And &H3FUI)

    nSK += 1
    T = SK(nSK) Xor ((X << 28) Or (X >> 4))
    Y = Y Xor SB7((T      ) And &H3FUI) Xor _
              SB5((T >>  8) And &H3FUI) Xor _
              SB3((T >> 16) And &H3FUI) Xor _
              SB1((T >> 24) And &H3FUI)
End Sub
// DES 64-bit block encryption/decryption

void des_crypt( uint32 SK[32], uint8 input[8], uint8 output[8] )
{
    uint32 X, Y, T;

    GET_UINT32( X, input, 0 );
    GET_UINT32( Y, input, 4 );

    DES_IP( X, Y );

    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );
    DES_ROUND( Y, X );  DES_ROUND( X, Y );

    DES_FP( Y, X );

    PUT_UINT32( Y, output, 0 );
    PUT_UINT32( X, output, 4 );
}
'DES 64-bit block encryption/decryption

Private Sub des_crypt(ByRef SK() As UInt32, _
	ByRef input() As Byte, ByRef output() As Byte)
    Dim X, Y, T As UInt32

    GET_UINT32(X, input, 0)
    GET_UINT32(Y, input, 4)

    DES_IP(X, Y, T)

    Dim nSK As Integer = -1
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)
    DES_ROUND(Y, X, T, SK, nSK) : DES_ROUND(X, Y, T, SK, nSK)

    DES_FP(Y, X, T)

    PUT_UINT32(Y, output, 0)
    PUT_UINT32(X, output, 4)
End Sub

历史

  • 2010.01.27
    • 初次发布
  • 2010.01.27
    • 通过添加空格和前导 0 来美化代码
    • 将移植示例添加到文章中
© . All rights reserved.