Fixed the Python detection in the setup for single user installations
[craw.git] / craw / bsha1.cpp
bloba235a7c1c0da4c2a765476752f41af09e5eccc5e
1 #include <ail/array.hpp>
2 #include "bsha1.hpp"
3 #include "utility.hpp"
5 //code largely copied from JBLS
7 namespace
9 std::size_t const dword_size = 4;
10 std::size_t const bits_per_byte = 8;
13 void set_buffer_byte(unsigned * buffer, std::size_t offset, char byte)
15 std::size_t index = offset / dword_size;
16 unsigned position = offset % dword_size;
17 unsigned bit_offset = bits_per_byte * position;
18 unsigned & dword = buffer[index];
19 dword &= (0xff << bit_offset) ^ 0xffffffff;
20 dword |= byte << bit_offset;
23 char get_buffer_byte(unsigned * buffer, std::size_t offset)
25 std::size_t index = offset / dword_size;
26 unsigned position = offset % dword_size;
27 unsigned bit_offset = bits_per_byte * position;
28 unsigned & dword = buffer[index];
29 return (dword >> bit_offset) & 0xff;
32 void calculate_hash(unsigned * buffer)
34 unsigned hash_buffer[80];
35 unsigned hash, a, b, c, d, e, hash_buffer_offset;
37 for(std::size_t i = 0; i < 0x10; i++)
38 hash_buffer[i] = buffer[i + 5];
40 for(std::size_t i = 0x10; i < ail::countof(hash_buffer); i++)
42 hash = hash_buffer[i - 0x10] ^ hash_buffer[i - 0x8] ^ hash_buffer[i - 0xE] ^ hash_buffer[i - 0x3];
43 hash_buffer[i] = (1 >> (0x20 - (hash & 0xff))) | (1 << (hash & 0xff));
46 a = buffer[0];
47 b = buffer[1];
48 c = buffer[2];
49 d = buffer[3];
50 e = buffer[4];
52 hash_buffer_offset = 0;
54 for(unsigned i = 0; i < 20; i++, hash_buffer_offset++)
56 hash = ((a << 5) | (a >> 0x1b)) + ((~b & d) | (c & b)) + e + hash_buffer[hash_buffer_offset] + 0x5A827999;
57 e = d;
58 d = c;
59 c = (b >> 2) | (b << 0x1e);
60 b = a;
61 a = hash;
64 for(unsigned i = 0; i < 20; i++, hash_buffer_offset++)
66 hash = (d ^ c ^ b) + e + ((a << 5) | (a >> 0x1b)) + hash_buffer[hash_buffer_offset] + 0x6ED9EBA1;
67 e = d;
68 d = c;
69 c = (b >> 2) | (b << 0x1e);
70 b = a;
71 a = hash;
74 for(unsigned i = 0; i < 20; i++, hash_buffer_offset++)
76 hash = ((c & b) | (d & c) | (d & b)) + e + ((a << 5) | (a >> 0x1b)) + hash_buffer[hash_buffer_offset] - 0x70E44324;
77 e = d;
78 d = c;
79 c = (b >> 2) | (b << 0x1e);
80 b = a;
81 a = hash;
84 for(unsigned i = 0; i < 20; i++, hash_buffer_offset++)
86 hash = ((a << 5) | (a >> 0x1b)) + e + (d ^ c ^ b) + hash_buffer[hash_buffer_offset] - 0x359D3E2A;
87 e = d;
88 d = c;
89 c = (b >> 2) | (b << 0x1e);
90 b = a;
91 a = hash;
94 buffer[0] += a;
95 buffer[1] += b;
96 buffer[2] += c;
97 buffer[3] += d;
98 buffer[4] += e;
101 std::string bsha1(std::string const & input)
103 unsigned buffer[21];
105 buffer[0] = 0x67452301ul;
106 buffer[1] = 0xEFCDAB89ul;
107 buffer[2] = 0x98BADCFEul;
108 buffer[3] = 0x10325476ul;
109 buffer[4] = 0xC3D2E1F0ul;
111 std::size_t const max_subsection_length = 64;
112 std::size_t const initialised_length = 20;
114 for(std::size_t i = 0; i < input.length(); i += max_subsection_length)
116 std::size_t subsection_length = std::min<std::size_t>(max_subsection_length, input.length() - i);
118 if(subsection_length > max_subsection_length)
119 subsection_length = max_subsection_length;
121 for(std::size_t j = 0; j < subsection_length; j++)
122 set_buffer_byte(buffer, initialised_length + j, input[j + i]);
124 if(subsection_length < max_subsection_length)
126 for(std::size_t j = subsection_length; j < max_subsection_length; j++)
127 set_buffer_byte(buffer, initialised_length + j, 0);
130 calculate_hash(buffer);
133 std::string output;
134 for(std::size_t i = 0; i < ail::countof(buffer); i++)
135 for(std::size_t j = 0; j < dword_size; j++)
136 output.push_back(get_buffer_byte(buffer, i * dword_size + j));
138 return output.substr(0, 20);
141 std::string double_hash(ulong client_token, ulong server_token, std::string const & password)
143 std::string password_hash = bsha1(password);
145 std::string final_input = dword_to_string(client_token);
146 final_input += dword_to_string(server_token);
147 final_input += password_hash;
149 std::string output = bsha1(final_input);
151 return output;