Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
尝试将旧的加密算法移植到C#_C#_Vb6 Migration_Encryption Symmetric_3des - Fatal编程技术网

尝试将旧的加密算法移植到C#

尝试将旧的加密算法移植到C#,c#,vb6-migration,encryption-symmetric,3des,C#,Vb6 Migration,Encryption Symmetric,3des,我首先要说的是,以下链接对我帮助很大: 我和他有同样的问题,只是他的修正没有修正我的代码 以下是我的旧(vb6)代码: 以下是新的C#版本: 而且,与上面链接的海报一样,密码的散列是相同的,加密字节数组的前8个字节是相同的。我将初始化向量设置为8字节零,但我认为如果加密数据的前8字节相同,那么初始化向量必须匹配。我只是不明白为什么接下来的8个字节不同。知道我做错了什么吗 谢谢 如果前8个字节相同,其余的则不同,听起来您使用的反馈形式与原始算法不同。尝试使用不同的CipherMode值,看看其中

我首先要说的是,以下链接对我帮助很大:

我和他有同样的问题,只是他的修正没有修正我的代码

以下是我的旧(vb6)代码:

以下是新的C#版本:

而且,与上面链接的海报一样,密码的散列是相同的,加密字节数组的前8个字节是相同的。我将初始化向量设置为8字节零,但我认为如果加密数据的前8字节相同,那么初始化向量必须匹配。我只是不明白为什么接下来的8个字节不同。知道我做错了什么吗


谢谢

如果前8个字节相同,其余的则不同,听起来您使用的反馈形式与原始算法不同。尝试使用不同的CipherMode值,看看其中是否有一个值与您匹配。

实际上有一个非常简单的解决方案,尽管它一点也不明显。你有一个代码块,上面写着“如果这个数据不是8的整数倍,请填充它。”但是,这会改变你加密的值,所以你会得到不同的结果


