85

I'm afraid I'll have tomatoes thrown at me for asking this old question, but here goes.

After reading that cooking up your own password hash out of existing hashing functions is dangerous over and over again I still don't understand the logic. Here are some examples:

  • md5(md5(salt) + bcrypt(password))
  • scrypt(bcrypt(password + salt))
  • sha1(md5(scrypt(password + md5(salt))))

The typical arguments against these go as follows:

You're not a cryptographer! You've got no idea if these hashes are more secure. Leave it to the experts who know what they're doing. These add no extra security.

Granted they don't improve the function as a hash (i.e. make it harder to reverse or find collisions etc.), but surely surely they don't make it worse as a hash? If they did then hackers would be able to re-hash standardly hashed passwords into these wacky hashes as they see fit and weaken the hash? I don't buy it.

Second argument:

Kerckoffs's principle: A cryptosystem should be secure even if everything about the system is known.

Agreed. This is basically the motivation for not storing your passwords as plaintext in the first place. But if my response to the first criticism stands then these wacky hashes still function as secure hashes, and our system doesn't break Kerckoffs's principle anymore than it would with a standard hash.

Here are two possible (and worthwhile, as far as I can see) advantages to using a "wacky" hash over a normal hash:

  1. Sure, your system should be secure if the attacker has the source code, but it's a very likely possibility that your attacker wont have access to your source code and probably won't be able to guess your wacky hash, making any attempt at a brute force impossible.
  2. (This one is the real motivation behind me asking this question) BCrypt is thought to be secure, hard for the CPU and GPU (great) but can be very fast with specialized hardware. SCrypt is said to be hard to bruteforce on CPUs, GPUs and currently available specialized hardward but is more recent and not trusted by the cryptographic community as much as BCrypt due to the lack of exposure it's had. But doesn't the hash BCrypt(SCrypt(password + salt)) get the best of both worlds?

I appreciate that the passion/anger behind most rants against these home-brewed hashes comes from the average programmer's lack of knowledge of what makes a good hash, and a worry that encouraging this sort of wacky-hashing will inevitably end up with weak and useless hashes getting into production code. But If the wacky hash is carefully constructed out of solid and trusted hashes, are the gains in security not very valuable and real?


Update

I got a bunch of good answers on this, thanks. What I seemed to be overlooking in my assumptions was that, although combining hashes can't make it easier to crack the original password and therefore crack the constituent hashes, the combination of two or more secure hashes can - at least in principle - be weaker than any one of its inner hashes due to the unstudied and complex interactions between them. Meaning it could be possible to find some string that got past the wacky hash without necessarily breaking the hashes that made it up.

2
  • 5
    If your goal is just to protect against an attacker without access to your source code, then using a pepper (basically a hard-coded secret value that you hash along with the password) would be sufficient, and less error-prone than creating your own hash function. Commented Apr 1, 2013 at 15:10
  • 11
    why not add a sleep(15000); after each hash? sure benefits are unknown but it certainly doesn't make it less secure :) Commented Apr 2, 2013 at 10:55

10 Answers 10

73

The fact that you need to ask this question is the answer itself - you do not know what is wrong with stacking these primitives, and therefore cannot possibly know what benefits or weaknesses there are.

Let's do some analysis on each of the examples you gave:

md5(md5(salt) + bcrypt(password))

I can see a few issues here. The first is that you're MD5'ing the salt. What benefit does this give? None. It adds complexity, and the salt is simply meant to be unique to prevent password collisions and pre-computation (e.g. rainbow table) attacks. Using MD5 here doesn't make any sense, and might actually weaken the scheme since MD5 has known trivial collisions. As such, there is a small possibility that introducing MD5 here might mean that two unique salts produce the same MD5 hash, resulting in an effectively duplicated salt. That's bad.

Next, you use bcrypt on the password. Ok. Well, most bcrypt implementations require a salt internally, so this is already technically invalid. Let's say you know that, and you meant to say bcrypt(md5(salt), password). This part is still falling to the weakness I described above, but it's not too shabby - remove the MD5 and it's a standard use of bcrypt.

Finally, you MD5 the whole thing. Why are you doing this? What is the purpose? What benefit does it bring? As far as I can see, there is no benefit at all. On the detriment side, it adds more complexity. Since most bcrypt implementations use the $2a$rounds$salt$hash notation, you're going to have to write code to parse that so that you can extract the hash part and store the rest separately. You're also going to need an MD5 implementation, which was unnecessary.

