I'm looking into different solutions regarding storing passwords in Database. After reading a lot I think i will end up with PBKDF2.
Although I'm a little bit confused regarding if I should input salt to my PBKDF2 function and store the salt in a column and the PBKDF2'd password in another column.
I'm also using CodeIgniter and found a library for PBKDF2 (https://github.com/HashemQolami/CodeIgniter-PBKDF2-Library) Which claims I don't need to store the salt separately.
Register user by using $pbkdf2['hash'] as user's password which has
been recommended; no need to store user's salt separately.
https://github.com/HashemQolami/CodeIgniter-PBKDF2-Library#step-2
So if I'm assuming correct all I need is to provide a password into the function and the function take care of the rest?
I'm the creator of CodeIgniter PBKDF2 Library. Just found this topic on SO, and I decide to clarify how this library works.
Here is the sample code from the doc:
# Load pbkdf2 library into your controller
$this->load->library('pbkdf2');
# Get password, which has been sent via POST method
$password = $this->input->post('password');
# Encrypt the given password using a random generated salt
$pbkdf2 = $this->pbkdf2->encrypt($password);
The encrypt() method, returns an array which has 3 keys: salt, password, hash.
The value of hash is the concatenation of salt and password.
This feature lets the user to choose how to use this library, whether to work with salt and password or hash (salt + password).
The syntax of encrypt() method:
encrypt( string $password [, mixed $good_hash = NULL [, bool $object_output = FALSE]] )
The function uses the given $good_hash as the salt to generate the encrypted password. And it uses a random generated salt if the $good_hash parameter is not given.
So, If you have stored the salt separately, you could pass it to the function as the second parameter to encrypt the given password:
$pbkdf2 = $this->pbkdf2->encrypt($password, $salt);
On the other hand, If you have stored the concatenation of salt and password into database, you could pass that to the function as the second parameter, too:
$pbkdf2 = $this->pbkdf2->encrypt($password, $hash);
The function will break the given $hash automatically to fetch the salt.
So, you could store the concatenation of salt and password in a column (64 characters by default) and then encrypt the new given password by using old stored one.
Putting all together
In the following, I'll show you how to work with this library to register/login the user, without storing the salt and the password separately.
Registering the user:
$this->load->library('pbkdf2');
$password = $this->input->post('password');
$pbkdf2 = $this->pbkdf2->encrypt($password);
# Store $pbkdf2['hash'] into User table as the user's password
Logging in the user:
$this->load->library('pbkdf2');
$username = $this->input->post('username', TRUE);
$password = $this->input->post('password');
# Fetch the stored user's password from the database
$user_password = $this->user_model->get_password_by($username);
# Check whether the User exists
if ($user_password)
{
# Encrypt the new given password by using the old one:
$pbkdf2 = $this->pbkdf2->encrypt($password, $user_password);
# Check whether the new generated password matches the old one
if ($pbkdf2['hash'] === $user_password) {
# Log in the user ...
} else {
# Show an error...
}
} else {
# Show an error...
}
Related
I have PythonScript#0 task in YAML file of the pipeline which is getting the email ID based on the Invidiual CI Requestor. & I have a secret variable value stored in the variable groups with the key of same email Id as CI Requestor.
VARIABLE GROUP:
key[myemail#email.com] = value["SECURETOKEN"]
# Getting the email ID of CI requestor
email = '$(Build.RequestedForEmail)'
group_variable = f"$({email})"
print(group_variable )
# Above variable is printing the value as "$(myemail#email.com)", which I do no expect.
I have tried all string concatenation methods to get the value. such as.
group_variable = f"$({email})"
group_variable = "$({})".format(email)
group_variable = "$({0})".format(email)
I want to get the value as "SECURETOKEN" instead of "$(myemail#email.com)". Any sort of help is appreciated. Thanks.
You cannot retrieve the value of a secret value from the API. It will always be empty. In order for the Python task to access the secret it must be passed in explicitly as an environment variable or an input parameter.
I am using "Platform agnostic Security Token" for oAuth in Golang - https://github.com/o1egl/paseto
I am not able to understand, why this is better than JWT even after reading README
My Major Question is:
Can "token" generated be altered like "JWT" and pass modified or tampered data?
Can "token" generated using "paseto" be decrypted and viewed like "JWT"?
Paseto library above uses "SET" and "GET" method inside their JSONToken method. Is that how we can verify authenticity of the user?
Sample Code:
symmetricKey := []byte("YELLOW SUBMARINE, BLACK WIZARDRY") // Must be 32 bytes
now := time.Now()
exp := now.Add(24 * time.Hour)
nbt := now
jsonToken := paseto.JSONToken{
Audience: "test",
Issuer: "test_service",
Jti: "123",
Subject: "test_subject",
IssuedAt: now,
Expiration: exp,
NotBefore: nbt,
}
// Add custom claim to the token
jsonToken.Set("data", "this is a signed message")
footer := "some footer"
v2 := paseto.NewV2()
// Encrypt data
token, err := v2.Encrypt(symmetricKey, jsonToken, footer)
// token = "v2.local.E42A2iMY9SaZVzt-WkCi45_aebky4vbSUJsfG45OcanamwXwieieMjSjUkgsyZzlbYt82miN1xD-X0zEIhLK_RhWUPLZc9nC0shmkkkHS5Exj2zTpdNWhrC5KJRyUrI0cupc5qrctuREFLAvdCgwZBjh1QSgBX74V631fzl1IErGBgnt2LV1aij5W3hw9cXv4gtm_jSwsfee9HZcCE0sgUgAvklJCDO__8v_fTY7i_Regp5ZPa7h0X0m3yf0n4OXY9PRplunUpD9uEsXJ_MTF5gSFR3qE29eCHbJtRt0FFl81x-GCsQ9H9701TzEjGehCC6Bhw.c29tZSBmb290ZXI"
// Decrypt data
var newJsonToken paseto.JSONToken
var newFooter string
err := v2.Decrypt(token, symmetricKey, &newJsonToken, &newFooter)
Now, if you see there is code: jsonToken.Set("data", "this is a signed message") and we can get that value in Decrypt data at the end where newJsonToken variable is created.
We can get the value of "data" key using: newJsonToken.Get("data").
But is above data "verifiable" and can't be tampered or modified on user's end?
Like in JWT debugger at JWT.io, People can tamper data and know the algorithm and pass "modified" data.
Can user do the same with my generated token as well? Can they decode and pass tampered data? or they can't decode data or view actual data at all?
1 - Can "token" generated be altered like "JWT" and pass modified or tampered data?
Note that token cannot be "altered" either using PASETO or JWT without knowing the signing key (which should of course be secret).
The fact you mention about being able to view the JWT token data in JWT.io page is because data is not encrypted (so you can see it without the key).
But token is signed, so if you modify any value and don't have the key, you won't be able to sign it back and the token receiver will note the token is not valid when trying to verify it.
2 - Can "token" generated using "paseto" be decrypted and viewed like "JWT"?
It depends on how you generate the PASETO token.
See here:
https://tools.ietf.org/id/draft-paragon-paseto-rfc-00.html#rfc.section.2
Format for the token is version.purpose.payload.
And from the docs:
The payload is a string that contains the token's data. In a local token, this data is encrypted with a symmetric cipher. In a public token, this data is unencrypted.
So if you generate the token as in the code snippet you posted (local token, with a symmetric key), then payload will be encrypted (you won't be able to see it unless you know the symmetric key and use that one to decrypt it).
If you use a public/private key pair, then payload will not be encrypted, so you'll be able to see it without the key (but you'll not be able to change it and sign it again without knowing the private key).
I'm using Hash::make to hash the customer id in my laravel api controller. But when I return the Hashed customer id I get wrong characters. Here is my code:
$key=Hash::make($input['key']);
$createnewkey=DB::table('customers')->where('custid', $input['custid'])
->update(array("key"=>$key));
return ["STATUS"=>1, "KEY"->$key];
I got for example : Av$#wqe#!3aferty10/2YyAU .... and that's saved in the database.
But the request response is : Av$#wqe#!3aferty10/\2YyAU the \ or / is always replaced with /\ that will corrupt my hash code compare
Laravel Hash use the password_hash function of the PHP. This function will generate the base64 encoded string. Which has the / in its character list. So if you will pass that in the URL your URL will get corrupted.
Instead, you can use hashids to encrypt the keys which are passed in URls.
This is the hashids port for laravel : https://github.com/vinkla/laravel-hashids
I am following OpenSSL directives to generate signatures. I am using ruby 2.1.0 and am generating signatures like this:
document = "This is a simple string document to be signed"
key = OpenSSL::PKey::RSA.new([private_key])
digest = OpenSSL::Digest::SHA256.new
signature = key.sign digest, document
The signature is transmitted and reaches the destination where it is to be verified. To verify, I do like this:
key = OpenSSL::PKey::RSA.new([pubkey])
digest = OpenSSL::Digest::SHA256.new
key.verify digest, signature, document # => valid
This is working because if we change just one letter of the document or signature, this returns invalid result:
key.verify digest, signature, changed_document # => Invalid
But with a different SHA, the verification command still results in a valid result:
digest = OpenSSL::Digest::SHA256.new('this will generate different SHA')
key.verify digest, signature, document # => valid
It confused me. Shouldn't a different SHA hash result in invalid result? What is the role of digest here?
Passing an argument to OpenSSL::Digest::SHA256.new causes that data to be added to the digest.
However, the openssl signing functions reset the digest before it is used and so that extra data has no effect in this particular case.
I have to encrypt a particular field value and store in DB. I have used RSA Encryption for Ruby. I was able to encrypt and save it, but then while decrypting it back, i am facing problem. What i have done is as follows,
key_pair = RSA::KeyPair.generate(512)
Stored key_pair in separate column.
ciphertext = key_pair.encrypt("Hello, world!")
Stored ciphertext in another column in same table.
While decrypting, i fetched the key_pair value from database and applied decrypting function
plaintext = key_pair.decrypt(ciphertext)
This step throws error
NoMethodError: undefined method `decrypt' for <String:0xa431b88>
because "key_pair" is not an instance of "RSA::KeyPair".
When i try to decrypt the stored value, i fetch key_pair value from database and then apply decrypt method on it. So the key_pair value has String class. I need a way to solve. Please guide me.
Before decrypt, try:
# get persisted value from DB; then
key_pair = RSA::KeyPair.new(your private key, your public key)
# and then decrypt
plaintext = key_pair.decrypt(ciphertext)