Passwords.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. * Redistributions of source code must retain the above copyright notice,
  6. this list of conditions and the following disclaimer.
  7. * Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. * Neither the name of LibCat nor the names of its contributors may be used
  11. to endorse or promote products derived from this software without
  12. specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  14. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  17. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  23. POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef CAT_PASSWORDS_HPP
  26. #define CAT_PASSWORDS_HPP
  27. #include <cat/rand/IRandom.hpp>
  28. namespace cat {
  29. /*
  30. Why are passwords needed?
  31. Passwords allow the client identity to be proved to the server. Usually
  32. the server identity is already proven by a secure connection, but the
  33. client identity is unproven until a password is provided.
  34. This could be done using signatures with two-way authentication in the
  35. secure connection establishment, however this is very slow and roughly
  36. doubles the work a server has to do to accept a connection.
  37. Passwords seem simple to implement at first but then you start imagining all
  38. the "what ifs":
  39. What if the password database is stolen?
  40. The user passwords had better not be stored in plaintext!
  41. So they must be hashed.
  42. What if two users have the same password?
  43. They would look the same hashed, so hash in the name with the password.
  44. What if name:password for two users is "me : pass" and "m : epass" ?
  45. They would look the same hashed, so insert a separator between the two
  46. before hashing, as in "me\r\npass" instead of just hashing "mepass".
  47. What if someone tries to crack the passwords?
  48. The password hash should be strengthened to make it harder to crack,
  49. by applying the hash function repeatedly. This does reduce the number of
  50. bits of entropy due to non-ideal hash function collisions, but this small
  51. effect is offset by the added difficulty to crack the password.
  52. What if the user has a common name like "dave"?
  53. The password hash should be salted to avoid falling to rainbow tables.
  54. What if the attacker tries to use the stolen password hash to log into the server?
  55. The client provides a hash pre-image during login, so the attacker would need
  56. to reverse the hash to do this, which is harder than cracking the password.
  57. What if an attacker has a way to actively or passively listen to login attempts?
  58. Then they would be able to steal the hash pre-image which would offer some
  59. amount of text password protection but would allow the attacker to log in
  60. as the user without knowing the password.
  61. Rainbow tables can be used to crack the pre-image to determine the password.
  62. If the connection is secure then the client has verified the server identity
  63. and these attacks are only possible through software bugs in the server.
  64. Protocol Description:
  65. H: 256-bit hash function Skein-256
  66. c: Client
  67. s: Server
  68. X: Strengthening factor
  69. Protocol 1: Creating a User Account
  70. c: Choose a name N
  71. c: Choose a password P
  72. c: Calculate I = H("N\r\nP") strengthened X times
  73. c2s CREATE_ACCOUNT || N || I (32 by)
  74. s: Verify account is not taken, then creates an account in the database
  75. s: Generate a 32-bit random salt S
  76. s: Calculate J = H(S || I)
  77. s: Store N, J and S in the account
  78. s2c ACCOUNT_CREATE_SUCCESS
  79. Protocol 2: Logging into a User Account
  80. c: Choose a name N
  81. c: Choose a password P
  82. c: Calculate I = H("N\r\nP") strengthened X times
  83. c2s LOGIN_REQUEST || N || I (32 by)
  84. s: Verify user name exists in account database
  85. s: Retrieve J, S from the account database
  86. s: Calculate J' = H(S || I)
  87. s: Verify J = J'
  88. s2c LOGIN_SUCCESS
  89. What if the user creates an account through a website?
  90. The server-side script on the website should execute a program that runs
  91. Protocol 1 to create the user account.
  92. Why use this sort of password authentication + Tunnel instead of SRP?
  93. Performance. The Tunnel key agreement takes much less CPU time than SRP
  94. and authenticates the server, which allows this protocol to be run without
  95. any disadvantages.
  96. */
  97. class PasswordBase
  98. {
  99. public:
  100. static const int HASH_BITS = 256;
  101. static const int HASH_BYTES = HASH_BITS / 8;
  102. static const int STRENGTHENING_FACTOR = 1000;
  103. };
  104. class PasswordCreator : public PasswordBase
  105. {
  106. public:
  107. // Hash a password for transmission to the server during account creation or login
  108. // NOTE: You should make the name all lowercase before passing it in
  109. // Returns false on failure
  110. bool HashPassword(const void *in_name, int name_bytes,
  111. const void *in_password, int password_bytes,
  112. void *out_hash /* 32 bytes */);
  113. // This version accepts non-unicode C strings with nul-terminators
  114. // It converts the name to lowercase internally
  115. bool HashPasswordString(const char *in_name,
  116. const char *in_password,
  117. void *out_hash /* 32 bytes */);
  118. };
  119. class PasswordVerifier : public PasswordBase
  120. {
  121. public:
  122. // Salt a hash for storage in the account database during account creation
  123. // Generates a 32-bit salt and a 256-bit hash for storage
  124. // Returns false on failure
  125. bool SaltHash(IRandom *prng,
  126. const void *in_hash /* 32 bytes */,
  127. void *out_salted_hash /* 32 bytes */,
  128. u32 *out_salt /* 4 bytes */);
  129. // Given the stored salted hash and salt, verify the client's password hash during login
  130. // Returns false if password is incorrect
  131. bool VerifyHash(const void *in_hash /* 32 bytes */,
  132. const void *in_salted_hash /* 32 bytes */,
  133. u32 in_salt /* 4 bytes */);
  134. };
  135. } // namespace cat
  136. #endif // CAT_PASSWORDS_HPP
粤ICP备19079148号