c语言中的SHA256实现

Posted

技术标签:

【中文标题】c语言中的SHA256实现【英文标题】:SHA256 implementation in c 【发布时间】:2014-04-05 12:02:35 【问题描述】:

我正在尝试从这个网站编程 SHA256 实现:http://bradconte.com/sha256_c 在 MSP430 MCU 板上。我正在使用开源 Energia IDE 进行编程。

这是测试代码:

 unsigned char  hash[32];
 SHA256_CTX ctx;
 sha256_init(&ctx);
 sha256_update(&ctx,(unsigned char*)"abc",3);
 sha256_final(&ctx,hash);
 PrintHex(hash);

这将转换为十六进制

 void PrintHex(unsigned char * data) 
 
    char tmp[16];
    for (int i=0; i<32; i++)  
    sprintf(tmp, "%02x",data[i]); 
    Serial.print(tmp); 
    
 

问题是输出总是一个错误的哈希码。

这是输出:

    2bb53935edbba17dc04a04854518754d8a66484491b585b0d0700cd2512f5420

是测试代码还是我在这里做错了什么?

【问题讨论】:

您的预期结果是什么? 这是预期的:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 用于 abc 字符 您能否使用普通编译器在您的桌面上测试您的代码,看看是否可行? 它在普通编译器中工作。那么问题可能是代码在IDE中无法正常工作? 我尝试在 16 位裸机平台 (St10) 上使用此代码并遇到完全相同的问题。 【参考方案1】:

我在我的系统(Mac OS X,x86 64 位)上运行了该代码,它给了我这个:

551ce4769446b343295ea7f819ba1c5557545e29a4de545746b2b246a9831f22

我认为我们可以安全地假设代码是垃圾:我使用一些在线工具验证了 ba7816b... 是正确的哈希值,现在我们看到您的平台和我的平台都产生了不同的结果。我注意到代码中有一些关于字节序的注释,所以我查了一下,你的系统也是小字节序的,所以这应该不是问题。我建议您寻找不同的实现方式。

【讨论】:

没那么快,问题是他假设 ulong 正好有 32 位——这在嵌入式系统上可能是有意义的,但在大多数计算机上却失败了;修复它会给我正确的结果。关于字节序:它是否说明了他假设的平台? @pattex007 如果代码确实无法使用,skalibs 有一个声称与字节顺序无关的实现,并且作者非常关心让他的代码在嵌入式系统上运行。 如何从“hash”变量中获取摘要? 我刚刚在 MacOS 10.11.3 上构建了这段代码,我得到了预期的结果,所以不幸的是,我会否决你的答案。【参考方案2】:

你不应该假设字符串编码在 C 中是可移植的。

试试这个代码:

unsigned char message[] = 0x61, 0x62, 0x63;
unsigned char hash[32];
SHA256_CTX ctx;
sha256_init(&ctx);
sha256_update(&ctx,message,sizeof message);
sha256_final(&ctx,hash);
PrintHex(hash);

【讨论】:

【参考方案3】:

我的意思是原来的网站不再有效,但我认为我有相同的实现,我在 MSP430 上遇到了同样的问题。问题是很久以前提出的,但仍然有人可能遇到类似的麻烦。

/*********************************************************************
* Filename:   sha256.c
* Author:     Brad Conte (brad AT bradconte.com)

因此,必须在原始实现中进行一些额外的更改,才能正确计算 MSP430 上的 SHA256 和。它可能取决于编译器 - 目前我使用的是 Texas CCStudio 的一个,这绝对不是 GNU GCC。

首先,sha256.h 文件应该修改如下:

...
/*************************** HEADER FILES ***************************/
#include <stdint.h>

/****************************** MACROS ******************************/
#define SHA256_BLOCK_SIZE 32            // SHA256 outputs a 32 byte digest

/**************************** DATA TYPES ****************************/
typedef uint8_t   BYTE;             // 8-bit byte
typedef uint32_t  WORD;             // 32-bit word, change to "long" for 16-bit machines

typedef struct 
    BYTE     data[64];
    WORD     datalen;
    uint64_t bitlen;
    WORD     state[8];
 SHA256_CTX;

...

在 16 位机器上 unsigned int 是一个没有符号的 16 位整数。所以将 WORD typedef 替换为合适的类型。我认为这很糟糕,使用自己的 WORDBYTE 定义,它们在 stdint.h 头文件中可用。

其次,我认为 sha256_transform 的实现编码错误。 BYTE 上存在按位运算,结果超出比例。

在执行按位运算之前在 BYTE 上添加显式转换后,所有实现都可以在 MSP430 MCU 上正常运行。请看下面的代码:

/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform ( SHA256_CTX *ctx, const BYTE data[] )

    WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

    for ( i = 0, j = 0; i < 16; ++i, j += 4)
        /* Add explicit (WORD) conversion before operating on bytes */
        m[i] = ((WORD)data[j] << 24) | ((WORD)data[j + 1] << 16) | ((WORD)data[j + 2] << 8) | ((WORD)data[j + 3]);
    for ( ; i < 64; ++i)
        m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

    a = ctx->state[0];
    b = ctx->state[1];

我希望这可以帮助某人解决问题。

【讨论】:

以上是关于c语言中的SHA256实现的主要内容,如果未能解决你的问题,请参考以下文章

Go语言实现md4md5sha256哈希算法加密

各种语言HMAC SHA256实现

安全算法之SHA1SHA1摘要运算的C语言源码实现

如何实现C语言的DES加密算法实现,请关注

RSA加密算法怎样用C语言实现? 急急急!!!

各种加密算法在Go语言中的使用