谁能给出System.Security.Cryptography.RijndaelManaged
使用 COM 从本机 Win32 使用的示例用法?
这是一个如何使用 .NET 的功能示例System.Security.Cryptography.SHA256Managed
注意:这是一个如何调用 SHA256Managed 的示例,而不是RijndaelManaged**。我展示这段代码是为了介绍一些使用早期和后期绑定调用 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;
我展示代码调用的真正原因SHA256Managed
是为了展示我arrays
在 Delphi 中传递给 COM 时遇到的困难。例如,如果您只是依赖IDispatch
后期绑定:
sha: OleVariant;
inputBuffer: OleVariant;
...
sha.TransformFinalBlock(inputBuffer, i, count);
然后在运行时你得到参数不正确;关于IDispatch
后期绑定的一些东西不支持传递一个OleVariant
字节数组。
safearray
这就是为什么我必须改为传递OleVariant
. 众所周知,Variant只是一个联合结构,我们关心SAFEARRAY
成员:
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
作为 a传递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
(a safearray) 和VT_SAFEARRAY
(a safearray) 并不是 COM 可调用包装器 IDispatch 接口准备接受的。也许它需要VT_CARRAY
。
或者可能不是。也许比我更聪明的人可以弄清楚。
奖金阅读
这本质上是对我 2008 年在 Borland 新闻组上提出的一个问题的重新表述