emysql_auth.erl 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. -module(emysql_auth).
  2. -export([make_auth/2, make_new_auth/3, password_old/2, password_new/2]).
  3. %%--------------------------------------------------------------------
  4. %% Macros
  5. %%--------------------------------------------------------------------
  6. -define(LONG_PASSWORD, 1).
  7. -define(LONG_FLAG, 4).
  8. -define(PROTOCOL_41, 512).
  9. -define(TRANSACTIONS, 8192).
  10. -define(SECURE_CONNECTION, 32768).
  11. -define(CONNECT_WITH_DB, 8).
  12. -define(MAX_PACKET_SIZE, 1000000).
  13. password_old(Password, Salt) ->
  14. {P1, P2} = hash(Password),
  15. {S1, S2} = hash(Salt),
  16. Seed1 = P1 bxor S1,
  17. Seed2 = P2 bxor S2,
  18. List = rnd(9, Seed1, Seed2),
  19. {L, [Extra]} = lists:split(8, List),
  20. list_to_binary(lists:map(fun (E) -> E bxor (Extra - 64) end, L)).
  21. %% part of do_old_auth/4, which is part of mysql_init/4
  22. make_auth(User, Password) ->
  23. Caps = ?LONG_PASSWORD bor ?LONG_FLAG bor ?TRANSACTIONS,
  24. Maxsize = 0,
  25. UserB = list_to_binary(User),
  26. PasswordB = Password,
  27. <<Caps:16/little, Maxsize:24/little, UserB/binary, 0:8,
  28. PasswordB/binary>>.
  29. %% part of do_new_auth/4, which is part of mysql_init/4
  30. make_new_auth(User, Password, Database) ->
  31. DBCaps = case Database of
  32. none ->
  33. 0;
  34. _ ->
  35. ?CONNECT_WITH_DB
  36. end,
  37. Caps = ?LONG_PASSWORD bor ?LONG_FLAG bor ?TRANSACTIONS bor
  38. ?PROTOCOL_41 bor ?SECURE_CONNECTION bor DBCaps,
  39. Maxsize = ?MAX_PACKET_SIZE,
  40. UserB = list_to_binary(User),
  41. PasswordL = size(Password),
  42. DatabaseB = case Database of
  43. none ->
  44. <<>>;
  45. _ ->
  46. list_to_binary(Database)
  47. end,
  48. <<Caps:32/little, Maxsize:32/little, 8:8, 0:23/integer-unit:8,
  49. UserB/binary, 0:8, PasswordL:8, Password/binary, DatabaseB/binary>>.
  50. hash(S) ->
  51. hash(S, 1345345333, 305419889, 7).
  52. hash([C | S], N1, N2, Add) ->
  53. N1_1 = N1 bxor (((N1 band 63) + Add) * C + N1 * 256),
  54. N2_1 = N2 + ((N2 * 256) bxor N1_1),
  55. Add_1 = Add + C,
  56. hash(S, N1_1, N2_1, Add_1);
  57. hash([], N1, N2, _Add) ->
  58. Mask = (1 bsl 31) - 1,
  59. {N1 band Mask , N2 band Mask}.
  60. rnd(N, Seed1, Seed2) ->
  61. Mod = (1 bsl 30) - 1,
  62. rnd(N, [], Seed1 rem Mod, Seed2 rem Mod).
  63. rnd(0, List, _, _) ->
  64. lists:reverse(List);
  65. rnd(N, List, Seed1, Seed2) ->
  66. Mod = (1 bsl 30) - 1,
  67. NSeed1 = (Seed1 * 3 + Seed2) rem Mod,
  68. NSeed2 = (NSeed1 + Seed2 + 33) rem Mod,
  69. Float = (float(NSeed1) / float(Mod))*31,
  70. Val = trunc(Float)+64,
  71. rnd(N - 1, [Val | List], NSeed1, NSeed2).
  72. dualmap(_F, [], []) ->
  73. [];
  74. dualmap(F, [E1 | R1], [E2 | R2]) ->
  75. [F(E1, E2) | dualmap(F, R1, R2)].
  76. bxor_binary(B1, B2) ->
  77. list_to_binary(dualmap(fun (E1, E2) ->
  78. E1 bxor E2
  79. end, binary_to_list(B1), binary_to_list(B2))).
  80. password_new(Password, Salt) ->
  81. Stage1 = crypto:sha(Password),
  82. Stage2 = crypto:sha(Stage1),
  83. Res = crypto:sha_final(
  84. crypto:sha_update(
  85. crypto:sha_update(crypto:sha_init(), Salt),
  86. Stage2)
  87. ),
  88. bxor_binary(Res, Stage1).