使用OpenSSL RSA_private_decrypt()函数时出错

时间:2014-09-07 09:55:47

标签: c encryption openssl

我尝试使用OpenSSL库来保护客户端和服务器之间的通信: 客户端要求输入名称,对其进行加密,然后将其发送给解密它的服务器。加密的字符串由服务器正确接收,但是当它被解密时,它有时会工作..但有时我会收到此错误

  

错误:0407106B:rsa例程:RSA_padding_check_PKCS1_type_2:块类型不是02

我发现了一个关于这个错误的类似问题,我做了建议的更正,但我仍然遇到问题,因为有时候它会起作用,有时也不会......

这是客户端和服务器代码:

    //client

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include<sys/time.h>

/*OpenSSL libraries*/

#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#include <openssl/evp.h>

void generate_RSA_keys(char* public, char* private) {

    char file_pem[strlen(private)];
    char file_pem_pub[strlen(public)];
    strcpy(file_pem, private);
    strcpy(file_pem_pub, public);
    FILE *fp;

    int bits = 1024;
    unsigned long exp = RSA_F4;
    RSA *rsa;
    rsa = RSA_generate_key(bits,exp,NULL,NULL);

    fp = fopen(file_pem, "w");
    unsigned char *kstr = "pass";
    PEM_write_RSAPrivateKey(fp,rsa,EVP_des_ede3_cbc(),kstr,strlen(kstr),NULL,NULL);
    fclose(fp);
    fp = fopen(file_pem_pub, "w");
    PEM_write_RSAPublicKey(fp, rsa);
    fclose(fp);
    RSA_free(rsa);
}

int main(int argc, char** argv) {

    char nome[36];
    unsigned char* cnome;
    int sk, ret;    
    int n, nlen;
    int port;
    int rsa_size;
    struct sockaddr_in server_addr;


    if(argc != 3) {
                fprintf(stderr, "Errore nel passaggio parametri\n");
                exit(1);
        }

    //Stabilisco connessione TCP col server 
        sk = socket(AF_INET, SOCK_STREAM, 0);
        if(sk < 0) {
                perror("Client socket error!");
                exit(1);
        }

    memset(&server_addr, 0, sizeof(server_addr));
        port = atoi(argv[2]);
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(port);
        ret = inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr.s_addr);
    if(ret == -1) {
                perror("Error");
                exit(1);
        }

        ret = connect(sk, (struct sockaddr*)&server_addr, sizeof(server_addr));
        if(ret == -1){
                perror("Connection failed!");
                exit(1);
        }

    printf("Connessione al server %s (porta %s) effettuata con successo\n", argv[1],
                                                        argv[2]);

    generate_RSA_keys("cpub.pem", "cpriv.pem");

    printf("Insert your name: ");
    fflush(stdout);

    scanf("%s", nome);

    //RSA ALGORITHM

    // Context allocation
    OpenSSL_add_all_algorithms();
    RSA* rsa = RSA_new();

    //Encryption
    FILE* fp;
    fp = fopen("spub.pem", "r");

    rsa = PEM_read_RSAPublicKey(fp, &rsa, NULL, NULL);
    rsa_size = RSA_size(rsa);

    cnome = (unsigned char*)malloc(rsa_size);
    memset(cnome, 0 , sizeof(cnome));

    nlen = strlen(nome);
    RSA_public_encrypt(nlen, (const unsigned char*)nome, cnome, rsa, RSA_PKCS1_PADDING);

    //Context deallocation
    RSA_free(rsa);
    fclose(fp);

    int c_len = strlen(cnome);
    ret = send(sk, (void*)cnome, c_len+1, 0);

    printf("nome = %s\ncnome = %s\n", nome, cnome);
    close(sk);
    return 0;
}


//server

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>


/*OpenSSL libraries*/

#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#include <openssl/evp.h>

