Link to home
Start Free TrialLog in
Avatar of _Stilgar_
_Stilgar_Flag for Israel

asked on

One-way encryption using Public/Private keys using the simplest code

Hi,

I'm looking for a good, robust and fast algorithm/class in C++ that will let me encrypt a string in a one-way manner, so its unbreakable (128 bit or even 256 bit). So if I have one server application and many desktop clients that should communicate with it using HTTP POSTs, I can encrypt some short data block (username + "|" + code, for instance) using some unique key and send it in the request. Then the server will use the same algorithm to encrypt the same data from its records and compare the resulting hash with the one provided in the request.

I'm not so familiar with encryption algorithms, so please let me know if this isn't the easier and best approach.

Target platform is Windows (safe to assume 98 and up), my IDE is VC++ 2005 (unmanaged C++). I will need to interact with this algorithm from .NET web application, so if the same code is already written for .NET that would be ideal (otherwise I will create this as a DLL and create a C# wrapper class for it).

Stilgar.
Avatar of alb66
alb66
Flag of Italy image

I agree; encryption algorithms can be pretty difficult to deal with.  The simplest public/private key algorithm that is still pretty good is the diffie-hellman key exchange algorithm.  I learned how it works through Wikipedia (http://en.wikipedia.org/wiki/Diffie-Hellman).  A quote from the page:

"If p were a prime of at least 300 digits, and a and b were at least 100 digits long, then even the best algorithms known today could not find a given only g, p, and ga mod p, even using all of mankind's computing power"

Once you obtain a private key between the sender and receiver, it's usually sufficient just to xor the key with the data you're sending.
Avatar of _Stilgar_

ASKER

I'm sorry the title is misleading. I have no need for Public/Private key mechanism - I don't have a requirement to decrypt the data. I only need to encrypt it - or Hash it (as long as no collisions occur, never). And I need the code to be on the public domain, and not GPL.

Stilgar.
Again - I'm using un-managed code. Pure C++ - I'm sure there are free classes for this out there.

Stilgar.
sure. cryptlib, the openssl libraries - there are dozens. in fact, given your choice of programming languages (c++) you have an embarrassment of riches in that direction.

http://www.cs.auckland.ac.nz/~pgut001/cryptlib/
http://www.openssl.org/

if you want one native to c# though, the bouncy castle libraries are probably your best choice

http://www.bouncycastle.org/
oh - and please note, that if you are using asymmetric encryption, 256 is a *small* key - you usually start at 1024 and work up (for RSA and DH anyhow; EC is currently considered more secure so can use smaller keys)
Dave,

I see you have much knowledge in this area, so can you please recommend on the best choice, given the following requirements:
- Need to work with unmanaged C++, if has a native .NET its a great plus, but not required.
- Totally open-source, not GPL'd
- Very strong encryption
- Fast and robust, so it can run well on less-equipped PCs as well.
- Easy integration with as small foot-print, code and depandancies as possible (one-two headers with a simple function call would be ideal).

"asymmetric encryption" is what I referred to as "Hashing"? And what is EC - if it's that good maybe thats the way to go?

Also what would be a "key" in my case - just a series of digits I will randomize on my end? please remember that the same key would be used in all desktop clients and the server application to create the one-way hashing.

Stilgar.
Not sure how you can say GPL isn't open source - maybe you mean a BSD style licence so you can include it in closed-source products?

if you want C# or Java, then bouncy castle has a BSD style licence (its free, and you aren't required to give away your source code afterwards)

if you want C++, then openssl uses a modified apache licence (with an attribution clause) - so you are required in your documentation and licensing to state you use openssl, but other than that you are free and clear. Cryptlib is subject to commercial licencing for non-free programs, so is not a good choice if you wish to make a profit :)

for openssl, you can either hardlink (so you can compile in the modules, at which point your compiler should only include those functions from the library it needs) or bind at runtime (in which case, you can use a library dll; this has the advantage that you can retroactively upgrade your crypto by upgrading the dll if needs be)

asymmetric encryption is a form of encryption where the encryption key is different to the decryption key - so someone with an encrypt-only program has no way to decrypt a message from another recipient. this is also called "public key" encryption
In practice, it is rare that PK is used directly - it is more common to find a randomly generated session key is used to symmetric-encrypt the plaintext, then the key itself is encrypted using PK methods.

There are three commonly known forms of PK:

RSA
DH (aka egimal)
Elliptic Curve

EC is relatively new, and some of the more efficient curves are patented (so you need to check your library doesn't use those)

hashing differs in that it cannot be inverted - there is no decryption key to a hash.

Common hashes are md5, sha, whirlpool and ripemd

when using a hash, there is no key - however, it is conventional to prepend a fixed string to the hash (called a "salt") to prevent people building a dictionary of every possible hash and just looking up the original text in there.
Yes, I referred to BSD style license.

I want C++. A .NET implemetation would be a great plus, but I can just make the C++ DLL and use it with a wrapper if there is none.

I guess I should go with Hashing then. You tell me - I want my different desktop client apps to authenticate against the server application and its backend DB, so I make the desktop app hash a string which is assembled from the username and code (not password, since this code is changed on successful authentication and sent back to the user for the next login), and this string is sent over an unsecured channel (HTTP POST for example). The server then assembles a similar string using the user ID and hashes it using the same algorithm. If the two string are a match, the user is authenticated and provided with a new code.
This should save me the PK headache - question is what hashing algorithm to use? is it proved to be one-way and unbreakable? and how exactly is the salt working, the cracker can just realize what it is and omit it?
Also, I assume one implementation in C++ is totally equal to another one in C# -- resulting string wise?

Stilgar.
SOLUTION
Avatar of JimBrandley
JimBrandley
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Is it indeed one-way and unbreakable?

Can you please provide some more details on the "salt" trick?

Also
Security is debatable. MD5 has shown some weakness and should not be used, but as far as I know, the other three are still considered cryptographically secure.  The only attack against MD5 (a structured collision attack) would not concern you as it requires more control over the message than a challenge/response protocol would allow the attacker, but I would advise not using md5 anyhow.


as JimBrandley says, SHA256 is a good choice - the site he points to offers public domain source for that, and yes, all implementations of SHA256 should produce the same output for the same input.

the algo is outlined here:

http://en.wikipedia.org/wiki/SHA-256

along to links to implementation libraries.

one advantage of using OpenSSL is that you can operate it in FIPS mode - I can't see this being much of an advantage in your case though, so you might want to check out the link JimBrandley posted to crypto++ to see if it is better suited to your needs.

the "salt trick" isn't much of a trick - its just prefixing the data with a random string so that the output hash is different every time even if the rest of the data is the same. one common use is in challenge/response protocols. This works as follows:

Server -> client : random data
Client: calculate hash of (random data+password)
Client -> server: username+hash
Server: calculate hash as above for the user's listed password plus the challenge

assuming the two match, you have successfully logged in, without the client having to hold state (ie, remember a code for "next time")
Thanks a lot. The point of the code the client remembers for "next time" is different - its intended to prevent from copying an identity. This is not used for registration purposes, but rather to disallow multiple logins by the same copy of the software (same user, several machines). But I guess this still can be considered as "salt" - the way you described this usually works is not so much of use with web-services, which is probably how we will implement our tool.

Is the SHA256 algorithm produces a string of a fixed length (I recall it does, but just to make sure)?

Also, technically this is still decryptable using a dictionary as you mentioned, only you would need to catch several responses in order to identify the correct password, then this is not all that secured if such a dictionary is in existance...?
In my case, no password is transferred, only a code which is valid only until the server accepts the authetication, then this is of no significance to me.

Stilgar.
I suppose that depends on your licensing model. Often, software is licensed either per simultaneous user (so you don't care if the same user logs in four times, as long as the company has paid for four logins) or per named user (in which case if a user logs in twice, you force-logout the first instance)

per-node "hard" licenses are not unknown, although they break some requirements for USG procurement (as lotus found out when they added something similar to their 1-2-3 product) and mean you spend an increasing amount of time authenticating user requests for the token to be "reset" due to windows re-installation, hardware failure and so forth.

but yeah, in your case I would treat the initial token as a password, and still do the challenge/response exchange with it - the issue there is that you usually need TWO components, the username (sent plaintext, to identify which password will be in use) and the secret token (password) to authenticate the host as a valid one. The only problem I can see then is how you get the new code to the user securely without invertible encryption.

Personally though - I wouldn't bother with any of that and would just use https to establish a crypto tunnel, and send the one-shot username and password that way. That way, all the traffic is encrypted, and you are using industry-standard methods that already have nat traversal, proxy traversal and various other network-friendly aspects built in.
Again - this module is not against piracy. We just want to ensure we know who is who, and keep users unique - imagine this is an IM application (which is not if you wonder...).

This is why I do this changing code, which is treated as a password but is not. It is used once to validate the user and then it expires, and I have no fear of it being sent as plain text because of this. I might come to regret that, but at this point I think this is the way to go.

I will be sending user ID plaintext, and then a hashed string assembled of username and this changing code.

The HTTPS approach is a possibility. Right now we can't have this, but in case we can - do I just post from my C++ code to HTTPS protocol using WinInet, and all the crypto tunnel creation etc. is handled there?
I would use the openssl libraries for the ssl tunnel, to get more control over it - but I am curious why using https isn't an option - particularly bearing in mind that, as you control *both* ends of the tunnel, you can issue your own https certificates for free.

I wasn't so concerned with sending the initial code ,as your comment that you send a code *back* to the client which will be used for future logins. If that code isn't sent securely, an interceptor could easily read and duplicate it for his own use. a hash is no good for this, as the user will not know in advance what the code will be, so can't generate his own for comparison.

in fact, in your given scenario, there is no need for the user to encrypt the one-shot code at all - even if an attacker intercepts it, it will be worthless to him (as it has already expired in the act of being sent)
I'm going to use standard web application on the server, without developing my own server application that uses openssl, so the certificate isn't free and I do not control both sides. And we currently have no platform for this.

The worse case scenario for my model is that the attacker sniffed the network and realized our protection scheme (which is not a trivial task since one way is encrypted). If he does realize the plaintext (which I can use some sort of predefined salt for) is the next-time-password, and snatches it and uses it (which involves some hacking since this process is auto), the original user will not be able to connect the next time and will go to our site or call and use his real password which is stored on the server only, and reset this login code, so the attacker is left outside the loop again. I agree this is not ideal, but the worst-case scenario is acceptable for this project scope - its sort of internal and not widely spread.
If you have any suggestion on a way to improve this I'm more than willing to listen, as long as integration is as simple as possible for both the C++ code and the server (ASP.NET).

I'm thinking maybe encrypt the password the server sends to the user after successful authentication? the issue I had with this is how to have the server encrypt it and only that specific client be able to decrypt it?
Maybe HTTPS is the solution, as long as I can indeed use the simple WinInet functions and not have to mess too
much with it. Also, this will need to be supported by .NET webservices.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry for not responding earlier - we have been redesigning...

I need only to know that: How can I establish an HTTPS connection using WinInet standard functions I can call from my C++ app, so I post user ID and password and recieve confirmation from the server through a secured channel?

Stilgar.
There is a decent example here:

http://www.codeproject.com/KB/IP/wininet_ssl___certificate.aspx

as this is CodeProject, you can almost certainly just copy his class definition straight into your code.
Thanks, although I suspect there is still some work needed on that code. Creating the request for exaple - I'm not quite sure it currently accepts a request string (e.g. variables I'm posting username=xxxx&password=xxxxx). I will probably need to dig in it a bit to find a way to do that.

Before I sign this off - I just want to make sure certificates are only needed on the server side and if I will use the code from that link it will not require any certificate from the user's end. Is that indeed the case (I mean, client certificates are being requested only on special cases)?

Stilgar.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I will probably need some aid when I will approach this (soon enough...), but for now you deserve some closure...

Thanks allot to all who have participated.