3

ここに私の問題があります: 私は 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;
}
4

2 に答える 2

1

変更した FeedBackSize は、操作の CFB モードに関連しています ( msdn ドキュメント)。したがって、C++ と C# のフィードバック サイズが同じであることも確認する必要があります。

あなたのバグは、C++ コードと C# コードの間の BlockSizes が悪意を持っている可能性があると思います。C# 実装で BlockSize = 8 を設定しようとしましたか?

于 2013-06-14T15:40:06.123 に答える