銀行の 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;
}
}