1

銀行の Web サービスを使用してクレジット カードの支払いを渡す際に問題が発生しています。彼らは、16 進形式であると予想されるアウトバウンド データで RC4 暗号化を必要とします。

これが彼らが私に使用するように与えたテスト Web サイトです: http://www.fyneworks.com/encryption/rc4-encryption/index.asp

サンプル カードを取得し、上記のフォームによって生成された値を渡すと、それらは正しく、カードは受け入れられます。以下のフランケンコード (インターネットで見つけたスニペットからまとめたもの) を使用すると、16 進数の値が正しくなく、毎回カードが拒否されます。場合によっては、encName が完全にオフになっています。encCCNum と encCVVTest の場合は半分くらいです。encExpyMonth と encExpyYear の場合は、完全に正しいです。

問題は私のアルゴリズムのどこかにあるか、16 進数の変換にあると確信していますが、暗号化プログラミングの経験があまりないので、どこからデバッグを開始すればよいかさえわかりません。誰か助けてくれませんか?これは 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;
        }

    }
4

1 に答える 1

4

独自の暗号コードをロールしないでください。通常は間違っています。Bouncy Castleには、RC4 をサポートする C# 実装があります。なぜそれを使用しないのですか?

于 2013-03-22T22:31:26.283 に答える