So, in terms of code footprint for potential attack vectors, you've gone from a simple bcrypt implementation, to a bcrypt implementation with custom parsing code, and MD5 implementation, and some glue code to stick it all together. For zero benefit, and a potential vulnerability in salt handling.

Next one:

scrypt(bcrypt(password + salt))

This one isn't too bad, but again you need some code to parse out the results of bcrypt into hash and salt / round count separately. In this case I'd guess that there is a slight benefit, because bcrypt and scrypt work in different ways for roughly the same goal, which would make it a little more difficult for an extremely well-funded attacker to build custom ASICs to break your scheme. But is that really necessary? Are you really going to hit a situation where a nation state will devote a few million dollars to just to break your hash? And, if that case ever arises, will it really bother the attacker to have to spend a few extra million to double their chip count?

Another potential issue with combining bcrypt and scrypt like this is that there has been very little study into how the two interact. As such, we don't know if there are any weird cases that can cause problems. As a more obvious example, take the one time pad. We compute c=m^k for some message m and some equally long perfectly random key k, and we get perfect security. So let's do it twice, for even more security! That gives us c=m^k^k... oh, wait, that just gives us m. So because we didn't take the time to properly understand how the internals of the system worked, we ended up with a real security vulnerability. Obviously it's more complicated in the case of KDFs, but the same principle applies.

And finally:

sha1(md5(scrypt(password + md5(salt))))

Again we're running into the MD5'ed salt issue. I'm also intrigued by MD5'ing the SHA1 hash. What possible benefit could that have, if you're already using a slow KDF like scrypt? The few nanoseconds it would take to compute those hashes pales in comparison to the hundreds of milliseconds it would take to compute the scrypt digest of the password. You're adding complexity for an absolutely irrelevant layer of "security", which is always a bad thing. Every line of code that you write is a potential vulnerability.


Now remember that point I made at the start of my answer. If, at any point in this answer, you thought "oh yeah, I didn't think about that", then my point is proven.

You're running into what I would describe as Dave's false maxim:

If I add more crypto things, it will be more secure.

This is a common trait among developers, and I once believed it too. It goes hand-in-hand with denial of other principles, such as Kerckhoff's Principle. Ultimately, you have to realise and accept that obscurity isn't a safety rail; it's a crutch for weak crypto. If your crypto is strong, it needs no crutch.

21
  • 26
    The interaction between the two is undefined, because nobody has studied it. Combining the two might provide more security, but it also might lead to unusual interactions between the internals of those hashes. A good example of this is the one time pad. Computing c=m^k gives you a perfect level of security when k is truly random and unknown to the attacker. So let's do it twice, for more security! So we end up with c=m^k^k, which results in m. Oh, whoops. Obviously the interactions are more complex in hashes, but the principle still stands.
    – Polynomial
    Commented Apr 1, 2013 at 13:09
  • 4
    My point is that since we don't know what potential problems might exist, why not go with the known safe route and just use scrypt with a decent work factor? It's more than secure enough for almost every purpose.
    – Polynomial
    Commented Apr 1, 2013 at 13:10
  • 2
    @Polynomial +1 Great answer. However I wasn't convinced about the bcrypt/scrypt part of your answer until I read your comment about one-time pads. Might consider adding that comment to your answer.
    – Phil
    Commented Apr 1, 2013 at 14:02
  • 10
    I still don't see why the scrypt(bcrypt(x)) thing could be a problem. If the two interact weirdly, just using bcrypt doesn't make it more secure- an attacker can simply scrypt() what you've bcrypt()'d. Additionally, if someone figures out a more intelligent way to guess the original plaintext for one hashing algorithm, they probably won't simultaneously have a faster way for the other algorithm. Say people legitimately thought ROT13 was a good hashing mechanism. If I used ROT13(bcrypt(x)), wouldn't I still be better off when people 'cracked' ROT13?
    – root
    Commented Apr 2, 2013 at 9:46
  • 4
    @Brilliand: Attackers will almost certainly find ways of speeding up both algorithms at least somewhat--probably by different amounts. If it turns out attackers find a 100:1 speedup for one algorithm and 2:1 for the other, the attackers would net about a 4:1 speedup against a system that used each algorithm for half as many rounds as could have used in the absence of the other. Unless one knows which system attackers would have "better luck" with, hedging bets hardly seems unreasonable.
    – supercat
    Commented Oct 19, 2014 at 22:39
