ここに私の問題があります: 私は C++ (crypto++ v5.6.1 を使用) でレガシー コードを持っており、C# (System.Security.Cryptography を使用して .NET 3.5) で新しいコードを開発しています。C++ コードを変更することはできませんが、以前に暗号化されたデータを復号化できる必要があり、以前のアプリケーションは、新しい C# コードで暗号化するデータを復号化できる必要があります。
使用されるアルゴリズムは、どちらの場合も CFB 暗号モードの TripleDES ですが、最終的に、暗号化されたデータは同じではなく、バイト数と最初のバイトは同じですが、それ以外のすべてのバイトは異なります。
パディングは、C++ コードで手動で (ゼロを追加して) 行われます。そこで、PaddingValue を PaddingMode.Zeros に設定しました。(C#コードで手動で最後にゼロを追加しようとしましたが、何も変わりませんでした)。
別の System.Text.Encoding を使用してみましたが、結果は同じです (実際、テストされた文字は「純粋な」ASCII (つまり、0 と 126 の間) です)。
C++ コードの MandatoryBlockSize() の値は 8 なので、FeedbackSize も 8 に設定します。しかし、私がそれを理解していれば、それは実際には私のIVのサイズですよね?
キーのサイズは 24 バイト (3 つの異なるキー) で、IV の長さは 8 バイトです。2 つのコードではどちらも同じです。
どちらの場合も代わりに CBC モードを使用すると、結果は同じになります (ただし、前述のように、レガシー コードを変更することはできません ...)、OFB & CTS モードは例外をスローします (一方は使用できず、他方は互換性がありません)。私の .NET アプリケーションでは、結果を比較できません。
.Net バージョン 3.5 および 4.0 で Mono を使用するか、.Net 3.5 または 4.0 でビジュアルを使用してみましたが、4 つの暗号化された結果は同じですが、元の結果とは異なります。
今、何をテストすればよいか本当にわかりません...Crypto++をC++/CLIプロジェクトにラップして、System.Security.Cryptographyの代わりに使用したくありません。
誰かがアドバイスを持っているか、私が間違っていることを教えてくれますか?
C++ コードは次のとおりです。
void *CryptData(BYTE *bDataIn, LONG lIn, LONG *lOut, byte* key, byte* iv)
{
byte *bIn;
byte *bOut;
LONG l2,lb;
CFB_FIPS_Mode<DES_EDE3>::Encryption encryption_DES_EDE3_CFB;
encryption_DES_EDE3_CFB.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
lb = encryption_DES_EDE3_CFB.MandatoryBlockSize();
l2 = ((lIn + lb - 1)/lb)*lb;
bIn = (byte*)malloc(l2);
bOut = (byte*)malloc(l2);
memset(bIn,0,l2);
memset(bOut,0,l2);
memcpy(bIn,bDataIn,lIn);
encryption_DES_EDE3_CFB.ProcessString(bOut, bIn, l2);
*lOut = l2;
return bOut;
}
C# コードは次のとおりです。
public FibxCrypt()
{
_cryptoAlgo = new TripleDESCryptoServiceProvider();
//_cryptoAlgo.GenerateKey();
_cryptoAlgo.Key = _key;
//_cryptoAlgo.GenerateIV();
_cryptoAlgo.IV = _iv;
_cryptoAlgo.Mode = CipherMode.CFB;
_cryptoAlgo.Padding = PaddingMode.Zeros;
_encoding = new UTF8Encoding();
}
private MemoryStream EncryptingString(string plainText, out long encryptSize)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = _cryptoAlgo.CreateEncryptor();
// Create the streams used for encryption.
//using (MemoryStream msEncrypt = new MemoryStream())
MemoryStream msEncrypt = new MemoryStream();
encryptSize = ((plainText.Length + _cryptoAlgo.FeedbackSize - 1) / _cryptoAlgo.FeedbackSize) * _cryptoAlgo.FeedbackSize;
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt, _encoding))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
// Return the encrypted memory stream.
return msEncrypt;
}
EDIT:ストリームを使用する代わりに、Encryptorを直接使用しようとしましたが、同じ問題が発生しました。
private MemoryStream EncryptingString(string plainText, out long encryptSize)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
ICryptoTransform encryptor = _cryptoAlgo.CreateEncryptor();
byte[] cipherData = encryptor.TransformFinalBlock(
_encoding.GetBytes(plainText), 0, plainText.Length);
// Return the encrypted memory stream.
return msEncrypt;
}