📄 sha.c
字号:
memcpy(s->block+offset, bitstr, NBYTES(bitcnt)); s->blockcnt += bitcnt; } return(savecnt);}/* shabits: updates state for bit-aligned input data */static ULNG shabits(UCHR *bitstr, ULNG bitcnt, SHA *s){ UINT i; UINT gap; ULNG nbits; UCHR buf[1<<9]; UINT bufsize = sizeof(buf); ULNG bufbits = (ULNG) bufsize << 3; UINT nbytes = NBYTES(bitcnt); ULNG savecnt = bitcnt; gap = 8 - s->blockcnt % 8; s->block[s->blockcnt>>3] &= ~0 << gap; s->block[s->blockcnt>>3] |= *bitstr >> (8 - gap); s->blockcnt += bitcnt < gap ? bitcnt : gap; if (bitcnt < gap) return(savecnt); if (s->blockcnt == s->blocksize) s->sha(s, s->block), s->blockcnt = 0; if ((bitcnt -= gap) == 0) return(savecnt); while (nbytes > bufsize) { for (i = 0; i < bufsize; i++) buf[i] = bitstr[i] << gap | bitstr[i+1] >> (8-gap); nbits = bitcnt < bufbits ? bitcnt : bufbits; shabytes(buf, nbits, s); bitcnt -= nbits, bitstr += bufsize, nbytes -= bufsize; } for (i = 0; i < nbytes - 1; i++) buf[i] = bitstr[i] << gap | bitstr[i+1] >> (8-gap); buf[nbytes-1] = bitstr[nbytes-1] << gap; shabytes(buf, bitcnt, s); return(savecnt);}/* shawrite: triggers a state update using data in bitstr/bitcnt */ULNG shawrite(UCHR *bitstr, ULNG bitcnt, SHA *s){ if (bitcnt < 1) return(0); if (SHA_LO32(s->lenll += bitcnt) < bitcnt) if (SHA_LO32(++s->lenlh) == 0) if (SHA_LO32(++s->lenhl) == 0) s->lenhh++; if (s->blockcnt == 0) return(shadirect(bitstr, bitcnt, s)); else if (s->blockcnt % 8 == 0) return(shabytes(bitstr, bitcnt, s)); else return(shabits(bitstr, bitcnt, s));}/* shafinish: pads remaining block(s) and computes final digest state */void shafinish(SHA *s){ UINT lenpos, lhpos, llpos; lenpos = s->blocksize == SHA1_BLOCK_BITS ? 448 : 896; lhpos = s->blocksize == SHA1_BLOCK_BITS ? 56 : 120; llpos = s->blocksize == SHA1_BLOCK_BITS ? 60 : 124; SETBIT(s->block, s->blockcnt), s->blockcnt++; while (s->blockcnt > lenpos) if (s->blockcnt < s->blocksize) CLRBIT(s->block, s->blockcnt), s->blockcnt++; else s->sha(s, s->block), s->blockcnt = 0; while (s->blockcnt < lenpos) CLRBIT(s->block, s->blockcnt), s->blockcnt++; if (s->blocksize > SHA1_BLOCK_BITS) { w32mem(s->block + 112, s->lenhh); w32mem(s->block + 116, s->lenhl); } w32mem(s->block + lhpos, s->lenlh); w32mem(s->block + llpos, s->lenll); s->sha(s, s->block);}/* shadigest: returns pointer to current digest (binary) */UCHR *shadigest(SHA *s){ digcpy(s); return(s->digest);}/* shahex: returns pointer to current digest (hexadecimal) */char *shahex(SHA *s){ int i; digcpy(s); s->hex[0] = '\0'; if (HEXLEN((size_t) s->digestlen) >= sizeof(s->hex)) return(s->hex); for (i = 0; i < s->digestlen; i++) sprintf(s->hex+i*2, "%02x", s->digest[i]); return(s->hex);}/* map: translation map for Base 64 encoding */static char map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";/* encbase64: encodes input (0 to 3 bytes) into Base 64 */static void encbase64(UCHR *in, int n, char *out){ UCHR byte[3] = {0, 0, 0}; out[0] = '\0'; if (n < 1 || n > 3) return; memcpy(byte, in, n); out[0] = map[byte[0] >> 2]; out[1] = map[((byte[0] & 0x03) << 4) | (byte[1] >> 4)]; out[2] = map[((byte[1] & 0x0f) << 2) | (byte[2] >> 6)]; out[3] = map[byte[2] & 0x3f]; out[n+1] = '\0';}/* shabase64: returns pointer to current digest (Base 64) */char *shabase64(SHA *s){ int n; UCHR *q; char out[5]; digcpy(s); s->base64[0] = '\0'; if (B64LEN(s->digestlen) >= sizeof(s->base64)) return(s->base64); for (n = s->digestlen, q = s->digest; n > 3; n -= 3, q += 3) { encbase64(q, 3, out); strcat(s->base64, out); } encbase64(q, n, out); strcat(s->base64, out); return(s->base64);}/* shadsize: returns length of digest in bytes */int shadsize(SHA *s){ return(s->digestlen);}/* shadup: duplicates current digest object */SHA *shadup(SHA *s){ SHA *p; SHA_new(0, p, 1, SHA); if (p == NULL) return(NULL); memcpy(p, s, sizeof(SHA)); return(p);}/* shadump: dumps digest object to a human-readable ASCII file */int shadump(char *file, SHA *s){ int i, j; SHA_FILE *f; UCHR *p = shadigest(s); if (file == NULL || strlen(file) == 0) f = SHA_stdout(); else if ((f = SHA_open(file, "w")) == NULL) return(0); SHA_fprintf(f, "alg:%d\nH", s->alg); for (i = 0; i < 8; i++) for (j = 0; j < (s->alg <= 256 ? 4 : 8); j++) SHA_fprintf(f, "%s%02x", j==0 ? ":" : "", *p++); SHA_fprintf(f, "\nblock"); for (i = 0; i < (int) (s->blocksize >> 3); i++) SHA_fprintf(f, ":%02x", s->block[i]); SHA_fprintf(f, "\nblockcnt:%u\n", s->blockcnt); SHA_fprintf(f, "lenhh:%lu\nlenhl:%lu\nlenlh:%lu\nlenll:%lu\n", (ULNG) LO32(s->lenhh), (ULNG) LO32(s->lenhl), (ULNG) LO32(s->lenlh), (ULNG) LO32(s->lenll)); if (f != SHA_stdout()) SHA_close(f); return(1);}/* fgetstr: reads (and returns pointer to) next line of file */static char *fgetstr(char *line, UINT maxsize, SHA_FILE *f){ char *p; if (SHA_feof(f) || maxsize == 0) return(NULL); for (p = line; !SHA_feof(f) && maxsize > 1; maxsize--) if ((*p++ = SHA_getc(f)) == '\n') break; *p = '\0'; return(line);}/* empty: returns true if line contains only whitespace characters */static int empty(char *line){ char *p; for (p = line; *p; p++) if (!isspace(*p)) return(0); return(1);}/* getval: null-terminates field value, and sets pointer to rest of line */static char *getval(char *line, char **pprest){ char *p, *v; for (v = line; *v == ':' || isspace(*v); v++) ; for (p = v; *p; p++) { if (*p == ':' || isspace(*p)) { *p++ = '\0'; break; } } *pprest = p; return(p == v ? NULL : v);}/* types of values present in dump file */#define T_C 1 /* character */#define T_I 2 /* normal integer */#define T_L 3 /* 32-bit value */#define T_Q 4 /* 64-bit value *//* ldvals: checks next line in dump file against tag, and loads values */static int ldvals( SHA_FILE *f, char *tag, int type, void *pval, int reps, int base){ char *p, *pr, line[512]; UCHR *pc = (UCHR *) pval; UINT *pi = (UINT *) pval; W32 *pl = (W32 *) pval; W64 *pq = (W64 *) pval; while ((p = fgetstr(line, sizeof(line), f)) != NULL) if (line[0] != '#' && !empty(line)) break; if (p == NULL || strcmp(getval(line, &pr), tag) != 0) return(0); while (reps-- > 0) { if ((p = getval(pr, &pr)) == NULL) return(1); switch (type) { case T_C: *pc++ = (UCHR) strtoul(p, NULL, base); break; case T_I: *pi++ = (UINT) strtoul(p, NULL, base); break; case T_L: *pl++ = (W32 ) strtoul(p, NULL, base); break; case T_Q: *pq++ = (W64 ) strto64(p ); break; } } return(1);}/* closeall: closes dump file and de-allocates digest object */static SHA *closeall(SHA_FILE *f, SHA *s){ if (f != NULL && f != SHA_stdin()) SHA_close(f); if (s != NULL) shaclose(s); return(NULL);}/* shaload: creates digest object corresponding to contents of dump file */SHA *shaload(char *file){ int alg; SHA *s = NULL; SHA_FILE *f; if (file == NULL || strlen(file) == 0) f = SHA_stdin(); else if ((f = SHA_open(file, "r")) == NULL) return(NULL); if ( /* avoid parens by exploiting precedence of (type)&-> */ !ldvals(f,"alg",T_I,(VP)&alg,1,10) || ((s = shaopen(alg)) == NULL) || !ldvals(f,"H",alg<=SHA256?T_L:T_Q,(VP)s->H,8,16) || !ldvals(f,"block",T_C,(VP)s->block,s->blocksize/8,16) || !ldvals(f,"blockcnt",T_I,(VP)&s->blockcnt,1,10) || (alg <= SHA256 && s->blockcnt >= SHA1_BLOCK_BITS) || (alg >= SHA384 && s->blockcnt >= SHA384_BLOCK_BITS) || !ldvals(f,"lenhh",T_L,(VP)&s->lenhh,1,10) || !ldvals(f,"lenhl",T_L,(VP)&s->lenhl,1,10) || !ldvals(f,"lenlh",T_L,(VP)&s->lenlh,1,10) || !ldvals(f,"lenll",T_L,(VP)&s->lenll,1,10) ) return(closeall(f, s)); if (f != SHA_stdin()) SHA_close(f); return(s);}/* shaclose: de-allocates digest object */int shaclose(SHA *s){ if (s != NULL) { memset(s, 0, sizeof(SHA)); SHA_free(s); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -