Re: How to pass a vc++ BSTR value to C#.Net





"shamsh" <shamsh0@xxxxxxxxxxxxx> wrote in message news:EB0B97AA-993D-4ED0-9688-CB91684DCAEE@xxxxxxxxxxxxxxxx
Let me put the whole scenario for you.
Currently the whole application is using this COM DLL which has function for
encryption/decryption.We are in process of converting lot of business object
to .Net and some will remain as it is in C++.We also have a equivalent .Net
code for encryption/decryption.
So we might have a suitation where an encryption might take place using COM
and decryption using .Net.
Thats the reason for not changing the signature of the function.
The C++ caller function need not bother about the binary data being
converted to BSTR ,it should be happy if it is getting an encrypted string
from the COM.

Actually I'm able to return the binary data in the form of BSTR by using
CCOMBSTR,but at .Net side while
decrypting(rsacryptoserviceprovider.decrypt()) is either giving "Bad Data" or
the number of bytes is more than 128 for which the rsa modulus doesn't
support.

This whole thing works perfectly if I write the encrypyed text(binary data)
at COM end to a .txt file and at the C# end read that binary file for
decryption.

Let me know if I was able to communicate your doubts,or if you want the
whole code.

You haven't really addressed the point on which I'm confused (side note: Who is teaching foreign students of English to use the word "doubt" when they mean "question"? I hear this mistake everywhere.)

Encryption of a string doesn't give you another string. It gives you binary data. So it's not appropriate for the C++ clients to be using BSTR either, everything should be SAFEARRAY(VT_UI1). Unless the interface was originally designed for strings and encryption was added later, in which case using the BSTR capability of having embedded nulls seems a reasonable way to avoid a breaking change to the interface. .NET is still going to have problems though, because .NET supports a subset of the BSTR concept which doesn't include the BSTR as a counted array of bytes.

So maybe a good option would be for the interface to go ahead an return a BSTR (counted array of bytes format), and provide a conversion function, not used by the C++ callers, which turns that BSTR into a SAFEARRAY(VT_UI1) or even directly into a .NET managed byte array. This could even be implemented in C# if desired. Just use IntPtr to hold the BSTR, call SysStringByteLen and use pointers or Marshal.Copy to transfer into a real byte array.

http://msdn.microsoft.com/en-us/library/ms146631.aspx




--
regards,
Shamsheer


"Ben Voigt [C++ MVP]" wrote:



"shamsh" <shamsh0@xxxxxxxxxxxxx> wrote in message
news:00E7F2AB-DF71-4257-80CD-7E6D54D6C6D5@xxxxxxxxxxxxxxxx
> I cannot pass the byteArray as it is from the C++ function as I'm not
> suposed
> to change the function signature(it is being called throughout the
> application).So I need to convert the byteArray to BSTR.

You can't change the signature because it would mess up other callers, but
you can add/change the conversion to BSTR? This doesn't make any sense to
me. Are you implementing an interface, the other providers of which are
really returning text strings and you need to return binary data instead?
In that case using the same interface is probably not the best idea because
you're violating the LSP in subtle ways.

> I'm very new to C++ code.Can you please provide the sample code.
> Moreover at C# end I need to do some kind of encoding to convert the
> encrypted string coming from C++ to, byteArray.
>
> -- > regards,
> Shamsheer
>
>
> "Ben Voigt [C++ MVP]" wrote:
>
>> shamsh wrote:
>> > I'm doing something like
>> > STDMETHODIMP CSecMgr::Encrypt(BSTR bstrEncryptText, BSTR*
>> > pbstrResultText) {
>> > // Encrypt data
>> > if (!CryptEncrypt(hKey, NULL, TRUE, 0, pbData, >> > &dwDataLen,
>> > dwEncryptedLen))
>> > {
>> > // Error
>> > _tprintf(_T("CryptEncrypt error 0x%x\n"),
>> > GetLastError()); return 1;
>> > }
>> >
>> > }
>> >
>> > I'm able to write (LPCVOID)pbData to a .txt file(binary) and at C#
>> > end I'm able to decrypt it back.
>> > Instead of writing it to a .txt file I'm supposed to make it as a
>> > return type. I'm doing something like
>> >
>> > char *pStr = new char[dwDataLen];
>> > memcpy(pStr, pbData, dwDataLen );
>> > //pStr[dwDataLen] = '\0';
>> > CString str(pStr);
>> > //delete [] pStr;
>> >
>> > //*pbstrResultText = CComBSTR(str); //BSTR(str.AllocSysString());
>> > tried this option
>> > *pbstrResultText = SysAllocStringByteLen(pStr,dwDataLen); // this >> > one
>> > also
>> >
>> > At the C#.net end
>> >
>> > public static string DecryptData(string data2Decrypt)
>> >
>> > {
>> >
>> > byte[] encryptedData = >> > StrToByteArray(data2Decrypt);
>> >
>> > // some other steps
>> >
>> > byte[] decryptedText = rsa.Decrypt(encryptedData,
>> > false); // This either gives BAD Data or size related error
>> > }
>> > public static byte[] StrToByteArray(string
>> > str) {
>> > System.Text.ASCIIEncoding encoding = new
>> > System.Text.ASCIIEncoding();
>> > return encoding.GetBytes(str);
>> > }
>>
>> Well, you don't want the ASCII encoding. You don't want any encoding >> at
>> all
>> (SysAllocStringByteLen works on raw bytes). It so happens that
>> Encoding.UnicodeEncoding is the "no translation" option.
>>
>> But you really should be passing a byte array because that's what you
>> have.
>> COM supports byte arrays, the C++ would be SAFEARRAY. Just do
>> SafeArrayCreateVector(VT_UI1, 0, length);SafeArrayAccessDatamemcpy or
>> directly perform your calculations into the array data
>> areaSafeArrayUnaccessData
>>
>>
>>
.



Relevant Pages

  • Re: How to pass a vc++ BSTR value to C#.Net
    ... in C++ which will convert BSTR into a SAFEARRAY. ... Encryption of a string doesn't give you another string. ... BSTR (counted array of bytes format), and provide a conversion function, not ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Signing binary data with CAPICOM
    ... You can place binary data in to the BSTR you are passing to CAPICOM. ... By definition this is a Unicode string. ...
    (microsoft.public.platformsdk.security)
  • Re: How to decrypt a string?
    ... converting a string to another string. ... No. Encryption works on binary data, and it's not safe to treat ...
    (microsoft.public.dotnet.framework)
  • Re: extended chars and a web service
    ... which can be represented as a string but seem to give a validation error ... >> When I send encrypted character to this web service ... > Encryption usually results in binary data rather than string data, ... > you shouldn't be passing binary data as if it were string data. ...
    (microsoft.public.dotnet.framework.webservices)
  • Re: TripleDES output size
    ... it is possible to securely encrypt a printable string to ... If you convert from your binary data to string with Base64 (which is ... I indeed use unicode encoding to feed the encryption provider and then ...
    (microsoft.public.dotnet.security)

Quantcast