#c #hash #sha256
#c #хэш #sha256
Вопрос:
У меня проблема, и я надеюсь, что вы сможете мне помочь.
У меня есть функция, написанная на C, которая возвращает значение хэша. Моя головная боль в том, что когда я запускаю программу из другого инструмента, ее выполнение занимает много времени, вероятно, потому, что внутри моей функции я запускаю команду, которая хэширует мое значение в SHA256, поэтому я хотел бы знать, есть ли другой способ сделать это, может быть, функция или что-то в этом роде.
Вот что у меня есть:
const char *EncryptSHA256 (char *Arg1) {
char command[128];
char result[512];
//I want to replace from here
snprintf(command, sizeof command, "echo -n %s | sha256sum | cut -c1-64",Arg1);
FILE *fpipe;
if (0 == (fpipe = (FILE*)popen(command, "r"))) {
perror("popen() failed.");
exit(1);
}
fread(result, 1, 512, fpipe);
pclose(fpipe);
const char *sha256 = amp;result[0];
//to here
return sha256;
}
Комментарии:
1. В C. Существует бесчисленное множество реализаций SHA256. Бросьте камень в поисковую систему, и вы обязательно попадете в нее.
2. Google «исходный код sha256 c»
Ответ №1:
Ваш код имеет неопределенное поведение, потому что вы возвращаете указатель на result
, локальный массив с автоматическим хранением. Чтение из этого массива вызывающим объектом имеет неопределенное поведение.
Вы должны, по крайней мере, сделать result
статичным, чтобы его содержимое оставалось читаемым после EncryptSHA256
возврата вызывающему его объекту.
Что касается неэффективности метода, вот общедоступная реализация SHA256, которую вы можете использовать непосредственно в своей программе:
/* public domain sha256 implementation based on fips180-3 */
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/* Public API */
struct sha256 {
uint64_t len; /* processed message length */
uint32_t h[8]; /* hash state */
uint8_t buf[64]; /* message block buffer */
};
/* reset state */
void sha256_init(struct sha256 *s);
/* process message */
void sha256_update(struct sha256 *s, const void *m, size_t len);
/* get message digest */
/* state is ruined after sum, keep a copy if multiple sum is needed */
/* part of the message might be left in s, zero it if secrecy is needed */
void sha256_sum(struct sha256 *s, uint8_t md[32]);
/* Implementation */
static uint32_t ror(uint32_t n, int k) {
return (n >> k) | (n << (32 - k));
}
#define Ch(x,y,z) (z ^ (x amp; (y ^ z)))
#define Maj(x,y,z) ((x amp; y) | (z amp; (x | y)))
#define S0(x) (ror(x,2) ^ ror(x,13) ^ ror(x,22))
#define S1(x) (ror(x,6) ^ ror(x,11) ^ ror(x,25))
#define R0(x) (ror(x,7) ^ ror(x,18) ^ (x>>3))
#define R1(x) (ror(x,17) ^ ror(x,19) ^ (x>>10))
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static void processblock(struct sha256 *s, const uint8_t *buf) {
uint32_t W[64], t1, t2, a, b, c, d, e, f, g, h;
int i;
for (i = 0; i < 16; i ) {
W[i] = (uint32_t)buf[4 * i 0] << 24;
W[i] |= (uint32_t)buf[4 * i 1] << 16;
W[i] |= (uint32_t)buf[4 * i 2] << 8;
W[i] |= buf[4 * i 3];
}
for (; i < 64; i )
W[i] = R1(W[i-2]) W[i-7] R0(W[i-15]) W[i-16];
a = s->h[0];
b = s->h[1];
c = s->h[2];
d = s->h[3];
e = s->h[4];
f = s->h[5];
g = s->h[6];
h = s->h[7];
#define ROUND(a,b,c,d,e,f,g,h,i)
t1 = h S1(e) Ch(e,f,g) K[i] W[i];
t2 = S0(a) Maj(a,b,c);
d = t1;
h = t1 t2;
for (i = 0; i < 64; ) {
ROUND(a, b, c, d, e, f, g, h, i); i ;
ROUND(h, a, b, c, d, e, f, g, i); i ;
ROUND(g, h, a, b, c, d, e, f, i); i ;
ROUND(f, g, h, a, b, c, d, e, i); i ;
ROUND(e, f, g, h, a, b, c, d, i); i ;
ROUND(d, e, f, g, h, a, b, c, i); i ;
ROUND(c, d, e, f, g, h, a, b, i); i ;
ROUND(b, c, d, e, f, g, h, a, i); i ;
}
#undef ROUND
s->h[0] = a;
s->h[1] = b;
s->h[2] = c;
s->h[3] = d;
s->h[4] = e;
s->h[5] = f;
s->h[6] = g;
s->h[7] = h;
}
static void pad(struct sha256 *s) {
unsigned r = s->len % 64;
s->buf[r ] = 0x80;
if (r > 56) {
memset(s->buf r, 0, 64 - r);
r = 0;
processblock(s, s->buf);
}
memset(s->buf r, 0, 56 - r);
s->len *= 8;
s->buf[56] = s->len >> 56;
s->buf[57] = s->len >> 48;
s->buf[58] = s->len >> 40;
s->buf[59] = s->len >> 32;
s->buf[60] = s->len >> 24;
s->buf[61] = s->len >> 16;
s->buf[62] = s->len >> 8;
s->buf[63] = s->len;
processblock(s, s->buf);
}
void sha256_init(struct sha256 *s) {
s->len = 0;
s->h[0] = 0x6a09e667;
s->h[1] = 0xbb67ae85;
s->h[2] = 0x3c6ef372;
s->h[3] = 0xa54ff53a;
s->h[4] = 0x510e527f;
s->h[5] = 0x9b05688c;
s->h[6] = 0x1f83d9ab;
s->h[7] = 0x5be0cd19;
}
void sha256_sum(struct sha256 *s, uint8_t md[20]) {
int i;
pad(s);
for (i = 0; i < 8; i ) {
md[4 * i 0] = s->h[i] >> 24;
md[4 * i 1] = s->h[i] >> 16;
md[4 * i 2] = s->h[i] >> 8;
md[4 * i 3] = s->h[i];
}
}
void sha256_update(struct sha256 *s, const void *m, unsigned long len) {
const uint8_t *p = m;
unsigned r = s->len % 64;
s->len = len;
if (r) {
if (len < 64 - r) {
memcpy(s->buf r, p, len);
return;
}
memcpy(s->buf r, p, 64 - r);
len -= 64 - r;
p = 64 - r;
processblock(s, s->buf);
}
for (; len >= 64; len -= 64, p = 64)
processblock(s, p);
memcpy(s->buf, p, len);
}
Вы бы изменили свою функцию на это:
const char *EncryptSHA256(char *Arg1) {
struct sha256 s;
unsigned char md[32];
static char result[65];
sha256_init(amp;s);
sha256_update(amp;s, Arg1, strlen(Arg1));
sha256_sum(amp;s, md);
for (int i = 0; i < 32; i ) {
sprintf(result i * 2, "x", md[i]);
}
return resu<
}
Вы также могли бы изменить API, чтобы передавать массив из 32 символов без знака для получения двоичной формы, если это более удобно.