Encrypt/decrypt a string without traditional encryption semantics (low security) - c#

I want to encrypt/decrypt (or shuffle/un-shuffle) a string without any dependencies on specialized .NET encryption namespaces or use of salt, keys, etc. Literally shuffling everything in the string beyond recognition and then un-shuffling when it's needed.
This is meant for a "no" security situation where even if the user manages to get a hold of the file where the encrypted string is held and figure out the encryption scheme, they don't gain anything meaningful for this specific application.
What is the easiest, most straightforward way of doing this other than shuffling a character array using a pre-defined RNG seed?

XOR every byte in the string with (length of the string modulus 256). If Mod returns 0, use some other known and fixed non-zero value.
I state this answer at the risk of security gurus coming back and saying.. bad answer.. don't do that.. leave it for us (security experts) etc etc.. But you already indicated what you really want is some form of obscurity, and not encryption or security.
Note - I do agree that this is no security by modern standards. Period.

Related

Best practice of Hashing passwords

I would like to know which method to use to store passwords in database. I have implemented it using MD5 but according to some posts SHA1 is more secure. Is there any other method which is more secure?
Please help me finding out a best method to secure passwords.
Sure SHA1 is more secure that MD5, but for most purposes it is not secure enough.
You will probably find useful the video How NOT to Store Passwords by Computerphile - 9 minutes and 24 seconds long.
You must realize that there is much to cover when it comes to authentication and access control, so having a good hashing scheme is not enough.
On storing passwords.
As you already know, you don't store the password. In fact, when it comes to storing passwords, in general terms you want to store salted hashes of the passwords, using a modern algorithm optimized for this purpose. For the salt it is considered ok to store it alongside to the hash, for the salt value use a random value as long as possible.
Note: When generating random value for security purposes, use a cryptographic secure generator (such as a subclass of RandomNumberGenerator for .NET - example). This random number generator are designed to be hard to predict. While standard random number generator are meant to be repeatable (That is with System.Random all you need is the seed to generate all the values, and to guess the seed all you need is enough consecutive values generated with the same seed).
Also note: Most hashes are optimized to be fast to calculate, in that category falls both MD5 and SHA1. You should choose one that is not that fast, so that the attack will take a reasonable amount of time to compute the hashes when trying to crack your passwords.
One such algorithm is BCrypt - others include Scrypt and PBKDF2 - on using BCrypt from C# you will find the article Use BCrypt to Hash Your Passwords: Example for C# and SQL Server useful. If you can't resource to BCrypt or similar algorithm, you should atleast use a variant of SHA2 (SHA256, SHA512 and so on).
Addendum: You can use the class HMACSHA256 which is available in the BLC as a key derivation function, pass your salt as key. This is preferible to appending or prepending the salt (which could fall to Length extension attacks). That is, if you use HMAC, and your hash algorithm is vulerable to Length extension attacks (known or to be discovered), your system is till secure. MD5, SHA1 and SHA2 as suceptible to this kind of attack. SHA3 is not. Sadly SHA3 is not included in the BLC (no, it is not SHA384), you can get it from Multiformats.Hash or HashLib. I have to mention that SHA3 is also designed to be fast when implemented in hardware. And remember, for passwords an slow hash is better.
Addendum: Argon2
As it was pointed a year ago this answer should be updated to mention of Argon2. I did write the original answer before that existed.
At the time, I had not found an implementation for C# that I was willing to recommend. Since this answer was brought to my attention, I had another look, and that is no longer the case.
You can use Isopoh.Cryptography.Argon2 which has fully managed code (it is not a C# binding for a C++ implementation, but full C# code), works on all major platforms and there are Nugets available.
Notes:
Use Argon2Version.Nineteen. This is Argon2 v.1.3 (Nineteen = 0x13) which fixes known vulnerabilities.
Use Argon2Type.DataDependentAddressin (Argon2d), or use Argon2Type.DataIndependentAddressing (Argon2i) with TimeCost >= 10. Argon2d is in theory vulnerable to side channel attacks, as such it is not recommended for code that runs on client machines. Isopoh.Cryptography.Argon2 mitigates this by using OS calls to prevent sensitive memory to be moved to virtual memory/pagefile/swap and zero it as soon as possible. On the other hand Argon2i has a Time-memory tradeoff vulnerability, which allows to compute the hashes faster by using more memory. The paper Towards Practical Attacks on Argon2i and Balloon Hashing shows that you need 10 iterations/passes to make the exploit inefficient, even in Argon2 v.1.3.
Here are some recommended reading:
Speed Hashing
You're Probably Storing Passwords Incorrectly
Everything you ever wanted to know about building a secure password reset feature
The definitive guide to form based website authentication
OWASP's Password Storage Cheat Sheet
OWASP's Forgot Password Cheat Sheet
Also the video: Crypto is Back! - Google Tech Talk - August 5, 2009 - 54 minutes and 32 seconds long.
On recovering a password.
First off: don't. The point of the password recovery option is not to recover the password, but to recover access to the application. So... how do you recover access to the application?
I'm glad you ask. What you need is an alternative way to verify the identity of the user. This could be a second factor authentication (anything from security question to using a hardware key generator). Yet, what is often done is to resource on third party, such as mail.
So, you want to know if the user is the owner of the email (or cellphone, or whatever) the user has previouly claim to own. In order to do so you send a code (often refered as token or cookie) to that email (or whatever). This must be a random generated code with a cryptographic secure generator so that nobody else - except the owner of that email (or whatever) - will be able to know what that code is.
Now, if the user presents to your application that code, you are almost sure it is the right user.
Almost because: emails (or whatever) could has been stored in an unsecure location. To mitigate that, you want to put a time limit on your code (cookie or token). Also, if a code has been used, it should NOT work again. And for extra security you could resource to a CAPTCHA, to ensure this code doesn't come from a bot that just got lucky.
For more on this topic (this links are also presented above):
Everything you ever wanted to know about building a secure password reset feature
OWASP's Forgot Password Cheat Sheet
SHA1 has less vulnerabilities than MD5. It's a newer algorithm that utilizes more bits and requires more processing to "crack." You can view most of the mainstream hash algorithms and their known vulnerabilities here: http://en.wikipedia.org/wiki/Cryptographic_hash_function
As someone already commented, definitely make sure you add "salt" to your password hash to further obscure any possible pattern.

Encrypt a string twice... Good, Bad or Ugly?

I'm working on an encryption class that is using Rijndael algorithm (C#, ASP.Net 4.5), and out of curiosity I was wondering how beneficial would it be to encrypt the string twice. I mean Encrypt the string with a key and then Encrypt the resulting encryption with another key?
Does this make it that much more secure (I know nothing is ever secure and there could be other holes in my software that could be used to exploit)? Is it worth the CPU overhead (not sure how heavy this is but I can't imagine it would light)?
I was looking for some suggestions online but was not able to find any. Any thoughts?
Have a couple of questions that may be of use to you:
Is there any benefit to encrypting twice using pgp?
Is encrypting twice good or bad?
https://crypto.stackexchange.com/questions/779/hashing-or-encrypting-twice-to-increase-security
https://crypto.stackexchange.com/questions/5382/is-it-safer-to-encrypt-twice-with-rsa
https://crypto.stackexchange.com/questions/2314/does-encrypting-twice-using-the-same-block-cipher-produce-a-security-weakness
General idea seems to be this point:
Well, think about it this way. If breaking one encryption with brute
force will take longer than the lifetime of the universe, are you any
safer with an encryption scheme that will take twice the lifetime of
the universe? No. The first encryption cannot be broken. Adding a
second encryption just adds computation overhead with no real benefit. - mikeazo
I would advise asking this question in https://crypto.stackexchange.com/, they may give you more detailed information on the topic.
There's a simple rule in cryptography. All the security should be in the key. Based on that there should be no additional security in encrypting twice because all your security should be in the choice and storage of your key.
Now that being said... you could get some additional security if you make wrong choices. For example say you encrypt the first time with ECB mode (Electronic Code book), because of the way that mode works (by encrypting each block of your plaintext separately), you could get extra security by encrypting a second time in a more secure mode (CBC or CTR). But... you could just as well encrypt in CBC mode the first time around.
You could encrypt the first time with an insecure algorithm (such as DES) and encrypt a second time with a much better algorithm (such as AES).
But these situations are hypothetical and would require you to intentionally make mistakes or be extremely negligent. If you use AES (Rijandael) twice in a secure mode like CTR or CBC then you will not get any additional security from encrypting twice so long as your key is stored securly and selected in a secure manner.

Same length output Encryption and Decryption in C# [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I encrypt a string and get a equal length encrypted string?
I am new to Encryption and Decryption. I have a string which is 24 char length. I need to encrypt and decrypt the word. The encryption may be less secure but I need encrypted word should be same length as input string (24 char). I have searched through web and find some sample Encryption algorithm (AES, MD5). But the encrypted word is too length than input string. This is product key that we will share to customer, so strong encryption is not required. It would be useful if you share sample codes.
Use Vernam cipher. For a single string with a truly-randomly generated key it's theoretically unbreakable. If you start using the same key for multiple strings you reduce its security significantly but apparently you are not looking for utmost security. If you are, you must be able to come up with a different random key for each encrypted password.
Although you can find lots of sample code on the web, I think it would be good practice to you to implement it yourself. It's pretty straightforward.
What you're looking for seems to be Format-preserving encryption, I don't think there are any implementations of this in .NET (I certainly haven't used any). You may need to think up a custom algorithm for this. You say strong encryption isn't required, but you'll obviously need the algorithm to not be obvious. Unfortunately there are literally hundreds of ways you could do this, so it depends on which one suits you.
This seems to be a great post for encryption algorithms
To make the cyphertext the same length as the plaintext, use a stream cypher. This can either be a block cypher in CTR mode, such as AES-CTR, or a dedicated stream cypher, like Rabbit or RC4.
Be aware that you cannot reuse a key for a stream cypher, otherwise an attacker will probably be able to break the encryption. Two cyphertexts that use the same key can be used to eliminate the key entirely, leaving just the two plaintexts.
If you only have the one 24 byte word to encrypt then this is not a problem. If you need to encrypt more than one piece of data, then key management becomes important.

How to encrypt variable length text in PHP and C#?

For a game I am currently making I am in need of encrypting a variable length string (this could be a short as 10 characters or a full XML document) in C# and then sending this to a PHP script which decrypts and processes the information. I am unfortunately completely in the dark when it comes to cryptography and am having trouble finding something that can suite my needs in this case. Is there a library which can do this kind of variable length encryption across multiple platforms such as this?
AES, sometimes called Rijndael, might be a choice for you. It's a standard created by the National Institute of Standards and Technology, an agency of the US government.
It's available in PHP using the mcrypt extension, and there seems to be a managed library built in to the .Net framework. See this previous SO question for more on C#'s implementation. I know little about C# and .Net, but the answer there has 23 votes, so is likely to be on to something. (Edit: #Fun Mun Pieng's answer contains a reference to AES itself, and might be more up to date or otherwise useful than the post I linked.)
AES is a block cypher, meaning that it operates best on lengths of text of a specific set of lengths. There are multiple operation modes and padding schemes that you'll want to read up on and select. If you use the same operation mode and padding on both sides, you should have perfect interoperability.
Keep in mind that AES is a symmetric cypher. This means that the same key is used to both encrypt and decrypt. It might not be the best choice for you. If your users gain access to the key, the encryption becomes worthless.
Public-key cryptography might be a better choice for you. It uses two keys instead of one. Data encrypted using the public key can only be decrypted by the private key. This means that you don't need to worry too much about the public key falling into the wrong hands, as no data can actually be decrypted about it. It may allow troublesome users to still craft legit-looking messages, though.
PHP's best option for public-key cryptography is the standard OpenSSL extension, which uses the industry standard RSA system. A quick look at Google suggests that there's also native .Net support for RSA as well. Like AES, you may need to worry about modes of operation or padding, but again you should get complete interoperation by using the same methodology on both sides. The one possible annoyance will be initial key creation, and how each side wants to store private and public keys.
For the C# part, you could use the System.Security.Cryptography namespace. Eg:
System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create();
System.Security.Cryptography.ICryptoTransform enc = aes.CreateEncryptor();
// byte[] input;
// byte[] output = new output[512]
int size = enc.TransformBlock(input, 0, input.Length, output, 0);
I have no idea how to do it for the PHP end, but I'm sure you can find a way to decrypt from standard algorithms such as DES, AES, RSA. And remember to pass the key.
For your case, I guess asymmetric encryption is more suitable.

Using GetHashCode to "secure" users passwords

The company I work for has taken on a support contract for a large order processing system. As part of the initial system audit I noticed that the passwords stored in the database were actually the hashcode of the password.
Essentially:
string pwd = "some pasword";
string securePwd = pwd.GetHashCode();
My question is, how secure or otherwise is this?
I'm not comfortable with it, but I don't know enough about how GetHashCode works. I would prefer to use something like an MD5 hash, but if I'm wasting my time then I won't bother.
You should use a salted, cryptographically strong hash, such as SHA256Managed.
Jeff Attwood has a few good posts on this topic:
Rainbow Hash Cracking
You're Probably Storing Passwords Incorrectly
It's not just insecure, but also subject to change:
http://netrsc.blogspot.com/2008/08/gethashcode-differs-on-systems.html
The value returned by GetHashValue for a given input has changed in the past.
There's no guarantee it will even be the same between different executions of the app.
GetHashCode returns a 32 bit integer as the hash value. Considering the birthday paradox, it's not a long enough hash value due to the relatively high probability of collisions, even if it were explicitly designed to be collision resistant, which is not.
You should go for SHA256 or another cryptographically secure hash function designed to handle such a task.
To store passwords, just using a simple hash function is not enough. You should add some random "salt" per user and iterate enough times so that it would be computationally expensive to brute force. Therefore, you should use something like bcrypt, scrypt, PBKDF2, with a large number of iterations.
I'd recommend using BCrypt instead. As others have already said using GetHashCode for passwords isn't a good idea.
GetHashCode was definitely not designed to be used in this way as the implementation does not guarantee different hash returns for different objects. This means that potentially multiple passwords could produce the same hash. It also isn't guaranteed to return the same hash value on different versions of the .NET framework meaning that an upgrade could potentially produce a different hash for the same string, rendering your passwords unusable to you.
It is recommended that you use a salted hash or even MD5 at a push. You can easily switch it to something within the Security.Cryptography namespace.
As others have said, GetHashCode isn't designed for what you're trying to do. There is a really excellent article on how to handle user passwords securely.
To summarise the article, you need to use either a relatively slow adaptive hashing scheme such as bcrypt, or alternatively the Stanford Secure Remote Password Protocol. I would suggest the former. And of course you should also use a salt.

Categories

Resources