[英]Adapt existing GOST code in C to hash a file
I am trying to hand-code the GOST hash function using C. I came across the following code by Markku-Juhani Saarinen (from link ). 我正在尝试使用C手动编码GOST哈希函数。我遇到了Markku-Juhani Saarinen的以下代码(来自link )。
/*
* gosthash.c
* 21 Apr 1998 Markku-Juhani Saarinen <mjos@ssh.fi>
*
* GOST R 34.11-94, Russian Standard Hash Function
*
* Copyright (c) 1998 SSH Communications Security, Finland
* All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gosthash.h"
/* lookup tables : each of these has two rotated 4-bit S-Boxes */
unsigned long gost_sbox_1[256];
unsigned long gost_sbox_2[256];
unsigned long gost_sbox_3[256];
unsigned long gost_sbox_4[256];
/* initialize the lookup tables */
void gosthash_init()
{
int a, b, i;
unsigned long ax, bx, cx, dx;
/* 4-bit S-Boxes */
unsigned long sbox[8][16] =
{
{ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3 },
{ 14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9 },
{ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11 },
{ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3 },
{ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2 },
{ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14 },
{ 13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12 },
{ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12 }
};
/* s-box precomputation */
i = 0;
for (a = 0; a < 16; a++)
{
ax = sbox[1][a] << 15;
bx = sbox[3][a] << 23;
cx = sbox[5][a];
cx = (cx >> 1) | (cx << 31);
dx = sbox[7][a] << 7;
for (b = 0; b < 16; b++)
{
gost_sbox_1[i] = ax | (sbox[0][b] << 11);
gost_sbox_2[i] = bx | (sbox[2][b] << 19);
gost_sbox_3[i] = cx | (sbox[4][b] << 27);
gost_sbox_4[i++] = dx | (sbox[6][b] << 3);
}
}
}
/*
* A macro that performs a full encryption round of GOST 28147-89.
* Temporary variable t assumed and variables r and l for left and right
* blocks
*/
#define GOST_ENCRYPT_ROUND(k1, k2) \
t = (k1) + r; \
l ^= gost_sbox_1[t & 0xff] ^ gost_sbox_2[(t >> 8) & 0xff] ^ \
gost_sbox_3[(t >> 16) & 0xff] ^ gost_sbox_4[t >> 24]; \
t = (k2) + l; \
r ^= gost_sbox_1[t & 0xff] ^ gost_sbox_2[(t >> 8) & 0xff] ^ \
gost_sbox_3[(t >> 16) & 0xff] ^ gost_sbox_4[t >> 24]; \
/* encrypt a block with the given key */
#define GOST_ENCRYPT(key) \
GOST_ENCRYPT_ROUND(key[0], key[1]) \
GOST_ENCRYPT_ROUND(key[2], key[3]) \
GOST_ENCRYPT_ROUND(key[4], key[5]) \
GOST_ENCRYPT_ROUND(key[6], key[7]) \
GOST_ENCRYPT_ROUND(key[0], key[1]) \
GOST_ENCRYPT_ROUND(key[2], key[3]) \
GOST_ENCRYPT_ROUND(key[4], key[5]) \
GOST_ENCRYPT_ROUND(key[6], key[7]) \
GOST_ENCRYPT_ROUND(key[0], key[1]) \
GOST_ENCRYPT_ROUND(key[2], key[3]) \
GOST_ENCRYPT_ROUND(key[4], key[5]) \
GOST_ENCRYPT_ROUND(key[6], key[7]) \
GOST_ENCRYPT_ROUND(key[7], key[6]) \
GOST_ENCRYPT_ROUND(key[5], key[4]) \
GOST_ENCRYPT_ROUND(key[3], key[2]) \
GOST_ENCRYPT_ROUND(key[1], key[0]) \
t = r; \
r = l; \
l = t;
/*
* "chi" compression function. the result is stored over h
*/
void gosthash_compress(unsigned long *h, unsigned long *m)
{
int i;
unsigned long l, r, t, key[8], u[8], v[8], w[8], s[8];
memcpy(u, h, sizeof(u));
memcpy(v, m, sizeof(u));
for (i = 0; i < 8; i += 2)
{
w[0] = u[0] ^ v[0]; /* w = u xor v */
w[1] = u[1] ^ v[1];
w[2] = u[2] ^ v[2];
w[3] = u[3] ^ v[3];
w[4] = u[4] ^ v[4];
w[5] = u[5] ^ v[5];
w[6] = u[6] ^ v[6];
w[7] = u[7] ^ v[7];
/* P-Transformation */
key[0] = (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) |
((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24);
key[1] = ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) |
((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16);
key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) |
(w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8);
key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) |
((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000);
key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) |
((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24);
key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) |
((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16);
key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) |
(w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8);
key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) |
((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
r = h[i]; /* encriphering transformation */
l = h[i + 1];
GOST_ENCRYPT(key);
s[i] = r;
s[i + 1] = l;
if (i == 6)
break;
l = u[0] ^ u[2]; /* U = A(U) */
r = u[1] ^ u[3];
u[0] = u[2];
u[1] = u[3];
u[2] = u[4];
u[3] = u[5];
u[4] = u[6];
u[5] = u[7];
u[6] = l;
u[7] = r;
if (i == 2) /* Constant C_3 */
{
u[0] ^= 0xff00ff00;
u[1] ^= 0xff00ff00;
u[2] ^= 0x00ff00ff;
u[3] ^= 0x00ff00ff;
u[4] ^= 0x00ffff00;
u[5] ^= 0xff0000ff;
u[6] ^= 0x000000ff;
u[7] ^= 0xff00ffff;
}
l = v[0]; /* V = A(A(V)) */
r = v[2];
v[0] = v[4];
v[2] = v[6];
v[4] = l ^ r;
v[6] = v[0] ^ r;
l = v[1];
r = v[3];
v[1] = v[5];
v[3] = v[7];
v[5] = l ^ r;
v[7] = v[1] ^ r;
}
/* 12 rounds of the LFSR (computed from a product matrix) and xor in M */
u[0] = m[0] ^ s[6];
u[1] = m[1] ^ s[7];
u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^
(s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^
(s[7] & 0xffff0000) ^ (s[7] >> 16);
u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^
(s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^
(s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^
(s[7] << 16) ^ (s[7] >> 16);
u[4] = m[4] ^
(s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^
(s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^
(s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^
(s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);
u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^
(s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^
(s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^
(s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16);
u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^
(s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^
(s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16);
u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^
(s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^
(s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^
(s[7] << 16) ^ (s[7] >> 16);
/* 16 * 1 round of the LFSR and xor in H */
v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16);
v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16);
v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16);
v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16);
v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16);
v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16);
v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16);
v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^
(u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000);
/* 61 rounds of LFSR, mixing up h (computed from a product matrix) */
h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^
(v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^
(v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^
(v[7] & 0xffff);
h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^
v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^
(v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16);
h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^
(v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^
(v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^
(v[7] >> 16);
h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^
(v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^
(v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^
(v[7] & 0xffff) ^ (v[7] >> 16);
h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^
(v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^
v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16);
h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^
(v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^
(v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^
(v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000);
h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^
(v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^
(v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7];
h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^
(v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^
(v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
}
/* Clear the state of the given context structure. */
void gosthash_reset(GostHashCtx *ctx)
{
memset(ctx->sum, 0, 32);
memset(ctx->hash, 0, 32);
memset(ctx->len, 0, 32);
memset(ctx->partial, 0, 32);
ctx->partial_bytes = 0;
}
/* Mix in a 32-byte chunk ("stage 3") */
void gosthash_bytes(GostHashCtx *ctx, const unsigned char *buf, size_t bits)
{
int i, j;
unsigned long a, b, c, m[8];
/* convert bytes to a long words and compute the sum */
j = 0;
c = 0;
for (i = 0; i < 8; i++)
{
a = ((unsigned long) buf[j]) |
(((unsigned long) buf[j + 1]) << 8) |
(((unsigned long) buf[j + 2]) << 16) |
(((unsigned long) buf[j + 3]) << 24);
j += 4;
m[i] = a;
b = ctx->sum[i];
c = a + c + ctx->sum[i];
ctx->sum[i] = c;
c = ((c < a) || (c < b)) ? 1 : 0;
}
/* compress */
gosthash_compress(ctx->hash, m);
/* a 64-bit counter should be sufficient */
ctx->len[0] += bits;
if (ctx->len[0] < bits)
ctx->len[1]++;
}
/* Mix in len bytes of data for the given buffer. */
void gosthash_update(GostHashCtx *ctx, const unsigned char *buf, size_t len)
{
size_t i, j;
i = ctx->partial_bytes;
j = 0;
while (i < 32 && j < len)
ctx->partial[i++] = buf[j++];
if (i < 32)
{
ctx->partial_bytes = i;
return;
}
gosthash_bytes(ctx, ctx->partial, 256);
while ((j + 32) < len)
{
gosthash_bytes(ctx, &buf[j], 256);
j += 32;
}
i = 0;
while (j < len)
ctx->partial[i++] = buf[j++];
ctx->partial_bytes = i;
}
/* Compute and save the 32-byte digest. */
void gosthash_final(GostHashCtx *ctx, unsigned char *digest)
{
int i, j;
unsigned long a;
/* adjust and mix in the last chunk */
if (ctx->partial_bytes > 0)
{
memset(&ctx->partial[ctx->partial_bytes], 0, 32 - ctx->partial_bytes);
gosthash_bytes(ctx, ctx->partial, ctx->partial_bytes << 3);
}
/* mix in the length and the sum */
gosthash_compress(ctx->hash, ctx->len);
gosthash_compress(ctx->hash, ctx->sum);
/* convert the output to bytes */
j = 0;
for (i = 0; i < 8; i++)
{
a = ctx->hash[i];
digest[j] = (unsigned char) a;
digest[j + 1] = (unsigned char) (a >> 8);
digest[j + 2] = (unsigned char) (a >> 16);
digest[j + 3] = (unsigned char) (a >> 24);
j += 4;
}
}
However, there is no main() function which I can use to compile an executable. 但是,没有main()函数可用于编译可执行文件。 I wanted a main of the type
main(int argc, char *argv[])
with which to call a file with the produced executable and have the file's contents hashed. 我想要一个main类型的
main(int argc, char *argv[])
用它来调用产生的可执行文件并对该文件的内容进行哈希处理。
I have gone through the code over and over again but I am stuck with calling the code's functions, I don't know how to proceed. 我已经一遍又一遍地遍历代码,但是我一直坚持调用代码的函数,但我不知道该如何进行。 Please, any ideas on how I can fill my main function to run this code?
请问我如何填写我的主要功能以运行此代码的任何想法?
EDIT 编辑
I tried the following main()
code but it does not seem to work: 我尝试了以下
main()
代码,但它似乎不起作用:
void main(int argc, char *argv[]){
if (argc!=2) {
fprintf(stderr, "Error: Provide name of one source file.\n");
exit(EXIT_FAILURE);
}
char *clear_file = argv[1];
const char *FILENAME_IN = clear_file;
FILE *infile;
infile = fopen(FILENAME_IN, "r");
GostHashCtx *ctx = malloc(sizeof(GostHashCtx));
unsigned char *digest, *buf;
char c;
if(infile == NULL){
fprintf(stderr, "Error: Source file not found.\n");
exit(EXIT_FAILURE);
}
gosthash_init();
gosthash_reset(ctx); //printf("CTX.PB=%d\n\n",ctx->partial_bytes);
int quit = 0;
while (quit == 0) {
int p = 0;
buf = malloc(256);
strcpy(buf, "");
while(((c = fgetc(infile)) != EOF) && (p < 256)) {
*(buf+p) = c;
p++;
}
//*(buf+p) = '\0';
if(c == EOF) quit = 1;
gosthash_update(ctx, buf, 256);
free(buf);
}
digest = malloc(256);
strcpy(digest, "");
gosthash_final(ctx, digest);
printf("%s\n", digest);
free(ctx);
free(digest);
}
To verify the output, I used an online tool to quickly convert the resulting string digest
to HEX but the result is incorrect for known test values of GOST hashing. 为了验证输出,我使用了一个在线工具,将生成的字符串
digest
快速转换为HEX,但是对于GOST哈希的已知测试值,结果不正确。 Please, any ideas as to why this might be the case? 请问关于为何可能会出现这种情况的任何想法?
Ok, so first you have to call gosthash_init
to fill the lookup tables. 好的,因此首先您必须调用
gosthash_init
来填充查找表。 Then you allocate as many contexts of type GostHashCtx
that you require - you probably just need one in your case. 然后,您分配所需
GostHashCtx
类型的上下文-在您的情况下,可能只需要一个即可。 You can reset it in advance to make sure the context is filled with zero values. 您可以预先重置它,以确保上下文填充零值。
Now you call gosthash_update
one or multiple times to hash all the bytes in the file (sequentially, of course). 现在,您调用
gosthash_update
一次或多次以对文件中的所有字节进行哈希处理(当然是顺序地进行)。 Finally you call gosthash_final
to create the hash. 最后,您调用
gosthash_final
创建哈希。 These steps perform the actual hashing. 这些步骤执行实际的哈希。
If you want to hash something else, first call gosthash_reset
, and then gosthash_update
and gosthash_final
again. 如果要哈希其他内容,请首先调用
gosthash_reset
,然后再次调用gosthash_update
和gosthash_final
。
When you get to the end of the file, if the file length is not a multiple of 256, you won't fill the buffer, but you still call gosthash_update
with a size of 256, which means it will hash in whatever random garbage happens to be in the rest of the buffer. 当到达文件末尾时,如果文件长度不是256的倍数,则不会填充缓冲区,但是您仍将调用
gosthash_update
的大小为256,这意味着它将在发生随机垃圾时进行哈希处理在缓冲区的其余部分。 Try changing that to gosthash_update(ctx, buf, p);
尝试将其更改为
gosthash_update(ctx, buf, p);
There's also no need to call malloc
-- just use local vars. 也不需要调用
malloc
只需使用本地var。 You can simplify things even more by using open/read instead of fopen/fgetc: 您可以使用open / read而不是fopen / fgetc进一步简化操作:
char buf[2048]; /* or any size you like */
int len;
int fd = open(FILENAME_IN, O_RDONLY);
GostHashCtxt ctx;
gosthash_init();
gosthash_reset(&ctx);
while ((len = read(fd, buf, sizeof(buf)) > 0)
gosthash_update(&ctx, buf, len);
gosthash_final(&ctx, buf);
write(1, buf, 32);
Note that the resulting digest is NOT a null-terminated string -- it is 32 bytes of binary data. 请注意,结果摘要不是以空值结尾的字符串-它是32字节的二进制数据。 So you can't safely print it with
printf("%s",
因此,您无法使用
printf("%s",
In case anyone else has the same problem I had, I am posting my final code for the main()
function here. 万一其他人遇到我遇到的同样问题,我将在这里发布
main()
函数的最终代码。 Thanks again to @ChrisDodd and @MaartenBodewes for their help. 再次感谢@ChrisDodd和@MaartenBodewes的帮助。
EDIT: I have made it CW for any improvements. 编辑:我做了任何改进的CW。 (The current code works fine under Windows with MinGW but does Segmentation fault in certain environments like openSUSE Linux due to the instruction
gosthash_final(ctx, digest);
which I traced back to the call to gosthash_compress()
in the gosthash_final()
function.) (当前的代码在Windows下正常工作与MinGW的 ,但确实分段故障在某些环境,如openSUSE的Linux的由于指令
gosthash_final(ctx, digest);
我追溯到调用gosthash_compress()
在gosthash_final()
函数)
/* I used this function to get the hash result in HEX format */
void hexify(unsigned char *in, char *out) {
char hex[64], tmp[3];
int i;
hex[0]='\0';
for(i=0; i<32; i++ )
{
sprintf(tmp, "%02X", in[i]);
strcat(hex, tmp);
}
strcpy(out, hex);
}
int main(int argc, char *argv[]){
if (argc!=2) {
fprintf(stderr, "Error: Provide name of one source file.\n");
exit(EXIT_FAILURE);
}
char *clear_file = argv[1];
const char *FILENAME_IN = clear_file;
FILE *infile;
infile = fopen(FILENAME_IN, "r");
GostHashCtx *ctx = malloc(sizeof(GostHashCtx));
unsigned char digest[32], buf[16];
char hex[64];
hex[0]='\0';
if(infile == NULL){
fprintf(stderr, "Error: Source file not found.\n");
exit(EXIT_FAILURE);
}
gosthash_init();
gosthash_reset(ctx);
size_t nread;
while ((nread = fread(buf, 1, sizeof(buf), infile)) > 0)
gosthash_update(ctx, buf, nread);
fclose(infile);
digest[0]='\0';
gosthash_final(ctx, digest);
hexify(digest, hex);
printf("HASH= %s\n", hex);
free(ctx);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.