2017-10-02 26 views
12

Tôi đang tìm cách bảo mật thư tôi đã gửi từ máy chủ node.js đến ứng dụng C++.RSA đăng nhập node.js và xác minh trong C++

Từ node.js, tôi đã tạo một cặp khóa.

Tôi đang sử dụng nút-rsa để đọc các khóa công khai đứng về phía Node.js (https://github.com/rzcoder/node-rsa)

var rsa = new nodeRSA(publicKeyBuffer ,{encryptionScheme :'pkcs1'}) 

Như thông điệp của tôi có thể dài, tôi tính toán một sha256 muối của thông điệp trước khi gọi mã hóa.

const hash = crypto.createHash('sha256').update(message + config.signSalt).digest('hex') 

phần này hoạt động tốt vì tôi có thể tạo cùng một giá trị băm chính xác trên mặt C++.

sau đó, tôi gọi hàm mã hóa của nút-rsa để tạo ra một bộ đệm

const signature = rsa.encrypt(hash) 

tôi đã cố gắng mã hóa khác nhau, nhưng khi dữ liệu được gửi qua một WebSocket (+ MsgPack đóng gói) các định dạng nhị phân là một lựa chọn tốt

về phía C++, tôi lần đầu tiên đọc là chìa khóa cho một char []

const char keyStr[] = "-----BEGIN RSA PRIVATE KEY-----\n" .......... 

BIO* bio = BIO_new_mem_buf(keyStr, (int)strlen(keyStr)); // -1: assume string is null terminated 

m_rsaPrivKey = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); 

if (!m_rsaPrivKey) 
     LogOutSys("ERROR: Could not load PRIVATE KEY! PEM_write_bio_RSAPrivateKey FAILED: %s\n", ERR_error_string(ERR_get_error(), NULL)); 

phím được đọc mà không có lỗi, sau đó, tôi đang tính toán hash từ tin nhắn, thực hiện một std :: string từ bộ đệm char unsigned

std::string hash = sha256(msg.c_str()); 

std::string signatureStr(signature.begin(), signature.end()); 

char *decrypt; 

int decryptLen; 

decrypt = new char[RSA_size(m_rsaPrivKey)]; 

decryptLen = RSA_private_decrypt((int)msg.size() + 1, (unsigned char*)msg.c_str(), (unsigned char*)decrypt, m_rsaPrivKey, RSA_NO_PADDING /* RSA_PKCS1_OAEP_PADDING */); 

if (decryptLen == -1) 
{ 
    char errStr[130]; 
    ERR_error_string(ERR_get_error(), errStr); 
    LogOutSys("Rsa::decrypt - Error decrypting string ssl error %s", errStr); 
} 

for (int i = 0; i < decryptLen; i++) 
{ 
    decryptData.push_back(decrypt[i]); 
} 

delete decrypt; 

các giải mã thất bại với các lỗi sau

RSA :: giải mã - Lỗi giải mã error error chuỗi ssl: 0406506C: lib (4) : func (101): lý do (108)

Tôi đã thử chế độ mã hóa và chế độ đệm khác nhau nhưng luôn gặp lỗi.

+0

Tại sao bạn không sử dụng 'dấu (đệm, [mã hóa], [source_encoding]) 'phương pháp về phía javascript (có nghĩa là để ký kết và nên thực hiện băm bên trong)? Cách bạn thực hiện nó sẽ không tạo ra chữ ký chính xác (phần đệm cho chữ ký và mã hóa khác nhau). Nó có thể giúp sử dụng tiện ích dòng lệnh 'openssl' để xác minh tính chính xác của khóa/chữ ký/mã hóa. 'PublicKeyBuffer' có chứa khóa công cộng hay khóa riêng (vì nó chứa một khóa riêng cho chữ ký, tên biến này khá là sai lạc)? Chúc may mắn! – vlp

+0

đó là lần đầu tiên tôi làm điều này vì vậy có lẽ tôi đang làm sai cách (đó là lý do tại sao tôi hỏi câu hỏi thực sự :)) có publicKeyBuffer chứa một khóa công khai. Tôi nghĩ nếu có thể ký với khóa công khai và xác minh với khóa riêng nhưng theo câu trả lời của bạn có thể nó không phải là trường hợp. –

+0

Bạn đã nói "khóa được đọc có lỗi". Ý của bạn có phải là các lỗi _without_ không? Nếu không thì có vẻ như vấn đề ở đó. –

Trả lời

2

(Giả sử bạn muốn đăng nhập bằng cách sử dụng khóa bí mật ở phía nodejs và xác minh bằng cách sử dụng khóa công khai ở phía openssl)

Ký chuỗi Test với khóa riêng mẫu, sử dụng ví dụ:

