i don't understand how one can create a rough Certificate just by making a MD5 collision. Even if you were able to find another string whose hash matches the original how would you sign it ? You do not have access to the Certificate authority's private key ?
Related
I have a table with User Agents Strings table with the following structure:
UserAgentStringID INT
UserAgentStringValue VARBINARY(8000)
The [UserAgentStringValue] field is encrypted with symmetric key. The previous version of the table structure was:
UserAgentStringID INT
UserAgentStringValue NVARCHAR(4000)
UserAgentStringHASH BINARY(32)
and I have index on the [UserAgentStringHASH] column in order to optimized searchers.
With the new format, such index is not efficient as the ENCRYPTION function uses InitializationVector in order to generate random values each time the encryption function is called with the same input:
Initialization vectors are used to initialize the block algorithm. It
is not intended to be a secret, but must be unique for every call to
the encryption function in order to avoid revealing patterns.
So, I can create index on my encrypted field, but if I try to search by encrypted value, I will not be able to find anything.
I do not want to use HASH because using hash function is not secure technique. If someone have my table data and table with all or huge amount of user agents, he/she will be able to perform an join by hash and reveal my data.
In SQL Server 2016 SP standard edition we have Always Encrypted which allows using Deterministic Encryption for column value - this means equal comparisons are working and indexes can be created.
I am looking for a way to optimize the search by other technique or a way to implement deterministic encryption using CLR for example?
Knowing there is no work around is OK for me, too. I guess I will pay the data protection with performance.
I am posting a workaround of this - it's not the ideal solution, but it is compromise between speed and security.
The details
a columns must be encrypted (lets say an email address)
fast search must be implemented (let say the email is used for login and we need to locate the record as fast as possible)
we are not able to use Always Encrypted deterministic encryption (due to various reasons)
we don't want to use hash function with salt - if one has the salt for each user, ze might be able to read the hashes using large sample database
The security hierarchy
There are various ways of implementing the security hierarchy. The following schema from the MSDN describes it very well.
In our environment we are using the Database Mater Key -> Certificate -> Symmetric Key hierarchy. Only DBAs know the DMK password, have access to certificate and symmetric keys. Some developers can do encrypt/decrypt data (using plain T-SQL) and other do not.
Note, using Always Encrypted you can have role separation - the people who works with the data have not access to the keys, and the people who have access to the keys, do not have access to the data. In our case, we want to protect our data from outsiders and have other techniques for granting/logging data access internally.
Developers with access to encrypted data
The developers who can access the protected data are able to encrypt and decrypt it. They have not access to the symmetric key values. If one have access to the symmetric key values, ze is able to decrypt the data event not having the certifications used for protecting the symmetric keys. Basically, only sys.admins and db_owners have access to the symmetric keys values.
How to hash
We need a hash to get fast searches, but we cannot use a salt which is not encrypted. And hash without a salt is like plain text from security perspective. So, we've decided to use use the symmetric key value as salt. It is get like this:
SELECT #SymmetricKeyValue = CONVERT(VARCHAR(128), DECRYPTBYCERT(C.[certificate_id], KE.[crypt_property]), 1)
FROM [sys].[symmetric_keys] SK
INNER JOIN [sys].[key_encryptions] KE
ON SK.[symmetric_key_id] = KE.[key_id]
INNER JOIN [sys].[certificates] C
ON KE.[thumbprint] = C.[thumbprint]
WHERE SK.[name] = #SymmetricKeyName;
And the value is concatenated to your email address and then the hash is calculated. It is good for us, because we are binding the hash to the security hierarchy. And it is not a different salt for each record, it is the same - but if one knows the symmetric key value, ze is able to decrypt the data directly.
Considerations
You need to create the routines (stored procedures, triggers) which are searching by hash values or computing hashes using the EXECUTE AS OWNER clause. Otherwise, developers will not be able to execute them as only sys.admins and db_owners have access to the symmetric key value.
I have problem in encrypting my plain text in C.
I am able to write and read the file in C
Inside the text:
ID Promo Points Password Name
1 NONE 0 awdawdawd daw
Which in this case it just print password in plain text, Is it possible to encrypt the data any method, which shows like this:
ID Promo Points Password Name
1 NONE 0 ENCRYPTEDDATA daw
Of course the password wont be "ENCRYPTEDDATA", I just want it avoid plain text which user can easily see the file.
The reason I create file cause I need to read it from the file and make a login function.
My program itself able to decrypt the password when in request of checking id and password.
It can use any method only the program can encrypt and decrypt the data
Any solution guys?
If possible I also need to limit the encrypted text
You should hash password with strong hash function like SHA2 and store the hash in your file rather than storing it in plain
Hashing might be better in this case than encryption, as for encryption you will have to worry about storing key somewhere securely.
When your login function needs to validate incoming password, you can just hash incoming password and match it against the hashed password from you file
If you want to protect your login then you should use a password hash, also known as a Password Based Key Derivation Function. These functions are often, but not always, based on a secure hash. You should not use a cryptographic hash such as SHA-2 for this purposes.
Common password hashes are PBKDF2, bcrypt, scrypt and Argon2. Argon2 is the most advanced one as winner of the password hashing competition. A password hash differs from a normal hash in two important aspects:
it uses key strengthening techniques to make it harder for adversaries to use a dictionary or brute force attack (in the form of an iteration count or work factor and possibly additional memory / threading related parameters);
it uses a salt - stored with the password hash - to avoid rainbow table attacks and to avoid duplicate hash values - which would show that an identical password is being used.
So although Pras is right about not using encryption I would not recommend a secure hash unless you are sure that the password is large enough and unique. In general those restrictions can nor should be enforced on password based authentication systems.
I'm working on a website (PHP + MySQL) that I've got to upgrade. Passwords are stored in the database in MD5, and I'd like it to be something more secure, like SHA-256.
I've already red this question about "converting" password hashes, but I got an other idea, and I'd like to know if it brings a security problem or not.
Currently, the passwords are checked in php by hashing (in MD5) the given password and compare it with the hash stored in database, ie: if(md5($password) == $hash)
Let's assume that I hash all the MD5 hashes in SHA-256. I'd have the sha-256 hash of a md5 hash.
Side note: I know it's not more secure to rehash a hash, that's not the point of my question
When a user wants to connect, I'd just have to change the md5($pass) in hash('sha256', md5($password), false) to make it match the value stored in database (assuming $password is the right one)
It seemed a good idea to me as I don't need to keep track of the md5 hash after conversion, ad this doesn't need me to create any new column in my table. I know that this is not going to give me the SHA-256 hash of the original password stored with md5 hash, but this is not my goal. It's just to change the encryption method. Moreover, brute-forcing it seems inefficient, as it is very unlikely that dictionary would have hashes of words...
Does this way of doing it is flawed?
Simple hashing of passwords is insufficient, it is subject to rainbow tables and is to fast.
Instead in PHP use Safe Password Hashing: password_hash() and password_verify() or a comparable function such as PBKDF2, Bcrypt or script. These function are more secure because of two additions: a repetition count and a random salt. It's all about raising the work factor the attacker must perform.
After all, the point is to have a secure system. Just making it more inconvenient for an attacker is not the answer, there are hacking programs out there to take advantage of poor password security.
So from what I have seen it is impossible to decrypt any hashing algorithm such as MD5 or SHA-1 without brute forcing it or using rainbow tables. This seemed to confuse me on a few aspects of using hashes. These confusing points are:
What would be the point of hashing in the first place if they cant be decrypted?
How would hashed passwords be able to be used in a database?
Also since people say it is like the modulo operation, what, if anything, is preventing multiple inputs to equate to the same hash?
If somebody simply does SHA1 or MD5 on a password, then they get almost no protection.
That's why it's important to understand the right way to handle "password hashing". Please read Our password hashing has no clothes
To answer your questions:
You can verify the user without "decrypting the hash": you simply "hash" the user entered password (along with salt and other parameters) upon login and verify that it matches the expected result that is stored in the database.
See 1 and the Troy Hunt link
People who say it is like a modulo operation are making a bad analogy: they are non-experts on this subject. Anyway, the properties of the "hash" function make it hard to find collisions, and the salt prevents two users with the same password from having the same password "hashes" in the database.
Other resources:
Salted password hashing - Doing it right
Method to Protect Passwords in Databases for Web Applications -- advanced reading: solves other problems with current solutions to protecting passwords. If you wonder why I put "hash" in quotes above, this will explain it.
It's not like a modulo. A hash is reasonably guaranteed to be unique based on the input. If you enter your passwords in a database as hashes, then all you need to do is to hash the password entry and check it against what you have stored in the database. This way, you are not storing readable passwords in the database which are openly visible to others. Normally, you would have a private key, some salt and something unique like a timestamp included in your hashing algorithm to ensure that it cannot be easily spoofed.
This may help you further:
http://searchsqlserver.techtarget.com/definition/hashing
Even if the process of hashing is basically non decryptable, the problem as pointed before is that each hash is nearly unique, so that means using websites like md5decrypt which contains a lot of different words and their encrypted hashes, one may find the password he is looking for.
That is if the password isn't strong enough in the first place. Obviously one shouldn't use the password "password" for instance because it will probably be found in most of the websites like md5decrypt.
What you should do to protect passwords on your website is actually simple. First, don't use old hashes like md5 or sha1. Use at least sha256, and if you've enough sql storage, sha384 or sha512. You should know that most of the online hashes database are only about the most commonly used hashes (let's say md5,sha1,sha256 in most cases). So you should find a hash type that isn't very represented on online database.
Then you should (you have actually to) use salt when encrypt users passwords, that is add some word, letters, whatever, to the password before you encrypt it, then store that salt somewhere so you can still allow people to log in. You could also add a pepper to the salt to make the all thing stronger.
While using the salt, try to find a way that hackers won't think about, for instance double the salt, or triple it, or try different ways to concat the salt and the actual password, etc. You could also make a double encryption with double salt, like sha512(sha384()), which would be almost impossible to find.
But, please, do not store unencrypted passwords !
The tweetnacl library provides two functions to generate public and secret key pairs: crypto_box_keypair(pk,sk); and crypto_sign_keypair(pk,sk);:
The first function initializes key pairs which are intended to be used to
encrypt messages using the crypto_box(c,m,mlen,n,pk,sk); API and to
decrypt these later using the crypto_box_open(c,n,pk,sk) function.
Good example code seems to be hard to find. Here is one for
the library libsodium which is as tweetnacl based on NaCl.
The second function however initializes a keypair which can be used to
sign a message using the crypto_sign(sm,&smlen,m,mlen,sk); API and
later verify the signature using crypto_sign_open(m,&mlen,sm,smlen,pk);
While looking at the key generation code I figured out that in both cases the key generation starts with a 256 bit random number but yields different
public keys in the end. In fact the returned 512 bit signing sk key contains a copy of the public key pk in its so to say upper half.
I've looked through all documentation I could find which is not much.
Currently I've come to the conclusion that there is no proper way to use the same single key pair for both facilities. Am I right?
They are not the same kind of keypairs. The key generation for both may start with a 32-byte seed, but the relationship between the generated public and private keys in the two types of keypairs are different, so you cannot use them interchangeably. The fact that the private signing key contains its public key has no bearing on this matter.