VB6解密函数转C#后无法兼容解密旧文件,求问题排查修复
VB6到C#解密逻辑迁移:兼容旧加密文件问题
问题背景
正在将VB6版本的文件解密逻辑迁移至C#,要求C#版本能够解密VB6版本加密的文件,但目前无法实现向后兼容。推测问题源于两种语言的类型处理、字符串操作差异。
VB6原解密代码
Public Function DecryptFile(File() As Byte) As Byte() Dim op1 As Integer Dim i As Double Dim j As Integer Dim k As Integer Dim l As Integer Dim M As Double Dim r As Integer Dim The_Password As String pwork = Swap(Expand_Process("Password")) l = Len(Trim(pwork)) M = UBound(File) k = 1 For i = 0 To M j = File(i) - Asc(Mid(pwork, k, 1)) If j < 0 Then j = j + 256 End If File(i) = j k = k + 1 If k > l Then k = 1 End If Next i DecryptFile = File End Function Public Function Swap(The_Data As String) Dim Y, x As Integer Dim rest As String Dim r As Integer Dim wrk As String rest = "" x = Len(The_Data) / 2 For Y = 1 To x wrk = Mid(The_Data, Y * 2, 1) & Mid(The_Data, Y * 2 - 1, 1) rest = rest & wrk Next Y Y = Len(The_Data) - (x * 2) If Y > 0 Then rest = rest & Right(The_Data, Y) End If Swap = rest End Function Public Function Expand_Process(The_Data As String) As String Dim p1 As Double Dim p2 As Integer Dim rd() As Variant Dim m1 As Integer Dim m2 As Integer Dim dwork As String rd = Array(7, 3, 5, 1, 4, 2) p1 = Round(Len("Password") / 5, 0) dwork = "" For p2 = 1 To 5 m1 = rd(p2) * p1 m2 = m1 - (p1 - 1) dwork = dwork & Mid(The_Data, m1, p1) Next p2 Expand_Process = dwork End Function
迁移后的C#代码(存在问题)
public byte[] Decrypt(byte[] file) { int op1; int i; int j; int k; int l; double m; int r; string pword = Swap(Expand_Process("Password")); l = pword.Trim().Length; m = file.GetUpperBound(0); k = 1; for (i = 0; i <= m; i++) { string mid = Microsoft.VisualBasic.Strings.Mid(pword, k, 1); int asc = Microsoft.VisualBasic.Strings.Asc(mid); j = file[i] - asc; if (j < 0) { j += 256; } file[i] = Convert.ToByte(j); k++; if (k > l) { k = 1; } } return file; } private string Expand_Process(string data) { double p1; int[] rd; double m1; double m2; rd = new int[] {7, 3, 5, 1, 4, 2}; p1 = Math.Round((double)("Password".Length / 5), 0); string dwork = ""; for (int p2 = 1; p2 <= 5; p2++) { m1 = rd[p2] * p1; m2 = m1 - (p1 - 1); dwork += dwork + Microsoft.VisualBasic.Strings.Mid(data, (int)m1, (int)p1); } return dwork; } private string Swap(string data) { int x; int y; string rest; int r; string wrk; rest = ""; x = data.Length / 2; for (y = 1; y <= x; y++) { wrk = Microsoft.VisualBasic.Strings.Mid(data, y * 2, 1) + Microsoft.VisualBasic.Strings.Mid(data, y * 2 - 1, 1); rest += wrk; } y = data.Length - (x * 2); if (y > 0) { rest += Microsoft.VisualBasic.Strings.Right(data, y); } return rest; }
问题排查与修复
1. Expand_Process方法的整数除法错误
VB6中Len("Password")返回8,8/5=1.6,Round(1.6,0)结果为2。但C#中"Password".Length /5是整数除法,结果为1(两个int相除会截断小数),转double后Round结果为1,与VB6逻辑不符。
修复:先将长度转为double再做除法:
p1 = Math.Round((double)"Password".Length / 5, 0);
2. Expand_Process方法的字符串拼接错误
原VB6代码中是dwork = dwork & Mid(...),即每次追加新的子串。但迁移后的C#代码写成了dwork += dwork + Mid(...),这会导致每次拼接时重复追加自身,生成错误的密码字符串。
修复:改为直接追加子串:
dwork += Microsoft.VisualBasic.Strings.Mid(data, (int)m1, (int)p1);
3. 其他潜在细节确认
- VB6的
UBound(File)与C#的file.GetUpperBound(0)行为一致,均返回数组最后一个元素的索引,循环范围正确。 - 字节转换部分:
j经过j +=256处理后范围在0-255之间,Convert.ToByte(j)是安全的,与VB6自动转换Byte的逻辑一致。 Swap方法中,VB6的Len(The_Data)/2赋值给Integer变量会自动取整,C#的data.Length/2(int除法)结果一致,字符串索引使用Microsoft.VisualBasic.Strings.Mid确保与VB6的1起始索引逻辑一致。
修复后的完整C#代码
public byte[] Decrypt(byte[] file) { string pword = Swap(Expand_Process("Password")); int l = pword.Trim().Length; int m = file.GetUpperBound(0); int k = 1; for (int i = 0; i <= m; i++) { string mid = Microsoft.VisualBasic.Strings.Mid(pword, k, 1); int asc = Microsoft.VisualBasic.Strings.Asc(mid); int j = file[i] - asc; if (j < 0) { j += 256; } file[i] = Convert.ToByte(j); k++; if (k > l) { k = 1; } } return file; } private string Expand_Process(string data) { int[] rd = new int[] {7, 3, 5, 1, 4, 2}; double p1 = Math.Round((double)"Password".Length / 5, 0); string dwork = ""; for (int p2 = 1; p2 <= 5; p2++) { int m1 = (int)(rd[p2] * p1); dwork += Microsoft.VisualBasic.Strings.Mid(data, m1, (int)p1); } return dwork; } private string Swap(string data) { string rest = ""; int x = data.Length / 2; for (int y = 1; y <= x; y++) { string wrk = Microsoft.VisualBasic.Strings.Mid(data, y * 2, 1) + Microsoft.VisualBasic.Strings.Mid(data, y * 2 - 1, 1); rest += wrk; } int yRemaining = data.Length - (x * 2); if (yRemaining > 0) { rest += Microsoft.VisualBasic.Strings.Right(data, yRemaining); } return rest; }
内容的提问来源于stack exchange,提问作者Jesse Fogel
相关产品推荐
相关产品推荐

