I'm not asking for a tutorial with code, I'm trying to do the research, but I want to make sure I'm asking the right questions.
What's the best form of encryption I can use out of the box with .NET?
Public/Private key, where do I store these things securely?
What tools should I have in order to do this properly?
I started off with an AESCryptoServiceProvider, encrypted a string I passed in, I was happy. Tested that if I called it twice it would come out with the same value. Then realized I hadn't provided any form of key, so a second run of the app yielded different results. So I began reading up, seeing RSA Public/Private keys etc. etc. And just want make sure I'm going down the right path with the reading I'm doing. There's tons of examples out there, few mention where you put these keys or where you even get them from.
There's a lot of cryptological functions in System.Security.Cryptography.
They have hashes, crypts, streams, and a lot more.
The RSA provider is a good one. And about storing the constants securely. I can only suggest storing them crypted in the solution.
You shouldn't be able to read them from the source, so there needs to be some kind of security after the assembly has build. Maybe obfuscation, maybe something else.
About the generating of the key, do not use your own system, or any development system I guess.
EDIT:
To generate keys you better use either user input, for example, just create a little application, that calculated the time it takes to type a certain piece of text, per letter.
Or use a HRNG/TRNG, Hardware Random Number Generator (uses input from the actual world, retrieved through sensors). Or True Random Number Generator, basically also HRNG, but mostly with other forms of input, very advanced.
RANDOM.ORG should be able to help you out.
If it's not that extreme important, just go smack your head against your keyboard, and see the results :).
Go for AES. Stack Overflow already has a wonderful implementation of AES Algorithm as an answer.
Regarding "Public/Private key, where do I store these things securely?", I recommend that you do not re-invent the wheel. Microsoft has already spent a great deal of effort to build, and is actively maintaining and (hopefully) improving, infrastructure to store private keys: https://msdn.microsoft.com/en-us/library/windows/desktop/bb204778%28v=vs.85%29.aspx. You can use the native key storage.
Related
I have been looking for a simple encryption/decryption class for storing information in the database. Trouble is I have no clue what I'm looking at half the time, so I really don't know if what I find is really all that worth implementing for what I need, whether it be over-complex or too easy to crack.
I have brain stormed about it for a bit, my first thought-train leading to a simple "switch, add, multiply" key for the ACII Values, but I think that wouldn't really be worth it after seeing what encryption classes actually are.
Essentially I'm looking for a key that encrypts any and all data (including table and column names) on storage, and decrypts on withdrawal. But like I said, doesn't need to be too complex, but if someone does want to access the data, they have to earn it haha.
Can anyone suggest a good link/provide a simple class for what I'm looking for? It could possibly be something I have found before, but like I said, I haven't the faintest as to what I'm looking at half the time
Thanks in advance!
Pre-emptive Edit I know some Databases have their own encrypt/decrypt methods, but I figure this is the easiest way to implement it because I will be working will multiple different database programs.
AES 256 is (while potentially overkill) a very secure encryption algorithm. Microsoft provides an implementation in System.Security.Cryptography and the example at MSDN is a great place to get started.
I've used this for database encryption and it works just fine.
Since you said you are new to encryption, I will try to touch on what encryption does, and doesn't do for you. Encryption takes normal data (ie. ("My private string")) and turns it into random data (bunch of bytes), only reversible by knowing the private key (in AES 256). Data, since it is different between cells, and likely private/important information is a good thing to encrypt.
Your database schema is constant, so encryption is only minimally useful here. The difference between calling a table "Names" and "A" and "oiaeoriuojdklfjsad" (this last is an example "encryption") is minimal. This is what is meant by "security by obfuscation". You could argue that choosing a random name is slightly more secure than a descriptive one, but it is really just going to confuse you when you try to use it, and the real "gold" a hacker will want is the data anyways. Knowing what kind of data it is isn't really going to help if it's going up against a good encryption algorithm.
Disclaimer: I'm perfectly aware that a client-side program will never be safe from a dedicated reverse engineer.
Mostly out of personal curiosity, I've been learning about "obfuscation" techniques for C# applications. It seems that a popular technique is "string encryption", which appears to encrypt the string constants in the software and decrypt them for use later. This makes them not appear properly in decompilers like Reflector (please correct me if this is wrong).
If this is true, and you only see an encrypted version of the string in Reflector, what needs to be done (i.e. how difficult is it) to work around this and get the decrypted string? Obviously it must be possible or the application wouldn't be able to do it, but just how much of a deterrent would it be?
I don't have any experience with C# obfuscators, but the Java obfuscators I've looked at (Stringer, Allatori, Zelix Klassmaster, JFuscator) were pretty bad. Usually, I can reverse engineer the encryption algorithm after a day or two, and then I can deobfuscate all apps protected by the same obfuscator version and other versions usually only require a slight tweak.
Note that this is for purely static analysis, to figure out the algorithm and write a script that decrypts it without executing any code. If your goal is to just decrypt things quickly, it's a lot easier to simply execute the decryption function. The good obfuscators have a call context check so you can't do it directly, but it's a simple matter to find and edit out the check. This could potentially be done in only a couple minutes.
Obviously, there are ways to make reverse engineering much harder, but they aren't done in practice.
If you have the encrypted strings in your application, then you also have the decryption key embedded in your application.
So, a moderately determined person could use a debugger to step through the decryption code to retrieve the key, and then decrypt all other strings in your application with the flick of a wrist.
How much time it would need to understand manually
depends on the general obfuscation level,
ie. if there is a method decrypt which can be called just like that...
with compiling and all probably <1min
The other, simple way: Recompile with debug information, set a breakpoint,
execute the program and just read the string in VS
("simple" depends what is necessary to get to this code part)
I only recently learned about the secureString class. I am sure it is not a total solution, but in combination with other techniques, it might help.
http://msdn.microsoft.com/en-us/library/system.security.securestring%28v=vs.80%29.aspx
The value of an instance of SecureString is automatically encrypted when the instance is initialized or when the value is modified.
Note that SecureString has no members that inspect, compare, or convert the value of a SecureString. The absence of such members helps protect the value of the instance from accidental or malicious exposure.
In fact, private methods are implemented in C# that can still be searched with Reflection.
What I am going to do is to write public string Encrypt(string data) and private string Decrypt(string cipher) methods to perform encryption and decryption.
Unfortunately, if someone knows .NET framework, he can use Reflection to find Decrypt methods and it decrypt everything that is encrypted.
It seems that is not that secure. So I want to make Decrypt method to truly private method.
But how to do that?
Updated 09 Jan 2012 10:52PM Sydney Time
bdares provides the technical explanation of this question
Eric Lippert provides the political explanation of this question
Thanks both experts!
You can't. If the attacker has access to your code, compiled or source, he can trace your program and find where it's being encrypted or decrypted.
You can add a layer of security by storing the key in a separate location, but generally if the attacker is executing code on your server, you're already screwed.
(You're only worried about this if the attacker is executing code on your server, because otherwise it doesn't matter whether or not the method is private. Also, he can't use reflection to find method names unless he's executing code on your server. In short: you're worrying about the wrong thing here.)
Your fundamental problem is that you've got the trust model wrong. If someone can use reflection then they are the user. You are the software provider. You work for them. Trust flows from them, not from you. They are the person who has to trust you, not you them.
If you don't trust the user then do not sell them your software in the first place. Don't sell weapons to people who you believe plan to attack you.
I believe you are referring to obfuscation, which is an attempt to hide/disguise code from being read by humans when opened in program such as Reflector.
Supplied within Visual Studio is a community use license for PreEmptive Solutions dotfuscator which will provide this functionality on small projects, and also for Windows Phone projects (if you download the add-on). There are also commercial platforms available too, from the same vendor and others .
This blog post explains a little more.
If you're creating your own encryption method, you're doing it wrong. People who know way more about encryption than you or I have already come up with excellent methods for encryption, and MS has implemented most of them already.
For good encryption, it's the keys, not the method, that makes encryption secure. Keep the keys safe and the algorithm can (and should) be published for all to see.
If you're trying to distribute both content and keep it encrypted, aka DRM, you're most probably doomed to failure unless you can keep the keys very well hidden in hardware, and even that will only buy you some time -- maybe months, maybe years.
I am not sure about your exact application. But if you are selling a product to a customer who will be doing both the Encryption and Decryption on their own system, then there is no way to keep the encryption secret from them. But you can instead allow them to generate a new Private Key for their own use. In this way each customer's data is 'secure' in regards to other customers; though obviously still not so secure within the same customer's site. In other situations where you control the encrypted content you can also look into creating a private master key to be generated on your side and only allow the customer to have a public key.
I need some ideas how to create a activation algorithm. For example i have demo certificate. Providing that the application runs in demo mode. When full version certificate is provided then application runs in full mode.
Is it even possible and how would be a good way creating this system?
One simple was i was thinking would be just have a 2 encrypted strings, now when the decryption is succsessful with the demo public key certificate then the application will run in demo mode and etc..
You could do something like:
Generate public/private key pair
As owner of private key, you can sign those "activation certificates" (called AC from now on)
In your app, with public key, you can check if the sign is correct
As Overbose mentioned -- you can't prevent reverse engineering. In general someone could take functionality and put it in his/hers own app and thus eliminate any possible activation algorithm. So you can only assume (or make) this is hard enough not to be worth the effort (this is the same as for cryptography -- when you make the cost of breaking the message greater then the profit of gaining it you can say it is well secured).
So you could:
Make executable self-verifying (signed by you, self-checking based on hard-coded public key (one thing: you must skip this value when self-checking)).
Do some tricks with pointers (point to the activation function, go to 7th bit and change value of it for something based on value of another pointer; in some weird places change hard-coded values to those based on occurrence of some bits in other places of the code; generally -- make it more difficult to break than by simply changing bits in executable with hex editor)
Try to make some protocol that your server would use to ask questions about the app ("gimme the value of 293 byte of yourself") and check answers.
Use imagination and think of some weird self-checking method nobody used before :)
As mentioned -- none of this is secure from cutting the authentication part off. But nothing is and this could make it harder for crackers.
Background: I've deployed an activation based system built on top of a third-party license system, i.e. server, database, e-commerce integrations. I've also separately written a C# activation system using RSA keys, but never deployed it.
Product Activation commonly means that the software must be activated on a given machine. I assume that's what you mean. If all you want to do is have two strings that mean "demo" and "purchased", then they will be decrypted and distributed within hours (assuming your product is valuable). There is just no point.
So. assuming you want "activation", then when the user purchases your software, the following process needs to happen:
Order-fulfillment software tells Server to generate "Purchase Key" and send to user
User enters "Purchase Key" into software
Software sends Purchase Key and unique Machine ID to server.
Server combines Purchase Key and Machine ID into a string and signs it with its certificate and returns it to user.
Software checks that signature is valid using Servers public key.
Software could check in lots of places: loading the sig in lots of places, checking it in others.
When generating Purchase Keys, the server can store not only what produce was purchased, but what level of product. You can also have "free" products that are time limited, so the user can try the full version of the software for 30 days.
You are using C#, so make sure you obfuscate the binaries, using dotfuscator or equivalent. However, even with that there is nothing you can do against a determined hacker. Your goal, I assume, is to force non-paying users to either be hackers themselves, or to have to risk using a cracked version: kids wont care, corporations might. YMMV.
The code that does the checking needs to be in every assembly that needs protecting, otherwise an attacker can trivially remove protection by replacing the assembly that does the checking. Cut and paste the code if you have to.
Or just buy something.
Another option is to have the server pre-generate "Purchase Keys" and give them to the Order fulfillment service, but then you dont get to link the key to the customers details (at least not until they register). Better to have the ecommerce server hit your server when a purchase has been made, and have your server send it out.
The hard part isn't so much the generation of activation keys as it is the creation of the server, database, and the integration with e-commerce software, and most of all, human issues: do you allow unlimited installs per Purchase Key? Only 1? If only 1 then you have to have customer-support and a way to allow a user to install it on a new machine. That's just one issue. All sorts of fun.
This guy wrote a blog post about a similar idea, explaining what he did with their own commercial software. Also wrote a list of recommendations about the most obvious cracking techniques. Hope it helps.
One simple was i was thinking would be just have a 2 encrypted
strings, now when the decryption is succsessful with the demo public
key certificate then the application will run in demo mode and etc..
Could be a simple solution. But this way you won't prevent someone to reverse engineer your binaries and make the execution jump to the correct line. Everyone has your program, has a complete version of it, so it's only a matter of find how to break this simple mechanism.
Maybe a better solution is encrypt a part of the binaries needed to use the full application version, instead of a simple string. This way to execute the application complete version someone need to decrypt those binaries in order to execute them.
Please take in consideration that even that solution isn't enough. There are other problems with that:
Does all the version of your tool will share the same encryption key? Breaking one of them for breaking all..
Even if you use a different key for each binary application released, does the encrypted binary are identical? Once cracked one, you can reuse the unencrypted binaries for all distributed applications.
How to solve these problems? There's no simple solution. Most of the more important commercial software with even sophisticated protection systems are broken just few hours or days after they have been released.
Product activation is not a problem that asymmetric cryptography can solve. Asymmetric cryptography is about keeping secrets from your adversary. The problem is that you can't keep a secret that is stored on you're adversaries machine, that would be security though obscurity.
The correct way to do product activation. Is to generate a Cryptographic Nonce that is stored in a database on your server. You give this Nonce to the customer when they buy the product, and then they activate it online. This activation process could download new material, which would make it more difficult for the attacker to modify the copy they have to "unlock" new features.
But even with DRM systems that require you to be online while using the product. Like the ones found in new games like "From Dust" are still broken within hours of their release.
One of the benefits of public key encryption is that you can verify the origin of a given piece of data. So if you store the public key in your assembly, then sign a given piece of data (say an authorization code or serial number) your assembly can verifiably determine that you were the one that created that data - and not a hacker. The actual data itself isn't all that important - it can be a simple pass/fail value.
This is actually pretty easy to do with .NET. You can use an x509 certificates or like we use in DeployLX Licensing the RSACryptoServiceProvider.
I would highly recommend buying a commercial product (doesn't really matter which one, though DeployLX is excellent) and not doing this yourself for 2 reasons
Even if you're a great developer, you'll probably get it wrong the first time. And any savings you might have enjoyed by rolling your own will be lost to recovering from that mistake.
You'll spend far more time working on your own system - time that you should spend making your product great.
The second phase in protecting the software is to make sure that it runs the way you created it - and hasn't been modified by a hacker. It really doesn't matter what encryption you use if hackers can check if( licensed ) to if( true ).
You can use AsProtect to solve this problem. This is good staring point.
So, to start off, I want to point out that I know that these things are never fool-proof and if enough effort is applied anything can be broken.
But: Say I hand a piece of software to someone (that I have written) and get them to run it. I want to verify the result that they get. I was thinking of using some sort of encryption/hash that I can use to verify that they've run it and obtained a satisfactory result.
I also don't want the result to be "fakeable" (though again, I know that if enough effort to break it is applied etc etc...). This means therefore, that if I use a hash, I can't just have a hash for "yes" and a hash for "no" (as this means the hash is going to be only one of 2 options - easily fakeable).
I want the user of the tool to hand something back to me (in possibly an email for example), something as small as possible (so for example, I don't want to be trawling through lines and lines of logs).
How would you go about implementing this? I possibly haven't explained things the greatest, but hopefully you get the gist of what I want to do.
If anyone has implemented this sort of thing before, any pointers would be much appreciated.
This question is more about "how to implement" rather than specifically asking about code, so if I've missed an important tag please feel free to edit!
I think what you're looking for is non-repudiation. You're right, a hash won't suffice here - you'd have to look into some kind of encryption and digital signature on the "work done", probably PKI. This is a pretty wide field, I'd say you'll need both authentication and integrity verification (e.g. Piskvor did that, and he did it this way at that time).
To take a bird's eye view, the main flow would be something like this:
On user's computer:
run process
get result, add timestamp etc.
encrypt, using your public key
sign, using the user's private key (you may need some way to identify the user here - passphrases, smart cards, biometrics, ...)
send to your server
On your server:
verify signature using the user's public key
decrypt using your private key
process as needed
Of course, this gets you into the complicated and wonderful world that is Public Key Infrastructure; but done correctly, you'll have a rather good assurance that the events actually happened the way your logs show.
I'm pasting in one of your comments here, because it goes to the heart of the matter:
Hi Eric. I should have pointed out
that the tool isn't going out
publically, it will go to a select
list of trusted users. The tool being
disassembled isn't an issue. I'm not
really bothered about encryption, all
I need to do is be able to verify that
they ran a specific process and got a
legitimate result. The tool verifies
stuff, so I don't want them to just
assume that something works fine and
not run the tool.
So basically, the threat we're protecting against is lazy users, who will fail to run the process and simply say "Yes Andy, I ran it!". This isn't too hard to solve, because it means we don't need a cryptographically unbreakable system (which is lucky, because that isn't possible in this case, anyway!) - all we need is a system where breaking it is more effort for the user than just following the rules and running the process.
The easiest way to do this is to take a couple of items that aren't constant and are easy for you to verify, and hash them. For example, your response message could be:
System Date / Time
Hostname
Username
Test Result
HASH(System Date / Time | Hostname | Username | Test Result)
Again, this isn't cryptographically secure - anyone who knows the algorithm can fake the answer - but as long as doing so is more trouble than actually running the process, you should be fine. The inclusion of the system date/time protects against a naive replay attack (just sending the same answer as last time), which should be enough.
How about you take the output of your program (either "yes" or "no"?), and concatenate it with a random number, then include the hash of that string?
So you end up with the user sending you something like:
YES-3456234
b23603f87c54800bef63746c34aa9195
This means there will be plenty of unique hashes, despite only two possible outputs.
Then you can verify that md5("YES-3456234") == "b23603f87c54800bef63746c34aa9195".
If the user is not technical enough to figure out how to generate an md5 hash, this should be enough.
A slightly better solution would be concatenate another (hard-coded, "secret") salt in order to generate the hash, but leave this salt out of the output.
Now you have:
YES-3456234
01428dd9267d485e8f5440ab5d6b75bd
And you can verify that
md5("YES-3456234" + "secretsalt") == "01428dd9267d485e8f5440ab5d6b75bd"
This means that even if the user is clever enough to generate his own md5 hash, he can't fake the output without knowing the secret salt as well.
Of course, if he is clever enough, he can extract the salt from your program.
If something more bullet-proof is needed, then you're looking at proper cryptographic signature generation, and I'll just refer you to Piskvor's answer, since I have nothing useful to add to that :)
In theory this is possible by using some sort of private salt and a hashing algorithm, basically a digital signature. The program has a private salt that it adds to the input before hashing. Private means the user does not have access to it, you however do know the salt.
The user sends you his result and the signature generated by the program. So you can now confirm the result by checking if hash(result + private_salt) == signature. If it is not, the result is forged.
In practice this is almost impossible, because you cannot hide the salt from the user. It's basically the same problem that is discussed in this question: How do you hide secret keys in code?
You could make the application a web app to which they have no source code access or access to the server on which it runs. Then your application can log its activity, and you can trust those logs.
Once a user has an executable program in their hands, then anything can be faked.
It's worth noting that you aren't really looking for encryption.
The "non-repudiation" answer is almost on the money, but all you really need to guarantee where your message has come from is to securely sign the message. It doesn't matter if someone can intercept and read your message, as long as they can't tamper with it without you knowing.
I've implemented something similar before information was sent plaintext - because it wasn't confidential - but an obfuscated signing mechanism meant that we could be (reasonably) confident that the message was generated by our client software.
Note that you can basically never guarantee security if the app is on someone else's hardware - but security is never about "certainty", it's about "confidence" - are you confident enough for your business needs that the message hasn't been tampered with?