製品のdllの1つを削除し、それを純粋なC#のものに置き換えるという割り当てが与えられました。古いDLLは、Win32ネイティブCryptoAPIへの呼び出しをラップする.NET2.0マネージC++(C ++ \ CLI)です。新しいDLLは、同じ名前とメソッドを持つ新しいオブジェクトを公開する必要がありますが、C#(.NET 4.0)で作成する必要があります。もちろん、新しいDLLは古いDLLと同じ方法で暗号化(および復号化)する必要があります。そうしないと、DBやファイルなどの永続ストレージに保存されているすべての暗号化パスワードが解決されません。
これは、ネイティブ(Win32)API呼び出しの(擬似)コードです(入力は常にUnicodeでエンコードされていることに注意してください)。
//buffer_to_encrypt - Is the input to the following procedure and is the buffer
// to be encrypted using 3DES and the below password to generate a valid 3DES key
// The buffer is Unicode encoded!!!
HCRYPTPROV m_provider = NULL;
HCRYPTHASH m_hash = NULL;
HCRYPTKEY m_key = NULL;
static const unsigned char password[] = {
0xF1, 0x49, 0x4C, 0xD0, 0xC1,
0xE2, 0x1A, 0xEA, 0xFB, 0x34,
0x25, 0x5A, 0x63, 0xA5, 0x29,
0x09, 0x8E, 0xB6, 0x7B, 0x75
}; //20 BYTES password
CryptAcquireContextW( &m_provider, NULL, NULL, PROV_DH_SCHANNEL, CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT);
CryptCreateHash( m_provider, CALG_SHA1, NULL, 0, &m_hash );
CryptHashData( m_hash, password, (DWORD)20, 0 ); //password is a 20Bytes buffer
CryptDeriveKey(m_provider, CALG_3DES, m_hash, CRYPT_EXPORTABLE, &m_key);
CryptEncrypt( m_key.handle(), NULL, TRUE, 0, buffer_to_encrypt, &dwFilled, (DWORD)total );
return buffer_to_encrypt;
今、私は.NET APIによって公開された新しい暗号オブジェクトでC#(System.Security.Cryptography名前空間)を使用して同じプロシージャを作成しようとしています。
class Encryptor
{
private static byte[] password = {
0xF1, 0x49, 0x4C, 0xD0, 0xC1,
0xE2, 0x1A, 0xEA, 0xFB, 0x34,
0x25, 0x5A, 0x63, 0xA5, 0x29,
0x09, 0x8E, 0xB6, 0x7B, 0x75
}; //20 BYTES password, same as the above native code
private static byte[] EncryptInternal(string source)
{
byte[] resultArray = null;
byte[] streamToEncrypt = Encoding.Unicode.GetBytes(source);
using (TripleDESCryptoServiceProvider prov3des = new TripleDESCryptoServiceProvider())
{
prov3des.Mode = CipherMode.ECB;
prov3des.Padding = PaddingMode.PKCS7;
using (PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, null)) //No slat needed here
{
prov3des.Key = pdb.CryptDeriveKey("TripleDES", "SHA1", prov3des.KeySize, ZeroIV);
}
ICryptoTransform cTransform = prov3des.CreateEncryptor();
resultArray = cTransform.TransformFinalBlock(streamToEncrypt, 0, streamToEncrypt.Length);
}
return resultArray;
}
}
ここで私は厄介な問題に直面しています-暗号化された配列(結果の暗号化されたバッファ)は両方の方法を使用して同じではありません!各配列の最初の8バイト(64ビット)は同一ですが、次のバイトは同一ではありません。これにより、短い文字列(最大3文字)は両方の方法を使用して同じように暗号化されますが、長い文字列は異なる暗号化データになります。
2つの方法を強制的に同等にするにはどうすればよいですか?つまり、出力が同じになるように同じ方法で暗号化および復号化するには?ここで何が欠けていますか?.NET APIとネイティブ(Win32)APIの間でデフォルト値\動作に変更はありますか?(Win32 Crypto APIのデフォルトの3DES暗号モードはEBCであると思いますが、C#を使用するデフォルトはCBCです。間違っている場合は修正してください)。
ありがとう!
オムリ