1

I am using this example that Brett gave:

Encrypt and decrypt a string

And doing this:

public static bool VerifyLicenseKey(string applicationGuid)
{
  Console.WriteLine("G: " + applicationGuid);
  var appSettings = AppSettings.GetInstance();
  if (appSettings == null)
  {
    return false;
  }
  var hwinfo = HardwareInfo.GetHardwareSerial();
  Console.WriteLine("h: " + hwinfo);
  Console.WriteLine("a: " + applicationGuid);
  var currentSerial = Crypto.EncryptStringAES(hwinfo, applicationGuid);
  Console.WriteLine("c: " + currentSerial);
  Console.WriteLine("o: " + appSettings.LicenseSerialNumber);
  if (currentSerial == appSettings.LicenseSerialNumber)
  {
    return true;
  }
  return false;
}

}

The GetHardwareSerial and applicationGuid are coming back the same every time but when I call the EncryptStringAES it is not.

Am I using the wrong class? Is it not suppose to be the same each time?

If not, does someone have a better example where the encryted values are the same?

Community
  • 1
  • 1
ErocM
  • 4,505
  • 24
  • 94
  • 161
  • 2
    Is this information actually secret, or does it just need to be correct? I think you want a [message authentication code](http://en.wikipedia.org/wiki/Message_authentication_code) or a [digital signature](http://en.wikipedia.org/wiki/Digital_signature), not encryption. – Craig Stuntz Feb 12 '13 at 15:06
  • Or you could use a simpler MD5 hash or CRC32 checksum. – John Willemse Feb 12 '13 at 15:11
  • I need it encrypted and not easily reproduced and the same encrypted value each time I encrypt it. – ErocM Feb 12 '13 at 15:12
  • Not an answer, but you might want to take a look at [this article](http://www.brandonstaggs.com/2007/07/26/implementing-a-partial-serial-number-verification-system-in-delphi/) about verifying license keys. – Bobson Feb 12 '13 at 15:15
  • 2
    What on earth are you trying to do here? This doesn't make any sense to me. Can you explain what problem you're trying to solve here and why you believe that encryption is an appropriate solution? Encryption should be used for two things and two things only: (1) encoding and decoding secret messages and (2) digitally signing a message. You seem to be doing neither of those things so it is very hard to evaluate where you're doing it wrong; the whole thing seems to be wrong. – Eric Lippert Feb 12 '13 at 15:18
  • 5
    As for your question: There is no requirement whatsoever that a given plaintext when encrypted twice produces the same ciphertext. The requirement is that the ciphertext produce the plaintext when decrypted; there may be many ciphertexts which decrypt to the same plaintext. As I said before, if you are not using the ciphertext to *protect a secret message* then you are using the wrong tool. – Eric Lippert Feb 12 '13 at 15:19
  • @EricLippert you are overthinking it. This is for a simple means of keeping the average joe from copying it from one computer to another. – ErocM Feb 12 '13 at 16:25
  • 3
    Then what do you need *encryption* for? If it is a simple mechanism then *keep it simple*. If what you need is a "please keep out" sign then why are you using a steel portcullis with lasers and crocodiles; or, more accurately, a steel portcullis with lasers and crocodiles and a wide open back door? – Eric Lippert Feb 12 '13 at 17:01
  • I did. I'm just hashing it now. Thanks! – ErocM Feb 12 '13 at 20:28

3 Answers3

4

Your "encryption" is actually just obfuscation and not too hard to bypass. All one needs to know is your application guid (probably stored public) and the method to get the same hardware ID (you probably didn't write that and it's easy to find).

Of course how hard do you want your protection to work depends also on how valuable or high-volume your software is, so simple obfuscation may be enough. Forget the AES, what you need here is a hash algorithm, such as SHA or MD5 where you can hash together your application guid, hardware number, user name etc and store the hash. For most typical users this will be enough of a deterrent.

If you insisto on having hard-to-crack protection you need is digital signatures and an activation procedure. See RSACryptoServiceProvider.

Basically you create a service that knows your private key and you place the matching public key in your software. Then from your software you call the service with HardwareInfo and whatever other info you want to have verified, the service signs it and returns a signature hash.

Once you have that on your client side you can use the public key to check the signature and even though the info can be stored in plaintext the signature can not be easily recreated.

Also check this question for more info.

Community
  • 1
  • 1
Sten Petrov
  • 10,943
  • 1
  • 41
  • 61
  • +1 yeah I'm just trying to make it where the average Joe cannot copy our software from one computer to another without some work. Great information though. It's a lot more than I really need. – ErocM Feb 12 '13 at 16:24
  • Good heavens, your sketched out solution sounds terrible. How is your proposed service not automatically susceptible to chosen-plaintext attacks? RSA depends for its security on the fact that *the text being encrypted with the private key was created by the key holder*. – Eric Lippert Feb 12 '13 at 21:35
  • @EricLippert Either I don't understand your comment or you don't understand the solution. Which part can be attacked with chosen plaintext? This is pretty much how all software activation works – Sten Petrov Feb 12 '13 at 21:37
  • The part where you say "you send a message to the service and it signs it with the private key". What stops the attacker from sending a message of their own choosing to the service? – Eric Lippert Feb 12 '13 at 21:39
  • @EricLippert What stops them is either their email has to be in your database linked to their purchase history OR an activation code randomly generated in your DB that only works once – Sten Petrov Feb 12 '13 at 21:41
  • Perhaps my article on the subject will help. http://blogs.msdn.com/b/ericlippert/archive/2009/12/14/use-the-right-tool-for-the-job.aspx – Eric Lippert Feb 12 '13 at 21:41
  • OK, so then what stops the attacker from *buying a copy of the software* and then supplying their own plaintext? Just because they gave you money doesn't mean they're not trying to compromise your private key. (Or, for that matter, trying to decrypt a message signed with your public key.) – Eric Lippert Feb 12 '13 at 21:45
  • As my linked post states you need to obfuscate your code so that you can reliably get some hardware or environment info. Your web service knows your private key and it's never sent out. Your database keeps count on activation calls. Of course all of this just makes cracking your protection much more expensive, not impossible, since there are multiple attack vectors: activation server, db etc. Consider that even Microsoft's own update mechanism was cracked by Flame - nothing is impossible, just reasonably hard to crack and cheap enough to implement as to be worth the effort – Sten Petrov Feb 12 '13 at 22:17
3

The algorithm you're referring to uses the RijndaelManaged class and it seems to be using the default value for its IV property which is (quite rightly) automatically set to a new random value whenever you create a new instance (see documentation).

Hence, you'll get a different result every time. (You'll find more about the purpose of the IV on Wikipedia, for example.)

Bruno
  • 119,590
  • 31
  • 270
  • 376
  • ah ok, do you have an example for an encryption that won't be dynamic? – ErocM Feb 12 '13 at 15:14
  • You can certainly set the IV property if you wish, although this will weaken the encryption. If you want the same result every time, use a cryptographic hash, not an encryption algorithm (although it's not the same purpose at all). – Bruno Feb 12 '13 at 15:15
  • are you referring to this section when you say set it: var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV) – ErocM Feb 12 '13 at 15:18
  • 1
    Yes, I don't see `aesAlg.IV` initialised anywhere in the code before, so I guess it's using the default value. It's a property that can be set. This being said, it's not clear whether what you're trying to do is a good idea. Using different IVs is actually a good thing. You seem to be a little confused between the purpose of encryption, signing and hashing. – Bruno Feb 12 '13 at 15:22
  • yup that's what I figured tyvm for the info – ErocM Feb 12 '13 at 16:24
0

Yeah most AES encryption is non-deterministic (and for good reason) it will not work for you, but since you just want to compare a cryptographic result and you aren't really wanting to decrypt, might I suggest using HMAC instead.

jbtule
  • 31,383
  • 12
  • 95
  • 128