NodeRSA=require('node-rsa'); 
key = new NodeRSA(null, {signingScheme: 'pkcs1-sha256'}); 
key.importKey('-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI2GkqoVj1l59MQh\nI/ZswgdnNG3o5XSmyeGgNdmTgQQ6cWCJcscCS6d3+nWFl3Xe7SxzKxo7pHMHTeJU\nGTZpLzW7fk5Y/ISWIr2Qsswpm8JUVOAUQVU/qwZYPr0ACCDQLGLaVByKFgvKnf5p\npkdroM63AFakn5YlCP+WM4ASuZyvAgMBAAECgYAUsBNIYZZu0fEBqoaDQyqpwmBb\noKvJ/YeNP8ofX/yADbr9DZqFlMRSWqt1+m1FgazRzpQCZa2IUw0DhJ+a4I1R6E30\nw7ZVWdVvWtkA70YGMaqB618fMR6SpTmzVGUjzQqk7Zim+uQVugTXEimC6/7sa7em\nLtVdjXuvOFOCVEeXwQJBAO/bN2q2u8YTBy9q4A34KoeeM8NX8zV3bRVhrB4eVcT0\ngpNNCrvjo2g5qKQs1fmLmjylSBihus0RjjJZTwxsffkCQQCXDRhh83OCtLfDEztO\nObu5BvVFcli76VEdw4EqzJtrddG77B43ggYYyJFxOuJHz+33oM4GtnHEiHkV9sRS\n47nnAkBcu8qPLZsnl4+9m3qIrBv1Vwr4SXa0gznffGXJNz096rLZNH4j6nzw/Ong\nn50S4BB/xf871rucMV9iw/i1+vQxAkEAjDBDKOVhlzVSN2Jp8Df02cxzZnixkfUA\nq7b+8lHjDODUPqztfmbWcbn0Ajq8OBnqqaA8lk5NWDGw74mOu79OkQJARDwRop7c\nfkd39rY/+an50uj2L4UJv1Jb+Yal5c0u37ACRnp+0n6qlcL0pj98UfW9H+oYFqwT\nKXzq4lptzgfQIg==\n-----END PRIVATE KEY-----\n', 'pkcs8'); 
signature=key.sign('Test', 'hex'); 

Đưa ra một hex chữ ký mã hóa:

'45f0c0672c8c07ecfe318b8ffa425c169ed2458ac6f0e4f1ffe0bcebec38cc3e59311858ed443d45f0dc81935ee0c490fa452b2f427d59a2c43fdd69f71f2b46d9e39072cb517b4afba5d5c66b26e14ca8a2900650b923fd77271deba84103d42c1f81619825d4987eeabc05401b0bc35bee08c59843aa94a535d2fb032b681b' 

Để xác minh chữ ký này với openssl, sử dụng ví dụ:

#include <stdlib.h> 
#include <stdio.h> 

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

int main(void) { 

    // Read public key from memory 
    EVP_PKEY *pubKey=NULL; 
    { 
     BIO * pubKeyPemBio = BIO_new_mem_buf("-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNhpKqFY9ZefTEISP2bMIHZzRt\n6OV0psnhoDXZk4EEOnFgiXLHAkund/p1hZd13u0scysaO6RzB03iVBk2aS81u35O\nWPyEliK9kLLMKZvCVFTgFEFVP6sGWD69AAgg0Cxi2lQcihYLyp3+aaZHa6DOtwBW\npJ+WJQj/ljOAErmcrwIDAQAB\n-----END PUBLIC KEY-----", -1); 
     if(pubKeyPemBio==NULL) { printf("Error at line %i\n", __LINE__); return 0; } 
     pubKey=PEM_read_bio_PUBKEY(pubKeyPemBio, &pubKey, NULL, NULL); 
     BIO_free(pubKeyPemBio); 
     if(pubKey==NULL) { printf("Error at line %i\n", __LINE__); return 0; } 
    } 

    // Verify signature 
    { 
     EVP_MD_CTX *ctx = EVP_MD_CTX_create(); 
     if(ctx==NULL) { printf("Error at line %i\n", __LINE__); return 0; } 

     int ret=EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, pubKey); 
     if(ret!=1) { printf("Error at line %i\n", __LINE__); return 0; } 

     ret=EVP_DigestVerifyUpdate(ctx, "Test", 4); 
     if(ret!=1) { printf("Error at line %i\n", __LINE__); return 0; } 

     ret=EVP_DigestVerifyFinal(ctx, "\x45\xf0\xc0\x67\x2c\x8c\x07\xec\xfe\x31\x8b\x8f\xfa\x42\x5c\x16\x9e\xd2\x45\x8a\xc6\xf0\xe4\xf1\xff\xe0\xbc\xeb\xec\x38\xcc\x3e\x59\x31\x18\x58\xed\x44\x3d\x45\xf0\xdc\x81\x93\x5e\xe0\xc4\x90\xfa\x45\x2b\x2f\x42\x7d\x59\xa2\xc4\x3f\xdd\x69\xf7\x1f\x2b\x46\xd9\xe3\x90\x72\xcb\x51\x7b\x4a\xfb\xa5\xd5\xc6\x6b\x26\xe1\x4c\xa8\xa2\x90\x06\x50\xb9\x23\xfd\x77\x27\x1d\xeb\xa8\x41\x03\xd4\x2c\x1f\x81\x61\x98\x25\xd4\x98\x7e\xea\xbc\x05\x40\x1b\x0b\xc3\x5b\xee\x08\xc5\x98\x43\xaa\x94\xa5\x35\xd2\xfb\x03\x2b\x68\x1b", 128); 
     if(ret!=1) { printf("Error at line %i\n", __LINE__); return 0; } 
     EVP_MD_CTX_destroy(ctx); 
    } 
    EVP_PKEY_free(pubKey); 

    printf("All OK!\n"); 
    return EXIT_SUCCESS; 
} 

