|
You code sample is what I was looking for. I have some questions if you don't mind.
Can I replace LPCBYTE with BYTE*
I added odbcss.h, but it adds a bunch of sql server stuff that I don't need.
Would Password be my KEY_192 with 24 bytes?
So I can add my IV_192 using CreateKeyParam?
|
|
|
|
|
jkirkerx wrote: You code sample is what I was looking for.
Great.
jkirkerx wrote: Can I replace LPCBYTE with BYTE*
Yes, you could do that. LPCBYTE is a Long Pointer to a Const[^] BYTE. It is good programming practice to pass a variable as constant if you do not want the variable to be modified. You have my permission to be a rogue programmer.
jkirkerx wrote: I added odbcss.h, but it adds a bunch of sql server stuff that I don't need.
Ok.
jkirkerx wrote: Would Password be my KEY_192 with 24 bytes?
So I can add my IV_192 using CreateKeyParam?
I read C/C++ better than I read English even though it is my native language. Show me some code.
Best Wishes,
-David Delaune
|
|
|
|
|
The asp.net version of the program used a key pair. Your example is very similar to what I wrote the 4th time, except you had the Base64 piece that I needed.
So in my 4th version, I had the CryptSetKeyParam to enter the IV for the symmetric key, to complete the pair, but in all honestly, I'm not really sure how it's used, because the asp.net version feed both into a function, and the underlying functionality was hidden.
Side question, How do get the length of a BYTE* for pwlen
BYTE KEY_192[24] = {42, 16, 93, 156, 78, 4, ...
BYTE IV_192[24] = {55, 103, 246, 79, 36, ...
CryptAcquireContext(&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, 0);
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, KEY_192, pwlen would be 24, 0);
CryptDeriveKey(hProv, CALG_3DES, hHash, 0, &hKey);
CryptSetKeyParam(hKey, KP_IV, IV_192, 0);
I like the idea of a definable password, so each copy of my program can have it's own unique key.
hmm.
|
|
|
|
|
jkirkerx wrote: Your example is very similar to what I wrote the 4th time, except you had the Base64 piece that I needed.
Great.
jkirkerx wrote: Side question, How do get the length of a BYTE* for pwlen
A BYTE is an unsigned char and typically for normal NULL terminated strings you would use strlen[^] or _tcslen[^] for obtaining the length of the string excluding the NULL terminator. This would be very common for username/password/key string variables.
However... in your case you are passing a constant array of BYTE so you could use the sizeof operator[^] to get the length in bytes.
CryptHashData(hHash, KEY_192, sizeof(KEY_192), 0);
I do not see anything wrong with the CryptSetKeyParam function you have shown. Are you receiving an error here?
Best Wishes,
-David Delaune
|
|
|
|
|
I went back to what I had before I posted, and changed CALG_DES to CALG_MD5. I don't get an error, , I'm just struggling in making my buffer that passes in/out in CryptEncrypt.
I get a value back that's sort or weird. It works, but I think the size of my buffer is too large.
Rã¾Î‚ò.¢Ó`Ï<oÝV|63¾ˆWãÔZ÷(šœ(è~Ó¥¶ãòõ¬"oÌtðaÏMûÏþƒÝÌXðýýýý««««««««îþîþîþîþîþîþ
I think the end in bold is a leak somewhere, or the buffer being too large
I know I need to CryptEncrypt once to get the buffer size, and do it again for the real thing.
I did a conversion to UTF8, that I think I need to dump. I'm going to dump it, and work on the buffer sizing.
This is what I had before I posted, with the one small change. It's not bad considering I had no clue what to do, but it's all I need, with the base64 at the end of the gig.
WCHAR* CA_Encryption::_encrypt_DES( WCHAR *pzInput )
{
BOOL bResult = FALSE;
WCHAR *szOutput = NULL;
DWORD cbKey64 = sizeof(KEY_64);
HCRYPTPROV hProv;
HCRYPTHASH hHash = NULL;
HCRYPTKEY hKey = NULL;
const int DES_SIZE = 64;
static BYTE hash[DES_SIZE];
DWORD buffer_size = sizeof(hash);
DWORD buffer_length;
int iChar = WideCharToMultiByte(CP_UTF8, 0, pzInput, -1, NULL, 0, NULL, NULL);
char *szInput = new char[iChar];
WideCharToMultiByte(CP_UTF8, 0, pzInput, -1, szInput, iChar, NULL, NULL);
bResult = CryptAcquireContextW( &hProv, 0, MS_STRONG_PROV, PROV_RSA_FULL, 0);
bResult = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
bResult = CryptHashData(hHash, KEY_64, sizeof(KEY_64), 0);
bResult = CryptDeriveKey(hProv, CALG_DES, hHash, 0, &hKey);
bResult = CryptSetKeyParam(hKey, KP_IV, IV_64, 0);
buffer_length = strlen((char *)szInput);
BYTE *szBuffer = new BYTE[64];
memcpy( szBuffer, (BYTE*)szInput, sizeof(szInput) );
delete [] szInput;
bResult = CryptEncrypt(hKey, 0, FALSE, 0, szBuffer, &buffer_size, buffer_length);
CryptDestroyKey(hKey);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return szOutput;
}
This is what I'm trying to copy from asp.net
Public Shared Function Encrypt(ByVal value As String) As String
If value <> "" Then
Dim cryptoProvider As DESCryptoServiceProvider = New DESCryptoServiceProvider()
Dim ms As MemoryStream = New MemoryStream()
Dim cs As CryptoStream = New CryptoStream(ms, cryptoProvider.CreateEncryptor(KEY_64, IV_64), _
CryptoStreamMode.Write)
Dim sw As StreamWriter = New StreamWriter(cs)
sw.Write(value)
sw.Flush()
cs.FlushFinalBlock()
ms.Flush()
Return Convert.ToBase64String(ms.GetBuffer(), 0, ms.Length)
Else
Encrypt = ""
End If
End Function
|
|
|
|
|
jkirkerx wrote: I get a value back that's sort or weird. It works, but I think the size of my buffer is too large.
Rã¾Î‚ò.¢Ó`Ï<oÝV|63¾ˆWãÔZ÷(šœ(è~Ó¥¶ãòõ¬"oÌtðaÏMûÏþƒÝÌXðýýýý««««««««îþîþîþîþîþîþ
I actually recognize those bytes.... the ýýýý are 0xFD and called Guard Bytes. This is how Visual Studio detects when you overwrite a buffer. It checks to see if they are still there.
The next bytes are: «««««««« and are created by HeapAlloc and we call them 0xAB 'No Man's Land' Guard Bytes.
The last bytes are: îþîþîþîþîþîþ are 0xFE and indicate a region of Freed Heap memory.
Think about this for 3 seconds... why do you think you see this wierdness? You see this because 'C' strings are supposed to be NULL terminated. The encrypted memory you just created has no NULL terminator so the Visual Studio debugger shows you the entire contents...
You can fix this by adding this immediately after your CryptEncrypt function call.
szBuffer[buffer_size] = 0;
This will allow Visual Studio to properly display the encrypted bytes as a NULL terminated string.
But by writing a zero there... you just overwrote 1 0xFD guard byte. So don't do it. Heh, I knew you were a rogue software engineer all along.
Btw, congratulations... this code looks like it would actually work correctly. You should probably add more error handling and clean it up a bit but looks OK.
Don't forget to sanitize your buffers with the SecureZeroMemory[^]. Otherwise EvilHacker1337 might be able to retrieve stale memory contents to retrieve sensitive data. (Looks like your key is hard-coded so its not like it would help much anyway)
Best Wishes,
-David Delaune
|
|
|
|
|
I'm trying to get a perfect match on my encryption program, so it matches my asp.net version. It looks like the code you approved actually works correctly, and I'm down to the Base64 part.
Is there a difference between your Base64Encode function and the function on this page?
http://msdn.microsoft.com/en-us/library/dhx0d524.aspx[^]
When looking at CryptBinaryToString, I'm not sure if it implies take a encryptedbinary and convert it to string, or encrypt a binary and convert to string.
|
|
|
|
|
Hey there,
jkirkerx wrote: I'm trying to get a perfect match on my encryption program, so it matches my asp.net version. It looks like the code you approved actually works correctly, and I'm down to the Base64 part.
Excellent.
jkirkerx wrote: Is there a difference between your Base64Encode function and the function on this page?
http://msdn.microsoft.com/en-us/library/dhx0d524.aspx[^]
If you are referring to the code sample in this post: Re: decrypting question[^]
Yeah... I remember helping that guy over a number of weeks and he was complaining about the Microsoft CryptBinaryToString function[^] appending two characters... a carriage return [CR] and line feed [LF] ... so the code sample I provided him removed those characters.
This would probably cause your strings to not match if the ASP version is doing the same... this is the code that removes the CRLF:
TCHAR pByteLF = *(LPWORD)(lpszBase64 + dwResult -1);
TCHAR pByteCR = *(LPWORD)(lpszBase64 + dwResult -2);
if(pByteCR == 0x0D && pByteLF == 0x0A)
{
*(LPWORD)(lpszBase64 + dwResult -2) = 0;
}
It looks like I was planning on making it optional to strip those characters... if you look at the function it contains a BOOL bStripCRLF
You could probably just finish the functionality that I left incomplete...
if(TRUE == bStripCRLF)
{
TCHAR pByteLF = *(LPWORD)(lpszBase64 + dwResult -1);
TCHAR pByteCR = *(LPWORD)(lpszBase64 + dwResult -2);
if(pByteCR == 0x0D && pByteLF == 0x0A)
{
*(LPWORD)(lpszBase64 + dwResult -2) = 0;
}
}
Today is Saturday so I will be coding for the next few hours. If you like... show me a sample with key, initialization vector, and output along with desired output. Don't post the key you intend to use in final production. With this I might be able to see what is causing any discrepancies.
Best Wishes,
-David Delaune
|
|
|
|
|
Sorry for the late reply, I wanted to eliminate as many possibilities as I could.
Well, this requires an expert in encryption, only because I want to match a asp.net result. Otherwise I would just go with it, and be a happy camper. It's beyond my skill level.
The base 64 seems fine.
It's either this MS_ENHANCED_PROV, PROV_RSA_FULL, or the key not being in the right format, or perhaps 5 other possibilities.
This is really important to me, I need it to support another program I wrote.
I have an easy to load sample that is fully documented, with notes from the asp.net side.
|
|
|
|
|
Hi,
Wow, what time zone are you in? The sun was rising out in the Atlantic ocean when you responded.
jkirkerx wrote: It's either this MS_ENHANCED_PROV, PROV_RSA_FULL, or the key not being in the right format, or perhaps 5 other possibilities.
Your not giving enough information... you need to tell me exactly which algorithm is not returning the expected value. The DES, 3DES, MD5 and Base64 algorithms are very standard... the only thing that would make them return an unexpected value... is an initialization vector or hash salt.
If you control both the ASP.NET and C++ source codes... could you step through a debugger in both and determine exactly which algorithm returns a different value?
The CryptSetKeyParam function[^] with either KP_SALT, KP_SALT_EX, KP_IV would potentially cause an encryption/hash algorithm to return an unexpected value. This is exactly what it is suppose to do...
You need to make sure salt and initialization vectors are the same in both your ASP.NET and C++ implementations.
Best Wishes,
-David Delaune
[EDIT]
I just recieved and read your e-mail. I'll take a look the source code you provided and we can correspond through e-mail from here. -Dave
modified 18-Dec-11 11:36am.
|
|
|
|
|
I'm in Huntington Beach CA. I think I'm the only programer in the city.
I was determined to figure it out last night, and went through it with a magnifying glass. Before I crashed, I decided that I should try to write the encryption in vb, so I just converted the one I used to this one that makes more sense to me. The new function produces the same result as the old function to the tee.
Old Function
Public Shared Function Encrypt(ByVal value As String) As String
If value <> "" Then
Dim cryptoProvider As DESCryptoServiceProvider = New DESCryptoServiceProvider()
Dim ms As MemoryStream = New MemoryStream()
Dim cs As CryptoStream = New CryptoStream(ms, cryptoProvider.CreateEncryptor(KEY_64, IV_64), _
CryptoStreamMode.Write)
Dim sw As StreamWriter = New StreamWriter(cs)
sw.Write(value)
sw.Flush()
cs.FlushFinalBlock()
ms.Flush()
Return Convert.ToBase64String(ms.GetBuffer(), 0, ms.Length)
Else
Encrypt = ""
End If
End Function
New Function
Public Shared Function _encrypt_DES(ByVal szInputW As String) As String
Dim szOutput As String = Nothing
Dim szBufferIn() As Byte = Nothing
Dim szBufferOut() As Byte = Nothing
If szInputW <> "" Then
Dim cryptoProvider As DESCryptoServiceProvider = New DESCryptoServiceProvider()
With cryptoProvider
.BlockSize = 64
.FeedbackSize = 8
.Key = KEY_64
.IV = IV_64
.Mode = CipherMode.CBC
.Padding = PaddingMode.PKCS7
End With
Dim symAlg As SymmetricAlgorithm = cryptoProvider
Dim xfrm As ICryptoTransform = Nothing
szBufferIn = UTF8Encoding.UTF8.GetBytes(szInputW)
xfrm = symAlg.CreateEncryptor()
szBufferOut = xfrm.TransformFinalBlock(szBufferIn, 0, szBufferIn.Length)
szOutput = Convert.ToBase64String(szBufferOut, 0, szBufferOut.Length)
Else
szOutput = ""
End If
Return szOutput
End Function
I think this is the part I'm missing in my c++ version, perhaps only the final block of the buffer byte array is being run with base64 to create the final encryption product.
szBufferOut = xfrm.TransformFinalBlock(szBufferIn, 0, szBufferIn.Length)
|
|
|
|
|
Sorry for the late reply, I was watching the New Orleans Saints defeat the Minnesota Vikings.
jkirkerx wrote: .Padding = PaddingMode.PKCS7
This is one of the reasons why you are getting a different result in your C++ code. I believe the C++ code is defaulting to PKCS5. Your .NET code is using PKCS7.
You can confirm this by querying your key parameters in your C++ project before you perform the encryption:
DWORD dwPadding = 0;
DWORD dwLength = sizeof(DWORD);
bResult = CryptGetKeyParam(hKey,KP_PADDING,(BYTE *)&dwPadding,&dwLength,0);
Yes... the wierd casts to BYTE * are necessary... these Microsoft cryptography functions are designed to accept BYTE * even though some calls want DWORD *
The value of dwPadding after this call will be 0x1 which == PKCS5_PADDING confirming that your C++ code defaults to PKCS5.
Everything in here must match your C++ code and vice-versa.
Your VB Code:
Dim cryptoProvider As DESCryptoServiceProvider = New DESCryptoServiceProvider()
With cryptoProvider
.BlockSize = 64
.FeedbackSize = 8
.Key = KEY_64
.IV = IV_64
.Mode = CipherMode.CBC
.Padding = PaddingMode.PKCS7
End With
In your C++ code you need to set these parameters to exactly match your .NET implementation.... here are a few:
Set mode to CBC:
DWORD dwMode = CRYPT_MODE_CBC;
bResult = CryptSetKeyParam(hKey, KP_MODE,(BYTE *)&dwMode, 0);
Set the Padding:
DWORD dwPadding = PKCS5_PADDING;
bResult = CryptSetKeyParam(hKey, KP_PADDING,(BYTE *)&dwPadding, 0);
Set the initialization vector:
BYTE IV_64[8] = {1, 2, 3, 4, 5, 6, 7, 8}; CryptSetKeyParam(hKey, KP_IV, IV_64, 0);
Set the feedback:
DWORD dwFeedback = 8;
bResult = CryptSetKeyParam(hKey, KP_MODE_BITS,(BYTE *)&dwFeedback, 0);
By the way... I am fairly certain that setting the feedback value has no effect when using the CBC mode...
Set the Block length:
DWORD dwBlockLength = 64;
bResult = CryptSetKeyParam(hKey, KP_BLOCKLEN,(BYTE *)&dwBlockLength, 0);
If you get all of the settings to match... the values you get out of the C++ code should perfectly match the values you get from the .NET code.
Btw, I don't think the default Microsoft provider supports PKCS7 padding... I believe the .NET framework uses its own provider. You will probably need to change your .NET padding to something both providers support.
Thats all I can think of for now.
Best Wishes,
-David Delaune
modified 18-Dec-11 17:51pm.
|
|
|
|
|
I give up.
After all that writing, only PKCS5 is available in c++, and only PKCS7 is asp.net
There are comments about 7 in wincrypt.h, but I'm not sure what it means.
bResult = CryptAcquireContextW( &hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, 0);
bResult = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
bResult = CryptHashData(hHash, KEY_64, sizeof(KEY_64), 0);
bResult = CryptDeriveKey(hProv, CALG_DES, hHash, 0, &hKey);
DWORD dwBlockLength = 64;
bResult = CryptSetKeyParam(hKey, KP_BLOCKLEN, (BYTE *)&dwBlockLength, 0);
DWORD dwFeedback = 8;
bResult = CryptSetKeyParam(hKey, KP_MODE_BITS, (BYTE*)&dwFeedback, 0);
errorCode = GetLastError();
bResult = CryptSetKeyParam(hKey, KP_IV, IV_64, 0);
errorCode = GetLastError();
DWORD dwMode = CRYPT_MODE_CBC;
bResult = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
errorCode = GetLastError();
DWORD dwSetPadding = PKCS5_PADDING;
bResult = CryptSetKeyParam(hKey, KP_PADDING, (BYTE *)&dwSetPadding, 0);
errorCode = GetLastError();
|
|
|
|
|
Hey Jim,
jkirkerx wrote: I give up.
Don't give up so easily man.
Lets step back and summarize your problem:
1.) You have implemented some encryption in ASP.NET and also VB.NET and you want to duplicate the encryption within C++ using the Microsoft cryptography provider.
2.) You have found that the encrypted messages do not match.
3.) The .NET framework implements its own provider that seems to do things a bit differently than the default Microsoft cryptographic service provider (which is what c++ will utilize).
Have you considered approaching the problem from the other side? Rather than attempt to duplicate the .NET cryptography within your C++ application. You could make native API calls from your .NET application and duplicate the C++ encryption code. The .NET framework is perfectly capable of making P/Invoke native API calls and this would ensure that all 3 code bases were the same.
Best Wishes,
-David Delaune
|
|
|
|
|
I considered that this morning. I made a shout out on another forum, and Igor replied this morning.
Your VB code isn't hashing or deriving anything. You are likely looking for CryptImportKey. That's how you obtain HCRYPTKEY handle from raw key material.
PKCS 5 and PKCS 7 specify the same padding algorithm. Your problem has nothing to do with padding, and is most likely due to the fact that you are encrypting with different keys.
Then there was that observation I made, but I'm not sure what to think of it. VB said I used this set of keys, and the key I used are on the bottom. I tried both sets, and I get different responses.
BYTE KEY_64[8] = {42, 16, 93, 156, 78, 4, 218, 32};
BYTE IV_64[8] = {55, 103, 246, 79, 36, 99, 167, 3};
Food for thought, just not sure how to proceed.
|
|
|
|
|
Jim,
jkirkerx wrote: Your VB code isn't hashing or deriving anything. You are likely looking for CryptImportKey. That's how you obtain HCRYPTKEY handle from raw key material.
I'm not understanding what your friend Igor is saying here... unless he is referring to something VB.NET/ASP.NET related...
jkirkerx wrote: PKCS 5 and PKCS 7 specify the same padding algorithm. Your problem has nothing to do with padding, and is most likely due to the fact that you are encrypting with different keys
It looks like I came to the same conclusion back in the year 2008: Re: CryptDecrypt Failure please help[^]
jkirkerx wrote: Food for thought, just not sure how to proceed.
Well, what I stated earlier is completely correct... if ALL of the settings are the same... padding, mode, block size etc... the results should be the same. At this point you just need to figure out what is different. Unfortunately I do not even have the .NET framework installed on any of by workstations... and when I install Visual Studio I always exclude the .NET stuff... otherwise I would be able to help identify the differences.
Best Wishes,
-David Delaune
|
|
|
|
|
I think he's saying to toss all the hash stuff, and import the key I hard coded. So instead of importing let's say a certificate key from file, import my hard coded key instead.
Then ignore what vb is doing and just trust it.
Toss this,
bResult = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
bResult = CryptHashData(hHash, KEY_64, sizeof(KEY_64), 0);
And Import Raw Material
bResult = CryptImportKey(hProv, KEY_64, sizeof(KEY_64), &hKey, 0, &hKey);
|
|
|
|
|
This was my interpretation of the advice. I'll take it for a test run, if good, I need to figure out how to code the key.
BYTE DesKeyBlob_64[] = {
0x08,0x02,0x00,0x00,0x01,0x66,0x00,0x00,
0x08,0x00,0x00,0x00,
0xf1,0x0e,0x25,0x7c,0x6b,0xce,0x0d,0x34
};
BYTE KEY_64[8] = {42, 16, 93, 156, 78, 4, 218, 32};
BYTE IV_64[8] = {55, 103, 246, 79, 36, 99, 167, 3};
<pre>
bResult = CryptAcquireContextW( &hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, 0);
bResult = CryptImportKey(hProv, DesKeyBlob_64, sizeof(DesKeyBlob_64), 0, CRYPT_EXPORTABLE, &hKey);
bResult = CryptSetKeyParam(hKey, KP_ALGID, (BYTE*)CALG_DES, 0);
bResult = CryptSetKeyParam(hKey, KP_IV, IV_64, 0);
|
|
|
|
|
jkirkerx wrote: BYTE DesKeyBlob_64[] = {
0x08,0x02,0x00,0x00,0x01,0x66,0x00,0x00, // BLOB header
0x08,0x00,0x00,0x00, // key length, in bytes
0xf1,0x0e,0x25,0x7c,0x6b,0xce,0x0d,0x34 // DES key with parity
};
Where did this come from? The source code that you sent me privately via e-mail does not contain a key blob. If your ASP.NET and VB.NET projects are using key blobs... then that changes everything...
-Dave
|
|
|
|
|
It came from a Microsoft MSDN description of CryptImportKey, saying that either use CryptDeriveKey, Gen Key or import Key.
I tried it because I was not able to use my existing key format in CryptImportKey, and it expected a Key Blob. So I just wanted to see if I could create a key without using CryptCreateHash.
Well it loads without error, the call to DES is suppose to be in the blob header I think. The key is not right but I did create a key without CryptCreateHash.
|
|
|
|
|
Perfect Match!, on the buffer value, and the base64 output. This is the framework for duplicating the asp.net DES and 3DES.
I need to clean it up, secure it, and take out the garbage to finalize it.
WOW, what a long journey, Thank you very much Dave for helping me out, and standing by my side during the journey, and not giving up on me.
#pragma comment (lib, "advapi32")
#pragma comment(lib, "crypt32.lib")
BYTE DesKeyBlob_64[] = {
0x08,0x02,0x00,0x00,0x01,0x66,0x00,0x00,
0x08,0x00,0x00,0x00,
0x2a,0x10,0x5D,0x9C,0x4E,0x4,0xDA,0x20
};
WCHAR* _encrypt_DES( WCHAR *pzInputW )
{
BOOL bResult = FALSE;
WCHAR *szOutput = NULL;
HCRYPTPROV hProv;
HCRYPTKEY hKey;
ALG_ID Algid;
PBYTE pbKeyBlob = NULL;
DWORD dwKeyBlobLen;
BYTE *pbBuffer;
DWORD dwBlockLen = 0;
DWORD dwDataLen = 0;
DWORD errorCode = 0;
DWORD cbData = 0;
BOOL bFinal = TRUE;
int iCharA = WideCharToMultiByte(CP_UTF8, 0, pzInputW, -1, NULL, 0, NULL, NULL);
char *szInputA = new char[iCharA];
WideCharToMultiByte(CP_UTF8, 0, pzInputW, -1, szInputA, iCharA, NULL, NULL);
bResult = CryptAcquireContextW( &hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
bResult = CryptImportKey(hProv, DesKeyBlob_64, sizeof(DesKeyBlob_64), 0, CRYPT_EXPORTABLE, &hKey);
bResult = CryptSetKeyParam(hKey, KP_IV, IV_64, 0);
dwDataLen = sizeof(ALG_ID);
cbData = sizeof(szInputA);
if (!CryptGetKeyParam(hKey, KP_ALGID, (BYTE *)&Algid, &dwDataLen, 0))
return 0;
if (GET_ALG_TYPE(Algid) != ALG_TYPE_STREAM) {
dwDataLen = sizeof(DWORD);
if (!CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwDataLen, 0))
return 0;
dwDataLen = ((cbData + dwBlockLen - 1) / dwBlockLen) * dwBlockLen;
if (!(pbBuffer = (BYTE *)LocalAlloc(LMEM_FIXED, dwDataLen)))
return 0;
}
else {
if (!(pbBuffer = (BYTE *)LocalAlloc(LMEM_FIXED, cbData)))
return 0;
}
CopyMemory(pbBuffer, szInputA, cbData);
if (!CryptEncrypt(hKey, 0, bFinal, 0, pbBuffer, &cbData, dwDataLen)) {
DWORD dwError = GetLastError();
if(ERROR_MORE_DATA == dwError) {
DWORD dwSizeNeeded = cbData;
CopyMemory( pbBuffer, szInputA, cbData );
bResult = CryptEncrypt(hKey, 0, FALSE, 0, pbBuffer, &dwSizeNeeded, dwDataLen);
}
LocalFree(pbBuffer);
return 0;
}
BYTE szByte[8];
for (int i = 0; i < cbData; ++i) {
szByte[i] = (BYTE)pbBuffer[i];
}
DWORD dwResult = 0;
TCHAR *szBase64 = NULL;
if(CryptBinaryToString((BYTE*)pbBuffer, 8, CRYPT_STRING_BASE64, NULL, &dwResult)) {
szBase64 = new TCHAR[dwResult];
CryptBinaryToString((BYTE*)pbBuffer, 8, CRYPT_STRING_BASE64, szBase64, &dwResult);
szOutput = (WCHAR*)szBase64;
delete [] szBase64;
}
SecureZeroMemory( pbBuffer, sizeof(pbBuffer) );
delete [] szInputA;
CryptDestroyKey(hKey);
CryptReleaseContext(hProv, 0);
return szOutput;
}
|
|
|
|
|
Hey Jim,
That is excellent news!
Just in time for Monday night football too. Since your over there in Huntington Beach, CA would that make you a San Francisco 49ers fan or San Diego Chargers fan? I'll be pulling for the Pittsburgh Steelers tonight... because if San Francisco loses the New Orleans Saints will have a chance to gain the #2 NFC slot and obtain the bye week.
Best Wishes,
-David Delaune
|
|
|
|
|
Chargers Fan, but they should of kept Marty Schottenheimer. The current coach did nothing but get good players injured over the last few years (LT).
Pittsburgh is the luckiest team I've ever seen, or perhaps I should say conservative but effective.
Ben knows what to do to win games, and the EST factor, east coast team playing on west coast should not be an issue. Without the December mud of Heines field, should be a close game.
I have bowling tonight, but will try to catch parts of the game.
|
|
|
|
|
That did fly way over my head.
So I don't need that line of code. I can just go straight to the next lines
bResult = CryptHashData(hHash, KEY_64, cbKey64, 0); <-- So this must be wrong as well
bResult = CryptDeriveKey(hProv, CALG_DES, hHash, 0, &hKey);
bResult = CryptSetKeyParam(hKey, KP_IV, IV_64, 0);
|
|
|
|
|
My function works good, only I don't get the exact value or match I expect.
I read up on Initialization vector, and used CyrptSetKeyParam to add my IV, but this occurs in the background, and you can't really check it, to make sure that's what happened.
If the IV is just a prefix, that goes in front of the data to be encrypted, then is it common practice to skip the CryptSetKeyParam, and just prefix the data to be encrypted?
I remarked out the CryptSetKeyParam, and I did get different values returned in the buffer, but not enough to get the results I'm looking for.
If I experiment with it, then I need to write a whole new buffer routine that adds the extra space, and do new calculations.
Without:
I˜a‚ú|¢-Øø×"©¨Nþt¾dÃMN££Ð¢æÀDµ£N»£jŽg5„Äþti«L6±†à©Cþìü
With:
€&§¶Í>ªÈÇ3,í&%®•Ï¢?¾(ÞÆø0Ç6Ÿ§ìÆ·(õæd¢‡ôKFo{ü‘ (!ÛÏß·Èh‰¶
|
|
|
|
|