## The Design of Software (CLOSED)A public forum for discussing the design of software, from the user interface to the code architecture. Now closed. |
||

The "Design of Software" discussion group has been merged with the main
Joel on Software discussion group.
The archives will remain online indefinitely. |
I have a real need to do the following.
1) I want to encrypt a buffer of data, within a web application, by calling the appropriate OpenSSL functions. Example: From PHP I would call: openssl_private_encrypt() to generate the encrypted data, using a private key (generated by the openssl command line tool). 2) The data is transmitted to a client application. 3) The Windows client, written in C++, calls the *equivalent* of openssl_public_decrypt() using the corresponding public key. And out pops the original data. Now, here's the problem: THERE ARE NO working, concise, simple examples of this corresponding type of logic on the C++ client side. There seems to be no one function or example of *anything* that performs the equivalent of "openssl_public_decrypt()" for a C++ application. I'm sure it's out there, for whomever wants to wade through 20,000 lines of unrelated code. I don't have the time to perform "code archaeology" at this level. I was able to get OpenSSL built successfully for Visual Studio 2008. Unfortunately, there are no concise, simple examples that distill down the encryption mechanics for C++ as they are done in PHP. The API is simply enormous. Someone uses OpenSSL in Windows applications, but I don't have a clue how they do so. I then tried the Crypto++ library. They have a nice API, but the published test suite crashes due to f*cking heap errors or runtime problems. (The code crashes with a malloc() equivalent. And yes, I am using the MSVC project file that is supplied with it. And there seem to be no errata on using different Visual Studio versions) WHY IS THIS SO "HARD"?!!! Please tell me how you have done this. A reward of everlasting appreciation awaits. Oh, yeah - it's not homework!! Thanks!!!
Public key cryptography is hard. Deal with it.
Seriously, I had the idea to slap together a simple RSA public key crypto system a year ago: it turns out that even for toy implementations (keys as small as 16 bits) you still need some kind of extended precision/bignum math library, since you will be raising number to fairly large powers, and you need exact answers (so floats, even doubles or long doubles, won't do). Other than the extended precision math lib, you also need some routines to calculate parts of the keys, and those are also non-trivial. In the end I gave up and used OpenSSL to do the work.
Oh, two other things:
First, my understanding of OpenSSL is that it doesn't use public key crypto for the actual encryption, only for the key exchange. You have a symmetric key that is used for the actual encryption of the message, but the key is encrypted using public key crypto so that it can be sent over an otherwise open channel without being revealed. This is done because the math involved in public key crypto is computationally expensive compared to common symmetric crypto algorithms, so you'd like to minimize you use of the slow, expensive math if at all possible. Implementing the key exchange logic is another not-so-simple part of the whole process (I was going to avoid that by using public key for the message encryption, speed and efficiency be damned). Second, I could dig up my notes on the subject if you are interested. In the meantime, you can read up on the RSA algorithm on Wikipedia, it's really not that hard (so long as you have the extended precision arithmetic library in hand).
"Now, here's the problem: THERE ARE NO working, concise, simple examples of this corresponding type of logic on the C++ client side."
Security is a process, not a product, especially not done with a working, concise and simple example. There is no such thing as "basic" cryptography. There is either working cryptography or snake oil. You should begin with learning about it, Wikipedia is an excellent start. That said, it depends on what you want to protect. If it is for some hobbyist online forum, you may go with it. But if you want to protect credit card transactions, by all means, ask someone who knows what he is doing to implement it.
Secure Thursday, September 18, 2008
That's very interesting, Jeffery - although not unexpected. A crypto professor I had once remarked that the reason most cryptographic software is written by Ph. D's is that cryptographic algorithms are unimaginably subtle. Common sense has to take a back seat to hard mathematical analysis, and as such, it's best left to the experts.
Re: Brother Beal and leaving it to the experts
Yes. In my case I'm still doing something boneheaded by misusing the OpenSSL calls to do pure public key crypto on my data, but it's all for in-house stuff that, basically, just needs to not be immediately readable while sitting on disk (we want to encrypt in an automated manner, but only be able to decrypt when an operator is on hand, so RSA lets us store the encryption key in the program, but keep the decryption key on removable media). I'm sure that this wouldn't stand up to a concerted attack, but it suits our simple needs. As for my notes on RSA, they're a precis of the Wikipedia page (which seems to have been erroneously edited in the intervening year to omit step 5): 1) we start with two prime numbers, P and Q 2) we get our "modulus", n = P*Q 3) then we get the "totient", T(n) = (P-1)*(Q-1) 4) next we select our "public exponent", e where 1 < e < T(n) and e and T(n) are co-prime (they share no common factors other than 1). 5) finally we calculate our "private exponent", d where de = 1+k*T(n) for some integer value k such that steps 4 and 5 can be done using something called the "extended Euclidean algorithm", look it up. The public key is the pair of numbers (n,e) while the private key is the pair (n,d). Given a message, M, you get the cypher text, C, of M by the following formula: C = (M^e)%n {the '^' operator is exponentiation} We get the original message back with the formula: M = (C^d)%n Now, the math LOOKS pretty simple, but it produces VERY large intermediate values, which is why you need the extended precision math library. The exponents e and d are frequently large. Even small values of e (e.g. 5 or 7) can result in intermediate values larger than 32-bits in length: e.g. if we are encoding individual bytes of the message with a public exponent of 5, the intermediate value (M^e) is 40-bits long. However, when the public exponent is small (e.g. 5 or 7) the private exponent becomes large, so the intermediate value (C^d) will be much larger than (M^e) and won't fit in a regular int or even a long long. Consider a toy example: 1) we select our prime numbers, P and Q, to be laughably small: 23 and 31 2) our modulus, n, is then n = 23*31 = 713 3) our totient, T(n), is T(n) = (23-1)*(31-1) = (22*30) = 660 4) we select a small public exponent, e = 7 5) we recast de = 1+k*T(n) to solve for d, d = (1+k*T(n))/e and try a couple of values for k until we get an integer value for d. After some trial and error we get k = 3 and our private exponent, d = 283 Now, the intermediate value for encryption (M^e) is only 56-bits long, which we can calculate in a long long, but the intermediate value for decryption (C^d) is 2264-bits long, so we need an extended precision math library to do the decryption. Oh bother. Also, this is, as I said, a toy example. The keys are only 17-bits long, so our encryption could be broken by trying every possible private key value, probably in only a second or so, even on the slowest computers. Real keys would be MUCH longer, as would the resulting private exponent, and the intermediate value for decryption would be correspondingly huge. Lecture's over; go out and play.
"First, my understanding of OpenSSL is that it doesn't use public key crypto for the actual encryption"
?? HUH! ?? OpenSSL is a library, not a protocol. You are confusing OpenSSL with the common implementation of SSL in browsers/VPNs. The OpenSLL lib supports RSA encrypt/decrypt via RSA_public_encrypt and RSA_private_decrypt Do NOT write your own crypto. It's far too easy to think it is correct, when infact it is can be very very wrong.
anon Thursday, September 18, 2008
Designing an encryption algorithm is difficult and best left to experts, implementing a simple one (at least fo rsymetric encryption) in your code is trivial.
You can do it in a dozen lines of code see http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
TEA has been proven to be very weak.
If your data MUST to be secure (rather than just obfuscated), don't use it.
anon Thursday, September 18, 2008
"Do NOT write your own crypto. It's far too easy to think it is correct, when infact it is can be very very wrong."
+1
Arethuza Thursday, September 18, 2008
Wannabee has a point here guys.
There ought to be a simple wrapper around the whole OpenSSL library for this. I remember many years ago I was looking at it. I started with a sample test program that came with and it took me days to whittle it down to something I could work with. The end result was a lot shorter than the original sample main(). Sorry it was for pay so I don't have the result.
Thanks for the responses, guys. At least I know that I am not insane or pathologically stupid.
Anon: >> The OpenSLL lib supports RSA encrypt/decrypt via RSA_public_encrypt and RSA_private_decrypt Hold up! Is it really that simple? Are these the APIs I have been looking for and bitching about?
Re: using RSA_public_encrypt/RSA_private_decrypt et. al.
Yes, this is the route I wound up taking. I consider it to be an abuse of the API because those routines are really meant to encrypt and decrypt the symmetric keys used during an SSL conversation; You can only encrypt a buffer of limited size, which is related to how much space you need to encrypt one of the symmetric keys (and to the padding mode). All that said, I've used it (or misused it) to encrypt blocks of data that I store on disk. It seems to work, but I wouldn't bet on it being very secure in the real cryptographic world. Re: not writing your own crypto I agree entirely. There is no way that an amateur is going to be able to write an effective crypto system. Just repurposing an existing, well-designed crypto system has obscure and severe perils.
Haha but even when you get the opensll call to work, you're still only halfway there, because there are numerous ways to parameterize the encryption/decryption - for example 'encryption schemes' and 'signature schemes'. Don't ask me what they mean, you can't configure them with the php RSA implementations (and I've tried at least 4 different ones) but CryptoPP requires you to specify which one to use (well there's a default but it's not the one that is used by the php mcrypt() (IIRC) function).
So anyway, my advice: use system("gpg --encrypt") in both C++ and php and don't try to do it in code. If you're not well versed in crypto, you'll set yourself up for a world of pain.
Joske Vermeulen Friday, September 19, 2008
Check out libtomcrypt - see http://libtomcrypt.com/download.html
It's C, not C++. but you shouldn't have problems linking with it. I've used it under Linux and also some embedded environments. This was a couple years back, but from what I recall the docs were good and much easier to understand than OpenSSL.
C_Hacker Friday, September 19, 2008
Here's an open source C++ library with many algorithms, I used it a long time ago so unfortunately don't remember if it was easy/hard to use but might be useful:
http://www.cryptopp.com/ |

Powered by FogBugz