15

Crypto primitives can be stacked safely, and increase security if, and only if, you know the primitives well enough to understand their weaknesses and how those weaknesses interact. If you don't know them, or don't understand the details - well, that's how you get Dave's protocol.

The problem is very few people know them all well enough to judge if a certain combination is safe. Which is why it needs to be something that is published and reviewed, if it's not been reviewed you have no way of knowing if it's as strong as scrypt or if it's closer to CRC32.

So, if you aren't an expert - it's quite possible that you have something weaker than the weakest primitive you've used (see Dave's protocol) and you wouldn't know it. Or at least you wouldn't know it untill it's cracked – finding your users' passwords on Pastebin isn't quite the ideal way to determine the scheme is flawed.

I do agree that some degree of obscurity can help from a defense in depth perspective, but the underlying system must be secure.

Between scrypt, bcrypt and PBDKF2 - at least one of them will be supported on pretty much every platform. These are known and well tested - they offer differing levels of protection, but they are still far more secure than a bizarre stacking of md5 and sha1.

4
  • 1
    I think that stacking of md5 and sha1 was a bad example, I'd never use that one and it was just for illustration. I'm particulary interested in the bcrypt-scrypt stack. I still don't understand how it could possibly make the hash weaker? As I said, it's a step that could be taken by a hacker if they wanted anyway so if it does weaken the hash then that's a huge problem even if I don't do it for them! Commented Apr 1, 2013 at 10:37
  • 2
    @GeorgePowell : A hacker isn't only interested in recovering original plaintext passwords. He might also be interested in finding collisions. It's possible that you increase the amount of collisions by chaining those functions together.
    – Christian
    Commented Dec 20, 2013 at 19:44
  • Could you explain why, if a hacker has access to the database, they are attempting to find collisions? Also, surely the number of collisions created by a hash function is a function of its quality? If hashing a hash results in more collisions I'd suggest the hash function is poor from the get-go.
    – monster
    Commented Nov 24, 2015 at 10:00
  • @GeorgePowell one way it could be weaker is that bcrypt might already include all parts/techniques from scrypt that make it stronger (or vice versa), but optimized to include just those pieces rather than the whole thing, so you'd get more security for the amount of execution time and memory you're willing to give it by just running the already expertly combined one, than by splitting up the execution time across both.
    – mtraceur
    Commented Jun 8, 2022 at 15:58
14

For your specific question of combining scrypt and bcrypt, remember that these functions have a configurable cost, and you want to raise that cost as much as possible, while keeping it tolerable for your specific usage. For instance, if you can use bcrypt with up to X iterations (beyond which it is too expensive for your server and your average number of user connections per second), or scrypt with up to Y iterations, then you cannot use scrypt(bcrypt) with X iterations for bcrypt then Y iterations for scrypt: this will be beyond your CPU budget.

Thus, if you cascade scrypt and bcrypt, then you must use both with less iterations than what you could have done with one alone. You don't "get the best of both worlds" by simply stringing them together. In fact, the best you can hope for is a kind of average between the two. And that comes at the price of more complex code, something which is inherently bad when talking about security (or, for that matter, maintainability).

7
  • 1
    Most algorithms are likely to become faster with time, though not necessarily by equal amounts. Suppose there's a 1% chance that method X will get sped up 100 fold, and a 10% chance it will get sped up two-fold; likewise for method Y. Unless I'm missing something, I would think that running both algorithms at half-strength would mean that a massive speedup would only be possible for the composite if one was possible for both constituent algorithms.
    – supercat
    Commented Nov 11, 2014 at 0:22
  • Yes, another issue is economies of scale. Mentioned here: security.stackexchange.com/questions/33531/…
    – Pacerier
    Commented Sep 10, 2016 at 2:47
  • @supercat but of course smart cryptographers presumably already thought about that, and deliberately designed each of these algorithms to combine different pieces which are unlikely to be sped up by the same ways. When you combine them, the default assumption is not "I am combining two differently secure techniques", the default assumption should be "the only thing I could change here is inefficiently increase the ratio of uninteresting glue versus the already combined differently secure techniques".
    – mtraceur
    Commented Jun 8, 2022 at 16:05
  • @mtraceur: Whether a cryptographic algorithm gets sped up two-fold or 100-fold will depend in significant measure upon the amount of money that gets spent on the effort. If one uses only popular algorithms, then money will likely get spent improving the performance of all of them. If a program spends 20% of its time on an algorithm that is less popular and attracts less investment, and is thus only spend up two-fold, then no amount of investment in the other algorithms could sped it up more than ten-fold.
    – supercat
    Commented Jun 8, 2022 at 19:18
  • 1
    @mtraceur: Few things are necessarily inevitable. My point was that a combination of two KDF functions that are run for less time than a single KDF would have been may be stronger than a single KDF would have been, in some plausible scenarios. Not that such combinations were always beneficial, much less worth the effort to set them up, but that they could in some cases be beneficial.
    – supercat
    Commented Jun 9, 2022 at 6:59
