Como chamar usar .NET RijndaelManaged de COM nativo?
Alguém pode dar exemplo de uso para usarSystem.Security.Cryptography.RijndaelManaged
do nativo Win32 usando COM?
Aqui está um exemplo funcional de como usar o .NETSystem.Security.Cryptography.SHA256Managed
Nota: Este é um exemplo de como chamar SHA256Managed enão RijndaelManaged **. Eu mostro este código para introduzir alguns dos conceitos complicados de chamar objetos COM com vinculação antecipada e tardia e para mostrar que chamando objetos .NET com Wrappers de COMé possível. Algumas pessoas podem vomitar as mãos ao ouvir que eu quero misturar o .NET eo Win32 COM.
Nota: A linguagem é Delphi (que é o que eu escrevi e testei), mas transcodificada para parecer um pouco mais como C # ou Java, então a questão é mais acessível a um público mais amplo:
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;
Com a função auxiliar:
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;
A verdadeira razão pela qual eu mostro o código chamandoSHA256Managed
é demonstrar as dificuldades que estou encontrando ao passararrays
para COM em Delphi. Por exemplo, se você simplesmente confiasseIDispatch
ligação tardia:
sha: OleVariant;
inputBuffer: OleVariant;
...
sha.TransformFinalBlock(inputBuffer, i, count);
Então, em tempo de execução, você obtémO parâmetro está incorreto; algo sobreIDispatch
ligação tardia não suporta passar umOleVariant
isso é uma matriz de bytes.
É por isso que eu tenho que passar pelosafearray
que está dentro doOleVariant
. Como todos nós sabemosVariante é apenas umestrutura sindical, onde nos preocupamos com oSAFEARRAY
membro:
data: PSafeArray;
data := PSafeArray(TVarData(inputBuffer).VArray);
sha.TransformFinalBlock(data, i, count);
Exceto tentando passar umPSafeArray
usandoIDispatch
ligação tardia faz com que o Delphi aumente:
Tipo não permitido na chamada de automação OLE
É por isso que somos forçados a abandonar parcialmenteIDispatch
ligação tardia paraICryptoTransform
ligação antecipada:
ICryptoTransform_Native = interface(IDispatch)
['{8ABAD867-F515-3CF6-BB62-5F0C88B3BB11}']
...
function TransformFinalBlock(inputBuffer: PSafeArray; inputOffset: Integer; inputCount: Integer): PSafeArray; safecall;
...
end;
com
crypto: ICryptoTransform;
sha: OleVariant;
inputBuffer: OleVariant;
crypto = IDispatch(sha) as ICryptoTransform;
crypto.TransformFinalBlock(
PSafeArray(TVarData(inputBuffer).VArray), //inputArray,
i, n);
Então deveria ser isso, certo? Nós resolvemos como passar matrizes para objetos COM .NET? eu deveria estar pronto para usarRijndael
agora; usar ligação inicial comPSafeArray
.
É isso que queremos testar com ligação tardia:
OleVariant aes := CreateOleObject('System.Security.Cryptography.RijndaelManaged');
OleVariant keyBytes = VarByteArrayOf(Key);
aes.Key := key;
que falha pela mesma razão acima - você não pode passarOleVariant
matrizes para objetos COM (o parâmetro está incorreto).
Então nós devemos apenas usar a ligação inicial deSymmetricAlgorithm.Key
e passar oKey
como umPSafeArray
:
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;
Exceto não háISymmetricAlgorithm
interface; eu inventei.
Se você importar a biblioteca de tipos demscorelib.tlb
, que contémICryptoTransform
, não há ligação antecipadaISymmetricAlgorithm
. Láé a atrasado 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;
Então, como posso definir oRijndaelManaged Key
eIV
do nativo Win32 COM? Que sintaxe de ligação tardia posso usar?
Como chamar usar .NET RijndaelManaged de COM nativo?
Outras tentativasComo não há limiteinterface
eu posso usar, eu tenho que focar em como passar uma matriz de bytesIDispatch
. O segredo é o que deveria estar noVariant
que eu passo para o objeto COM.
Desde a versão com ligação inicial usadasafearrays
vou começar com isso. Primeiro de tudo eu voumanualmente conjuntoOleVariant
me estruturar.
Para cada uma das seguintes tentativas, o seguinte é verdadeiro:
key: OleVariant;
data: PSafeArray;
data := PSafeArray(TVarData(keyBytes).VArray);
definindo oenum variante eu mesmo.
Tentativa 1: VT_ARRAY
Um ponteiro SAFEARRAY.
TVarData(key).VType := VT_ARRAY;
TVarData(key).VArray := data;
Tentativa 2: VT_ARRAY
Um ponteiro SAFEARRAY.
TVarData(key).VType := VT_ARRAY or VT_I1;
TVarData(key).VArray := data;
Tentativa 3: VT_SAFEARRAY
Um array seguro. Use VT_ARRAY em VARIANT.
TVarData(key).VType := VT_SAFEARRAY or VT_I1;
TVarData(key).VArray := data;
Tentativa 4: VT_SAFEARRAY
Um array seguro. Use VT_ARRAY em VARIANT.
TVarData(key).VType := VT_SAFEARRAY;
TVarData(key).VArray := data;
Todos eles falham com umThe parameter is incorrect
erro.
Eu tenho a sensação de queVT_ARRAY
(um safearray) eVT_SAFEARRAY
(um safearray) simplesmente não são o que a interface IDispatch do COM Callable wrapper está preparada para aceitar. Talvez precise serVT_CARRAY
.
Ou talvez não. Talvez alguém mais esperto do que eu possa descobrir.
Leitura de bônusEsta é, essencialmente, uma reformulação de uma pergunta que fiz em 2008 sobre os Newsgroups da Borland.
Compilador Delphi tem conhecimento interno de COM SafeArrays?
.Net mshtml: Como passar um SAFEARRAY BSTR?