2011-11-26 21 views
7

Tôi đang viết một thường trình trong C đọc chuỗi base64 bằng khóa công khai và tiến hành mã hóa chuỗi. Tôi cũng kiểm tra giải mã cùng chuỗi nhưng tôi nhận được lỗi 0x0407106B khi cố gắng thực hiện việc giải mã:Lỗi mã hóa và giải mã 0x0407106B sử dụng OpenSSL

$ openssl errstr 0x0407106B 
error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02 

Dưới đây là đoạn code

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <openssl/rsa.h> 
#include <openssl/engine.h> 

//#define PADDING RSA_PKCS1_OAEP_PADDING 
#define PADDING RSA_PKCS1_PADDING 
//#define PADDING RSA_NO_PADDING 

main() { 

// public key 
char *b64_pKey = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp2w+8HUdECo8V5yuKYrWJmUbL\ntD6nSyVifN543axXvNSFzQfWNOGVkMsCo6W4hpl5eHv1p9Hqdcf/ZYQDWCK726u6\nhsZA81AblAOOXKaUaxvFC+ZKRJf+MtUGnv0v7CrGoblm1mMC/OQI1JfSsYi68Epn\naOLepTZw+GLTnusQgwIDAQAB\n-----END PUBLIC KEY-----\n"; 

// private key 
char *b64priv_key = "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCp2w+8HUdECo8V5yuKYrWJmUbLtD6nSyVifN543axXvNSFzQfW\nNOGVkMsCo6W4hpl5eHv1p9Hqdcf/ZYQDWCK726u6hsZA81AblAOOXKaUaxvFC+ZK\nRJf+MtUGnv0v7CrGoblm1mMC/OQI1JfSsYi68EpnaOLepTZw+GLTnusQgwIDAQAB\nAoGBAKDuq3PikblH/9YS11AgwjwC++7ZcltzeZJdGTSPY1El2n6Dip9ML0hUjeSM\nROIWtac/nsNcJCnvOnUjK/c3NIAaGJcfRPiH/S0Ga6ROiDfFj2UXAmk/v4wRRUzr\n5lsA0jgEt5qcq2Xr/JPQVGB4wUgL/yQK0dDhW0EdrJ707e3BAkEA1aIHbmcVfCP8\nY/uWuK0lvWxrIWfR5MlHhI8tD9lvkot2kyXiV+jB6/gktwk1QaFsy7dCXn7w03+k\nxrjEGGN+kQJBAMuKf55lDtU9K2Js3YSStTZAXP+Hz7XpoLxmbWFyGvBx806WjgAD\n624irwS+0tBxkERbRcisfb2cXmAx8earT9MCQDZuVCpjBWxd1t66qYpgQ29iAmG+\njBIY3qn9uOOC6RSTiCCx1FvFqDMxRFmGdRVFxeyZwsVE3qNksF0Zko0MPKECQCEe\noDV97DP2iCCz5je0R5hUUM2jo8DOC0GcyR+aGZgWcqjPBrwp5x08t43mHxeb4wW8\ndFZ6+trnntO4TMxkA9ECQB+yCPgO1zisJWYuD46KISoesYhwHe5C1BQElQgi9bio\nU39fFo88w1pok23a2CZBEXguSvCvexeB68OggdDXvy0=\n-----END RSA PRIVATE KEY-----\n"; 

// String to encrypt 
char *str = "1234"; 

ERR_load_crypto_strings(); 

BIO *bpo = BIO_new_mem_buf(b64_pKey, -1); 
RSA *pubKey = PEM_read_bio_RSA_PUBKEY(bpo, NULL, NULL, NULL); 

if (!pubKey) { 
    printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); 
    return; 
} 

int rsa_length = RSA_size(pubKey); 

BIO *b64 = NULL; 
BIO *bmem = NULL; 
BUF_MEM *bptr = NULL; 

unsigned char encrypted[2560] = { 0 }; 
unsigned char retencrypted[2560] = { 0 }; 

int resultEncrypt = RSA_public_encrypt(PADDING, str, encrypted, pubKey, PADDING); 
if (resultEncrypt == -1) { 
    printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); 
    return; 
} 

