c-生成哈希时,使用-pg和优化的奇怪行为



我决定制作一个程序来找到一个开头有一定数量零的sha3-512哈希(比如hashcash(。它在我最初的测试中运行得很好,所以我决定用gprof对它进行评测,看看我是否能让它更快。在我用-pg编译并运行它之后,我想我应该去买一张彩票。在第一个nonce上,我得到了一个8个零的散列。然而,我又跑了一次,一开始我又得到了一个8个零的数字。事实上,散列中有许多明显的模式。经过几次测试,我发现只有当我使用-pg编译-O1、-O2和-O3中的一个时,才会发生这种情况。

这是程序

#include <tomcrypt.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <stdio.h>
unsigned char* randstring(size_t length) {
srand(time(NULL));
unsigned char* randomString = NULL;
if (length) {
randomString = malloc(sizeof(char) * (length));
if (randomString) {
for (int n = 0; n < length; n++) {
int key = rand() % 255;
randomString[n] = (unsigned char)key;
}
}
}
return randomString;
}
void find_nonce(int zeroes, int* nonce_ptr, unsigned char* returner) {
unsigned char string[40];
unsigned char* rand_string = randstring(30);
memcpy(string, rand_string, 30);
free(rand_string);
//string is longer than rand_string because i need romm to put the nonce in
int nonce = 0;
int idx;
if (register_hash(&sha3_512_desc) == -1) {
printf("Error registering SHA3-512.n");
exit(1);
}
idx = find_hash("sha3-512");
if (idx == -1) {
printf("Invalid hash name!n");
exit(1);
}
int res_bool = false;
unsigned char res[64];
unsigned long res_size;
char nonce_str[11];
int nonce_len = 0;
while (!res_bool) {
//Put the nonce into a string
sprintf(nonce_str, "%d", nonce);
//Put the nonce string into the string as an unsigned char (hash_memory takes an unsigned char)
for (int i = 0, j = 11;; ++i, ++j) {
if (nonce_str[i] == '') {
break;
}
string[j] = (unsigned char)nonce_str[i];
nonce_len++;
}
//Hash it
hash_memory(idx, string, 30+nonce_len, res, &res_size);
nonce_len = 0;
//Check if the string has a sufficient number of zeroes at the start
res_bool = true;
for (int i = 0; i < zeroes; i++) {
if ((int)res[i] != 0) {
res_bool = false;
break;
}
}
nonce++;
}
*nonce_ptr = nonce;
for (int i = 0; i < 64; i++) {
returner[i] = res[i];
}
}
int main(int argc, char** argv) {
//Getting command-line arguments
int zeroes = atoi(argv[argc - 1]);

int nonce;
unsigned char hash[64];
//Timing the execution
clock_t start, end;
double cpu_time_used;
start = clock();
find_nonce(zeroes, &nonce, hash);
end = clock();
cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
//Printing the output to the screen
printf("Hash was ");
for (int i = 0; i < 64; i++) {
printf("%d ", (int)hash[i]);
}
printf("nNonce to get the hash was %dnIt took %f seconds to calculaten", nonce, cpu_time_used);
return 0;
}

下面是五个测试的输出示例:

Hash was 0 0 0 0 0 0 0 0 6 203 85 177 228 127 0 0 192 128 164 212 252 127 0 0 129 219 85 177 228 127 0 0 0 235 105 177 228 127 0 0 144 128 164 212 252 127 0 0 2 0 0 0 0 0 0 0 48 130 164 212 252 127 0 0 
Nonce to get the hash was 1
It took 0.000000 seconds to calculate
Hash was 0 0 0 0 0 0 0 0 6 203 214 123 135 127 0 0 64 216 207 126 253 127 0 0 129 219 214 123 135 127 0 0 0 235 234 123 135 127 0 0 16 216 207 126 253 127 0 0 2 0 0 0 0 0 0 0 176 217 207 126 253 127 0 0 
Nonce to get the hash was 1
It took 0.000000 seconds to calculate
Hash was 0 0 0 0 0 0 0 0 6 123 219 55 192 127 0 0 144 108 17 232 252 127 0 0 129 139 219 55 192 127 0 0 0 155 239 55 192 127 0 0 96 108 17 232 252 127 0 0 2 0 0 0 0 0 0 0 0 110 17 232 252 127 0 0 
Nonce to get the hash was 1
It took 0.000000 seconds to calculate
Hash was 0 0 0 0 0 0 0 0 6 107 181 157 222 127 0 0 64 183 143 12 253 127 0 0 129 123 181 157 222 127 0 0 0 139 201 157 222 127 0 0 16 183 143 12 253 127 0 0 2 0 0 0 0 0 0 0 176 184 143 12 253 127 0 0 
Nonce to get the hash was 1
It took 0.000000 seconds to calculate
Hash was 0 0 0 0 0 0 0 0 6 139 121 81 110 127 0 0 32 171 61 179 254 127 0 0 129 155 121 81 110 127 0 0 0 171 141 81 110 127 0 0 240 170 61 179 254 127 0 0 2 0 0 0 0 0 0 0 144 172 61 179 254 127 0 0 
Nonce to get the hash was 1
It took 0.000000 seconds to calculate

res_size未初始化。它包含垃圾,垃圾根据编译器标志的不同而不同。

另一方面,hash_memory希望它具有输出缓冲区的大小。它要做的第一件事是检查是否有足够的空间,如果没有,它就会退出。

所以,您看到的不是散列,而是缓冲区的初始状态。

始终测试返回值!

最新更新