¿Cómo llamar a usar .NET RijndaelManaged desde COM nativo?
¿Puede alguien dar ejemplo de uso para usarSystem.Security.Cryptography.RijndaelManaged
de Win32 nativo utilizando COM?
Aquí hay un ejemplo funcional de cómo usar .NETSystem.Security.Cryptography.SHA256Managed
Nota: Este es un ejemplo de cómo llamar a SHA256Managed, yno RijndaelManaged **. muestro este código para presentar algunos de los conceptos difíciles de llamar a objetos COM con enlace temprano y tardío, y para mostrar que llamar a objetos .NET con envoltorios que se pueden llamar a COMes posible. Algunas personas pueden levantar esas manos al escuchar que quiero mezclar .NET y Win32 COM.
Nota: El lenguaje es Delphi (que es lo que escribí y probé), pero transcodificado para que se parezca un poco más a C # o Java, por lo que la pregunta es más accesible para una audiencia más amplia:
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;
Con la función 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;
La verdadera razón por la que muestro el código llamandoSHA256Managed
es demostrar las dificultades que encuentro al pasararrays
a COM en Delfos. Por ejemplo, si simplemente confiaste enIDispatch
encuadernación tardía
sha: OleVariant;
inputBuffer: OleVariant;
...
sha.TransformFinalBlock(inputBuffer, i, count);
Luego en el tiempo de ejecución se obtieneEl parámetro es incorrecto; algo sobreIDispatch
la vinculación tardía no es compatible con pasar unaOleVariant
eso es una matriz de bytes.
Es por eso que tengo que pasar elsafearray
eso esta dentro deOleVariant
. Como todos sabemosVariante es solo unestructura sindical, donde nos importa elSAFEARRAY
miembro:
data: PSafeArray;
data := PSafeArray(TVarData(inputBuffer).VArray);
sha.TransformFinalBlock(data, i, count);
Excepto tratar de pasar unPSafeArray
utilizandoIDispatch
la unión tardía hace que Delphi vomite:
Tipo no permitido en la llamada de automatización OLE
Por eso nos vemos obligados a abandonar parcialmente.IDispatch
vinculación tardía paraICryptoTransform
encuadernación temprana
ICryptoTransform_Native = interface(IDispatch)
['{8ABAD867-F515-3CF6-BB62-5F0C88B3BB11}']
...
function TransformFinalBlock(inputBuffer: PSafeArray; inputOffset: Integer; inputCount: Integer): PSafeArray; safecall;
...
end;
con
crypto: ICryptoTransform;
sha: OleVariant;
inputBuffer: OleVariant;
crypto = IDispatch(sha) as ICryptoTransform;
crypto.TransformFinalBlock(
PSafeArray(TVarData(inputBuffer).VArray), //inputArray,
i, n);
Así que debería ser eso, ¿verdad? ¿Hemos resuelto cómo pasar matrices a objetos COM .NET? Debería estar todo listo para usarRijndael
ahora; utilizar el enlace temprano conPSafeArray
.
Esto es lo que queremos probar con el enlace tardío:
OleVariant aes := CreateOleObject('System.Security.Cryptography.RijndaelManaged');
OleVariant keyBytes = VarByteArrayOf(Key);
aes.Key := key;
que falla por la misma razón arriba - no puedes pasarOleVariant
Arrays a objetos COM (El parámetro es incorrecto).
Así que deberíamos usar la unión temprana deSymmetricAlgorithm.Key
y pasar elKey
como unPSafeArray
:
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;
Excepto que no hayISymmetricAlgorithm
interfaz; Lo inventé.
Si importa la biblioteca de tipos desdemscorelib.tlb
, que contieneICryptoTransform
, no hay enlace tempranoISymmetricAlgorithm
. Ahíes a con retraso 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;
Entonces, ¿cómo puedo configurar elRijndaelManaged Key
yIV
de nativo Win32 COM? ¿Qué sintaxis de enlace tardío puedo usar?
¿Cómo llamar a usar .NET RijndaelManaged desde COM nativo?
Más intentosDado que no hay un límite tempranointerface
Puedo usar, tengo que concentrarme en cómo pasar una matriz de bytes a través deIDispatch
. El secreto es lo que debe estar en elVariant
que paso al objeto COM.
Desde la versión precoz utilizadasafearrays
, voy a empezar con eso. En primer lugar lo haréa mano conjuntoOleVariant
estructurarme
Para cada uno de los siguientes intentos, se cumple lo siguiente:
key: OleVariant;
data: PSafeArray;
data := PSafeArray(TVarData(keyBytes).VArray);
estableciendo elvariante enumeración yo mismo.
Intento 1: VT_ARRAY
Un puntero de seguridad.
TVarData(key).VType := VT_ARRAY;
TVarData(key).VArray := data;
Intento 2: VT_ARRAY
Un puntero de seguridad.
TVarData(key).VType := VT_ARRAY or VT_I1;
TVarData(key).VArray := data;
Intento 3: VT_SAFEARRAY
Una matriz segura. Usa VT_ARRAY en VARIANT.
TVarData(key).VType := VT_SAFEARRAY or VT_I1;
TVarData(key).VArray := data;
Intento 4: VT_SAFEARRAY
Una matriz segura. Usa VT_ARRAY en VARIANT.
TVarData(key).VType := VT_SAFEARRAY;
TVarData(key).VArray := data;
Todos ellos fallan con unaThe parameter is incorrect
error.
Me da la sensación de queVT_ARRAY
(un safearray) yVT_SAFEARRAY
(un safearray) simplemente no son lo que la interfaz IDispatch del contenedor Callable de COM está preparado para aceptar. Tal vez sea necesarioVT_CARRAY
.
O tal vez no. Tal vez alguien más inteligente que yo pueda resolverlo.
Lectura de bonosEsto es, esencialmente, una reformulación de una pregunta que hice en 2008 en los Grupos de Noticias Borland
¿El compilador de Delphi tiene conocimiento incorporado de COM SafeArrays?
.NET mshtml: ¿Cómo pasar un BSTR SAFEARRAY?