/* 
* Show base 64 encrypted string 
*/ 
b64 = BIO_new((BIO_METHOD *)BIO_f_base64()); 
BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); 
bmem = BIO_new(BIO_s_mem()); 
b64 = BIO_push(b64, bmem); 
BIO_write(b64, encrypted, resultEncrypt); 
BIO_flush(b64); 
BIO_get_mem_ptr(b64, &bptr); 

memcpy(retencrypted, bptr->data, bptr->length); 
BIO_free(b64); 
BIO_free(bpo); 
RSA_free(pubKey); 

printf("Encrypted string:%s\n",retencrypted); 

/* 
* Now decrypt this very string with the private key 
*/ 

BIO *bpop = BIO_new_mem_buf(b64priv_key, -1); 
RSA *privKey = PEM_read_bio_RSAPrivateKey(bpop, NULL, NULL, NULL); 

if (!privKey) { 
    printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); 
    return; 
} 

rsa_length = RSA_size(privKey); 

unsigned char decrypted[2560] = { 0 }; 

int resultDecrypt = RSA_private_decrypt(RSA_size(privKey), retencrypted, decrypted, privKey, PADDING); 

if (resultDecrypt == -1) { 
    printf("%s\n", ERR_error_string(ERR_get_error(), NULL)); 
    return; 
} 

printf("resultDecrypt=%d\ndecrypted string: %s\n",resultDecrypt,decrypted); 
BIO_free(bpop); 
RSA_free(privKey); 
ERR_free_strings(); 
} 

Lưu ý: Tôi xuất khóa riêng sử dụng

openssl rsa -in rsa_privatekey.pem -check 

và khóa công khai:

openssl rsa -in rsa_privatekey.pem -pubout 

Tại sao tôi gặp lỗi?

+0

Bạn có cần có dòng mới ở cuối chuỗi chứng chỉ không? http://srdevspot.blogspot.com/2011/08/openssl-error0906d064pem.html – mdec

+0

Đã cố gắng thêm dòng mới vào cả hai khóa nhưng có cùng kết quả. – xain

+1

Tôi có [sửa ví dụ của bạn trên đây] (https://gist.github.com/superwills/5415344) – bobobobo

Trả lời

3

Vấn đề là bạn đang cố gắng giải mã kết quả được mã hóa base64. Bạn nên cố gắng giải mã kết quả mã hóa.

Đó là, thay vì:

int resultDecrypt = RSA_private_decrypt(RSA_size(privKey), retencrypted, decrypted, privKey, PADDING); 

Bạn nên gọi:

int resultDecrypt = RSA_private_decrypt(RSA_size(privKey), encrypted, decrypted, privKey, PADDING); 

Ngoài ra, có một vấn đề trong cuộc gọi mã hóa:

int resultEncrypt = RSA_public_encrypt(PADDING, str, encrypted, pubKey, PADDING); 

Tại sao các bạn đi qua PADDING là flen? Đây phải là độ dài của chuỗi (tức là 4 hoặc 5, tùy thuộc vào việc bạn muốn mã hóa ký tự null).

Nếu bạn muốn viết chuỗi được mã hóa dưới dạng ASCII (được mã hóa bằng base64), thì tốt. Nhưng bạn phải giải mã nó trước khi bạn giải mã nó.

1

Lỗi bạn nhận được là block type is not 02.

Mặc dù Omri đúng là bạn truyền sai dữ liệu và bạn chỉ mã hóa 1 byte, lỗi là do sizeof(encrypted) quá lớn (2560). Nói cách khác, bộ thu dữ liệu của bạn cho RSA_public_encrypt phải là con trỏ thường xuyên unsigned char*, không phải là một unsigned char[2560].

Nơi bạn có

unsigned char encrypted[2560] = { 0 }; //X 2560?? RSA_public_encrypt fails. 

Bạn nên sử dụng

unsigned char *encrypted = (unsigned char*)malloc(rsa_length) ; 
RSA_public_encrypt(DATALEN, (const unsigned char*)str, encrypted, pubKey, PADDING) ; 

Thông báo lỗi Omri chỉ ra, rằng bạn sử dụng PADDING như arg đầu tiên RSA_public_encrypt, trong khi nó phải là dữ liệu DATALEN chiều dài.

Nếu bạn khắc phục, bạn sẽ gặp phải lỗi tương tự sau đó với giải mã khóa cá nhân. Sửa chữa nó và bạn đang trên con đường của bạn.