<p>As much as you're being downvoted and attacked, your idea is absolutely right, correct, and valid.</p>
<p>You've nearly reinvented <em>bcrypt</em>.</p>
<blockquote>
<p>Let's say we have encryption algorithm (doesn't matter which one):</p>
</blockquote>
<p>I'll choose <a href="https://en.wikipedia.org/wiki/Blowfish_(cipher)" rel="nofollow noreferrer"><strong>blowfish</strong></a>.</p>
<blockquote>
<p>Then generate random sequence of chars consisting predefined array (for instance just random sequence of digits)</p>
</blockquote>
<p>I'll pick a sequence of 24 characters. And even better if it's an even multiple of the <em>blowfish</em> 8-byte blocksize:</p>
<pre><code>   OrpheanBeholderScryDoubt
   \______/\______/\______/
      |       |       |
8-bytes     8-bytes   8-bytes
</code></pre>
<blockquote>
<p>Encrypt sequence with our algorithm with given password and store it somewhere in safe place (let's call it as saved value)</p>
</blockquote>
<p>The password needs to be transformed into a 72-byte encryption key - the key size of blowfish. Bcrypt does this with a function called <strong><code>ExpensiveKeySetup</code></strong>:</p>
<pre><code>String password = &quot;correct horse battery staple&quot;;
Int32 costFactor = 12;
Byte[16] salt = CryptGenRandom(16);
Byte[72] key  = ExpensiveKeySetup(password, salt, costFactor);
</code></pre>
<p>And then we'll encrypt our random sequence of chars. And just to be extra secure: we'll encrypt it <strong>64</strong> times:</p>
<pre><code>Byte[24] ciphertext = BytesOf(&quot;OrpheanBeholderScryDoubt&quot;);
for int i = 1 to 64 do
   ciphertext = BlowfishEncrypt(cipherText, ref key);
</code></pre>
<p><em>(Why use 3-DES when you can use 64-DES<a href="https://tenor.com/view/thejoke-joke-you-youmissedthejoke-wellheresthething-gif-5049374" rel="nofollow noreferrer">!</a>)</em></p>
<p>And now you have your stuff to store:</p>
<ul>
<li>costFactor</li>
<li>salt</li>
<li>ciphertext</li>
</ul>
<p>Bcrypt coverts the salt and ciphertext to base64, and gives you a string:</p>
<pre><code><span class="math-container">$2b$</span>[costFactor]$[salt][ciphertext]
</code></pre>
<p>Such as:</p>
<p><span class="math-container">$2a$</span>12$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa</p>
<blockquote>
<p>Now time to check password validity</p>
<p>Try to decrypt saved value with probe password</p>
</blockquote>
<p>Rather than decrypt, just repeat the encryption of <em>&quot;OrpheanBeholderScryDoubt&quot;</em>, with the password, and the same salt. And compare the result to what you stored.</p>
<p>It would be nice if the community was nice, helpful, or knowledgeable - rather than just attacking or using clichés.</p>

CC BY-SA 4.0
2020-04-18T12:41:48.650Z
2021-02-25T04:42:03.837Z
2021-02-25T04:42:03.837Z
Ian Boyd
<p>The first problem you face is that a password cannot be used as an encryption key. For instance, let the password be <code>$%^gHk23</code>. How do you interpret this as an AES-256 key?</p>

<p>The second problem is that the client has to send the password in clear, and then the server tries to make a key from it, and decrypt saved values.</p>

<p>Thirdly, the scheme is fixed. No <a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29" rel="noreferrer">salting</a> whatsoever is incorporated in it, and thus it is vulnerable to a variety of attack, most notably the <a href="http://en.wikipedia.org/wiki/Dictionary_attack" rel="noreferrer">dictionary attack</a>.</p>

<p>The hashing scheme you described at the beginning of your post is very old. Today, an extremely secure password-based identification scheme, named <a href="http://srp.stanford.edu/" rel="noreferrer">SRP</a>, is gaining momentum. (See also the <a href="http://srp.stanford.edu/demo/demo.html" rel="noreferrer">demo</a>.)</p>

CC BY-SA 2.5
2011-02-17T12:43:07.400Z
1) I meant based on password calculate hash value which use as say AES key... Or I'm not right?
Barmaley
CC BY-SA 2.5
2011-02-17T12:43:53.140Z
About salting and SRP - let me review those methods. I'm sorry - I'm not professional cryptographer...
Barmaley
CC BY-SA 2.5
2011-02-17T13:00:23.423Z
@Sadeq: in my case client-server channel is secure, so SRP is not required. In contrary server storage is vulnerable, so attacker can review all values stored in server. So I'm talking about way how to verify password validity.
Barmaley
CC BY-SA 2.5
2011-02-17T13:24:46.030Z
@barmaley: Please review this part of your question: "So password protection relies on strength of hashing function." To me, this says that you are going to use a method which is not based on hashing. Then in a comment above, you said: "I meant based on password calculate hash value which use as say AES key." This seems contradictory, right?
Sadeq Dousti
CC BY-SA 2.5
2011-02-17T13:27:14.140Z
@barmaley: If the channel is secure, you must mention this as part of your model, since this is very important. Please clarify what you mean by "secure": Is is just confidential, or provides both confidentiality and integrity? Moreover, please decide if you want to use hash functions or not. (If I were you, I'd allow the use of salted hash mechanisms.)
Sadeq Dousti
CC BY-SA 2.5
2011-02-17T13:38:50.503Z
@Sadeq: client and server are in the same application/environment - so channel provides confidentiality and integrity. About hashing/non-hashing issue: I'm asking about security of password storage mechanism rather than hash strength. Essential part not about transforming password to key using hash (can be used another approach) but about safety of password validity using described approach
Barmaley
CC BY-SA 2.5
2011-02-17T14:20:59.643Z
@barmaley: OK, I almost got it. IMO, the approach you described seems vulnerable to the following attack: The attacker steals the **saved values** (since you said the storage is not secure), and then mounts a dictionary attack on it. This can be easy unless you assume that passwords have high entropy (that is, they are chosen at random), and are long enough. Example: `apple tree` is a low-entropy pass, while `$%^gHk23` is a high-entropy one.
Sadeq Dousti
CC BY-SA 2.5
2011-02-17T14:29:25.657Z
The mention of salting and dictionary attack is timely, because Anonymous just used rainbow tables to hack HBGary.  HBGary could have defended against that by salting their passwords, which they did not do, despite being a professional security company.  Ars Technica has produced some fascinating articles about this.  The one that discusses salting and rainbow tables is [here](http://arstechnica.com/tech-policy/news/2011/02/anonymous-speaks-the-inside-story-of-the-hbgary-hack.ars).
Aaron Sterling
CC BY-SA 2.5
2011-02-17T15:00:29.473Z
@Aaron: Thanks. I didn't hear this exciting piece of news!
Sadeq Dousti
CC BY-SA 2.5
2011-02-18T08:11:16.743Z
@Sadeq: thanx a lot - I understand vulnerability point of proposed approach. So as far as I understood I need to use some kind of salting approach - can you point me to a good resource about that?
Barmaley
CC BY-SA 2.5
2011-02-18T10:35:24.233Z
@barmaley: You're most welcome! You may start by reading the Wikipedia page I addressed in the answer. You can also take a look at [this post](http://stackoverflow.com/q/420843/459391) on stackoverflow.
Sadeq Dousti
CC BY-SA 2.5
2011-02-17T10:57:22.923Z
2011-02-17T10:57:22.923Z
Sadeq Dousti
<p>Usually to check password validity we used to create over given password it hash value and compare it with stored one. So password protection relies on strength of hashing function.</p>

<p>Could it be used another approach? </p>

<ol>
<li>Let's say we have encryption algorithm (doesn't matter which one). </li>
<li>Let assume we have some array of predefined chars (for instance just digits)</li>
<li>Then generate random sequence of chars consisting predefined array (for instance just random sequence of digits)</li>
<li>Encrypt sequence with our algorithm with given password and store it somewhere in safe place (let's call it as saved value)</li>
<li><strong>EDIT</strong> Also presumed that channel between client and server provides confidentiality and integrity</li>
</ol>

<p>Now time to check password validity</p>

<ol>
<li>Trying to decrypt saved value with probe password</li>
<li>If decryption successfull (meaning mathematically correct) check decrypted value to presence of predefined chars array. For instance if value consists only digits - we assume that password is correct. If decrypted value contains extra chars (except digits) - we would assume that password is incorrect.</li>
</ol>

<p>Now question: what do you think about crypto-strength of this method?</p>

CC BY-SA 2.5
2011-02-17T09:58:54.007Z
I am no expert in cryptography, but I guess all passwords are essentially known if your predefined array is leaked (and the encryption method is known). Hashing does not have that problem. Even if the hashed values are leaked (and the hashing alg is known), there is little but brute-force you can do to figure out the original password (afaik).
Raphael
CC BY-SA 2.5
2011-02-17T13:07:49.673Z
And in my case the same is right. Say if stored value leaked, attacker even knowing encryption algorithm should somehow restore unknown array (which he knows only consist some digits). So the only option again is brute-force - or I'm not right?
Barmaley
CC BY-SA 2.5
2011-02-17T16:12:58.013Z
@barmaley: Some people think you don't need to be a cryptographer to do cryptography. They are very, very wrong. If you don't know what you're doing, you'll make mistakes. Unfortunately, some engineers are not aware of that, and as a result some funny things happen, for example WEP uses a stream cipher together with CRC.
Yuval Filmus
CC BY-SA 2.5
2011-02-17T19:16:29.140Z
I agree with Yuval, for real applications use publicly available tested code.
Kaveh
CC BY-SA 2.5
2011-02-17T19:23:13.983Z
ps: I am not sure if we want to allow discussions on crypto protocols proposed by non-experts on the site. IMHO, if this is a research-level question in theoretical computer science, then it falls in the domain of *unpublished work which is not peer-reviewed* policy, so I am voting to close the question as "not a real question".
Kaveh
CC BY-SA 2.5
2011-02-18T08:12:46.197Z
@Yuval: this is exactly reason why I'm asking :) I don't want to be guy like WEP inventors :)
Barmaley
CC BY-SA 2.5
2011-02-18T08:15:50.937Z
@Kaveh: if you won't allow these kind of discussions here that'd mean that CS guys will be apart from real life ones, so there'll be disasters like WEP issues... Anyway - it's your decision.
Barmaley
CC BY-SA 2.5
2011-02-18T22:42:25.693Z
barmaley, I think crypto protocols are complicated constructions and people who lack the basic knowledge on the topic should not design them.  If you seriously want to design crypto protocols you should at least have the basic knowledge in crypto, in which case you should start by reading the crypto textbooks. IMHO, trying to reinvent the wheel and asking researchers to verify it is a bad idea. I don't like the idea of non-experts lacking basic knowledge submitting the ideas they come up with here and ask experts check their correctness. The previous and this comment are personal opinions.
Kaveh
CC BY-SA 2.5
2011-02-18T22:43:08.610Z
Please also note that the scope of this site is *research level theoretical computer science*, it is not our job on cstheory to make sure people don't make disastrous mistakes.
Kaveh
<cr.crypto-security><randomness><hash-function>
Password checking algorithm
Barmaley
# Password checking algorithm

(Asked by: username_0 on 2011-02-17)

Usually to check password validity we used to create over given password it hash value and compare it with stored one. So password protection relies on strength of hashing function.

Could it be used another approach?

1. Let's say we have encryption algorithm (doesn't matter which one).
2. Let assume we have some array of predefined chars (for instance just digits)
3. Then generate random sequence of chars consisting predefined array (for instance just random sequence of digits)
4. Encrypt sequence with our algorithm with given password and store it somewhere in safe place (let's call it as saved value)
5. **EDIT** Also presumed that channel between client and server provides confidentiality and integrity

Now time to check password validity

1. Trying to decrypt saved value with probe password
2. If decryption successfull (meaning mathematically correct) check decrypted value to presence of predefined chars array. For instance if value consists only digits - we assume that password is correct. If decrypted value contains extra chars (except digits) - we would assume that password is incorrect.

Now question: what do you think about crypto-strength of this method?

**Tags:** cr.crypto-security, randomness, hash-function
> **Comments:**
> **username_1**: I am no expert in cryptography, but I guess all passwords are essentially known if your predefined array is leaked (and the encryption method is known). Hashing does not have that problem. Even if the hashed values are leaked (and the hashing alg is known), there is little but brute-force you can do to figure out the original password (afaik).  
> **username_0**: And in my case the same is right. Say if stored value leaked, attacker even knowing encryption algorithm should somehow restore unknown array (which he knows only consist some digits). So the only option again is brute-force - or I'm not right?  
> **username_2**: @barmaley: Some people think you don't need to be a cryptographer to do cryptography. They are very, very wrong. If you don't know what you're doing, you'll make mistakes. Unfortunately, some engineers are not aware of that, and as a result some funny things happen, for example WEP uses a stream cipher together with CRC.  
> **username_3**: I agree with Yuval, for real applications use publicly available tested code.  
> **username_3**: ps: I am not sure if we want to allow discussions on crypto protocols proposed by non-experts on the site. IMHO, if this is a research-level question in theoretical computer science, then it falls in the domain of *unpublished work which is not peer-reviewed* policy, so I am voting to close the question as "not a real question".  
> **username_0**: @Yuval: this is exactly reason why I'm asking :) I don't want to be guy like WEP inventors :)  
> **username_0**: @Kaveh: if you won't allow these kind of discussions here that'd mean that CS guys will be apart from real life ones, so there'll be disasters like WEP issues... Anyway - it's your decision.  
> **username_3**: barmaley, I think crypto protocols are complicated constructions and people who lack the basic knowledge on the topic should not design them.  If you seriously want to design crypto protocols you should at least have the basic knowledge in crypto, in which case you should start by reading the crypto textbooks. IMHO, trying to reinvent the wheel and asking researchers to verify it is a bad idea. I don't like the idea of non-experts lacking basic knowledge submitting the ideas they come up with here and ask experts check their correctness. The previous and this comment are personal opinions.  
> **username_3**: Please also note that the scope of this site is *research level theoretical computer science*, it is not our job on cstheory to make sure people don't make disastrous mistakes.  

