-->

如何从本地COM调用.NET使用RijndaelManaged的?(How to call use

2019-06-27 01:51发布

谁能给用法示例使用System.Security.Cryptography.RijndaelManaged使用COM从本地Win32?


下面是如何使用.NET的功能例如System.Security.Cryptography.SHA256Managed

:这是如何调用SHA256Managed一个例子,而不是 RijndaelManaged的**。 我显示此代码来介绍一些调用COM对象与棘手的概念,早期和晚期绑定,并表明与调用COM调用包装.NET对象可能的。 有些人可能会扔了那听到的时候我的手想混合.NET和Win32 COM。

注:语言是德尔福(这是我写的和测试它),而转码,使它看上去稍微更象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;

真正的原因我展示的代码调用SHA256Managed是证明通过当我遇到困难arrays ,以COM在Delphi中。 例如,如果你单纯倚重IDispatch后期绑定:

sha: OleVariant;
inputBuffer: OleVariant;
...
sha.TransformFinalBlock(inputBuffer, i, count);

然后,在运行时,你得到的参数不正确 ; 一些关于IDispatch后期绑定不支持将一个OleVariant是字节数组。

这就是为什么我要,而不是通过safearray是内部OleVariant 。 正如我们都知道的一个变体仅仅是一个联合结构 ,我们关心的SAFEARRAY成员:

data: PSafeArray;

data := PSafeArray(TVarData(inputBuffer).VArray);
sha.TransformFinalBlock(data, i, count);

除了试图通过一个PSafeArray使用IDispatch后期绑定的原因德尔福投掷了:

不允许的类型在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 (一个SAFEARRAY)和VT_SAFEARRAY (一个SAFEARRAY)绝对不会和COM调用包装IDispatch接口就是准备接受。 也许它需要VT_CARRAY

或者可能不是。 也许有人比我聪明可以计算出来。

奖金阅读

这是本质上,我提出的问题在2008年Borland的新闻组的重新措辞

Delphi编译器已经内置的COM SAFEARRAYS的知识呢?

  • .NET MSHTML:如何通过一个BSTR SAFEARRAY?
文章来源: How to call use .NET RijndaelManaged from native COM?