You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenMP并行暴力破解10位数字密码时遇总线/段错误等问题

问题修复方案:OpenMP暴力破解10位密码的段错误、流冲突与哈希计算问题

一、解决段错误/总线错误

这类错误90%源于内存越界或线程非法共享资源,按以下步骤修复:

  • 放弃全局存储所有密码:10位数字共10^10个可能,全局数组存储必然爆内存。每个线程负责独立数值区间,在线程内部动态生成当前尝试的密码字符串(用局部数组),比如用snprintf生成带前导0的10位数字。
  • 检查哈希缓冲区大小:比如MD5哈希输出是16字节,分配缓冲区时要确保足够(比如unsigned char hash[MD5_DIGEST_LENGTH]),别用小于实际长度的数组,避免写入越界。
  • 禁用全局共享的计算变量:密码、哈希相关变量绝对不能用全局,必须是线程局部变量。多个线程同时读写全局变量会导致数据混乱,甚至触发非法内存访问。

二、修复多线程流写入冲突

用#pragma omp critical是正确方向,但要严格控制保护范围:

  • 只把输出操作包在critical块里,别把密码生成、哈希计算逻辑也裹进去(否则直接退化成单线程)。比如找到密码后的打印代码:
#pragma omp critical
{
    std::cout << "找到密码:" << password << std::endl;
}
  • 所有控制台输出、文件写入等IO操作,都要单独放在critical块中,避免多个线程同时写流导致输出乱码或崩溃。

三、修复哈希十六进制计算错误

哈希计算错误通常是线程共享哈希上下文或十六进制转换逻辑有问题:

  • 每个线程独立创建哈希上下文:如果用OpenSSL的哈希接口(比如EVP系列),每个线程必须自己创建、初始化、销毁上下文,绝对不能共享。示例代码:
// 线程内部局部定义上下文
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_md5(), nullptr);
EVP_DigestUpdate(ctx, password, strlen(password));
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
EVP_DigestFinal_ex(ctx, hash, &hash_len);
EVP_MD_CTX_free(ctx);
  • 十六进制转换要补前导0:用%02x格式化每个哈希字节,确保每个字节转为两位十六进制字符,同时用局部数组存转换后的结果,避免线程间覆盖。示例:
char hex_hash[33]; // MD5对应32位十六进制+结束符
for(int i=0; i<hash_len; i++){
    sprintf(&hex_hash[i*2], "%02x", hash[i]);
}
hex_hash[32] = '\0';

四、可运行的核心示例代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <openssl/md5.h>
#include <omp.h>

// 目标哈希(示例:空字符串的MD5)
const char TARGET_HASH[] = "d41d8cd98f00b204e9800998ecf8427e";

int main() {
    omp_set_num_threads(2);
    
    // 静态调度均匀分配任务区间
    #pragma omp parallel for schedule(static)
    for(unsigned long long i=0; i<10000000000ULL; i++){
        char password[11];
        // 生成带前导0的10位数字密码
        snprintf(password, sizeof(password), "%010llu", i);
        
        // 计算MD5哈希
        unsigned char hash[MD5_DIGEST_LENGTH];
        MD5((unsigned char*)password, strlen(password), hash);
        
        // 转换为十六进制字符串
        char hex_hash[33];
        for(int j=0; j<MD5_DIGEST_LENGTH; j++){
            sprintf(&hex_hash[j*2], "%02x", hash[j]);
        }
        hex_hash[32] = '\0';
        
        // 比对哈希
        if(strcmp(hex_hash, TARGET_HASH) == 0){
            #pragma omp critical
            {
                std::cout << "找到密码:" << password << std::endl;
            }
            // 找到后终止所有线程
            #pragma omp cancel for
        }
    }
    return 0;
}

编译命令:g++ -fopenmp -o password_crack password_crack.cpp -lcrypto

关键注意事项

  • 所有线程非安全资源(哈希上下文、IO流、全局变量)必须隔离,线程局部变量是最优解决方案。
  • 用schedule(static)让OpenMP均匀分配任务区间,避免线程负载不均。
  • 找到目标后用#pragma omp cancel for立即终止所有线程,减少无效计算。

内容的提问来源于stack exchange,提问作者Evelina Markova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 19:52:40