rails - Creating a Secure ID / Password - ruby-on-rails

I'm looking for a RAIL way to create a very secure UID that will act as a authentication token.
I had been using UUID but was told they are not secure. I'd like to learn, what is the method of choice these days in ruby/rails 3?

This question is in no way Rails specific.
UUID is not secure for the simple fact that it is a unique identifier and it contains 'constant' parts of a given machine (e.g. it might use the MAC address for a machine), which makes it easier to guess.
If you want 100k+ strings without someone guessing one, you need to be able to distribute your keys across a large key-space. Let me explain:
If you only need 1 key (let's), you might pick 'A'. In a key-space of A-Z you have 1:26 chance of guessing it. Now, if you'd extend your key-space to A-Za-z you have a 1:52 chance of guessing.
Need more security still? Use a longer key: 'AA' 1:2704 chance.
Now, if you'd want to have 2000 keys and use a key length of 2 (e.g. 'AA'), there's a 2000:2704 => 1:1.352 chance someone might guess it. Pretty bad.
So, the key here is to pick a very long key size. With Digest::SHA1 you get 40-character keys (using Hex, with 16 different values per character). That's 1.46150164e48 unique values. Your 100k values should be random enough.
Edit:
With 40-digit HEX SHA1 values you have a 1:461501640000000000000000000000000000000000000000000 chance of guessing one. That takes ages.

Related

Can I use GUID to implement oauth_token or oauth_nonce

I want to know how oauth_token, oauth_nonce or oauth_token_secret is implemented.
I have already read the specification about oauth1.0 and oauth1.0a, but i am confused about how they are implemented.
For oauth_token, I just know it's a string, but are there any more information about how it's implemented, for example how Google or Facebook implements it,can it just be a GUID?
For oauth_nonce, as i know, it should be unique per request, but GUID is also unique, can i just use it? From a lot website i see it is a number converted to Base 64 string, why should it be like this?
Keep in mind that GUID is unique but usually not totally random. To avoid collisions, some parts of the GUID are based on the MAC address and current timestamp of the generating computer. This makes a GUID easier to guess than a totally random number of the same length.
I think a GUID is ok to use for generating unique non-secret values. They are quite long though. Given the short lifetime of most kinds of tokens, I guess creating random bits is easier and simply faster, and still reasonably unique. It also saves bandwidth and storage to use smaller ids.
Since you often can't transmit raw bits, Base64 encoding is done to send the random number using only ASCII characters. I've also seen Base62 encoding used for this, which is sometimes more convenient because it doesn't contain any special characters (only 0-9a-zA-Z).

ASP.NET MVC Model id type --- best practices

Simple question. I have several different models stored in SQL databases. A Table of images records with byte data, large multi-field user data table, ect. All of these models require primary keys. Most beginner tutorials show usage of int for ids. Is this standard and professional. I find it odd to start use int since is variable in length and starts with 1 :S
Sorry for the amateur question, but I couldn't find any adequate materials on the subject via google.
There's nothing implicitly unprofessional about the use of INT or any other integral data type as a primary key or identity column. It just depends on your business needs. In the interest of keeping programming as simple as possible, the INT data type is a fine choice for many business needs:
It is capable of representing about 2.1 billion unique records.
It consumes minimal hard disk space in modern hardware.
It is fast for SELECTs and UPDATEs.
It is fairly ease to refactor up to a larger integral if the number of records threatens to exceed the limits. BIGINT can address more records than you can put in your database. Seriously.
One reason you might not want to use an integral primary key:
You might use a Guid (or UNIQUEIDENTIFIER in SQL Server terms) for global uniqueness. In other words, if you migrate your data to another location, the primary key should still be unique.
Yes, int is industry standard.
Even beyond databases, I rarely see C# code with uint or any of the other variants for representing whole numbers. Occasionally byte is used in arrays. long is used when int may not be big enough to cover all possibilities.
One advantage of always using int is that you can pass id variables around without having to worry about casting between the different integer types.
This is 100% ok, and widely used. Some use longs for primary keys, since their max value is bigger. Though, not necessary in most occasions.
Guid type is also used sometimes as an ID. It has some benefits, like fixed length, global uniqueness and unpredictability. And some issues like lower search performance and it's hard to remember.

SHA1 not secure? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is SHA-1 secure for password storage?
I am new to encryption and I have a doubt. It may be a stupid question but I am going to ask. I know SHA1 is not decrypt-able. But a quick thought, if a hacker create a table containing two columns - non encrypted password and its SHA1 encrypted value. And the rows contains passwords of all combinations of characters which he generated using a program in 6 months (say 900 million records). Can't he easily get the non encrypted password if he got an SHA1 encrypted password?
If yes is there any solution to prevent this?
Thanks in advance.
The attack you’re describing is called a rainbow table. Yes, it certainly is a valid concern for short passwords – thus the typical security requirements on the minimum length of passwords. However, the size of the table needs to grow exponentially with the length of the password; for example, an alphanumeric case-sensitive password would increase the table by a factor of 62 for each additional character. Thus, it becomes intractable to compute beyond a certain length. (Just 8 characters would give rise to around 218 trillion combinations.)
Another precaution you could take is to salt your passwords (which may simplistically involve appending a constant string to each password before computing its hash). This way, even if the attacker has access to a pre-computed rainbow table, it would be of no use against your hashes; a new rainbow table would have to be computed for each salt.
The common solution to prevent rainbow table attacks is using a Salt.
I would add though, that SHA1 is not considered very secure. Using brute force to find the unscrambled passwords is quite easy with a powerful computer. For storing passwords, it's recommended to use a slow hashing algorithm like bcrypt or PBKDF2.
Yes. That is why its important to salt your hash. As long as your has is properly salted the type of table you are talking about is only useful for a single password.
see http://msdn.microsoft.com/en-us/magazine/cc164107.aspx for example
A dictionary attack, such as the one you described, can be prevented by salting the hash. Essentially, you force the length and complexity of the plaintext beyond the scope of the dictionary being used.
It's simple to implement, too. One way is to maintain a password, such as "0shunF1ave" and attach it to your plaintext. So, instead of storing SHA1(password), you'd store SHA1("0shunF1ave"+password). When you verify the password, you perform the same hash against the candidate like SHA1("0shunF1av1"+candidate) to your originally stored hash and see if they match.

If you know the length of a string and apply a SHA1 hash to it, can you unhash it?

Just wondering if knowing the original string length means that you can better unlash a SHA1 encryption.
No, not in the general case: a hash function is not an encryption function and it is not designed to be reversible.
It is usually impossible to recover the original hash for certain. This is because the domain size of a hash function is larger than the range of the function. For SHA-1 the domain is unbounded but the range is 160bits.
That means that, by the Pigeonhole principle, multiple values in the domain map to the same value in the range. When such two values map to the same hash, it is called a hash collision.
However, for a specific limited set of inputs (where the domain of the inputs is much smaller than the range of the hash function), then if a hash collision is found, such as through an brute force search, it may be "acceptable" to assume that the input causing the hash was the original value. The above process is effectively a preimage attack. Note that this approach very quickly becomes infeasible, as demonstrated at the bottom. (There are likely some nice math formulas that can define "acceptable" in terms of chance of collision for a given domain size, but I am not this savvy.)
The only way to know that this was the only input that mapped to the hash, however, would be to perform an exhaustive search over all the values in the range -- such as all strings with the given length -- and ensure that it was the only such input that resulted in the given hash value.
Do note, however, that in no case is the hash process "reversed". Even without the Pigeon hole principle in effect, SHA-1 and other cryptographic hash functions are especially designed to be infeasible to reverse -- that is, they are "one way" hash functions. There are some advanced techniques which can be used to reduce the range of various hashes; these are best left to Ph.D's or people who specialize in cryptography analysis :-)
Happy coding.
For fun, try creating a brute-force preimage attack on a string of 3 characters. Assuming only English letters (A-Z, a-z) and numbers (0-9) are allowed, there are "only" 623 (238,328) combinations in this case. Then try on a string of 4 characters (624 = 14,776,336 combinations) ... 5 characters (625 = 916,132,832 combinations) ... 6 characters (626 = 56,800,235,584 combinations) ...
Note how much larger the domain is for each additional character: this approach quickly becomes impractical (or "infeasible") and the hash function wins :-)
One way password crackers speed up preimage attacks is to use rainbow tables (which may only cover a small set of all values in the domain they are designed to attack), which is why passwords that use hashing (SHA-1 or otherwise) should always have a large random salt as well.
Hash functions are one-way function. For a given size there are many strings that may have produced that hash.
Now, if you know that the input size is fixed an small enough, let's say 10 bytes, and you know that each byte can have only certain values (for example ASCII's A-Za-z0-9), then you can use that information to precompute all the possible hashes and find which plain text produces the hash you have. This technique is the basis for Rainbow tables.
If this was possible , SHA1 would not be that secure now. Is it ? So no you cannot unless you have considerable computing power [2^80 operations]. In which case you don't need to know the length either.
One of the basic property of a good Cryptographic hash function of which SHA1 happens to be one is
it is infeasible to generate a message that has a given hash
Theoretically, let's say the string was also known to be solely of ASCII characters, and it's of size n.
There are 95 characters in ASCII not including controls. We'll assume controls weren't used.
There are 95ⁿ possible such strings.
There are 1.461501×10⁴⁸ possible SHA-1 values (give or take) and a just n=25, there are 2.7739×10⁴⁹ possible ASCII-only strings without controls in them, which would mean guaranteed collisions (some such strings have the same SHA-1).
So, we only need to get to n=25 when this becomes impossible even with infinite resources and time.
And remember, up until now I've been making it deliberately easy with my ASCII-only rule. Real-world modern text doesn't follow that.
Of course, only a subset of such strings would be anything likely to be real (if one says "hello my name is Jon" and the other says "fsdfw09r12esaf" then it was probably the first). Stil though, up until now I was assuming infinite time and computing power. If we want to work it out sometime before the universe ends, we can't assume that.
Of course, the nature of the attack is also important. In some cases I want to find the original text, while in others I'll be happy with gibberish with the same hash (if I can input it into a system expecting a password).
Really though, the answer is no.
I posted this as an answer to another question, but I think it is applicable here:
SHA1 is a hashing algorithm. Hashing is one-way, which means that you can't recover the input from the output.
This picture demonstrates what hashing is, somewhat:
As you can see, both John Smith and Sandra Dee are mapped to 02. This means that you can't recover which name was hashed given only 02.
Hashing is used basically due to this principle:
If hash(A) == hash(B), then there's a really good chance that A == B. Hashing maps large data sets (like a whole database) to a tiny output, like a 10-character string. If you move the database and the hash of both the input and the output are the same, then you can be pretty sure that the database is intact. It's much faster than comparing both databases byte-by-byte.
That can be seen in the image. The long names are mapped to 2-digit numbers.
To adapt to your question, if you use bruteforce search, for a string of a given length (say length l) you will have to hash through (dictionary size)^l different hashes.
If the dictionary consists of only alphanumeric case-sensitive characters, then you have (10 + 26 + 26)^l = 62^l hashes to hash. I'm not sure how many FLOPS are required to produce one hash (as it is dependent on the hash's length). Let's be super-unrealistic and say it takes 10 FLOP to perform one hash.
For a 12-character password, that's 62^12 ~ 10^21. That's 10,000 seconds of computations on the fastest supercomputer to date.
Multiply that by a few thousand and you'll see that it is unfeasible if I increase my dictionary size a little bit or make my password longer.

