6

ファイルに保存する必要があるデータを暗号化するために、C++ で DPAPI を使用しています。問題は、C# からそのファイルを読み取る必要があるため、次のことができる必要があるということです。

C++ 暗号化、C++ 復号化 (正常に動作しています)

C# 暗号化、C# 復号化 (正常に動作しています)

C++ 暗号化、C# 復号化、およびその逆 (機能しない)

C# では、DllImport を使用してメソッド CryptProtectData と CryptUnprotectData を pInvoke し、こちらで説明されているように実装しています。C# では ProtectedData クラスに含まれるメソッドを使用できることはわかっていますが、両方のコード (c++ と c#) の外観と動作がほぼ同じであることを確認するために、この方法で ( DllImport を使用して) 実行しています。

奇妙なことに、両方のコードが同じように見えても、たとえば次のテキストの場合、異なる出力が得られます。

「プレーンテキスト」

C ++で私は得る:

01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB 01 00 00 00 2E 6F 88 86 E6 16 9B 4F 9B BF 35 DA 9F C6 EC 12 00 000 00 00 02 0 00 03 66 00 00 A8 00 00 00 10 00 00 00 93 06 68 39 DB 58 FE E9 C4 1F B0 3D 7B 0A B7 48 00 00 00 00 04 80 00 00 A0 00 00 00 10 00 00 4 00 84 5A 5A 34 15 97 DC 5B 1F 6C A4 19 D9 10 00 00 00 F5 33 9F 55 49 94 26 54 2B C8 CB 70 7B FE EC 96 14 00 00 00 C5 23 DA BA C8 23 6C 0B B3 88 69 06 200 AE 9 76 A7 63 E4

そしてC#で私は得る:

01 00 00 00 D0 8C 9D DF 01 15 D1 11 8C 7A 00 C0 4F C2 97 EB 01 00 00 00 2E 6F 88 86 E6 16 9B 4F 9B BF 35 DA 9F C6 EC 12 00 000 00 00 02 0 00 03 66 00 00 A8 00 00 00 10 00 00 00 34 C4 40 CD 91 EC 94 66 E5 E9 23 F7 9E 04 9C 83 00 00 00 00 04 80 00 00 A0 00 00 00 10 00 00 4 00 2E 26 12 5 0A D1 11 1D 4D EF 13 1D B2 6F 10 00 00 00 81 9D 46 37 D1 68 5D 17 B8 23 78 48 18 ED 06 ED 14 00 00 00 E4 45 07 1C 08 55 99 80 A4 3 59 BC303 39 05 C4BB

ご覧のとおり、最初の文字は同じですが、残りは同じではありません。そのため、なぜこれが起こっているのかについて誰かが考えている場合は、助けていただければ幸いです.

ありがとう。

C++ のコード:


value = "plain text";
DATA_BLOB DataIn;
DATA_BLOB DataOut;

BYTE *pbDataInput =(BYTE *)(char*)value.c_str();
DWORD cbDataInput = strlen((char *)pbDataInput)+1;
DataIn.pbData = pbDataInput; 
DataIn.cbData = cbDataInput;

CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut))

C# のコード:

(この Microsoft の例と同じなので、私の C# コードがここでどのように見えるかを確認できます)

4

1 に答える 1

5

C++ と C# コードを投稿していただけると助かります。おそらく、微妙なパラメータの違いか、このようなものがあります。たとえば、pOptionalEntropy パラメータが同じであることを確認する必要があります (または NULL に設定して、これがエラー ソースかどうかをテストします)。また、必ず同じ PC で暗号化と復号化を試みてください。

[...]通常、復号化は、データが暗号化されたコンピューターでのみ実行できます

(出典: MSDN )

編集:投稿したコードとMSDNのC#バージョンに関するいくつかのコメント(以下の一部):

public byte[] Encrypt(byte[] plainText, byte[] optionalEntropy) {
  [...]
  int bytesSize = plainText.Length;
  plainTextBlob.pbData = Marshal.AllocHGlobal(bytesSize);
  plainTextBlob.cbData = bytesSize;
  Marshal.Copy(plainText, 0, plainTextBlob.pbData, bytesSize);
  [...]
  dwFlags = CRYPTPROTECT_LOCAL_MACHINE|CRYPTPROTECT_UI_FORBIDDEN;
  [...]
  if(null == optionalEntropy)
  {//Allocate something
  optionalEntropy = new byte[0]; // Is copied to entropyBlob later
  }
  [...]
  retVal = CryptProtectData(ref plainTextBlob, "", ref entropyBlob,    
    IntPtr.Zero, ref prompt, dwFlags, 
    ref cipherTextBlob);
  [...]
}

両方を表示するための C++ コードを次に示します。

[...]
BYTE *pbDataInput =(BYTE *)(char*)value.c_str();
DWORD cbDataInput = strlen((char *)pbDataInput)+1;
[...]
CryptProtectData(&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut))

パラメータが一致しておらず、それが違いの原因だと思います。

まずは旗です。C# コードは dwFlags != 0 を使用し、C++ コードは dwFlags = 0 を使用するため、これは明らかに違いです。

エントロピーについてはわかりません。optionalEntropy = null を渡さなかった場合は違いますが、null の場合は "new byte[0]" 割り当てがあり、これが何を作成するかはわかりませんが、少なくとも試してみるべきだと思いますC++ コードと一致するように、entropyBlob の代わりに IntPtr.Zero を CryptProtectData に渡します。

最後になりましたが、重要なことですが、C++ コードには、C 文字列を区切る末尾の NUL が含まれています。ここで使用されている暗号化がどのように機能するかはわかりませんが、1 バイトが異なる場合 (またはこの場合のようにもう 1 バイト)、C# コードに終了 NUL を含めるか、C++ コードでそれを削除する必要があります。

于 2009-09-18T22:27:26.497 に答える