Một số (ngẫu nhiên) ghi chú:

  • mã ở trên chỉ là một bằng chứng của khái niệm làm việc cho dấu hiệu RSA/xác minh giữa các nodej và openssl. Xin vui lòng không mong đợi nó là một thực hiện an toàn với xử lý lỗi chính xác, độ dài khóa an toàn, an toàn chống lại các cuộc tấn công thời gian/bên kênh vv

  • chuỗi ký/đệm có thể tùy ý miễn là băm được thực hiện bởi nút-rsa

  • mã hóa công cộng quan trọng/tin có thể thu được trong nodejs sử dụng ví dụ key.exportKey('pkcs8-public')/key.exportKey('pkcs8')

  • chọn mã hóa phù hợp với bạn (Tôi đã sử dụng chuỗi và chuỗi hex vì chúng có thể đọc được rõ ràng). Bạn có thể muốn sử dụng bộ đệm

Chúc may mắn!

Tuyên bố từ chối trách nhiệm: Tôi không có chuyên gia mật mã, vì vậy vui lòng xác thực ý kiến ​​của tôi.


sử dụng khóa bí mật:

-----BEGIN PRIVATE KEY----- 
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI2GkqoVj1l59MQh 
I/ZswgdnNG3o5XSmyeGgNdmTgQQ6cWCJcscCS6d3+nWFl3Xe7SxzKxo7pHMHTeJU 
GTZpLzW7fk5Y/ISWIr2Qsswpm8JUVOAUQVU/qwZYPr0ACCDQLGLaVByKFgvKnf5p 
pkdroM63AFakn5YlCP+WM4ASuZyvAgMBAAECgYAUsBNIYZZu0fEBqoaDQyqpwmBb 
oKvJ/YeNP8ofX/yADbr9DZqFlMRSWqt1+m1FgazRzpQCZa2IUw0DhJ+a4I1R6E30 
w7ZVWdVvWtkA70YGMaqB618fMR6SpTmzVGUjzQqk7Zim+uQVugTXEimC6/7sa7em 
LtVdjXuvOFOCVEeXwQJBAO/bN2q2u8YTBy9q4A34KoeeM8NX8zV3bRVhrB4eVcT0 
gpNNCrvjo2g5qKQs1fmLmjylSBihus0RjjJZTwxsffkCQQCXDRhh83OCtLfDEztO 
Obu5BvVFcli76VEdw4EqzJtrddG77B43ggYYyJFxOuJHz+33oM4GtnHEiHkV9sRS 
47nnAkBcu8qPLZsnl4+9m3qIrBv1Vwr4SXa0gznffGXJNz096rLZNH4j6nzw/Ong 
n50S4BB/xf871rucMV9iw/i1+vQxAkEAjDBDKOVhlzVSN2Jp8Df02cxzZnixkfUA 
q7b+8lHjDODUPqztfmbWcbn0Ajq8OBnqqaA8lk5NWDGw74mOu79OkQJARDwRop7c 
fkd39rY/+an50uj2L4UJv1Jb+Yal5c0u37ACRnp+0n6qlcL0pj98UfW9H+oYFqwT 
KXzq4lptzgfQIg== 
-----END PRIVATE KEY----- 

Với tương ứng khóa công khai:

-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNhpKqFY9ZefTEISP2bMIHZzRt 
6OV0psnhoDXZk4EEOnFgiXLHAkund/p1hZd13u0scysaO6RzB03iVBk2aS81u35O 
WPyEliK9kLLMKZvCVFTgFEFVP6sGWD69AAgg0Cxi2lQcihYLyp3+aaZHa6DOtwBW 
pJ+WJQj/ljOAErmcrwIDAQAB 
-----END PUBLIC KEY----- 
Các vấn đề liên quan