Skip to content

Commit 5f8b522

Browse files
committed
password cracking
1 parent b4440d3 commit 5f8b522

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ My solutions to CUDA challenges on https://leetgpu.com/
1717
[Softmax](https://leetgpu.com/challenges/softmax) | [Link](./softmax.cu) | Medium |
1818
[Dot Product](https://leetgpu.com/challenges/dot-product) | [Link](./dot_product.cu) | Medium |
1919
[Softmax Attention](https://leetgpu.com/challenges/softmax-attention) | [Link](./softmax_attention.cu) | Medium |
20+
[Password Cracking (FNV-1a)](https://leetgpu.com/challenges/password-cracking-fnv-1a) | [Link](./password_cracking_fnv_1a.cu) | Medium |

password_cracking_fnv_1a.cu

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include "solve.h"
2+
#include <cuda_runtime.h>
3+
4+
// FNV-1a hash function that takes a byte array and its length as input
5+
// Returns a 32-bit unsigned integer hash value
6+
__device__ unsigned int fnv1a_hash_bytes(const unsigned char* data, int length) {
7+
const unsigned int FNV_PRIME = 16777619;
8+
const unsigned int OFFSET_BASIS = 2166136261;
9+
10+
unsigned int hash = OFFSET_BASIS;
11+
for (int i = 0; i < length; i++) {
12+
hash = (hash ^ data[i]) * FNV_PRIME;
13+
}
14+
return hash;
15+
}
16+
17+
__device__ unsigned int repeated_hash(const unsigned char* password, int password_length, int R) {
18+
unsigned int hash = fnv1a_hash_bytes(password, password_length);
19+
for (int i = 0; i < R - 1; i++) {
20+
hash = fnv1a_hash_bytes((const unsigned char*)&hash, sizeof(hash));
21+
}
22+
return hash;
23+
}
24+
25+
template<int password_length>
26+
__global__ void password_crack_kernel(unsigned int target_hash, int R, char* output_password) {
27+
int tid = threadIdx.x;
28+
29+
// generate password
30+
char test_pw[password_length + 1];
31+
test_pw[password_length] = '\0';
32+
test_pw[0] = 'a' + (tid % 26);
33+
if constexpr (password_length > 1) {
34+
test_pw[1] = 'a' + (tid / 26);
35+
}
36+
if constexpr (password_length > 2) {
37+
int block_id = blockIdx.x;
38+
#pragma unroll
39+
for (int i = 2; i < password_length; i++) {
40+
test_pw[i] = 'a' + (block_id % 26);
41+
block_id /= 26;
42+
}
43+
}
44+
45+
unsigned int hash = repeated_hash((const unsigned char*)test_pw, password_length, R);
46+
47+
if (hash == target_hash) {
48+
// found the password
49+
for (int i = 0; i < password_length; i++) {
50+
output_password[i] = test_pw[i];
51+
}
52+
output_password[password_length] = '\0';
53+
}
54+
}
55+
56+
57+
// output_password is a device pointer
58+
void solve(unsigned int target_hash, int password_length, int R, char* output_password) {
59+
switch (password_length) {
60+
case 1:
61+
password_crack_kernel<1><<<1, 26>>>(target_hash, R, output_password);
62+
break;
63+
case 2:
64+
password_crack_kernel<2><<<1, 26*26>>>(target_hash, R, output_password);
65+
break;
66+
case 3:
67+
password_crack_kernel<3><<<26, 26*26>>>(target_hash, R, output_password);
68+
break;
69+
case 4:
70+
password_crack_kernel<4><<<26*26, 26*26>>>(target_hash, R, output_password);
71+
break;
72+
case 5:
73+
password_crack_kernel<5><<<26*26*26, 26*26>>>(target_hash, R, output_password);
74+
break;
75+
case 6:
76+
password_crack_kernel<6><<<26*26*26*26, 26*26>>>(target_hash, R, output_password);
77+
break;
78+
default:
79+
// can't get here
80+
return;
81+
}
82+
}

0 commit comments

Comments
 (0)