const char* PE_(bin_pe_compute_authentihash)(RBinPEObj* pe) {
	if (!pe->spcinfo || !pe->spcinfo->messageDigest.digestAlgorithm.algorithm) {
		return NULL;
	}

	char *hashtype = strdup (pe->spcinfo->messageDigest.digestAlgorithm.algorithm->string);
	r_str_replace_char (hashtype, '-', 0);
	ut64 algobit = r_hash_name_to_bits (hashtype);
	if (!(algobit & (R_HASH_MD5 | R_HASH_SHA1 | R_HASH_SHA256))) {
		eprintf ("Authenticode only supports md5, sha1, sha256. This PE uses %s\n", hashtype);
		free (hashtype);
		return NULL;
	}
	free (hashtype);
	ut32 checksum_paddr = pe->nt_header_offset + 4 + sizeof (PE_(image_file_header)) + 0x40;
	ut32 security_entry_offset =  pe->nt_header_offset + sizeof (PE_(image_nt_headers)) - 96;
	PE_(image_data_directory) *data_dir_security = &pe->data_directory[PE_IMAGE_DIRECTORY_ENTRY_SECURITY];
	PE_DWord security_dir_offset = data_dir_security->VirtualAddress;
	ut32 security_dir_size = data_dir_security->Size;

	RBuffer *buf = r_buf_new ();
	r_buf_append_buf_slice (buf, pe->b, 0, checksum_paddr);
	r_buf_append_buf_slice (buf, pe->b,
		checksum_paddr + 4,
		security_entry_offset - checksum_paddr - 4);
	r_buf_append_buf_slice (buf, pe->b,
		security_entry_offset + 8,
		security_dir_offset - security_entry_offset - 8);
	r_buf_append_buf_slice (buf, pe->b,
		security_dir_offset + security_dir_size,
		r_buf_size (pe->b) - security_dir_offset - security_dir_size);

	ut64 len;
	const ut8 *data = r_buf_data (buf, &len);
	char *hashstr = NULL;
	RHash *ctx = r_hash_new (true, algobit);
	if (ctx) {
		r_hash_do_begin (ctx, algobit);
		int digest_size = r_hash_calculate (ctx, algobit, data, len);
		r_hash_do_end (ctx, algobit);
		hashstr = r_hex_bin2strdup (ctx->digest, digest_size);
		r_buf_free (buf);
		r_hash_free (ctx);
	}
	return hashstr;
}
const char* PE_(bin_pe_compute_authentihash)(RBinPEObj* pe) {
	if (!pe->spcinfo || !pe->spcinfo->messageDigest.digestAlgorithm.algorithm) {
		return NULL;
	}

	char *hashtype = strdup (pe->spcinfo->messageDigest.digestAlgorithm.algorithm->string);
	r_str_replace_char (hashtype, '-', 0);
	ut64 algobit = r_hash_name_to_bits (hashtype);
	if (!(algobit & (R_HASH_MD5 | R_HASH_SHA1 | R_HASH_SHA256))) {
		eprintf ("Authenticode only supports md5, sha1, sha256. This PE uses %s\n", hashtype);
		free (hashtype);
		return NULL;
	}
	free (hashtype);
	ut32 checksum_paddr = pe->nt_header_offset + 4 + sizeof (PE_(image_file_header)) + 0x40;
	ut32 security_entry_offset =  pe->nt_header_offset + sizeof (PE_(image_nt_headers)) - 96;
	PE_(image_data_directory) *data_dir_security = &pe->data_directory[PE_IMAGE_DIRECTORY_ENTRY_SECURITY];
	PE_DWord security_dir_offset = data_dir_security->VirtualAddress;
	ut32 security_dir_size = data_dir_security->Size;

	RBuffer *buf = r_buf_new ();
	r_buf_append_buf_slice (buf, pe->b, 0, checksum_paddr);
	r_buf_append_buf_slice (buf, pe->b,
		checksum_paddr + 4,
		security_entry_offset - checksum_paddr - 4);
	r_buf_append_buf_slice (buf, pe->b,
		security_entry_offset + 8,
		security_dir_offset - security_entry_offset - 8);
	r_buf_append_buf_slice (buf, pe->b,
		security_dir_offset + security_dir_size,
		r_buf_size (pe->b) - security_dir_offset - security_dir_size);

	ut64 len;
	const ut8 *data = r_buf_data (buf, &len);
	char *hashstr = NULL;
	RHash *ctx = r_hash_new (true, algobit);
	if (ctx) {
		r_hash_do_begin (ctx, algobit);
		int digest_size = r_hash_calculate (ctx, algobit, data, len);
		r_hash_do_end (ctx, algobit);
		hashstr = r_hex_bin2strdup (ctx->digest, digest_size);
		r_buf_free (buf);
		r_hash_free (ctx);
	}
	return hashstr;
}