Advertisement
limimage

lab2

Mar 20th, 2020
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.95 KB | None | 0 0
  1. #include<bits/stdc++.h>
  2. #include "cryptopp/sha.h"
  3. using CryptoPP::SHA256;
  4.  
  5. using namespace std;
  6. using uc = unsigned char;
  7. using vuc = vector<uc>;
  8.  
  9. //Constants
  10. constexpr int RANDSZ = (1 << 20);
  11. constexpr int MINNUMBIT = 15;
  12. constexpr int MAXNUMBIT = 20;
  13. constexpr int MAXNUMCOL = 100;
  14. constexpr int MMASK = (1 << 16) - 1;
  15. constexpr int DIGEST_SIZE = 32;
  16.  
  17. mutex mtx1;
  18. mutex mtx2;
  19.  
  20. //to compile this:
  21. //-l:libcryptopp.a
  22.  
  23. //function that allows print vuc in hex
  24. ostream& operator<<(ostream& out, const vuc& v) {
  25. for (auto& c: v)
  26. out << setw(2) << setfill('0') << hex << (int)c;
  27. out << endl;
  28. }
  29.  
  30. vuc sha256(vuc data) {
  31. vuc ans(CryptoPP::SHA256::DIGESTSIZE);
  32. try {
  33. byte const* pbData = (byte*)data.data();
  34. unsigned int nDataLen = data.size();
  35. byte abDigest[CryptoPP::SHA256::DIGESTSIZE];
  36.  
  37. CryptoPP::SHA256().CalculateDigest((CryptoPP::byte*)abDigest, (CryptoPP::byte*)pbData, nDataLen);
  38.  
  39. memcpy(&ans[0], abDigest, CryptoPP::SHA256::DIGESTSIZE);
  40. }
  41. catch(...){};
  42. return ans;
  43. }
  44.  
  45. //Generate salt
  46. vuc GenSalt(int size) {
  47. vuc buff;
  48. try {
  49. unsigned seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
  50. mt19937 Mrand(seed);
  51. buff.resize(size);
  52. for (int i = 0; i < size; i++)
  53. buff[i] = Mrand() % UCHAR_MAX;
  54. }
  55. catch (...) {}
  56. return buff;
  57. }
  58.  
  59. //return first sz bits of sha256
  60. unsigned int shaxx(vuc data, int sz) {
  61. vuc hash;
  62. unsigned int ans = 0;
  63. try {
  64. hash = sha256(data);
  65. for (int i = 0, j = 0; i < sz; i += 8, j++)
  66. ans <<= 8, ans ^= ((unsigned int)hash[j]);
  67. }
  68. catch(...){};
  69. return ans;
  70. }
  71.  
  72. // add (zeros) to the end
  73. vuc pad(unsigned int val) {
  74. vuc res;
  75. try {
  76. res.resize(DIGEST_SIZE);
  77. fill(res.begin(), res.end(), 0);
  78. int j = 0;
  79. stack<uc> st;
  80. while(val) {
  81. st.push(val & (unsigned int)UCHAR_MAX);
  82. val >>= 8;
  83. }
  84. while(st.size())
  85. res[j++] = st.top(), st.pop();
  86. }
  87. catch(...){};
  88. return res;
  89. }
  90.  
  91. //function that return collision and size of map for task1
  92. tuple<vuc, vuc, long long> subtask1(int sz) {
  93. unordered_map<unsigned int, vuc> mp;
  94. try {
  95. auto start = chrono::high_resolution_clock::now();
  96. while(true) {
  97. vuc data = GenSalt(DIGEST_SIZE);
  98. unsigned int hash = shaxx(data, sz);
  99. if (mp.count(hash)) {
  100. return {data, mp[hash], mp.size()};
  101. }
  102. mp[hash] = data;
  103. }
  104. }
  105. catch(...){}
  106. }
  107.  
  108.  
  109.  
  110. //check that first q bits of val is '0' q = (num_bits_of_shaxx) / 2 - log2(num_threads) in my case
  111. bool check(int val, int num, int log2numth = 1) {
  112. return ((val & ((1 << num) - (1 << ((num >> 1) - log2numth)))) == 0);
  113. }
  114.  
  115. //function that find collision (rho)
  116. void process(vuc init, pair<int, int>* ans1, pair<int, int>* ans2, int num_bit, unordered_map<unsigned int, pair<int, int>>* st, bool flag) {
  117. unsigned int i = 0, temp;
  118.  
  119. while(true) {
  120.  
  121. //in case of cycle without 'good' distinguish points
  122. if (i > (1 << (num_bit >> 1)))
  123. return;
  124.  
  125. mtx1.lock();
  126. if (*ans1 != pair<int, int>()) {
  127. mtx1.unlock();
  128. return;
  129. }
  130. mtx1.unlock();
  131.  
  132. temp = shaxx(init, num_bit);
  133.  
  134. if (check(temp, num_bit)) {
  135. mtx2.lock();
  136. if ((*st).count(temp)) {
  137. *ans1 = {i, flag};
  138. *ans2 = (*st)[temp];
  139. mtx2.unlock();
  140. return;
  141. }
  142. (*st)[temp] = {i, flag};
  143. mtx2.unlock();
  144. }
  145.  
  146. init = pad(temp);
  147. i++;
  148. }
  149. }
  150.  
  151. //func make initial values's numbers of iterations equal (крч, приводит к такому виду, в котором им нужно одинаковое число итераций(применение shaxx и padding) до коллизии)
  152. void correctInitVals(pair<int, int>& i, pair<int, int>& j, vuc& init1, vuc& init2, vuc& cp1, vuc& cp2, int size) {
  153. //check that data from different threads
  154. if (i.second != j.second) {
  155. if (i.second == 1)
  156. swap(i, j);
  157. }
  158. else {
  159. if (i.second == 1)
  160. memcpy(&init1[0], &init2[0], init1.size());
  161. else
  162. memcpy(&init2[0], &init1[0], init2.size());
  163. }
  164.  
  165. //to equalize num_of_iter
  166. while(i.first > j.first) {
  167. memcpy(&cp1[0], &init1[0], init1.size());
  168. init1 = pad(shaxx(cp1, size));
  169. i.first--;
  170. }
  171. while(j.first > i.first) {
  172. memcpy(&cp2[0], &init2[0], init2.size());
  173. init2 = pad(shaxx(cp2, size));
  174. j.first--;
  175. }
  176. }
  177.  
  178. tuple<vuc, vuc, long long> subtask2(int sz) {
  179. pair<int, int> i; // idx/thread_id
  180. pair<int, int> j; // idx/thread_id
  181. unordered_map<unsigned int, pair<int, int>> st;
  182. vuc initValFirstThread, initValSecondThread, cp1, cp2; //cp1 - copy of initValFirstThread, cp2 - copy of initValSecondThread
  183. try {
  184. initValFirstThread = GenSalt(DIGEST_SIZE);
  185. initValSecondThread = GenSalt(DIGEST_SIZE);
  186. cp1.resize(DIGEST_SIZE);
  187. cp2.resize(DIGEST_SIZE);
  188. memcpy(&cp1[0], &initValFirstThread[0], DIGEST_SIZE);
  189. memcpy(&cp2[0], &initValSecondThread[0], DIGEST_SIZE);
  190.  
  191. thread th1(process, initValFirstThread, &i, &j, sz, &st, 0);
  192. thread th2(process, initValSecondThread, &i, &j, sz, &st, 1);
  193.  
  194. if (th1.joinable())
  195. th1.join();
  196. if (th2.joinable())
  197. th2.join();
  198.  
  199. //in case of cycle without 'good' distinguish points
  200. if (i.first == 0 && j.first == 0)
  201. return {vuc(), vuc(), -1};
  202.  
  203. correctInitVals(i, j, initValFirstThread, initValSecondThread, cp1, cp2, sz);
  204.  
  205. while(true) {
  206. if (initValFirstThread == initValSecondThread)
  207. break;
  208. memcpy(&cp1[0], &initValFirstThread[0], DIGEST_SIZE);
  209. memcpy(&cp2[0], &initValSecondThread[0], DIGEST_SIZE);
  210. initValFirstThread = pad(shaxx(cp1, sz));
  211. initValSecondThread = pad(shaxx(cp2, sz));
  212. }
  213. }
  214. catch(...) {}
  215. return {cp1, cp2, st.size()};
  216. }
  217.  
  218. //count requred info about func, flag is used for print collisions
  219. void task_handler(function<tuple<vuc, vuc, long long>(int i)> func, bool flag = 0) {
  220. for (int i = MINNUMBIT; i <= MAXNUMBIT; i++) {
  221.  
  222. double tim = 0;
  223. long long sz = 0;
  224. int num_of_itr = 0;
  225. set<pair<vuc, vuc>> st;
  226.  
  227. while(st.size() < MAXNUMCOL) {
  228. auto start = chrono::high_resolution_clock::now();
  229. auto [a, b, c] = func(i);
  230. auto fn = chrono::high_resolution_clock::now();
  231. if (c != -1) { // to don't count case when can't find distinguished point
  232. tim += (chrono::duration_cast<chrono::duration<double>>(fn - start)).count();
  233. st.emplace(a, b);
  234. sz += c;
  235. num_of_itr++;
  236. }
  237. }
  238. if (flag) {
  239. for (auto [a, b]: st) {
  240. cout << a << b << endl;
  241. //cout << sha256(a) << sha256(b) << endl << endl; //to check correctness
  242. }
  243. return;
  244. }
  245. cout << i << " initValFirstThread bits of sha256 - time = " << tim / num_of_itr << " ms, size = " << sz * sizeof(int) / num_of_itr << " bytes" << endl;
  246. }
  247. }
  248.  
  249. int main() {
  250. //task_handler(subtask1);
  251. //task_handler(subtask2);
  252. return 0;
  253. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement