System.Security.Cryptography.RijndaelManaged
COMを使用してネイティブWin32から使用するための使用例を誰か教えてもらえますか?
.NET の使用方法の機能例を次に示します。System.Security.Cryptography.SHA256Managed
注: これは、 RijndaelManaged**ではなく、SHA256Managed を呼び出す方法の例です。このコードを示して、アーリー バインディングとレイト バインディングを使用した COM オブジェクトの呼び出しに関するいくつかのトリッキーな概念を紹介し、COM 呼び出し可能ラッパーを使用して .NET オブジェクトを呼び出すことが可能であることを示します。.NET と Win32 COM を混在させたいと聞いて手を挙げてしまう人もいるかもしれません。
注:言語は Delphi (私が書いてテストしたもの) ですが、C# や Java のように見えるようにトランスコードされているため、より幅広い聴衆が質問にアクセスしやすくなっています。
public static string HashStr256(String szPlaintext)
{
OleVariant sha = CreateOleObject('System.Security.Cryptography.SHA256Managed');
OleVariant inputBuffer = VarByteArrayOf(szPlaintext);
Integer l = VarArrayLowBound(inputBuffer, 1);
Integer h = VarArrayHighBound(inputBuffer, 1);
ICryptoTransform crypto = IDispatch(sha) as ICryptoTransform;
crypto.TransformFinalBlock(
PSafeArray(TVarData(inputBuffer).VArray), //inputArray,
l, //input array offset
h-l+1); //input array count
OleVariant digest := sha.Hash;
Result := ToBase64String(BytesOfVarByteArray(digest));
end;
ヘルパー関数を使用:
function VarByteArrayOf(const s: string): OleVariant;
var
Data: Pointer;
begin
//Create variant byte array to hold the bytes
Result := VarArrayCreate([0, Length(s)-1], varByte);
//Copy from Delphi array to Variant Array
if Length(s) > 0 then
begin
Data := VarArrayLock(Result);
try
System.Move(s[1], Data^, Length(s));
finally
VarArrayUnlock(Result);
end;
end;
end;
コード呼び出しを表示する本当の理由は、Delphi で COMSHA256Managed
に渡すときに遭遇する問題を示すためです。arrays
たとえば、単純にIDispatch
遅延バインディングに依存している場合:
sha: OleVariant;
inputBuffer: OleVariant;
...
sha.TransformFinalBlock(inputBuffer, i, count);
次に、実行時にThe parameter is wrong ;を取得します。遅延バインディングに関する何かは、バイト配列であるIDispatch
を渡すことをサポートしていません。OleVariant
そのため、代わりに のsafearray
中にある を渡す必要がありOleVariant
ます。ご存知のように、Variantは単なるunion structureSAFEARRAY
であり、メンバーを気にします。
data: PSafeArray;
data := PSafeArray(TVarData(inputBuffer).VArray);
sha.TransformFinalBlock(data, i, count);
PSafeArray
遅延バインディングを使用して渡そうとすることを除いて、IDispatch
Delphi は次のようにスローアップします。
OLE オートメーション呼び出しでは型を使用できません
これが、早期バインディングIDispatch
のために遅延バインディングを部分的に放棄せざるを得ない理由です。ICryptoTransform
ICryptoTransform_Native = interface(IDispatch)
['{8ABAD867-F515-3CF6-BB62-5F0C88B3BB11}']
...
function TransformFinalBlock(inputBuffer: PSafeArray; inputOffset: Integer; inputCount: Integer): PSafeArray; safecall;
...
end;
と
crypto: ICryptoTransform;
sha: OleVariant;
inputBuffer: OleVariant;
crypto = IDispatch(sha) as ICryptoTransform;
crypto.TransformFinalBlock(
PSafeArray(TVarData(inputBuffer).VArray), //inputArray,
i, n);
それで、それでいいですよね?配列を COM .NET オブジェクトに渡す方法は解決しましたか? これで使用する準備が整いましたRijndael
。で事前バインディングを使用しPSafeArray
ます。
これは、遅延バインディングで試したいことです。
OleVariant aes := CreateOleObject('System.Security.Cryptography.RijndaelManaged');
OleVariant keyBytes = VarByteArrayOf(Key);
aes.Key := key;
上記と同じ理由で失敗します-OleVariant
配列をCOMオブジェクトに渡すことができません(パラメーターが正しくありません)。
したがって、 の事前バインディングを使用して、を としてSymmetricAlgorithm.Key
渡す必要があります。Key
PSafeArray
var
symmetric: ISymmetricAlgorithm;
aes: OleVariant;
keyBytes: OleVariant;
begin
aes := CreateOleObject('System.Security.Cryptography.RijndaelManaged');
symmetric:= (IDispatch(aes) as ISymmetricAlgorithm;
symmetric.Key := PSafeArray(TVarData(inputBuffer).VArray);
...
end;
ISymmetricAlgorithm
インターフェイスがないことを除いて。私はそれを作りました。
mscorelib.tlb
を含むからタイプ ライブラリをインポートする場合、事前ICryptoTransform
バインディングはありませんISymmetricAlgorithm
。レイト バウンドがあります。 ISymmetricAlgorithm
IID__SymmetricAlgorithm: TGUID = '{05BC0E38-7136-3825-9E34-26C1CF2142C9}';
CLASS_SymmetricAlgorithm: TGUID = '{5B67EA6B-D85D-3F48-86D2-8581DB230C43}';
_SymmetricAlgorithm = interface;
SymmetricAlgorithm = _SymmetricAlgorithm;
_SymmetricAlgorithm = interface(IDispatch)
['{05BC0E38-7136-3825-9E34-26C1CF2142C9}']
end;
_SymmetricAlgorithmDisp = dispinterface
['{05BC0E38-7136-3825-9E34-26C1CF2142C9}']
end;
では、 RijndaelManaged Key
をIV
ネイティブの Win32 COM から設定するにはどうすればよいでしょうか。どの遅延バインディング構文を使用できますか?
ネイティブ COM から .NET RijndaelManaged を呼び出す方法は?
さらなる試み
使用できるアーリー バインドがないためinterface
、バイト配列を渡す方法に集中する必要がありますIDispatch
。秘密はVariant
、COM オブジェクトに渡す必要があるものです。
初期バインド版が使用されているので、それからsafearrays
始めます。まず、自分で構造を手動で設定します。OleVariant
次の試行のそれぞれについて、次のことが当てはまります。
key: OleVariant;
data: PSafeArray;
data := PSafeArray(TVarData(keyBytes).VArray);
バリアント列挙型を自分で設定します。
試行 1 :
VT_ARRAY
SAFEARRAY ポインター。TVarData(key).VType := VT_ARRAY; TVarData(key).VArray := data;
試行 2 :
VT_ARRAY
SAFEARRAY ポインター。TVarData(key).VType := VT_ARRAY or VT_I1; TVarData(key).VArray := data;
試行 3 :
VT_SAFEARRAY
安全な配列。VARIANT で VT_ARRAY を使用します。TVarData(key).VType := VT_SAFEARRAY or VT_I1; TVarData(key).VArray := data;
試行 4 :
VT_SAFEARRAY
安全な配列。VARIANT で VT_ARRAY を使用します。TVarData(key).VType := VT_SAFEARRAY; TVarData(key).VArray := data;
それらはすべてエラーで失敗しThe parameter is incorrect
ます。
VT_ARRAY
(セーフ配列) とVT_SAFEARRAY
(セーフ配列) は、COM Callable ラッパーの IDispatch インターフェイスが受け入れる準備ができているものではないことがわかります。おそらくそれはする必要がありますVT_CARRAY
。
またはそうでないかもしれません。私より頭のいい人なら解るかもしれません。
ボーナスリーディング
これは基本的に、私が 2008 年に Borland Newsgroups で尋ねた質問の言い換えです。