CI encrypt and decrypt - codeigniter

I get that the encryption class produces different output each time the same word/string is encrypted, for example, $this->encrypt->encode("word") ran five times would produce five different encrypted strings.
How can I reference the encrypted string in a DB query if each time I call $this->encrypt->encode("word") gives me something different?
Asked in a different way, is there something I can encrypt with that doesn't have a random value so that each time I encrypt I get the same output for the same input?

Base64 encoding is not encryption (referring to your own answer). I have not used codeigniter, but I notice on its doc pages that it allows:
$this->encrypt->set_mode();
You could encrypt with ECB mode (MCRYPT_MODE_ECB) for deterministic encryption where the same data always encrypts to the same ciphertext. This way, you encrypt your search string, and it will match the encrypted data in the database.
This is considered a weakness of ECB mode, but in this case, the deterministic behavior may be what you want.

I think base64_encode($str) is what I'm looking for.

this code works only on php 5.5 or higher
echo password_hash(variable, PASSWORD_DEFAULT);
The first parameter is the password string that needs to be hashed and the second parameter specifies the algorithm that should be used for generating the hash.
The default algorithm is currently bcrypt, but a stronger algorithm may be added as the default later at some point in the future and may generate a larger string. If you are using PASSWORD_DEFAULT in your projects, be sure to store the hash in a column that’s capacity is beyond 60 characters. Setting the column size to 255 might be a good choice. You could also use PASSWORD_BCRYPT as the second parameter. In this case the result will always be 60 characters long.
and to check the password hash here is the syntax
<?php
if (password_verify($oldpassword, $hash)) {
// Success!
// the first parameter is your password that's not yet encrypted, the secode is your password encrypted
}
else {
// Invalid password
}

Related

Laravel: Hash::check() returns `true` for two different messages

I observed a very strange behavior with Laravel's Hash Facade using Hash::make() to create a digest (with bcrypt) and save it to the database. For example, the plain text
AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAA=
yields $2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK.
Now, when using Hash::check() with the plain text and digest mentioned above returns true of course. However, changing one character in the plain text (e.g. replacing the last A with a B) and checking it against the same digest returns true as well:
>>> Hash::check('AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAA=', '$2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK')
=> true
>>> Hash::check('AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAB=', '$2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK')
=> true
>>> Hash::check('AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3eSoadAxaGpB3ABwCr5qkyxHH4QY9vHKr6u5IrAAAAAAENAACr5qkyxHH4QY9vHKr6u5IrAARi2BmGAAC=', '$2y$10$fq6jvoNL/RShVKfNDy64EOGW0gLzd0GvfS.di16Z9LcCK7DpIHONK')
=> true
Based on my understanding what hashing does this shouldn't be possible, but it doesn't seem to be a collision as replacing B by C also yields true.
I'm using Laravel 8.0 with PHP 7.4.11.
Any idea what I'm doing wrong here?
UPDATE:
Found this hint in the official PHP documentation for password_hash:
Caution: Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being truncated to a maximum length of 72 characters.
I then checked this and indeed, modifying any of the characters behind AAMkAGEzN2EyZTg4LWRiNTUtNGIwYS04ZTA1LWE2Y2U5OTRjYjQ0ZgBGAAAAAACxCzc14g3e doesn't change the result whereas exchanging e.g. the last e with f returns false for Hash::check(). The length of the string is 72 characters so it may be an effect of the truncation. But why? This isn't mentioned in the Laravel Hash documentation. I have several passwords that are longer than 72 characters so it actually doesn't matter how they end?
As a result, I need to use another function of Laravel to hash longer messages? Which one?
I did some research and came to this conclusion:
In the official laravel docs they refer to php's official docs. Here they have a caution section at password saying:
Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being truncated to a maximum length of 72 characters.
I checked your string, and it has a length of 152. So in your case, you should use a different algorithm(you can set this in config/hashing.php at driver) or make sure the input string is max 72 characters.

Encrypt or hash a string to decimal numbers in Ruby

In one of our signup processes, in a Ruby on Rails app, I want to send someone an email with a 6-digit numerical code that they need to copy or type into a box on the page.
How I thought I might do it is to have a string on the page, in a hidden field, say, which, on generating the email, gets combined with some secret key from our codebase, then hashed or encrypted to a series of decimal numbers. I then take the last six of these and put them in the email.
When the form is submitted, with the original string, and the 6 digits the user has typed in, I can repeat the process on the string and test that it produces the same six digits as the user entered.
The question is: how do I hash/encrypt a string to get a series of decimal numbers?  The original string can be anything (including a different set of decimal numbers), it just needs to be something that is randomly generated really.
Note: Do not use this as a security measure. You've stated that you intend to use this only as a kind of diy captcha system, and this answer is provided in that context.
OpenSSL provides good hash functions. Once you have the hash in hex the to_i method takes a base argument, so converting to decimal is simple. Then back to a string because that makes it easier to get the last characters.
require 'openssl'
hash = OpenSSL::Digest::SHA256.hexdigest('user#example.com' + Random.new_seed.to_s)
message = hash.to_i(16).to_s.chars.last(6).join
You could then store any part of this along with an expiration time.

Can you encode an image directly to sha1 to save space in localStorage?