void generate_RSA_keys(char* public, char* private) {

    printf("inizio generazione chiavi\n");
    char file_pem[strlen(private)];
    char file_pem_pub[strlen(public)];
    strcpy(file_pem, private);
    strcpy(file_pem_pub, public);
    FILE *fp;

    int bits = 1024;
    unsigned long exp = RSA_F4;
    RSA *rsa;
    rsa = RSA_generate_key(bits,exp,NULL,NULL);

    fp = fopen(file_pem, "w");
    unsigned char *kstr = "pass";
    PEM_write_RSAPrivateKey(fp,rsa,EVP_des_ede3_cbc(),kstr,strlen(kstr),NULL,NULL);
    fclose(fp);
    fp = fopen(file_pem_pub, "w");
    PEM_write_RSAPublicKey(fp, rsa);
    fclose(fp);
    RSA_free(rsa);
    printf("fine generazione chiavi\n");
}

int main(int argc, char *argv[]) {

        //VARIABILI
        struct sockaddr_in serveraddr;
        struct sockaddr_in clientaddr;
        socklen_t addrlen;

    int sk;         //listening socket
        int c_sk;       //connection socket

    int ret, c_len;
    int rsa_size, n;
    char cnome[1024];
    char *nome;
    int yes = 1;    //per la setsockopt()
    int port;

    //CODICE
        if(argc != 3) {
                fprintf(stderr, "Errore nel passaggio parametri\n");
                exit(1);
        }

    if(atoi(argv[2]) < 1024) {
        fprintf(stderr, "Numero di porta non valido\n");
        exit(1);
    }

        printf("Indirizzo: %s (Porta: %s)\n", argv[1], argv[2]);

    sk = socket(AF_INET, SOCK_STREAM, 0); //listening socket
        if(sk < 0) {
                perror("Server socket error!");
                exit(1);
        }
    if(setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
                perror("Server setsockopt error!");
                exit(1);
        }
    memset(&serveraddr, 0, sizeof(serveraddr));
        port = atoi(argv[2]);
        serveraddr.sin_family = AF_INET;
    ret = inet_pton(AF_INET, argv[1], &serveraddr.sin_addr.s_addr);
        serveraddr.sin_port = htons(port);

    ret = bind(sk, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
        if(ret == -1) {
                perror("Server bind error!");
                exit(1);
        }

    ret = listen(sk, 10);
        if(ret == -1) {
                perror("Server listen error!");
                exit(1);
        }

    addrlen = sizeof(clientaddr);

    c_sk = accept(sk, (struct sockaddr*)&clientaddr, &addrlen);
        if(c_sk == -1) {
            perror("Server accept error!");
                exit(1);
        }

    generate_RSA_keys("spub.pem", "spriv.pem"); 

    ret = recv(c_sk, (void*)cnome, sizeof(cnome), 0);

    //RSA ALGORITHM
    //Context allocation
    OpenSSL_add_all_algorithms();
    RSA* rsa = RSA_new();

    FILE* fp;
    fp = fopen("spriv.pem", "r");

    //Decryption
    rsa = PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL);

    rsa_size = RSA_size(rsa);

    nome = (unsigned char*)malloc(rsa_size);
    memset(nome, 0, sizeof(nome));

    n = RSA_private_decrypt(rsa_size, (unsigned char*)cnome, nome, rsa, RSA_PKCS1_PADDING);
    char err[1024];
    ERR_load_crypto_strings();
    ERR_error_string(ERR_get_error(), err);
    fprintf(stderr, "%s\n", err);
    //Context deallocation
    RSA_free(rsa);
    fclose(fp);

    close(sk);
    close(c_sk);

    return 0;
}

1 个答案:

答案 0 :(得分:0)

密文包含看似随机数的所有字节。您不能将其视为字符串,如果要将其用作字符串,请使用base 64对其进行编码。使用strlen确定长度肯定不起作用,因为密文可能包含00字符(或可能不是)。