SHA1 以流方式对长度前缀的消息进行校验和
SHA1 checksumming a length-prefixed message in a streaming fashion
Git-SHA 的计算方法是在消息前加上 "blob $DecimalMessageLength[=11=]"
前缀,然后对带前缀的消息进行 SHA1 校验和计算。
根据 SHA1 算法的特性,是否可以以流方式执行此操作,即在消息正文经过哈希处理后添加前缀?
下面的 C 示例(link 和 -lcrypto
安装了 libssl-dev;它可能不是很有用,因为这个甚至没有公开 SHA1 算法,但我正在玩...) :
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
int pr_dgst(unsigned char const Dgst[static SHA_DIGEST_LENGTH])
{
char const digits[]="0123456789abcdef";
char digest_pr[(SHA_DIGEST_LENGTH)*2+1];
for(size_t i=0;i<SHA_DIGEST_LENGTH;i++){
digest_pr[i*2+0]=digits[Dgst[i]/16];
digest_pr[i*2+1]=digits[Dgst[i]%16];
}
digest_pr[(SHA_DIGEST_LENGTH)*2]='[=10=]';
return puts(digest_pr);
}
int main()
{
system("echo gitsha; printf '%s' 'abc' | git hash-object --stdin");
#define STR_STRLEN(A) A, (sizeof(A)/sizeof(*(A))-1) //paste string literal and its length
unsigned char digest[SHA_DIGEST_LENGTH];
SHA_CTX ctx;
SHA1_Init(&ctx); SHA1_Update(&ctx,STR_STRLEN("blob 3[=10=]abc")); SHA1_Final(digest,&ctx);
pr_dgst(digest); //prints the same as the system command
//do this in a streaming fashion??
SHA1_Init(&ctx);
size_t len = 0;
SHA1_Update(&ctx,STR_STRLEN("a")); len++;
SHA1_Update(&ctx,STR_STRLEN("b")); len++;
SHA1_Update(&ctx,STR_STRLEN("c")); len++;
//"prepend" "blob 3[=10=]" now?
SHA1_Final(digest,&ctx);
/*pr_dgst(digest);*/
}
只能将字节添加到消息流的末尾 - 否则散列函数将被加密破坏。
一个 为 2 个文件设置 前缀 的好处之一是您可以存储 2 files with a known bare SHA-1 collision into the same repository and they would get different blob IDs!
Git-SHA 的计算方法是在消息前加上 "blob $DecimalMessageLength[=11=]"
前缀,然后对带前缀的消息进行 SHA1 校验和计算。
根据 SHA1 算法的特性,是否可以以流方式执行此操作,即在消息正文经过哈希处理后添加前缀?
下面的 C 示例(link 和 -lcrypto
安装了 libssl-dev;它可能不是很有用,因为这个甚至没有公开 SHA1 算法,但我正在玩...) :
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
int pr_dgst(unsigned char const Dgst[static SHA_DIGEST_LENGTH])
{
char const digits[]="0123456789abcdef";
char digest_pr[(SHA_DIGEST_LENGTH)*2+1];
for(size_t i=0;i<SHA_DIGEST_LENGTH;i++){
digest_pr[i*2+0]=digits[Dgst[i]/16];
digest_pr[i*2+1]=digits[Dgst[i]%16];
}
digest_pr[(SHA_DIGEST_LENGTH)*2]='[=10=]';
return puts(digest_pr);
}
int main()
{
system("echo gitsha; printf '%s' 'abc' | git hash-object --stdin");
#define STR_STRLEN(A) A, (sizeof(A)/sizeof(*(A))-1) //paste string literal and its length
unsigned char digest[SHA_DIGEST_LENGTH];
SHA_CTX ctx;
SHA1_Init(&ctx); SHA1_Update(&ctx,STR_STRLEN("blob 3[=10=]abc")); SHA1_Final(digest,&ctx);
pr_dgst(digest); //prints the same as the system command
//do this in a streaming fashion??
SHA1_Init(&ctx);
size_t len = 0;
SHA1_Update(&ctx,STR_STRLEN("a")); len++;
SHA1_Update(&ctx,STR_STRLEN("b")); len++;
SHA1_Update(&ctx,STR_STRLEN("c")); len++;
//"prepend" "blob 3[=10=]" now?
SHA1_Final(digest,&ctx);
/*pr_dgst(digest);*/
}
只能将字节添加到消息流的末尾 - 否则散列函数将被加密破坏。
一个 为 2 个文件设置 前缀 的好处之一是您可以存储 2 files with a known bare SHA-1 collision into the same repository and they would get different blob IDs!