Convert SHA1 back to string

I have a user model on my app, and my password field uses sha1. What i want is to, when i get the sha1 from the DB, to make it a string again. How do i do that?
You can't - SHA1 is a one-way hash. Given the output of SHA1(X), is not possible to retrieve X (at least, not without a brute force search or dictionary/rainbow table scan)
A very simple way of thinking about this is to imagine I give you a set of three-digit numbers to add up, and you tell me the final two digits of that sum. It's not possible from those two digits for me to work out exactly which numbers you started out with.
See also
Is it possible to reverse a sha1?
Decode sha1 string to normal string
Thought relating MD5, these other questions may also enlighten you:
Reversing an MD5 Hash
How can it be impossible to “decrypt” an MD5 hash?
You can't -- that's the point of SHA1, MDB5, etc. Most of those are one-way hashes for security. If it could be reversed, then anyone who gained access to your database could get all of the passwords. That would be bad.
Instead of dehashing your database, instead hash the password attempt and compare that to the hashed value in the database.
If you're talking about this from a practical viewpoint, just give up now and consider it impossible. Finding the original string is impossible (except by accident). Most of the point of a cryptographically secure hash is to ensure you can't find any other string that produces the same hash either.
If you're interested in research into secure hash algorithms: finding a string that will produce a given hash is called a "preimage". If you can manage to do so (with reasonable computational complexity) for SHA-1 you'll probably become reasonably famous among cryptanalysis researchers. The best "break" against SHA-1 that's currently known is a way to find two input strings that produce the same hash, but 1) it's computationally quite expensive (think in terms of a number of machines running 24/7 for months at a time to find one such pair), and does not work for an arbitrary hash value -- it finds one of a special class of input strings for which a matching pair is (relatively) easy to find.
SHA is a hashing algorithm. You can compare the hash of a user-supplied input with the stored hash, but you can't easily reverse the process (rebuild the original string from the stored hash).
Unless you choose to brute-force or use rainbow tables (both extremely slow when provided with a sufficiently long input).
You can't do that with SHA-1. But, given what you need to do, you can try using AES instead. AES allows encryption and decryption.

Resources