Correct logic to use when implementing 2fa on my site? - two-factor-authentication

I am using the "sonata-project/google-authenticator" library. It allows me to generate a QR code as follows:
$g = new \Google\Authenticator\GoogleAuthenticator();
$salt = 'XJDDJKSLJNASDJNASDASDASD';
$secret = $uid.$salt;
$url = $g->getURL($uid, 'coinula.com', $secret);
My question is around this:
The secret I provide, is that the secret that these guys are showing to the user? So that secret is the "global" key and the qr code is just a picture version of this code?
Am I supposed to store the secret and keep it safe on my side? Or is that something that the user should be able to write down and decide if he wants to keep it. I.e. Is the purpose of the secret for me NOT to store it? Or is there a reason I must store it?

Turned out to be a dumb question, but I'll answer it anyway. The secret must be stored in order for you to match it to the user. Would've been nicer if you could specify your own secret. I suppose there might be a way, but I'm going ahead with this way. So I'll be using the secret that is generated and storing that in the DB in order to compare it.

Related

Theory of Retrieving Hashed Passwords

This is a theory question, as I already know the following:
Hashes are not encryptions
Hashes can be broken https://crackstation.net/
That my code is not serious enough to be used on an enterprise site
But my question is just on the theory of it all.
In theory, if I stored a hashed password into a database, how could I check it when a user comes to log in? Is it that simple or is there a standard way to actually store and retrieve passwords in SQLite3?
If you can offer some SQLite3 code or guidance on where to start, that would be appreciated.
import sqlite3
import hashlib
def encrypt_password(password):
encrypted_pass = hashlib.sha1(password.encode('utf-8')).hexdigest()
return encrypted_pass
cemail = input("E: ")
cpassword = input("P: ")
connection = sqlite3.connect('/Users/Air/Desktop/users.db')
connection.create_function('encrypt', 1, encrypt_password)
cursor_v = connection.cursor()
cursor_v.execute("insert into user (cemail, cpassword) values (?,encrypt(?))", (cemail, cpassword))
connection.commit()
cursor_v.close()
When dealing with passwords, there's an absolute ton of information you need to know as a minimum:
Firstly, hashing passwords must be slow, which is the exact opposite of what a hash function is usually intended for.
Use bcrypt or PBKDF2 for this purpose. MD5/SHA1/256/512 are not sufficient for a password and offer no real protection when faced with a GPU-based bruteforcer (such as hashcat).
Second, verification of passwords must be in constant-time, aka they must complete in the same time regardless of the length of a string.
String comparison functions are at risk of a timing attack, and this means that the hash can be deduced by repeatedly giving different inputs to your verification function until enough information about the hash is revealed.
To get around this, use a cryptography library that does this for you.
If you have no other choice, the following pseudocode should help you see how a constant-time algorithm generally works (though you should still use a library!)
def verify(hash, input):
key = secure_random(32)
hash = hmac_sha_512(key, hash)
input = hmac_sha_512(key, bcrypt(input))
results = []
for i, letter in input
results.add(hash[i] === letter)
return false not in results
Thirdly, passwords should have a cryptographically random salt used throughout the hashing. A secure random source of randomness is generally taken from /dev/urandom or a library dedicated to it.
To answer the question of Well how do I verify a password if I can't see the original value? — simple, just hash whatever a user gives you and see if the hash matches the one in the database. But see above for the huge pitfall there.
You cannot retrieve hashed password but compare new password whether it is the same. IF HASH(new_password) == hashed_password_in_db THEN ..ok.. ELSE ..wrong password....

Best way to add Camel route to encrypt and sign based on file name

Based on file name prefix, I want to PGP encrypt and sign with different keys. I can use multiple encryption routes and direct them using a Message Router. Do anyone know a way to avoid multiple routs and get the related PGP keys at route running time?
final PGPDataFormat encryptAndSign01 = new PGPDataFormat();
encryptAndSign01.setKeyFileName(conf.pgpPublicKeyFile);
encryptAndSign01.setKeyUserid(conf.pgpEncryptUser01);
encryptAndSign01.setSignatureKeyFileName(conf.pgpPrivateKeyFile);
encryptAndSign01.setSignatureKeyUserid(conf.pgpSignUser01);
encryptAndSign01.setSignaturePassword(conf.pgpSignUser01Passphrase);
from("encrypt01")
.marshal(encryptAndSign01)
.to("file:tmp/output?fileName=${file:name}.pgp");
...
from("file:tmp/output?include=output.*.csv")
.choice()
.when(...)
.to(direct:encrypt01)
.when(...)
.to(direct:encrypt02);
You can specify the parameters of encryption by using the message header just like this
But I think it could be more easy if you use different routes to do the job.

Can I read Captcha data from JavaScript in a secure way?

