如何在C编程中使用SHA1散列

时间:2012-02-14 21:27:51

标签: c hash

我正在尝试编写一个证明SHA1几乎无冲突的C程序,但我无法弄清楚如何为我的输入值实际创建哈希值。我只需要创建哈希值,并将十六进制值存储到一个数组中。在谷歌搜索之后,我发现OpenSSL文档指示我使用它:

 #include <openssl/sha.h>

 unsigned char *SHA1(const unsigned char *d, unsigned long n,
                  unsigned char *md);

 int SHA1_Init(SHA_CTX *c);
 int SHA1_Update(SHA_CTX *c, const void *data,
                  unsigned long len);
 int SHA1_Final(unsigned char *md, SHA_CTX *c);

我相信我应该使用unsigned char * SHA1或SHA1_Init,但我不确定参数是什么,假设x是我要输入的输入。有人请为我清楚这个吗?感谢。

7 个答案:

答案 0 :(得分:46)

如果您同时拥有所有数据,只需使用SHA1功能:

// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash

另一方面,如果您一次只得到一个数据,并且想要在收到数据时计算哈希值,那么请使用其他函数:

// Error checking omitted for expository purposes

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1_Final(hash, &ctx);

答案 1 :(得分:12)

他们是实现同样目标的两种不同方式。

具体来说,您 使用SHA_Init,然后SHA_Update根据需要多次传递数据,然后SHA_Final获取摘要,<强>或你SHA1

两种模式的原因是,当对大文件进行散列时,通常以块的形式读取文件,因为替代方案会占用大量内存。因此,随时跟踪SHA_CTX - SHA上下文 - 可以让您解决这个问题。该算法内部也适合这个模型 - 也就是说,数据一次在块中传递。

SHA方法应该相当简单。另一个是这样的:

unsigned char md[SHA_DIGEST_LENGTH];
SHA_CTX context;
int SHA1_Init(&context);

for ( i = 0; i < numblocks; i++ )
{
    int SHA1_Update(&context, pointer_to_data, data_length);
}
int SHA1_Final(md, &context);

至关重要的是,最后md将包含二进制摘要,而不是十六进制表示 - 它不是字符串,不应该用作一个字符串。

答案 2 :(得分:3)

第一个函数(SHA1())是更高级别的函数,它可能是你想要的函数。该文档非常清楚使用 - d是输入,n是其大小,md是放置结果的位置(您分配它)。

至于其他3个功能 - 这些是较低级别的,我很确定它们在内部被第一个使用。它们更适合需要以逐块方式处理的较大输入。

答案 3 :(得分:2)

  

我相信我应该使用In:DataFrame(PrunedModel) Out:LoadError: MethodError: `convert` has no method matching convert(::Type{DataFrames.DataFrame}, ::DecisionTree.Node) This may have arisen from a call to the constructor DataFrames.DataFrame(...), since type constructors fall back to convert methods. Closest candidates are: call{T}(::Type{T}, ::Any) convert(::Type{DataFrames.DataFrame}, !Matched::Array{T,2}) convert(::Type{DataFrames.DataFrame}, !Matched::Dict{K,V}) ... while loading In[22], in expression starting on line 1 in call at essentials.jl:56 In:typeof(PrunedModel) Out:DecisionTree.Node unsigned char *SHA1 ...

对于OpenSSL库的更高版本,如1.0.2和1.1.0,项目建议使用EVP接口。 OpenSSL wiki上提供了使用EVP Message Digests和SHA256的示例:

SHA1_Init

答案 4 :(得分:1)

Adam Rosenfield的答案很好,但是使用strlen而不是sizeof,否则将计算hash,包括null终止符。在这种情况下哪个可能很好,但如果你需要将你的哈希值与其他工具生成的哈希值进行比较,则不行。

// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);

unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash

答案 5 :(得分:1)

像这样计算哈希

// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);

// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char tmphash[SHA_DIGEST_LENGTH];
SHA1_Final(tmphash, &ctx);

最后,您可以通过这样的代码将哈希解码为人类可读的形式。

unsigned char hash[SHA_DIGEST_LENGTH*2];

int i = 0;
for (i=0; i < SHA_DIGEST_LENGTH; i++) {
    sprintf((char*)&(hash[i*2]), "%02x", tmphash[i]);
}
// And print to stdout
printf("Hash: %s\n", hash);

答案 6 :(得分:0)

让代码说话

SQLite 开发树包含用于将 SHA1 应用于整个数据库的工具 DBHASH 的源代码。完成 SHA1 实现。

您可能会发现研究该代码是可行的。

ps:还有 SHA1 implemented as SQLite user-defined 函数。