Jak dzwonić za pomocą .NET RijndaelZarządzany z rodzimego COM?
Czy ktoś może podać przykład użycia do używaniaSystem.Security.Cryptography.RijndaelManaged
z natywnego Win32 przy użyciu COM?
Oto funkcjonalny przykład korzystania z .NETSystem.Security.Cryptography.SHA256Managed
Uwaga: To jest przykład, jak zadzwonić do SHA256Managed inie Rijndael Zarządzane **. pokazuję ten kod, aby przedstawić niektóre z trudnych koncepcji wywoływania obiektów COM z wczesnym i późnym wiązaniem oraz aby pokazać, że wywoływanie obiektów .NET za pomocą COM Callable Wrappersjest możliwy. Niektórzy ludzie mogą rzucić te ręce, słysząc, że chcę połączyć .NET i Win32 COM.
Uwaga: Językiem jest Delphi (to jest to, co napisałem i przetestowałem), ale transkodowane, aby wyglądało nieco bardziej jak C # lub Java, więc pytanie jest bardziej dostępne dla szerszej publiczności:
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;
Z funkcją pomocnika:
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;
Prawdziwy powód, dla którego pokazuję wywołanie koduSHA256Managed
jest pokazanie trudności, które napotykam podczas przechodzeniaarrays
do COM w Delphi. Na przykład, jeśli po prostu polegałeśIDispatch
późne wiązanie:
sha: OleVariant;
inputBuffer: OleVariant;
...
sha.TransformFinalBlock(inputBuffer, i, count);
Następnie w czasie wykonywania otrzymaszParametr jest niepoprawny; coś oIDispatch
późne wiązanie nie wspiera przejściaOleVariant
to jest tablica bajtów.
Dlatego muszę przekazaćsafearray
to jest w środkuOleVariant
. Jak wszyscy wiemyWariant jest po prostustruktura związku, gdzie zależy nam naSAFEARRAY
członek:
data: PSafeArray;
data := PSafeArray(TVarData(inputBuffer).VArray);
sha.TransformFinalBlock(data, i, count);
Z wyjątkiem próby przekazaniaPSafeArray
za pomocąIDispatch
późne wiązanie powoduje, że Delphi rzuca się w górę:
Typ niedozwolony w wywołaniu automatyzacji OLE
Dlatego jesteśmy zmuszeni do częściowego porzuceniaIDispatch
późne wiązanie dlaICryptoTransform
wczesne wiązanie:
ICryptoTransform_Native = interface(IDispatch)
['{8ABAD867-F515-3CF6-BB62-5F0C88B3BB11}']
...
function TransformFinalBlock(inputBuffer: PSafeArray; inputOffset: Integer; inputCount: Integer): PSafeArray; safecall;
...
end;
z
crypto: ICryptoTransform;
sha: OleVariant;
inputBuffer: OleVariant;
crypto = IDispatch(sha) as ICryptoTransform;
crypto.TransformFinalBlock(
PSafeArray(TVarData(inputBuffer).VArray), //inputArray,
i, n);
Więc to powinno być, prawda? Rozwiązaliśmy sposób przekazywania tablic do obiektów COM .NET? powinienem być gotowy do użyciaRijndael
teraz; używaj wczesnego wiązania zPSafeArray
.
To właśnie chcemy wypróbować z późnym wiązaniem:
OleVariant aes := CreateOleObject('System.Security.Cryptography.RijndaelManaged');
OleVariant keyBytes = VarByteArrayOf(Key);
aes.Key := key;
to z tego samego powodu nie powiedzie się - nie możesz przejśćOleVariant
tablice do obiektów COM (parametr jest niepoprawny).
Powinniśmy więc użyć wczesnego wiązaniaSymmetricAlgorithm.Key
i przekazaćKey
jakPSafeArray
:
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;
Z wyjątkiem, że nie maISymmetricAlgorithm
berło; wymyśliłem to.
Jeśli importujesz bibliotekę typów zmscorelib.tlb
, który zawieraICryptoTransform
, nie ma wczesnego wiązaniaISymmetricAlgorithm
. Tamjest a spóźniony 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;
Więc jak mogę ustawićRijndaelManaged Key
iIV
z natywnego Win32 COM? Jakiej późnej składni mogę użyć?
Jak dzwonić za pomocą .NET RijndaelZarządzany z rodzimego COM?
Dalsze próbyPonieważ nie ma wcześniejszego wejściainterface
Mogę użyć, muszę się skupić na tym, jak przekazać tablicę bajtówIDispatch
. Sekret jest tym, co powinno być wVariant
że przechodzę do obiektu COM.
Od czasu użycia wersji wcześniejszejsafearrays
zacznę od tego. Przede wszystkim będęręcznie zestawOleVariant
skonstruować siebie.
Dla każdej z następujących prób obowiązuje:
key: OleVariant;
data: PSafeArray;
data := PSafeArray(TVarData(keyBytes).VArray);
ustawianiewariant enum sam.
Próba 1: VT_ARRAY
Wskaźnik SAFEARRAY.
TVarData(key).VType := VT_ARRAY;
TVarData(key).VArray := data;
Próba 2: VT_ARRAY
Wskaźnik SAFEARRAY.
TVarData(key).VType := VT_ARRAY or VT_I1;
TVarData(key).VArray := data;
Próba 3: VT_SAFEARRAY
Bezpieczna tablica. Użyj VT_ARRAY w VARIANT.
TVarData(key).VType := VT_SAFEARRAY or VT_I1;
TVarData(key).VArray := data;
Próba 4: VT_SAFEARRAY
Bezpieczna tablica. Użyj VT_ARRAY w VARIANT.
TVarData(key).VType := VT_SAFEARRAY;
TVarData(key).VArray := data;
Wszystkie z nich zawodząThe parameter is incorrect
błąd.
Rozumiem toVT_ARRAY
(safearray) iVT_SAFEARRAY
(asekuracja) nie jest tym, co gotowy jest zaakceptować interfejs IDispatch opakowującego COM. Być może tak musi byćVT_CARRAY
.
Albo może nie. Może ktoś mądrzejszy ode mnie może to zrozumieć.
Czytanie premiiJest to zasadniczo powtórzenie pytania, które zadałem w 2008 r. Na temat grup dyskusyjnych Borland
Kompilator Delphi ma wbudowaną znajomość COM SafeArrays?
.NET mshtml: Jak przekazać BSTR SAFEARRAY?