We use Captcha control in a registration form that we make full client validation for all fields in JavaScript ( JQuery ) beside server validation ..
I tried a lot of ways but all will write the Captcha value in JavaScript that can be accessed by anyone :(
I search if is there any way that allow me validate Captcha value in client side using JQuery in secure way or it can't be done ?
It cannot be done.
Javascript is client-side, as you know, and any code client-side has to be treated as potentially compromised as you don't have control over it.
At best, you could resort to sending up a salted hash of the value along with the salt, but even that in itself could be used to test guess values before actually submitting it.
Everything else relies on calls to the server.
As per comment request, here's the general idea:
Firstly, on the server, calculate a random string to be used as the salt. This should be roughly unique every request. The purpose of this string is to prevent rainbow table attacks.
Now, saving this string separately, but also create another string that is the concatenation of random string and the Captcha answer. Of this new combined string you generate the hash (for example, SHA-1) of it.
using System.Web.Security;
...
string hashVal = FormsAuthentication.HashPasswordForStoringInConfigFile(combined, "SHA1");
Both the random string and the hash value need to be placed in the page for the javascript to be able to read.
On the client side, when a user answers the Captcha, take the random string and concatenate it with the answer (getting the idea here?). Taking this string, you can use something like the SHA-1 JQuery plugin to hash it and compare it with the pre-computed hash you sent up.
hashVal = $.sha1(combinedString)
If it matches, it is (almost) certainly the correct answer. If it doesn't, then it is 100% the wrong answer.
you could use ajax to post the current value to the server, which would respond true or false. that would keep you from doing a real post and also from giving away the catpcha's value in html.
My solution )) Every time when page shows captcha to the user, you can dynamically generate obfuscated JavaScript functions(i think the best way 5 or 10).
For example, one function(or 3)) ) can set cookies with pregenerated hash(server returns it)(from real value of the captcha), other functions must realize server side algorithm to check value which user's typed. I can say that it works for 100%, because it is very hard to parse dynamically javascript + we set user cookies on client side(It is very hard for Bots's to find out where and how you set and check cookies), by using JavaScript.

Generation of Email Validation Links

For a Web Application I'd like to generate an email validation link and send it to the user. Like on many public websites, the user should click it to validate his email address. Looks similar to this:
http://www.foo.bar/validation?code=421affe123j4h141k2l3bjkbf43134kjbfkl34bfk3b4fkjb43ffe
Can anybody help me with some hints about the proper generation of those validation tokens? Googling best practices turned out to be more difficult than I though it would be. The links should:
... not require the user to log in first.
... not reveal any login credentials to keep the application secure
... allow me as a developer to efficiently validate the token. I'm pretty sure I need a way to extract the user identifier out of the code to meet this criteria. Don't I?
Furthermore, would you go for a random code, which is saved somewhere, or a generated code which I can recalculate for validation?
Thanks for any replies!
Matthias
P.S. I'm working with ASP.NET 3.5, in case there's an out-of-the-box feature to perform this.
Some suggestions to get you started:
Use GUIDs
Use some sort of salted hash (MD5, SHA1, etc)
Use a random string of characters (the more characters the less likely you'll have collisions)
Store it in a database temporarily, and timestamp it so that it expires after a certain period of time
The simplest way to do it is generate a GUID, store that in the database tying it to their user account and then give them a time-frame within which to click a link with that GUID in.
That validates they are the correct person without making the URL calculable whilst making it resistant to dictionary style attacks.
I construct the hash in a way that can be re-created:
code = MD5( my_hash + user_email + register_timestamp )
Then send a link to http://example.com/validation/?code = 4kj34....
Validation does a lookup like:
SELECT id
FROM users
WHERE
MD5( CONCAT( my_hash, user_email, register_timestamp ) ) = code
AND activated = 0
If you get a single result, update their 'activated' field and sign them in. You can also do some math on their 'register_timestamp' field for a poor man's TTL
I would probably use a Guid. Just create a Guid (by calling Guid.NewGuid()), store it as the validation token for that user, and include it in the validation link.

How can I encrypt a cookie content in a simple way in C# 3.0?

How can I encrypt a cookie in a direct and simple way?
Thanks!!
You probably shouldn't be doing this. If the cookie is sensitive, store it only on the server.
If you really need to, there are a number of ways to do it. First, you will need to convert the plaintext to a byte array, like this:
var plainBytes = Encoding.UTF8.GetBytes(plaintext);
If you're sure that your plaintext will never use Unicode, you can use Encoding.ASCII instead; this will result in a smaller cookie).
Then, you will need to encrypt it. The easiest way to do that is to use DPAPI, like this. (First, add a reference to System.Security.dll). Note that this will not work on a server farm.
var encryptedBytes = ProtectedData.Protect(plainBytes, null, DataProtectionScope.CurrentUser);
Finally, you need to convert it back to text so you can put it in the cookie. This is best done in Base64, like this:
Response.AddCookie("MyEncryptedCookie", Convert.ToBase64String(encryptedBytes));
To decrypt the cookie, you'll need to reverse these steps, like this:
var encryptedBytes = Convert.FromBase64String(Request.Cookies["MyEncryptedCookie"].Value);
var decryptedBytes = ProtectedData.Unprotect(encryptedBytes , null, DataProtectionScope.CurrentUser);
var plaintext = Encoding.UTF8.GetString(decryptedBytes);
Note that the cookie will be very large, even for small plaintexts.
If you want to use this on a server farm, you can use AES; look at System.Security.Cryptography.RijndaelManaged.
The simplest way will be to not encrypt it! Just use the cookie ID (plus a salt) to look up the values (contents) on the server.
The most secure way to do this is to use ASP.Net session state instead of cookies. Since session state is never sent to the client, you will have nothing to worry about.

Resources