I'm looking to encrypt license keys on an audio software plugin. The biggest risk to the integrity of the license keys is small-time crackers decompiling the code and looking for the encryption key. My solution is to store an arbitrary number in the code and feed it to an algorithm that will obfuscate the encryption key while still allowing me to differ the key between projects (I'm a freelancer).
My question is - will seeding the C++ random number generator create the same psuedo-random encryption key every time, or will it differ between runs, libraries, etcetera. It's fine if it differs between operating systems, I just need it to not differ between SDKs and hosting softwares on the same computer.
srand and rand will produce the same sequence of numbers when you use the same implementation. Change compilers, even to a newer version of the same compiler, and there are no guarantees,
But the new random number generators, introduced in C++11 and defined in <random>, are requires to generate the same sequence of numbers on all implementations.
Say, if I have a byte array of a various length and a pass-phrase, what is the quickest way to encrypt it in a platform-independent way?
PS. I can make a SHA1 digest on the pass-phrase but how do I apply it to the byte array -- doing a simple repeated XOR makes it too obvious.
PS2. Sorry, crypto guys, if I"m asking too obvious stuff...
A Hash (like sha1) create a one-way result, you cannot decrypt a hash. XORing the data is not secure by any means, don't do that.
If you need to be able to decrypt the data, then I suggest using something like Twofish which uses a symmetric key block cipher and is not restricted by licensing or patents (thus you can find platform independent reference code).
Could somebody compare the safety of algorithms AES-CMAC with only 5 rounds, MD4 or some else hash function for checksums? Both in terms of speed and safety. We want fast and reliable checksum for detecting random error changes in streams (no bad guys involved). Ideally also with standard C/C++ implementation.
CRCs are explicitly designed to detect transmission errors; unlike hashes they provide concrete guarantees on what errors they will definitely detect. If it's transmission errors rather than an adversary you're concerned about, use a CRC.
I am just wondering if you are supposed to write a sort of really secure application with data being transmitted over insecure networks, what kind of encryption algorithm will you use it in order to make it safe ? I know several c++ libraries for encryption providing nice functions with different algorithms, but i'm not quite sure which cipher to use - AES, DES, RSA, Blowfish or maybe something more different ?
Please provide your ideas and suggestions.
While some encryption algorithms are easier to break then others, the weak spot is more about key generation. If your key generation algorithm is predictable, it will be easier to figure out your key and decrypt the packet.
So, I wouldn't sweat which encryption algorithm (AES is fine). But make sure you have a good source of real randomness to generate your keys.
If you are on any of the common POSIX OS, look into using /dev/random to generate your key.
use AES for data encryption and use RSA to exchange AES key between parties
You have listed too few requirements for your encryption needs. It depends on circumstances.
For example, if both end-points of the communication link are trusted, you could just worry about encryption and have both of them produce public-keys for the other end to encrypt information with. In this case, RSA would be my personal choice.
However, if you do not trust the other end-point, and am using the encryption to determine whether it "has the key", then you would be counting on preset keys, rather than private/public encryption. In this case, Triple DES (DES is considered a little weak these days) may be a good choice.
Hope this helps!
Any of the well know ciphers have well understood levels of security so that part is easy. I'd be more concerned about the quality and trust level of the library you use and bugs in your use of it. Have you considered using external programs like ssh to do the key gen and handle the connection, and drive that with an API library?
Crypto++, perhaps the best known, largest, and best crypto library for C++, contains several algorithms you can use. It can also give you a good cryptographically secure random library for use with these algorithms.
According to their FAQ, that depends quite a bit on what you want to do. From their recommended list of algorithms:
block cipher: DES-EDE3, AES, Serpent (Serpent is slower than AES but has a larger security margin and is not vulnerable to timing attacks.)
stream cipher: any of the above block ciphers in CTR mode
fast stream cipher: Salsa20, Panama, Sosemanuk (available in version 5.5)
hash function: SHA-256, SHA-512, Whirlpool
message authentication code: HMAC/SHA1 or HMAC with one of the above hash functions
public key encryption: RSA/OAEP/SHA1, ECIES
signature: RSA/PSS/H, ECDSA/H, which H one of the above hash functions
key agreement: DH, ECDH
random number generator: RandomPool, AutoSeededRandomPool
We can't give an exact answer because there isn't one without knowing more about what you're trying to accomplish.
First of all you have to split up symmetric block ciphers with public key ciphers:
they have really different performances
their implementation is really different
their strenghts/weaknesses are based upon different factors
By the way:
DES is not considered secure anymore, you should always avoid using it
AES is still considered safe (you could use 256 bits keys)
RSA's (and other public key algorithms like ElGamal, Ellipctic Curve) security is based on the hardness of the mathematical problems on which these algorithms are based. For example: number factorization. If the number of bits you use to store the keys are big enough you can consider them enough safe.
However things can change according to the power of CPUs in few years so you shouldn't consider them safe forever..
One thing to consider is that public key ciphers are usually slower than block ciphers, that's why commong protocols usually use the first ones to exchange a simmetric key that then is used with an algorithm like AES.
The answer is: don't. If it has to be secure and you ask this question it means that you need to find a security expert to do it. You are not going to design a secure protocol by asking for help on SO. You can [maybe] use an existing protocol such as ssh or TLS, but if you roll your own you will fail.
If you want to transmit data over an insecure network, you need more than a cipher, you need a secure protocol, potentially including key distribution and authentication.
If you're really serious about crypto implementation, not just doing it to understand the basic mathematics of cryptography, then you need to do more than implement the number-crunching correctly. You also need to worry about side-channel attacks. For example, if your implementation takes a different amount of time depending on the key, as is common, then an attacker can deduce information about the key from your various response times. And that's just the basic algorithm, never mind putting it all together.
This is in general an unsolved problem and an area of ongoing research. Most or all implementations are flawed, although for the latest versions of well-used libraries probably not in a way that anyone has publicly announced they can exploit. Timing-based attacks on OpenSSL have been demonstrated in the past, albeit only on a highly predictable local network AFAIK. You can basically spend as long as you like on it, up to and including your entire career.
In practice, just use SSL, in whatever implementation comes with your platform.
Actually, we may not need to know all the details. But, IMHO, cascade these algorithms with Chain Of Responsibility Pattern, or Composite + Strategy.
My application needs to use a couple of hard-coded symmetric cryptographic keys (while I know that storing a public key would be the only perfect solution, this is non-negotiable). We want the keys to be stored obfuscated, so that they won't be recognizable by analyzing the executable, and be "live" in memory for as little time as possible - as to increase the difficulty of a memory dump retrieving them in clear-text. I'm interested in using C++ features (using some sort of scoped_key comes to mind). The solution must be portable - Windows, Linux, MacOS -, so it cannot take advantage of the operating system crypto API.
How would you go about designing such a system? Thanks a lot.
All you're going for here is security through obscurity. If you have one of us come up with an idea, you won't even have that.
John Skeet has a good article on this too.
Do something random is all I can say.
your scoped_key can be simply a KeyHolder object on the stack. Its constructor takes the obfuscated buffer and makes a real key out of it and its destructor zeros out the memory and deallocates the memory.
As for how to actually obfuscate the key in the binary, One silly choice you might try is put inside a much larger random binary block and remember its offset and size and probably XOR it with some short random sequence.
If you do the XORing thing you can actually avoid ever having the real key in memory. simply modify the decryption to read a byte from the key and before using it, to XOR it with the appropriate value.
*Add here disclaimer on how foolish security through obscurity is*
Have you considered if this is actually the weak point in your program? Let's assume for the sake of argument that you're doing a license check - though other checks apply equally well. No matter how well hidden your key, and how well obfuscated your algorithm, at some point you have to do something like this:
if(!passesCheck()) {
exit(1);
}
Your potential adversary doesn't have to find the key, decrypt it, figure out the algorithm, or anything else. All they have to do is find the location in the code where you determine if the check succeeded, and replace the 'jnz' instruction with a 'jmp' to make the test pass unconditionally.
You should look into Tamper Resistance software, such as Cloakware and Arxan.
TR is NOT cheap :)
If you do not take advantage of whatever platform you will run on, you cannot guarantee that you can effectively hide a symmetric cryptographic key in your program. You can assume that an attacker will have a debugger and will eventually figure out how to set a breakpoint in the function that has to use the key to decrypt. Then it's game over.
Why not look at steganography, as you can hide the key in an image. It is possible to find the key, but if the image doesn't follow an obvious pattern (such as an image of space would) then it may be harder. This can be cross-platform.