SEXP digest(SEXP Txt, SEXP Algo, SEXP Length, SEXP Skip, SEXP Leave_raw) { FILE *fp=0; char *txt; int algo = INTEGER_VALUE(Algo); int length = INTEGER_VALUE(Length); int skip = INTEGER_VALUE(Skip); int leaveRaw = INTEGER_VALUE(Leave_raw); SEXP result = NULL; char output[128+1], *outputp = output; /* 33 for md5, 41 for sha1, 65 for sha256, 128 for sha512; plus trailing NULL */ int nChar; int output_length = -1; if (IS_RAW(Txt)) { /* Txt is either RAW */ txt = (char*) RAW(Txt); nChar = LENGTH(Txt); } else { /* or a string */ txt = (char*) STRING_VALUE(Txt); nChar = strlen(txt); } if (skip>0) { if (skip>=nChar) nChar=0; else { nChar -= skip; txt += skip; } } if (length>=0 && length<nChar) nChar = length; switch (algo) { case 1: { /* md5 case */ md5_context ctx; output_length = 16; unsigned char md5sum[16]; int j; md5_starts( &ctx ); md5_update( &ctx, (uint8 *) txt, nChar); md5_finish( &ctx, md5sum ); memcpy(output, md5sum, 16); if (!leaveRaw) for(j = 0; j < 16; j++) sprintf(output + j * 2, "%02x", md5sum[j]); break; } case 2: { /* sha1 case */ int j; sha1_context ctx; output_length = 20; unsigned char sha1sum[20]; sha1_starts( &ctx ); sha1_update( &ctx, (uint8 *) txt, nChar); sha1_finish( &ctx, sha1sum ); memcpy(output, sha1sum, 20); if (!leaveRaw) for( j = 0; j < 20; j++ ) sprintf( output + j * 2, "%02x", sha1sum[j] ); break; } case 3: { /* crc32 case */ unsigned long val, l; l = nChar; val = digest_crc32(0L, 0, 0); val = digest_crc32(val, (unsigned char*) txt, (unsigned) l); sprintf(output, "%2.2x", (unsigned int) val); break; } case 4: { /* sha256 case */ int j; sha256_context ctx; output_length = 32; unsigned char sha256sum[32]; sha256_starts( &ctx ); sha256_update( &ctx, (uint8 *) txt, nChar); sha256_finish( &ctx, sha256sum ); memcpy(output, sha256sum, 32); if(!leaveRaw) for( j = 0; j < 32; j++ ) sprintf( output + j * 2, "%02x", sha256sum[j] ); break; } case 5: { /* sha2-512 case */ int j; SHA512_CTX ctx; output_length = SHA512_DIGEST_LENGTH; uint8_t sha512sum[output_length], *d = sha512sum; SHA512_Init(&ctx); SHA512_Update(&ctx, (uint8 *) txt, nChar); // Calling SHA512_Final, because SHA512_End will already // convert the hash to a string, and we also want RAW SHA512_Final(sha512sum, &ctx); memcpy(output, sha512sum, output_length); // adapted from SHA512_End if(!leaveRaw) { for (j = 0; j < output_length; j++) { *outputp++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *outputp++ = sha2_hex_digits[*d & 0x0f]; d++; } *outputp = (char)0; } break; } case 101: { /* md5 file case */ int j; md5_context ctx; output_length = 16; unsigned char buf[1024]; unsigned char md5sum[16]; if (!(fp = fopen(txt,"rb"))) { error("Cannot open input file: %s", txt); return(NULL); } if (skip > 0) fseek(fp, skip, SEEK_SET); md5_starts( &ctx ); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; md5_update( &ctx, buf, nChar ); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) md5_update( &ctx, buf, nChar ); } fclose(fp); md5_finish( &ctx, md5sum ); memcpy(output, md5sum, 16); if (!leaveRaw) for(j = 0; j < 16; j++) sprintf(output + j * 2, "%02x", md5sum[j]); break; } case 102: { /* sha1 file case */ int j; sha1_context ctx; output_length = 20; unsigned char buf[1024]; unsigned char sha1sum[20]; if (!(fp = fopen(txt,"rb"))) { error("Cannot open input file: %s", txt); return(NULL); } if (skip > 0) fseek(fp, skip, SEEK_SET); sha1_starts ( &ctx ); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; sha1_update( &ctx, buf, nChar ); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) sha1_update( &ctx, buf, nChar ); } fclose(fp); sha1_finish ( &ctx, sha1sum ); memcpy(output, sha1sum, 20); if(!leaveRaw) for( j = 0; j < 20; j++ ) sprintf( output + j * 2, "%02x", sha1sum[j] ); break; } case 103: { /* crc32 file case */ unsigned char buf[1024]; unsigned long val; if (!(fp = fopen(txt,"rb"))) { error("Cannot open input file: %s", txt); return(NULL); } if (skip > 0) fseek(fp, skip, SEEK_SET); val = digest_crc32(0L, 0, 0); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; val = digest_crc32(val , buf, (unsigned) nChar); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) val = digest_crc32(val , buf, (unsigned) nChar); } fclose(fp); sprintf(output, "%2.2x", (unsigned int) val); break; } case 104: { /* sha256 file case */ int j; sha256_context ctx; output_length = 32; unsigned char buf[1024]; unsigned char sha256sum[32]; if (!(fp = fopen(txt,"rb"))) { error("Cannot open input file: %s", txt); return(NULL); } if (skip > 0) fseek(fp, skip, SEEK_SET); sha256_starts ( &ctx ); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; sha256_update( &ctx, buf, nChar ); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) sha256_update( &ctx, buf, nChar ); } fclose(fp); sha256_finish ( &ctx, sha256sum ); memcpy(output, sha256sum, 32); if(!leaveRaw) for( j = 0; j < 32; j++ ) sprintf( output + j * 2, "%02x", sha256sum[j] ); break; } case 105: { /* sha2-512 file case */ int j; SHA512_CTX ctx; output_length = SHA512_DIGEST_LENGTH; uint8_t sha512sum[output_length], *d = sha512sum; unsigned char buf[1024]; if (!(fp = fopen(txt,"rb"))) { error("Cannot open input file: %s", txt); return(NULL); } if (skip > 0) fseek(fp, skip, SEEK_SET); SHA512_Init(&ctx); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; SHA512_Update( &ctx, buf, nChar ); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) SHA512_Update( &ctx, buf, nChar ); } fclose(fp); // Calling SHA512_Final, because SHA512_End will already // convert the hash to a string, and we also want RAW SHA512_Final(sha512sum, &ctx); memcpy(output, sha512sum, output_length); // adapted from SHA512_End if(!leaveRaw) { for (j = 0; j < output_length; j++) { *outputp++ = sha2_hex_digits[(*d & 0xf0) >> 4]; *outputp++ = sha2_hex_digits[*d & 0x0f]; d++; } *outputp = (char)0; } break; } default: { error("Unsupported algorithm code"); return(NULL); } } if (leaveRaw && output_length > 0) { PROTECT(result=allocVector(RAWSXP, output_length)); memcpy(RAW(result), output, output_length); } else { PROTECT(result=allocVector(STRSXP, 1)); SET_STRING_ELT(result, 0, mkChar(output)); } UNPROTECT(1); return result; }
static char * digest_string( char *txt, int algo, int length, char *output) { FILE *fp=0; error_message = NULL; int nChar = strlen(txt); if (length>=0 && length<nChar) nChar = length; switch (algo) { case 1: { /* md5 case */ md5_context ctx; unsigned char md5sum[16]; int j; md5_starts( &ctx ); md5_update( &ctx, (uint8 *) txt, nChar); md5_finish( &ctx, md5sum ); for(j = 0; j < 16; j++) { sprintf(output + j * 2, "%02x", md5sum[j]); } break; } case 2: { /* sha1 case */ int j; sha1_context ctx; unsigned char sha1sum[20]; sha1_starts( &ctx ); sha1_update( &ctx, (uint8 *) txt, nChar); sha1_finish( &ctx, sha1sum ); for( j = 0; j < 20; j++ ) { sprintf( output + j * 2, "%02x", sha1sum[j] ); } break; } case 3: { /* crc32 case */ unsigned long val, l; l = nChar; val = digest_crc32(0L, 0, 0); val = digest_crc32(val, (unsigned char*) txt, (unsigned) l); sprintf(output, "%2.2x", (unsigned int) val); break; } case 101: { /* md5 file case */ int j; md5_context ctx; unsigned char buf[1024]; unsigned char md5sum[16]; if (!(fp = fopen(txt,"rb"))) { error_message = (strcat("Can not open input file: ", txt)); return (char *)NULL; } md5_starts( &ctx ); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; md5_update( &ctx, buf, nChar ); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) md5_update( &ctx, buf, nChar ); } fclose(fp); md5_finish( &ctx, md5sum ); for(j = 0; j < 16; j++) sprintf(output + j * 2, "%02x", md5sum[j]); break; } case 102: { /* sha1 file case */ int j; sha1_context ctx; unsigned char buf[1024]; unsigned char sha1sum[20]; if (!(fp = fopen(txt,"rb"))) { error_message = (strcat("Can not open input file: ", txt)); return (char *)NULL; } sha1_starts ( &ctx ); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; sha1_update( &ctx, buf, nChar ); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) sha1_update( &ctx, buf, nChar ); } fclose(fp); sha1_finish ( &ctx, sha1sum ); for( j = 0; j < 20; j++ ) sprintf( output + j * 2, "%02x", sha1sum[j] ); break; } case 103: { /* crc32 file case */ unsigned char buf[1024]; unsigned long val; if (!(fp = fopen(txt,"rb"))) { error_message = (strcat("Can not open input file: ", txt)); return (char *)NULL; } val = digest_crc32(0L, 0, 0); if (length>=0) { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0 && length>0) { if (nChar>length) nChar=length; val = digest_crc32(val , buf, (unsigned) nChar); length -= nChar; } } else { while( ( nChar = fread( buf, 1, sizeof( buf ), fp ) ) > 0) val = digest_crc32(val , buf, (unsigned) nChar); } fclose(fp); sprintf(output, "%2.2x", (unsigned int) val); break; } default: { error_message = ("Unsupported algorithm code"); return (char *)NULL; } } return output; }