2

System.Security.Cryptography.RijndaelManagedCOMを使用してネイティブ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遅延バインディングを使用して渡そうとすることを除いて、IDispatchDelphi は次のようにスローアップします。

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渡す必要があります。KeyPSafeArray

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 KeyIVネイティブの 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 で尋ねた質問の言い換えです。

Delphi コンパイラには、COM SafeArray の知識が組み込まれていますか?

4

0 に答える 0