9

If you apply unsafe operations to a secure algorithm, you can definitely break the hashing function. Your new function could even be far worse than the weakest link.

Why don't attackers use this to break secure functions? It doesn't help them. For example, if I overwrite the first 440 bits of a password safely stored using bcrypt with zeroes, I can easily find a matching password by brute force, but that password will only work on my own terrible algorithm. A sane implementation would probably reject it.

Zeroing large chunks of a hash is clearly bad, but even safe operations can be combined into something dangerous. Adding two numbers (modulo n to ensure a constant length) is 'safe'. Generally, no entropy is lost. Still, h(x) + h(x) mod n reduces the quality of the hash h(x) by one bit, as the result is always even. The equally safe operator XOR does even worse, as h(x) XOR h(x) always returns zero.

These pitfalls are fairly obvious, but not all of them are. Keep in mind that, as always, it is trivial to invent a scheme good enough that you won't find any weaknesses yourself, but very difficult to invent one where no one else can.

1
  • 2
    Good answer, I think I understand the gist: wacky hashes could make it easier to find a match by brute force but couldn't make it easier to find the original password that was used. This is why hackers have no use applying the weaker hash themselves. Cracking the stacked hash does not imply cracking the inner-hashes. Commented Apr 1, 2013 at 11:20
9

In addition to Adam's answer, I'd like to also mention that any time you use cryptography, you should have a strong and unavoidable reason to do so. In your examples above, this does not exist.

md5(md5(salt) + bcrypt(password))
scrypt(bcrypt(password + salt))

The bcrypt and scrypt algorithms are already strong enough, and considered effectively unbreakable. What problem are you trying to solve? And why do you believe that combining their results (particularly with md5) will solve it? In the best case scenario, you've likely merely reduced the difficulty of cracking the password to that of the weakest hash, rather than actually improving security. And the worst case scenario is frighteningly undefined.

md5(sha1(md5(md5(password) + sha1(password + salt)) + password))

This solution is even worse. It manually implements a repeated hashing scheme, but without enough rounds to actually impose a significant work factor on attackers.

In a nutshell, the problem is that:

  • you're throwing around cryptography without actually having a problem that needs solving
  • you've dramatically increased the likelihood of introducing flaws in your implementation
  • you've likely decreased security to the weakest of the hashing algorithms, and
  • you've introduced an unknown worst-case scenario where none used to exist
6
  • The "problem that i'm trying to solve" or the advantages of doing them was addressed at the end of the question. And I still don't understand how a stack of hashes like sha1(md5(bcrypt())) could be weaker than bcrypt! Please explain, if putting md5 ontop of bcrypt made it weaker then why on earth aren't hackers doing it themselves once they get the bcryt-ed passwords? Commented Apr 1, 2013 at 10:57
  • @GeorgePowell Your sha1(md5(bcrypt())) scheme makes no sense. What does it offer that bcrypt alone doesn't? If you're looking for more security in bcrypt, why not just increase the work factor, or switch to scrypt? Abusing other hash primitives, especially mainly-broken ones like MD5, for an undefined and minuscule benefit (which may actually be a detriment) isn't smart and can only provide you with more complexity.
    – Polynomial
    Commented Apr 1, 2013 at 11:06
  • 5
    The security issue isn't really a cryptographic one. You have to write lines of code to produce this implementation, and every line you write brings potential vulnerabilities. Even subtle things like how Unicode is handled on certain machines can be catastrophic from a security perspective. Keep it simple, keep the implementation clean of needless crud, and you'll be safer.
    – Polynomial
    Commented Apr 1, 2013 at 12:11
  • 2
    @GeorgePowell It doesn't help them. Imagine there exists a hash function that has an output space of one single byte. It is obviously trivial for an attacker to brute force our passwords if we use that at any point to compute digests (even if we later pass that to something like bcrypt). But the fact that this weak hash exists doesn't allow an attacker to use it against us, because we're not using it. Commented Apr 1, 2013 at 15:28
  • 1
    @GeorgePowell Additionally, the "problem" that you're trying to solve doesn't actually exist. It is purely imaginary. If it existed, professional cryptographers would be scrambling like mad to put out a permanent solution. Your apparent belief that 1) a practical problem exists, 2) there is no published solution, and 3) the "solution" is trivial comes along with the implicit assertion that professional cryptographers are stupid and/or lazy. Otherwise they'd already have come up with a fix, right? Commented Apr 1, 2013 at 15:34
