Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jul 5th, 2005, 3:19 PM   #1
SugarDaddy
Newbie
 
Join Date: Jul 2005
Posts: 1
Rep Power: 0 SugarDaddy is on a distinguished road
MS CryptoAPI frustration - Cryptography

Hello. Here's a quick breakdown of my problem. Any help would be greatly appreciated.

I have an application written in MFC that communicates via HTTP with a server running PHP 5. No problems there. However, the communication needs to be encrypted for reasons that are unimportant. On the server, a PHP script generates a unique identifier (using libmcrypt) that is used as a session key for the encryption / decryption. The session key is then encrypted using Triple DES, base64 encoded, the initialization vector attached to the front, then base64 encoded again. The client's username and password is used as the key to encrypt the session key.

Great, so that all works. On the client side is where the problem occurs. I am using Microsoft's CryptoAPI to do the decryption. After base64 decoding and parsing out the initialization vector and generating the decryption key, the decryption process fails. CryptoAPI's CryptDecrypt function shoots back NTE_BAD_DATA. The CryptDecrypt function has a flag used in block encryption/decryption that says whether the plain text to decrypt is the final block or not. Being that I'm not using block encryption, I set that flag to TRUE. The documentation for NTE_BAD_DATA says that when that flag is TRUE, then the padding is wrong. So I set the flag to FALSE and it decrypts without fail. However, the result is not correct. What's going on? I'm not crypto expert, so I'm hoping someone around here is.


Pseudo of what I'm doing to decrypt:
CryptAcquireContext(&hProv,...)
CryptCreateHash(&hHash,...)
CryptHashData("username+password")
CryptDeriveKey(hHash, &hKey)
CryptDecrypt(hKey, &decryptData)

So it's basically by the book. One thing to note is that the doc for CryptDecrypt says "Decrypts data previously encrypted with CryptEncrypt"

That seems pretty weak to me if CryptDecrypt can ONLY decrypt data encrypted with CryptEncrypt. Shouldn't it be based on the algorithm, not the implementation? I would think so, but then I realize that it's Microsoft and I start to doubt that reasoning.

Any help would be greatly, greatly appreciated.
SugarDaddy is offline   Reply With Quote
Old Jul 6th, 2005, 3:05 AM   #2
mackenga
Professional Programmer
 
Join Date: Mar 2005
Location: Glasgow, Scotland
Posts: 314
Rep Power: 4 mackenga is on a distinguished road
Well, I'm not a crypto expert exactly but since there are no replies...

Frankly, I'm boggling about the notion that the only block doesn't decrypt correctly when treated as the 'last block'. I've boggled for a few minutes now, and bear in mind this is more general principles I'm thinking about rather than inside knowledge of the specific process in question, but here's my best shot.

If it uses padding, the block encryption/decryption expects a particular block size. This full size would be occupied by your ciphertext on a non-final block, but partially occupied by padding on a final block. So when you say it's the final block, the padding is wrong, but when you don't say so, the padding couldn't be since there shouldn't be any. What might be wrong, though, is the size of the block. I mean, if it normally expects blocks a certain size, with the final block padded as necessary, then it may not be sure how to react to your arbitrary sized single block.

Given it as a non-final block, I don't know what it would do. It might just assume that this is the block size, however many bytes it's been given; is there any way to /set/ the block size? This could be a clue; do you need to explicitly tell it not to work with multiple blocks? If the function that did the encrypting wasn't expecting to be sending standard-sized blocks, maybe it didn't pad it; if the function you're using to decrypt assumes it always gets padding and always deals with blocks of a fixed size, maybe you need to tweak the other end to get it to play the game; why not produce a fixed-size block at the other end, if this is possible, just to go easy on the MS code? (How often have we all had to do something like this? "X is working, it's Y's fault, but we need to change X, because it's Microsoft Y and will probably only be fixed by stealth in five years' time.")

If the system is expecting, say, 1K blocks to pluck a number out of the air, and you give it a 512 byte complete ciphertext and tell it it's a non-final block, then judging by the behaviour you describe what it's probably doing is reading past the end of the buffer to get its 1K just because it expects them to be there. This would give it the wrong ciphertext, hence the wrong plaintext but wouldn't set any alarm bells ringing if you're just passing in a pointer, and wouldn't cause any serious misbehaviour from the program since it'll only be reading through the pointer anyway, and not way off in some random location.

Like I say, I'm no expert so that's all I can really suggest. Hope this is better than nothing.

Last edited by mackenga; Jul 6th, 2005 at 3:09 AM. Reason: Something occurred to me
mackenga is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 5:55 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC