哈希密码并使用C中的签名进行检查

时间:2017-06-08 09:06:37

标签: 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

1 个答案:

答案 0 :(得分:2)

您以两种人类可读格式转换文件:

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

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

此外,你实际上有一些内存泄漏:你没有释放public_decrypt中的rsa实例也没有释放返回的字符串(加密,签名,cypher0 x )......

进一步推荐pt:

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

如果你已经有一个合适的常数,请使用它... sizeof(char)根据定义,它总是1,所以你可以放弃它...