A webapp I created supports offline storage... but it very quickly becomes maxed out when users add 10-13 photos. The photos are stored as super long base64 encoded strings.... but can they be stored as sha1?
Hashing is different of Encryption/Encoding
Base64 is an Encoding Method witch means that you can Decode without the need of a key
SHA1 is an Hashing Method witch means that it will generate a string depending of the content to be hashed, it can not be decoded or decrypted
Then you have Encryption (for example AES) that you Encrypt the content with that algorithm and with a key, to decrypt the data you need the encryption method and the key, without one of these elements you can not decrypt the data.
If you store the photos as SHA1 it will save a lot of space, but you can never retrieve them because all you have is a string with the hashed content.
I don't think there is a way to escape the space occupied by the photos, you might try saving to a byte array but I think the occupied space is the same because you need all the photo information to be available again
Examples (Encoding, Hashing, Encrypting word "teste")
Base64 Encoding: dGVzdGU=Website to test the encoding: https://www.base64encode.org/
SHA1 Hashing: 2e6f9b0d5885b6010f9167787445617f553a735f
Website to test the hashing to SHA1: http://www.sha1hash.com/
AES Encryption generates a byte array.Base64 equivalent to the AES Byte Array: SUpXhKOAO1pQdXD2igf0cw==Key used: key_to_encrypt_decryptSize: 128 BitWebsite to test the encryption of AES: http://aesencryption.net/

Password Hashes Characters in Applications

I appreciate your time.
I'm trying to understand something. Why is it that hashes that I generate manually only seem to include alphanumeric characters 0-9, a-f, but all of the hashes used by our favorite applications seem to contain all of the letters [and capitalized ones at that]?
Example:
Manual hash using sha256:
# sha256sum <<< asdf
d1bc8d3ba4afc7e109612cb73acbdddac052c93025aa1f82942edabb7deb82a1 -
You never see any letters above f. And nothing is capitalized.
But if I create a SHA hash using htpasswd, it's got all the alphanumerics:
# htpasswd -snb test asdf
test:{SHA}PaVBVZkYqAjCQCu6UBL2xgsnZhw=
Same thing happens if you look at a password hash in a website CMS database for example. There must be some extra step I'm missing or the end format is different than the actual hash format. I thought it might be base64 encoded or something, but it did not seem to decode.
Can someone please explain what's happening behind the scenes here? My friend explained that piping "asdf" to sha256sum is showing the checksum, which is not the actual hash itself. Is that correct? If so, how can I see the actual hash?
Thank you so much in advanced!
There's two things going on here.
First, your manual hash is using a different algorithm than htpasswd. The -s flag causes htpasswd to use SHA1, not SHA256. Use sha1sum instead of sha256sum.
Second, the encoding of the hashes are different. Your manual hash is Hex encoded, the htpasswd hash is Base64 encoded. The htpasswd hash will decode, it just decodes to binary. If you try to print this binary it will look like =¥AU™¨Â#+ºPöÆ'f (depending on what character encoding you're using), and that may be why you believe it's not decoding.
If you convert the Base64 directly to Hex (you can use an online tool like this one), you'll find that sha1sum will generate the same hash.
My friend explained that piping "asdf" to sha256sum is showing the checksum, which is not the actual hash itself.
Your friend is incorrect. You're seeing the Hex encoding of the hash. But the piping does affect the hash that's generated, it adds a newline character, so what you're actually hashing is asdf\n. Use this command instead:
echo -n "asdf" | sha1sum
It is base64 encoded.
Base64 encoding ends an an equal sign. So that is the first indicator. Although the htpasswd man page doesn't mention it, other Apache docs about "the password encryption formats generated and understood by Apache" does say that the SHA format understood by Apache is base64 encoded.

Ruby OpenSSL AES generate random key

I have an elementary problem that I can't seem to figure out. I'm trying to generate a random key in AES-256-CBC that can be used to encrypt/decrypt data.
Here is what i'm doing:
require 'openssl'
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.encrypt
puts cipher.random_key
>> "\xACOM:\xCF\xB3#o)<&y!\x16A\xA1\xB5m?\xF1 \xC9\x1F>\xDB[Uhz)\v0"
That gives me the string above, which looks nothing like keys i've used in the past. I am very new to encryption as you may be able to tell, but I'm trying to understand if I need to further prepare the string. I created a quick view in rails so I could go to /generate and it would render a simple html page with a random key. It wouldn't even render the page and was complaining about invalid uTF8. the only way I could get the page to display was to Base64 encode the key first.
I know i'm missing something stupid. Any ideas would be great.
EDIT:
This is what it looks like if I Base64encode. Should I be stripping the = signs off or something?
AES-128-CBC
Random Key: 0xdq+IZdmYHHbLC9Uv8jgQ==
Random IV: vp08d/nFGE3R8HsmOzYzOA==
AES-256-CBC
Random Key: BW0wY5fUkcwszV5GIczI+D45eFOz/Ehvw5XdZIavVOQ=
Random IV: D0pXdwQAqu+XSOv8E/dqBw==
Thanks for the help!
To answer your question (quoted from Wikipedia):
The '==' sequence indicates that the last group contained only one
byte, and '=' indicates that it contained two bytes.
In theory, the padding character is not needed for decoding, since the
number of missing bytes can be calculated from the number of Base64
digits. In some implementations, the padding character is mandatory,
while for others it is not used.
For Ruby and your use case the answer is: No problem to strip the =

Resources