c - 散列密码并使用 C 中的签名进行检查

标签 c hash rsa digital-signature sha1

我有三个二进制文件:cipher01.bin、cipher02.bin 和 cipher03.bin。 此外,我还有一个 sign.bin 和一个 pubkey.pem 文件。任务是散列所有三个密码并将其与签名进行比较。因此,我使用 RSA 使用来自 pubkey.pem 的公钥来解密 sign.bin。

结果看起来不错,但没有一个密码哈希属于签名。但我知道,至少有一个密码属于签名,因为这是我们大学的任务。也许我忘记了什么,但我不知道是什么。

到目前为止,这是我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/** converts unsigned character to readble string*/
char *pt(unsigned char *md) {
  int i;
  char *buf = (char*)malloc(sizeof(char)*80);

  for(int i = 0; i < SHA_DIGEST_LENGTH;i++) {
    sprintf(&(buf[i*2]),"%02x",md[i]);
  }

  return (buf);
}

/** returns error */
void err_exit(void) {
  printf("%s\n",ERR_error_string(ERR_get_error(),NULL));

  ERR_free_strings();
  exit(EXIT_FAILURE);
}

/** reads a file */
char * readFile(char * filename,long int * filesize) {
  FILE *fin;
  char *buf;

  if((fin=fopen(filename,"r"))==NULL) {
    printf("Error opening %s.\n",filename);
    exit(EXIT_FAILURE);
  }

  fseek(fin,0L,SEEK_END);
  *filesize = ftell(fin);
  rewind(fin);

  if(!(buf=malloc(*filesize))) {
    printf("Memory exhausted. Stop.\n");
    exit(EXIT_FAILURE);
  }


  fread(buf,*filesize,1,fin);
  fclose(fin);

  return buf;
}

/** hash a file with sha1 */
char * hashBinaryFile(char * filename) {
  long int filesize = 0;

  EVP_MD_CTX c;
  unsigned char md[SHA_DIGEST_LENGTH];

  ERR_load_crypto_strings();

  EVP_MD_CTX_init(&c);

  /** reads files into buf */
  char * buf = readFile(filename,&filesize);

  if((EVP_DigestInit(&c,EVP_sha1()))==0) {
    err_exit();
  }

  if((EVP_DigestUpdate(&c,buf,filesize))==0) {
    err_exit();
  }

  if((EVP_DigestFinal(&c,md,NULL))==0) {
    err_exit();
  }

  //printf("%s\n",pt(md));

  EVP_MD_CTX_cleanup(&c);
  free(buf);
  ERR_free_strings();

  return pt(md);

}

int padding = RSA_PKCS1_PADDING;

/** loads public key and creates rsa */
RSA * createRSAWithFilename(char * filename,int public) {
  FILE * fp = fopen(filename,"rb");

  if(fp == NULL) {
    printf("Unable to open file %s \n",filename);
    return NULL;    
  }

  RSA *rsa= RSA_new() ;

  if(public) {
    rsa = PEM_read_RSA_PUBKEY(fp, &rsa,NULL, NULL);
  } else {
    rsa = PEM_read_RSAPrivateKey(fp, &rsa,NULL, NULL);
  }

  return rsa;
}

/** decrypt signature */
char * public_decrypt(unsigned char * enc_data,int data_len, unsigned char *decrypted) {
  RSA * rsa = createRSAWithFilename("archieve/pubkey.pem",1);
  int  result = RSA_public_decrypt(data_len,enc_data,decrypted,rsa,padding);
  return pt(decrypted);
}

int main(int argc,char *argv[]) {
  /** decrypt signature */
  long int encrypted_length;
  long int decrypted_length; 
  unsigned char decrypted[4098]={};
  char * encrypted = readFile("archieve/s72897-sig.bin",&encrypted_length);
  char * sign = public_decrypt(encrypted,encrypted_length, decrypted);

  char * cipher01 = hashBinaryFile("archieve/s72897-cipher01.bin");
  char * cipher02 = hashBinaryFile("archieve/s72897-cipher02.bin");
  char * cipher03 = hashBinaryFile("archieve/s72897-cipher03.bin");

  if(strcmp(sign,cipher01)==0) {
    printf("cipher01\n");
  } else if(strcmp(sign,cipher02)==0) {
    printf("cipher02\n");
  } else if(strcmp(sign,cipher03)==0) {
    printf("cipher03\n");
  } else {
    printf("No cipher matches the signature\n");
  }

  return 0;
}

感谢您的帮助。

编辑:修复了一些代码

Edit2:链接到 *.zip https://ufile.io/tqwoh

最佳答案

您将文件转换为人类可读格式两次:

char * public_decrypt(...)
{
    return pt(decrypted);
    //     ^
}

int main(int argc,char *argv[])
{
    char * sign = pt(public_decrypt(encrypted,encrypted_length, decrypted));
    //            ^

此外,您实际上有一些内存泄漏:您没有释放 public_decrypt 中的 rsa 实例,也没有释放返回的字符串 (encrypted, sign, cypher0x)...

进一步推荐给pt:

char *buf = (char*)malloc(sizeof(char) * 2 * SHA_DIGEST_LENGTH);

如果您已经有合适的常量,请使用它...sizeof(char) 根据定义始终为 1,因此您可以放弃它...

关于c - 散列密码并使用 C 中的签名进行检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44431290/

相关文章:

c - 使用指针为 C 中的 3D 数组分配内存?

c - LIBUSB_ERROR_TIMEOUT 当我尝试使用 libusb raspberry pi 3 发送 usb 数据时

c - 内存使用不足会导致内存泄漏吗?

c - atol 对不同的字符串产生相同的结果

openssl - 由 Windows CNG(下一代加密)生成的 RSA SHA512 签名 NCryptSignHash 与由 openssl 生成的签名不匹配 RSA_sign

c - 使用 C 将字符串中每个字符的位置从其当前位置循环移动到它的右边

javascript - d3 对其他需要文件中的节点哈希更改没有反应

使用自定义类类型作为键的 C++ unordered_map

c# - 导入 RSA CngKey 并存储在 MicrosoftSoftwareKeyStorageProvider 中

java - 生成的RSA公钥和私钥模数在Java/Android中是一样的