只要删除整个
if(streamToEncrypt.Length.Dump(“Length”)%8!=0{}
块,您就会得到预期的结果。

粘贴代码时出现两个错误-您在函数中重新定义
密码,而
填充模式是
填充模式.PKCS7
,而不是
填充模式.PKS7
。如果您能为每个版本提供一个输入和输出示例,这样我们就可以比较它们,这也会有所帮助;它们并不存在于真正的代码中。这里是输出:Encrypt(“这是一个测试”,“测试”):来自vb6的结果:
{88 241 158 115 160 7 65 122 202 119 153 101 247 247 57 140}
来自c的结果:
{88 241 158 115 160 7 65 122 163 192 255 202 43 175 83 151 24 121 240 70}
我刚刚在键入时注意到,vb6的结果长度为16字节,而c#的结果长度为24字节。我想这也表明我在某个地方遇到了麻烦,这也是我的第一个想法。我尝试了所有的枚举值都没有用。我们会的。我会成为猴子的叔叔。当我进行初始比较时,我注意到传递到旧VB6代码中的字节数组被第一个
CryptEncrypt()
调用填充以检索长度,然后是
ReDim缓冲区(bfrlen-1)
,后面是for循环,所以我只是模仿它。完美无瑕!谢谢@zeusalmighty——我猜C#library足够聪明,可以根据需要自动填充。有时只需要另一双眼睛。很高兴我能帮忙!只是想了想;为什么填充在vb6代码中有效,而在c代码中无效?据推测,在分组密码中,它一次对一个块进行编码(64位对吗?),因此填充的16字节数组应该返回与未添加的14字节数组相同的结果,不是吗?这与
prov3des.Padding=PaddingMode.PKCS7
行有关。有效选项和详细信息如下所示。用
0
手动填充它相当于
PaddingMode.zero
。使用
PaddingMode。如果不进行填充,则没有一个
会爆炸。您可以尝试手动模拟
PaddingMode.PKCS7
,方法是使用代码中
(8-(streamToEncrypt.Length%8))
的字节值填充所有额外的点,但随后必须截断结果(因为它假定这些额外字符是字符串的一部分)。@zeusalmighty-如果您想作为新问题提问,我可以比评论中提供的要详细一点。
Private Const ALG_CLASS_DATA_ENCRYPT = 24576&
Private Const ALG_CLASS_HASH = 32768
Private Const ALG_SID_3DES = 3&
Private Const ALG_SID_SHA1 = 4&
Private Const ALG_TYPE_ANY = 0&
Private Const ALG_TYPE_BLOCK = 1536&
Private Const CALG_3DES = (ALG_CLASS_DATA_ENCRYPT Or ALG_TYPE_BLOCK Or ALG_SID_3DES)
Private Const CALG_SHA1 = (ALG_CLASS_HASH Or ALG_TYPE_ANY Or ALG_SID_SHA1)
Private Const CRYPT_SILENT = &H40&
Private Const CRYPT_VERIFYCONTEXT = &HF0000000
Private Const MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0"
Private Const PROV_RSA_FULL = 1&

Private Declare Function CryptAcquireContextApi Lib "advapi32.dll" Alias "CryptAcquireContextA" (ByRef phProv As Long, ByVal pszContainer As String, ByVal pszProvider As String, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptCreateHashApi Lib "advapi32.dll" Alias "CryptCreateHash" (ByVal hProv As Long, ByVal Algid As Long, ByVal hKey As Long, ByVal dwFlags As Long, ByRef phHash As Long) As Long
Private Declare Function CryptDecryptApi Lib "advapi32.dll" Alias "CryptDecrypt" (ByVal hKey As Long, ByVal hHash As Long, ByVal Final As Long, ByVal dwFlags As Long, ByRef pbData As Byte, ByRef pdwDataLen As Long) As Long
Private Declare Function CryptDeriveKeyApi Lib "advapi32.dll" Alias "CryptDeriveKey" (ByVal hProv As Long, ByVal Algid As Long, ByVal hBaseData As Long, ByVal dwFlags As Long, ByRef phKey As Long) As Long
Private Declare Function CryptDestroyHashApi Lib "advapi32.dll" Alias "CryptDestroyHash" (ByVal hHash As Long) As Long
Private Declare Function CryptDestroyKeyApi Lib "advapi32.dll" Alias "CryptDestroyKey" (ByVal hKey As Long) As Long
Private Declare Function CryptEncryptApi Lib "advapi32.dll" Alias "CryptEncrypt" (ByVal hKey As Long, ByVal hHash As Long, ByVal Final As Long, ByVal dwFlags As Long, ByRef pbData As Byte, ByRef pdwDataLen As Long, ByVal dwBufLen As Long) As Long
Private Declare Function CryptGetHashParamApi Lib "advapi32.dll" Alias "CryptGetHashParam" (ByVal hHash As Long, ByVal dwParam As Long, pbData As Any, pdwDataLen As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptHashDataApi Lib "advapi32.dll" Alias "CryptHashData" (ByVal hHash As Long, ByRef pbData As Byte, ByVal dwDataLen As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptReleaseContextApi Lib "advapi32.dll" Alias "CryptReleaseContext" (ByVal hProv As Long, ByVal dwFlags As Long) As Long
Private Declare Function CryptGetKeyParamApi Lib "advapi32.dll" Alias "CryptGetKeyParam" (ByVal hKey As Long, ByVal dwParam As Long, ByRef pbData As Byte, ByRef pdwDataLen As Long, dwFlags As Long) As Long

Private Declare Sub CopyMemoryApi Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Function Encrypt(message As String, Password As String) As String

   If CryptAcquireContextApi(provider, vbNullString, ProviderName, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) = 0 Then
      Goto Encrypt_Failure
   End-If
   If CryptCreateHashApi(provider, CALG_SHA1, 0&, 0&, hash) = 0 Then
      Goto Encrypt_Failure
   End-If

   buffer = StrConv(Password, vbFromUnicode)
   If CryptHashDataApi(hash, buffer(0), CLng(UBound(buffer) + 1), 0&) = 0 Then
      GoTo Encrypt_Failure
   End If

   If CryptDeriveKeyApi(provider, CALG_3DES, hash, 1&, key) = 0 Then
      key = 0
      GoTo Encrypt_Failure
   End If

   length = Len(message)
   bfrlen = length
   If CryptEncryptApi(key, 0&, 1&, 0&, ByVal 0&, bfrlen, bfrlen) = 0 Then
      GoTo Encrypt_Failure
   End If

   ReDim buffer(bfrlen - 1)

   For i = 0 To length - 1
      buffer(i) = Asc(Mid(message, i + 1, 1))
   Next i

   If CryptEncryptApi(key, 0&, 1&, 0&, buffer(0), length, bfrlen) = 0 Then
      GoTo Encrypt_Failure
   End If

   Call CryptDestroyKeyApi(key)
   Call CryptReleaseContextApi(provider, 0)

   Encrypt = left(StrConv(buffer, vbUnicode), length)

Encrypt_Failure:
   If key Then
      Call CryptDestroyKeyApi(key)
   End If
   If hash Then
      Call CryptDestroyHashApi(hash)
   End If
   If provider Then
      Call CryptReleaseContextApi(provider, 0)
   End If

Exit Function
   public byte[] Encrypt(string source, string pass)
    {
        byte[] password = Encoding.UTF8.GetBytes(pass);
        byte[] resultArray = null;
        byte[] streamToEncrypt = Encoding.UTF8.GetBytes(source);

        if(streamToEncrypt.Length % 8 != 0)
        {
            byte[] inputArray = new byte[streamToEncrypt.Length + (8 - (streamToEncrypt.Length % 8))]; //add padding to the end to make the message groups of 8 bytes
            int i = 0;
            foreach (byte element in streamToEncrypt)
            {
                inputArray[i] = element;
                i++;
            }
            streamToEncrypt = inputArray;
        }


        using (TripleDESCryptoServiceProvider prov3des = new TripleDESCryptoServiceProvider())
        {

           prov3des.Mode = CipherMode.CBC;
           prov3des.Padding = PaddingMode.PKCS7;
           prov3des.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; //8 bytes, zero-ed

            using (PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, null)) //No salt needed here
            {
                prov3des.Key = pdb.CryptDeriveKey("TripleDES", "SHA1", 168, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
            }

            ICryptoTransform cTransform = prov3des.CreateEncryptor();
            resultArray = cTransform.TransformFinalBlock(streamToEncrypt,0,streamToEncrypt.Length);

        }

        return resultArray;

    }