2013-03-22 102 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