我正在尝试编写一个证明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是我要输入的输入。有人请为我清楚这个吗?感谢。
答案 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 函数。