¿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 intentos

Dado 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 bonos

Esto 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?

Respuestas a la pregunta(0)

Su respuesta a la pregunta