6

Hash functions are built by cryptographers and destroyed by cryptographers. There are many strong hash functions as well as weak ones still being use today. Programmers should trust the cryptographers and the hash function. If there was ever a vulnerability in the hash function, then you would surely hear about it on the internet or through co-workers and then cryptographers will surely to a deep investigation. With any secure hash algorithm, it's only known weakness may be a bruteforce attack.

Combining hash functions adds almost no extra security and anything you might want to add, is probably already implemented in the function already.

Salting a password is great for reducing the effectiveness against rainbow tables such that a password couldn't be just "looked up." Whether you hash a function twice or change the hash function, it is essentially salting the password. And most functions include an easy method to salt so there is really no need to implement this.

Lets say I want to create my own secure hash because everyone does it. And since I'm not a cryptographer, I will need it "really" secure, because of course, every programmer knows how to make a secure hash instead of using the secure ones already created. So I create my devious hash function, mod10(md5(sha1(bcrypt(password + salt)))).

As you can see from my hash function, it is really secure because I use so many different things in it. Of course in this silly example, it is easy to see there are only going to be 10 different possible outputs. But by simply using a single secure hash function, it would have completely avoided this.

Sure, your system should be secure if the attacker has the source code, but it's a very likely possibility that your attacker wont have access to your source code and probably won't be able to guess your wacky hash, making any attempt at a brute force impossible

So we are assuming an attacker got ahold of the database table that contains the hashes. I would assume it would be very likely that an attacker can get the webpage files aswell. Your systems running these services maybe the same exploit that allowed you database to get taken. A database server is setup so that that public cannot directly access it. On the other hand, your web server containing your code, is on the front lines.

5

Anytime you increase the complexity of an algorithm or even add more lines of code, you increase the points of failure in your application. There may be unintended consequences of combining algorithms. This may lead to certain tells or other signs which can actually weaken the cryptographic strength of the system.

The more libraries you use in your application, the greater the risk to your application in general. If a flaw is found in one implementation that allows a weakness, code execution, etc. then your application is vulnerable. If you happened by luck to select another algorithm that was not attacked, your safe for the time being (of course you could also be on the unlucky side of luck).

Remember KISS: Keep it simple, stupid, or else you may get lost in the complexity.

2

I am going to disagree with a whole bunch of people who are smarter than me and more experienced in security than I am. So I am probably wrong.

Improvising your own hash function is a good idea - if you do it right. Follow these 3 simple steps.

  1. Identify a weakness or flaw in the existing hash functions.
  2. Improvise your own hash function that does not have this flaw.
  3. Verify that your improvised hash function has all the strengths of the existing hash functions.

After you complete step 3, you would be a fool not to use your improvised hash function.

2
  • 5
    The problem is that you can't complete step 3. No one in the world is capable of unilaterally determining that a new hash algorithm is strong. This is why, in order to gain acceptance, new candidate algorithms go though massive multi-year refereed peer-reviewed competitions and undergo exceptional amounts of scrutiny. You simply can't know if an algorithm is safe in a vacuum.
    – Xander
    Commented Apr 2, 2013 at 0:54
  • 1
    @Xander, I can not complete any one of the steps. So for me, I don't improvise. While step 3 is probably the most important, step 1 is the most basic. If you can't at least identify a problem with an existing secure hash function, then why are you wasting your time improvising a new hash function.
    – emory
    Commented Apr 3, 2013 at 1:04