---

## 2 answers

### Answer by username_5 on 2011-02-17. Score: 9 | Accepted answer

The first problem you face is that a password cannot be used as an encryption key. For instance, let the password be `$%^gHk23`. How do you interpret this as an AES-256 key?

The second problem is that the client has to send the password in clear, and then the server tries to make a key from it, and decrypt saved values.

Thirdly, the scheme is fixed. No [salting](http://en.wikipedia.org/wiki/Salt_%28cryptography%29) whatsoever is incorporated in it, and thus it is vulnerable to a variety of attack, most notably the [dictionary attack](http://en.wikipedia.org/wiki/Dictionary_attack).

The hashing scheme you described at the beginning of your post is very old. Today, an extremely secure password-based identification scheme, named [SRP](http://srp.stanford.edu/), is gaining momentum. (See also the [demo](http://srp.stanford.edu/demo/demo.html).)

> **Comments:**
> **username_0**: 1) I meant based on password calculate hash value which use as say AES key... Or I'm not right?  
> **username_0**: About salting and SRP - let me review those methods. I'm sorry - I'm not professional cryptographer...  
> **username_0**: @Sadeq: in my case client-server channel is secure, so SRP is not required. In contrary server storage is vulnerable, so attacker can review all values stored in server. So I'm talking about way how to verify password validity.  
> **username_5**: @barmaley: Please review this part of your question: "So password protection relies on strength of hashing function." To me, this says that you are going to use a method which is not based on hashing. Then in a comment above, you said: "I meant based on password calculate hash value which use as say AES key." This seems contradictory, right?  
> **username_5**: @barmaley: If the channel is secure, you must mention this as part of your model, since this is very important. Please clarify what you mean by "secure": Is is just confidential, or provides both confidentiality and integrity? Moreover, please decide if you want to use hash functions or not. (If I were you, I'd allow the use of salted hash mechanisms.)  
> **username_0**: @Sadeq: client and server are in the same application/environment - so channel provides confidentiality and integrity. About hashing/non-hashing issue: I'm asking about security of password storage mechanism rather than hash strength. Essential part not about transforming password to key using hash (can be used another approach) but about safety of password validity using described approach  
> **username_5**: @barmaley: OK, I almost got it. IMO, the approach you described seems vulnerable to the following attack: The attacker steals the **saved values** (since you said the storage is not secure), and then mounts a dictionary attack on it. This can be easy unless you assume that passwords have high entropy (that is, they are chosen at random), and are long enough. Example: `apple tree` is a low-entropy pass, while `$%^gHk23` is a high-entropy one.  
> **username_6**: The mention of salting and dictionary attack is timely, because Anonymous just used rainbow tables to hack HBGary.  HBGary could have defended against that by salting their passwords, which they did not do, despite being a professional security company.  Ars Technica has produced some fascinating articles about this.  The one that discusses salting and rainbow tables is [here](http://arstechnica.com/tech-policy/news/2011/02/anonymous-speaks-the-inside-story-of-the-hbgary-hack.ars).  
> **username_5**: @Aaron: Thanks. I didn't hear this exciting piece of news!  
> **username_0**: @Sadeq: thanx a lot - I understand vulnerability point of proposed approach. So as far as I understood I need to use some kind of salting approach - can you point me to a good resource about that?  
> **username_5**: @barmaley: You're most welcome! You may start by reading the Wikipedia page I addressed in the answer. You can also take a look at [this post](http://stackoverflow.com/q/420843/459391) on stackoverflow.  

---

### Answer by username_4 on 2020-04-18. Score: 3

As much as you're being downvoted and attacked, your idea is absolutely right, correct, and valid.
You've nearly reinvented bcrypt.

Let's say we have encryption algorithm (doesn't matter which one):

I'll choose blowfish.

Then generate random sequence of chars consisting predefined array (for instance just random sequence of digits)

I'll pick a sequence of 24 characters. And even better if it's an even multiple of the blowfish 8-byte blocksize:
   OrpheanBeholderScryDoubt
   \______/\______/\______/
      |       |       |
8-bytes     8-bytes   8-bytes


Encrypt sequence with our algorithm with given password and store it somewhere in safe place (let's call it as saved value)

The password needs to be transformed into a 72-byte encryption key - the key size of blowfish. Bcrypt does this with a function called ExpensiveKeySetup:
String password = "correct horse battery staple";
Int32 costFactor = 12;
Byte[16] salt = CryptGenRandom(16);
Byte[72] key  = ExpensiveKeySetup(password, salt, costFactor);

And then we'll encrypt our random sequence of chars. And just to be extra secure: we'll encrypt it 64 times:
Byte[24] ciphertext = BytesOf("OrpheanBeholderScryDoubt");
for int i = 1 to 64 do
   ciphertext = BlowfishEncrypt(cipherText, ref key);

(Why use 3-DES when you can use 64-DES!)
And now you have your stuff to store:

costFactor
salt
ciphertext

Bcrypt coverts the salt and ciphertext to base64, and gives you a string:
$2b$[costFactor]$[salt][ciphertext]

Such as:
$2a$12$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa

Now time to check password validity
Try to decrypt saved value with probe password

Rather than decrypt, just repeat the encryption of "OrpheanBeholderScryDoubt", with the password, and the same salt. And compare the result to what you stored.
It would be nice if the community was nice, helpful, or knowledgeable - rather than just attacking or using clichés.


---

