2013-03-22 106 views
1

我在使用银行的Web服务传递信用卡付款时遇到了一些问题。他们需要对出站数据进行RC4加密,他们期望它是十六进制格式。RC4加密与预期不符

下面是测试网站,他们给我的使用方法:http://www.fyneworks.com/encryption/rc4-encryption/index.asp

当我把样卡,并通过由上述表格所产生的价值,它们是正确的,并且该卡被接受。当我在下面使用我的frankencode(从我在互联网上找到的片段拼凑而成)时,十六进制值不正确,并且每次都会拒绝该卡。在某些情况下,encName是完全关闭的。在encCCNum和encCVVTest的情况下,它大约是一半的权利。在encExpyMonth和encExpyYear的情况下,它的完全正确。我确定这个问题是在我的算法某处,或者甚至可能是十六进制转换,但我真的没有太多的密码编程经验,所以我甚至不知道从哪里开始调试。有人可以帮帮我吗?这是C#.net中的Web应用程序,顺便说一句。

rc4encrypt rc4 = new rc4encrypt(); 
rc4.Password = "B83E13EC"; 
rc4.PlainText = sNameTest; 
encName = rc4.EnDeCrypt(); 
rc4.Password = "B83E13EC"; 
rc4.PlainText = sCCNumTest; 
encCCNum = rc4.EnDeCrypt(); 
rc4.Password = "B83E13EC"; 
rc4.PlainText = sExpyMonthTest; 
encExpyMonth = rc4.EnDeCrypt(); 
rc4.Password = "B83E13EC"; 
rc4.PlainText = sExpyYearTest; 
encExpyYear = rc4.EnDeCrypt(); 
rc4.Password = "B83E13EC"; 
rc4.PlainText = sCVVTest; 
encCVVTest = rc4.EnDeCrypt(); 

    public class rc4encrypt 
    { 
     protected int[] sbox = new int[256]; 
     protected int[] key = new int[256]; 

     protected string plaintext, password; 

     public string PlainText 
     { 
      set { plaintext = value; } 
      get { return plaintext; } 
     } 

     public string Password 
     { 
      set { password = value; } 
      get { return password; } 
     } 

     private void RC4Initialize(string strPwd) 
     { 
      // Get the length of the password 
      // Instead of Len(), we need to use the Length property 
      // of the string 
      int intLength = strPwd.Length; 

      // Set up our for loop. In C#, we need to change our syntax. 

      // The first argument is the initializer. Here we declare a 
      // as an integer and set it equal to zero. 

      // The second argument is expression that is used to test 
      // for the loop termination. Since our arrays have 256 
      // elements and are always zero based, we need to loop as long 
      // as a is less than or equal to 255. 

      // The third argument is an iterator used to increment the 
      // value of a by one each time through the loop. Note that 
      // we can use the ++ increment notation instead of a = a + 1 
      for (int a = 0; a <= 255; a++) 
      { 
       // Since we don't have Mid() in C#, we use the C# 
       // equivalent of Mid(), String.Substring, to get a 
       // single character from strPwd. We declare a character 
       // variable, ctmp, to hold this value. 

       // A couple things to note. First, the Mod keyword we 
       // used in VB need to be replaced with the % 
       // operator C# uses. Next, since the return type of 
       // String.Substring is a string, we need to convert it to 
       // a char using String.ToCharArray() and specifying that 
       // we want the first value in the array, [0]. 

       char ctmp = (strPwd.Substring((a % intLength), 
        1).ToCharArray()[0]); 

       // We now have our character and need to get the ASCII 
       // code for it. C# doesn't have the VB Asc(), but that 
       // doesn't mean we can't use it. In the beginning of our 
       // code, we imported the Microsoft.VisualBasic namespace. 
       // This allows us to use many of the native VB functions 
       // in C# 

       // Note that we need to use [] instead of() for our 
       // array members. 
       key[a] = Microsoft.VisualBasic.Strings.Asc(ctmp); 
       sbox[a] = a; 
      } 

      // Declare an integer x and initialize it to zero. 
      int x = 0; 

      // Again, create a for loop like the one above. Note that we 
      // need to use a different variable since we've already 
      // declared a above. 
      for (int b = 0; b <= 255; b++) 
      { 
       x = (x + sbox[b] + key[b]) % 256; 
       int tempSwap = sbox[b]; 
       sbox[b] = sbox[x]; 
       sbox[x] = tempSwap; 
      } 
     } 

     public string EnDeCrypt() 
     { 
      int i = 0; 
      int j = 0; 
      string cipher = ""; 

      // Call our method to initialize the arrays used here. 
      RC4Initialize(password); 

      // Set up a for loop. Again, we use the Length property 
      // of our String instead of the Len() function 

      for (int a = 1; a <= plaintext.Length; a++) 
      { 
       // Initialize an integer variable we will use in this loop 
       int itmp = 0; 


       // Like the RC4Initialize method, we need to use the % 
       // in place of Mod 
       i = (i + 1) % 256; 
       j = (j + sbox[i]) % 256; 
       itmp = sbox[i]; 
       sbox[i] = sbox[j]; 
       sbox[j] = itmp; 

       int k = sbox[(sbox[i] + sbox[j]) % 256]; 

       // Again, since the return type of String.Substring is a 
       // string, we need to convert it to a char using 
       // String.ToCharArray() and specifying that we want the 
       // first value, [0]. 

       char ctmp = plaintext.Substring(a - 1, 1).ToCharArray() 
        [0]; 

       // Use Asc() from the Microsoft.VisualBasic namespace 
       itmp = Microsoft.VisualBasic.Strings.Asc(ctmp); 

       // Here we need to use^operator that C# uses for Xor 
       int cipherby = itmp^k; 

       // Use Chr() from the Microsoft.VisualBasic namespace     
       cipher += Microsoft.VisualBasic.Strings.Chr(cipherby); 
      } 

      // Return the value of cipher as the return value of our 
      // method 

      //Convert to hexadecimal - added by BN 
      string finalcipher = string.Empty; 
      char[] values = cipher.ToCharArray(); 
      foreach (char letter in values) 
      { 
       // Get the integral value of the character. 
       int value = Convert.ToInt32(letter); 
       // Convert the decimal value to a hexadecimal value in string form. 
       finalcipher += String.Format("{0:X}", value); 

      } 

      return finalcipher; 
     } 

    } 
+0

虽然很明显没有官方的微软产品,但现在有很多这样的实现。这里有一个例子:http://www.codeproject.com/Articles/5068/RC4-Encryption-Algorithm-C-Version – 2013-03-22 22:30:28

+0

这是一些非常转换的代码。 '(strPwd.Substring((%intLength),1).ToCharArray()[0])' - >'strPwd [a%intLength]',对于初学者... – 2013-03-22 23:24:33

+0

@romkyns - 我没有写任何它在十六进制转换之外。它从我能找到的几个解决方案拼凑在一起。 – optionsix 2013-03-25 13:43:09

回答

3

请勿扮演您自己的加密代码。它通常是错误的。 Bouncy castle有一个支持RC4的C#实现。为什么不使用它?

+4

似乎更像是评论而不是答案。 – 2013-03-22 22:39:18

+0

同意。永远不要试图推出自己的产品。它通常不会很好地结束。 – 2013-03-22 22:40:28

+0

@GregS我同意,尽管在这种情况下,我们将调试RC4的实现,这是不符合的方式stackoverflow工程.. – 2013-03-22 23:01:36