0

When concatenating different hash functions because you are worried the one it is vital that you apply the salt back before applying the next hashing algorithm, then any collision weaknesses in one of the algorithm won't taint the second hash function that you are using:

scrypt(bcrypt(password + salt) + salt)

But I think scrypt is an established technique now, Argon 2i has won the password hashing competition and is believed to be more secure and bcrypt has been around a long time and has proven to be secure against trivial bypasses.

Therefore the following would make more sense, and would combine the strength of argon 2i, but would fall back to bcrypt if a future attacker showed how to trivially break argon 2i, which is currently thought to be hard:

bcrypt(Argon2i(password + salt) + salt)

But you are less likely to make a mistake if you simply do:

scrypt(password + salt) Or bcrypt(password + salt)

Remember, most breaches are due to human error in the code, much better to keep it simple and thoroughly review your code with dynamic, static analysis and human code reviewers, to make sure no sql injection attacks slip through (Remember always parameterize your database queries!)

-2

I have learned a lot with this thread, so I thought in a way to easily understand the possible outcome when combined different methods (of course, it won't fit all cases):

[W=weak, S=strong]:

Formula        | Example
---------------|-----------------
W(W) = W       | md5(sha1(pwd))
W(S) = W       | md5(bcrypt(pwd))
S(W) = W       | bcrypt(md5(pwd)) 
S(S) = S-      | bcrypt(scrypt(pwd)) //their interaction is unknown
W+S = W        | md5(pwd)+brcypt(pwd) 
S+S = W        | bcrypt(pwd)+scrypt(pwd)
W'+S" = S      | md5(pwd1)+brcypt(pwd2) //pwd1 != pwd2
S'+S" = 2S     | bcrypt(pwd1)+scrypt(pwd2) //pwd1 != pwd2
SUBSTR(W) = W  | substr(md5(pwd),n); //Shorter the string, the weaker
SUBSTR(S) = S- | substr(bcrypt(pwd),n); //Shorter the string, the weaker
S+x = S+       | bcrypt(pwd)+x   //x=Variable str. unrelated to pwd
S(S+x) = S-    | bcrypt(scrypt(pwd)+x) //x=Variable str. unrelated to pwd
ROT13(S) = S   | ROT13(bcrypt(pwd))  

What I want to achieve here is to show in a simple way that those combinations won't add extra security in most of the cases (so added complexity is not worthy).

9
  • It is impossible to say such a general thing as S(S) = S-. As Polynomial explained in a comment above, repeating a strong hashing function can in principle result in a completely useless hash. What are these "Formulas" based on? Commented Apr 14, 2016 at 17:54
  • @GeorgePowell: Yes, S(S) could lead to an unexpected behavior, which could potentially result in a useless hash. That is why is marked: S-, which means it will be less strong than S alone, so it is not recommended. As we are not specifying the actual algorithms, we can't be 100% sure it will produce useless hashes, but should be avoided due to such risk. These "Formulas" have no scientific grounds in any way and are just my attempt to represent such interactions in an easy way so anyone trying to "run their own" can have an idea of what to expect and avoid their use.
    – lepe
    Commented Apr 15, 2016 at 0:57
  • @lepe, W(S) = W? Are you sure? See security.stackexchange.com/questions/33531/…
    – Pacerier
    Commented Sep 10, 2016 at 2:49
  • @Pacerier: One point to analyze is "collision probability". If you use MD5 to hash a bcrypt hash, you are increasing the chances of collision and thus, reducing its strength. Also, if the MD5 hash is compromised, brute-forcing the MD5 hash directly could be much faster, removing "S" from the formula (depending on implementation that could be a huge issue). One more point is that if the W algorithm has a security flaw, it can make the W(S) flawed as well. For those reasons, W(S) should never be considered S or S+. It's better to use S alone to prevent adding complexity and unnecessarily risks.
    – lepe
    Commented Sep 12, 2016 at 1:13
  • @lepe, 1) Sure you could bruteforce W, but bruteforcing W gives you S(password), not the password itself. In other words, after bruteforcing W you are back at square one. See the link to Root's comment above. 2) Next, if the W algorithm has a security flaw, it cannot make W(S) flawed. [cont]
    – Pacerier
    Commented Sep 18, 2016 at 19:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .