Können Sie mir helfen, meinen Kopf um openssl public key-Verschlüsselung mit rsa.h in c++?
Ich versuche, meinen Kopf um public-key-Verschlüsselung die openssl-Implementierung von rsa in C++. Können Sie mir helfen? So weit sind meine Gedanken (bitte ggf. korrigieren)
- Alice ist verbunden mit Bob über ein Netzwerk
- Alice und Bob wollen eine sichere Kommunikation
- Alice generiert ein öffentliches /privates Schlüsselpaar und sendet den öffentlichen Schlüssel an Bob
- Bob erhält öffentlichen Schlüssel und verschlüsselt einen zufällig generierten symmetrischen cypher key (z.B. mit blowfish) mit dem öffentlichen Schlüssel und sendet das Ergebnis an Alice
- Alice entschlüsselt den Geheimtext mit der ursprünglich generierten privaten Schlüssel und erhält so den symmetrischen blowfish-Schlüssel
- Alice und Bob nun haben beide wissen der symmetrischen blowfish-key und kann das herstellen einer sicheren Kommunikationskanal
Nun, ich habe mir bei der openssl/rsa.h rsa implementation (da ich bereits über praktische Erfahrung mit openssl/blowfish.h), und ich sehe diese zwei Funktionen:
int RSA_public_encrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int RSA_private_decrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
Wenn Alice zu generieren *rsa, wie funktioniert diese Ausbeute den rsa-Schlüssel-paar? Gibt es so etwas wie rsa_public und rsa_private, die abgeleitet sind von rsa? *Rsa enthalten sowohl öffentliche als auch private Schlüssel und die oben genannten Funktion automatisch Streifen, die notwendigen Schlüssel, je nachdem, ob es Bedarf der öffentlichen oder privaten Teil? Sollten zwei einzigartige *rsa-Zeiger erzeugt werden, so dass tatsächlich haben wir die folgenden:
int RSA_public_encrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa_public, int padding);
int RSA_private_decrypt(int flen, unsigned char *from,
unsigned char *to, RSA *rsa_private, int padding);
Zweitens, in welchem format sollte die *rsa-public-key gesendet werden, Bob? Muss es sein, neu interpretiert, in ein Zeichen-array und dann an den standard-Weg? Ich habe gehört, etwas über Zertifikate -- sind Sie etwas zu tun mit es?
Sorry für all die Fragen,
Die Besten Wünsche,
Ben.
EDIT: Coe bin ich derzeit beschäftigt:
/*
* theEncryptor.cpp
*
*
* Created by ben on 14/01/2010.
* Copyright 2010 __MyCompanyName__. All rights reserved.
*
*/
#include "theEncryptor.h"
#include <iostream>
#include <sys/socket.h>
#include <sstream>
theEncryptor::theEncryptor()
{
}
void
theEncryptor::blowfish(unsigned char *data, int data_len, unsigned char* key, int enc)
{
// hash the key first!
unsigned char obuf[20];
bzero(obuf,20);
SHA1((const unsigned char*)key, 64, obuf);
BF_KEY bfkey;
int keySize = 16;//strlen((char*)key);
BF_set_key(&bfkey, keySize, obuf);
unsigned char ivec[16];
memset(ivec, 0, 16);
unsigned char* out=(unsigned char*) malloc(data_len);
bzero(out,data_len);
int num = 0;
BF_cfb64_encrypt(data, out, data_len, &bfkey, ivec, &num, enc);
//for(int i = 0;i<data_len;i++)data[i]=out[i];
memcpy(data, out, data_len);
free(out);
}
void
theEncryptor::generateRSAKeyPair(int bits)
{
rsa = RSA_generate_key(bits, 65537, NULL, NULL);
}
int
theEncryptor::publicEncrypt(unsigned char* data, unsigned char* dataEncrypted,int dataLen)
{
return RSA_public_encrypt(dataLen, data, dataEncrypted, rsa, RSA_PKCS1_OAEP_PADDING);
}
int
theEncryptor::privateDecrypt(unsigned char* dataEncrypted,
unsigned char* dataDecrypted)
{
return RSA_private_decrypt(RSA_size(rsa), dataEncrypted,
dataDecrypted, rsa, RSA_PKCS1_OAEP_PADDING);
}
void
theEncryptor::receivePublicKeyAndSetRSA(int sock, int bits)
{
int max_hex_size = (bits / 4) + 1;
char keybufA[max_hex_size];
bzero(keybufA,max_hex_size);
char keybufB[max_hex_size];
bzero(keybufB,max_hex_size);
int n = recv(sock,keybufA,max_hex_size,0);
n = send(sock,"OK",2,0);
n = recv(sock,keybufB,max_hex_size,0);
n = send(sock,"OK",2,0);
rsa = RSA_new();
BN_hex2bn(&rsa->n, keybufA);
BN_hex2bn(&rsa->e, keybufB);
}
void
theEncryptor::transmitPublicKey(int sock, int bits)
{
const int max_hex_size = (bits / 4) + 1;
long size = max_hex_size;
char keyBufferA[size];
char keyBufferB[size];
bzero(keyBufferA,size);
bzero(keyBufferB,size);
sprintf(keyBufferA,"%s\r\n",BN_bn2hex(rsa->n));
sprintf(keyBufferB,"%s\r\n",BN_bn2hex(rsa->e));
int n = send(sock,keyBufferA,size,0);
char recBuf[2];
n = recv(sock,recBuf,2,0);
n = send(sock,keyBufferB,size,0);
n = recv(sock,recBuf,2,0);
}
void
theEncryptor::generateRandomBlowfishKey(unsigned char* key, int bytes)
{
/*
srand( (unsigned)time( NULL ) );
std::ostringstream stm;
for(int i = 0;i<bytes;i++){
int randomValue = 65 + rand()% 26;
stm << (char)((int)randomValue);
}
std::string str(stm.str());
const char* strs = str.c_str();
for(int i = 0;bytes;i++)key[i]=strs[i];
*/
int n = RAND_bytes(key, bytes);
if(n==0)std::cout<<"Warning key was generated with bad entropy. You should not consider communication to be secure"<<std::endl;
}
theEncryptor::~theEncryptor(){}
Gott, du hast absolut Recht. Danke herzlich für den Hinweis es aus 🙂
Ich aktualisiert meine Antwort zeigt, wie Sie mithilfe der
EVP_Seal*()
Funktionen - Sie sind ziemlich gut, sobald Sie ein funktionierendes Beispiel zu sehen, es ist die Dokumentation, dass etwas fehlt.InformationsquelleAutor Ben J | 2010-01-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollten Sie tatsächlich mit dem höheren "Envelope Encryption" - Funktionen von
openssl/evp.h
eher als die low-level-RSA-Funktionen direkt. Diese machen den Großteil der Arbeit für Sie und meinen Sie nicht das Rad neu zu erfinden.In diesem Fall, die Sie verwenden würden, die
EVP_SealInit()
,EVP_SealUpdate()
undEVP_SealFinal()
Funktionen. Die Entschlüsselung Funktionen sindEVP_OpenInit()
,EVP_OpenUpdate()
undEVP_OpenFinal()
. Ich würde vorschlagen, mitEVP_aes_128_cbc()
als der Wert der Ziffer-type-parameter.Sobald der öffentliche Schlüssel geladen in ein
RSA *
Griff, Sie verwendenEVP_PKEY_assign_RSA()
steckte es in eineEVP_PKEY *
Griff für die GD-Funktionen.Sobald Sie haben das vor sich geht, zu lösen die Authentifizierung problem, das ich bereits in meinem Kommentar, müssen Sie etabliert eine Vertrauenswürdige Autorität ("Trient"). Trents öffentlichen Schlüssel bekannt ist auf alle Nutzer verteilt, die mit der Anwendung oder ähnliches - nur laden Sie es aus einer PEM-Datei). Statt Austausch bare RSA-Parameter, die Alice und Bob austauschen x509-Zertifikate, die Ihre RSA-public-keys zusammen mit Ihrem Namen und signiert von Trent. Alice und Bob dann überprüfen Sie das Zertifikat Sie erhalten von den anderen (mit Trents öffentlichen Schlüssel, die Sie bereits kennen), einschließlich der Prüfung, dass die damit verbundenen Namen der richtige ist, bevor Sie fortfahren das Protokoll. OpenSSL beinhaltet Funktionen zum laden und überprüfen der Zertifikate in der
x509.h
header.Hier ist ein Beispiel, wie
EVP_Seal*()
um eine Datei zu verschlüsseln gegeben, dem öffentlichen Schlüssel des Empfängers. Es nimmt die PEM RSA-Public-Key-Datei (ie erwirtschaftetopenssl rsa -pubout
) als Befehlszeile argument, liest die Quelldaten von stdin und schreibt die verschlüsselten Daten auf stdout. Zum entschlüsseln verwenden SieEVP_Open*()
statt, undPEM_read_RSAPrivateKey()
zu Lesen, einen privaten Schlüssel und nicht als öffentlichen Schlüssel.Es ist nicht wirklich schwer und sicherlich weniger fehleranfällig als Unordnung zu erzeugen Polsterung, IVs und so auf sich selbst (das Siegel-Funktion funktioniert sowohl für die RSA-und AES-Teile der deal). Trotzdem, der code:
Den code, den Sie gepostet haben zeigt schön, warum sollte man den höher-level-Funktionen - Sie verliebt habe in ein paar Fallstricke:
rand()
ist mit Nachdruck nicht einen kryptographisch starken Zufallszahlengenerator! Erstellung Ihrer symmetrischen Schlüssel mitrand()
ist genug, um das ganze system völlig unsicher. (DieEVP_*()
Funktionen erzeugen die erforderlichen Zufallszahlen selbst, mit einem kryptografisch starken RNG, ausgesät aus einer entsprechenden Entropie-Quelle).Werden Sie durch die IV für CFB-Modus auf einen festen Wert (null). Dies negiert jeden Vorteil bei der Verwendung von CFB-Modus in den ersten Platz (sodass Angreifer trivial durchzuführen, block-Ersatz-Angriffe und schlechter). (Die
EVP_*()
Funktionen erzeugen einen entsprechenden IV für Sie, wenn es nötig ist).RSA_PKCS1_OAEP_PADDING
sollte verwendet werden, wenn Sie die Definition eines neuen Protokolls, sondern als Interaktion mit einem bestehenden Protokoll.Den entsprechenden Entschlüsselungs-code für die Nachwelt:
Mit Bezug auf die Zertifikat-Sache, das macht sicherlich Sinn. Gestern habe ich gelesen, dass bei der ursprünglichen Regelung, die ich oben beschrieben, Alice anmelden sollten Ihren öffentlichen Schlüssel kann dann überprüft werden, die von Bob für die Authentizität, kam ich auch zu verstehen, dass dies nicht oversome die Sicherheitsanfälligkeit, die du oben erwähnt, ich glaube, das ist der Grund, warum es notwendig zu veröffentlichen, die öffentlichen Schlüssel und speichern Sie es als ein Zertifikat einer vertrauenswürdigen Zertifizierungsstelle
Danke für deinen code caf -- aber dann wieder, ich denke immer noch, die leichter zu umgehen, die GD-Funktionen und call-Sachen direkt....aber dann habe ich ein prob müssen nur lernen, Sie zu benutzen...ich habe bearbeitet Sie meine original post mit einer Klasse kapselt die Art und Weise, in der ich mit Sachen...Cheers.
Wenn Sie denken, es ist einfacher, an die low-level-Funktionen direkt, das ist ein guter Indikator, dass Sie etwas falsch machen. Es ist sehr einfach zu bauen, etwas, das aussieht wie es funktioniert, ist aber eigentlich unsicher - sogar trivial unsicher. Siehe mein neuestes update.
Done (sorry für die Verzögerung 😉
InformationsquelleAutor
Eigentlich kein problem, ich habe gerade gelesen, dass im Grunde, das RSA-Objekt ist eine Struktur, die enthält sowohl die öffentlichen als auch privaten Bereichen. Kann man extrahieren des öffentlichen Feld-Daten und sendet das an Bob.
I. e. im Grunde, zum extrahieren des öffentlichen Felder aus rsa und speichert jedes in zwei verschiedenen Puffern (die sind char-arrays und kann anschließend an Bob), Sie:
Und dann Bob, auf der Empfängerseite rekonstruiert wie folgt:
Bob können dann mit rsa* öffentlich verschlüsseln des symmetrischen cypher-Taste, die dann gesendet werden, zu Alice. Alice kann dann entschlüsseln mit dem privaten Schlüssel
Ben.
InformationsquelleAutor
Schreibe ich zwei Beispiele um CAF-code. Sie sind stark modifiziert und verwendet OpenSSL ist
BIO
container für mehr Abstraktion.Einem Beispiel verwendet eine Datei als Eingabe und das andere Beispiel verwendet einen string-Puffer. Es nutzt
RSA
undDES
jedoch können Sie leicht ändern Sie es aus dem code. Kompilieren der Anweisungen im code. Ich brauchte ein Beispiel, ich hoffe, jemand findet das nützlich. Ich bemerkte auch den code. Sie können es von hier:Nehmen Datei als input:
https://github.com/farslan/snippets/blob/master/hybrid_file.c
Nehmen string-Puffer als input:
https://github.com/farslan/snippets/blob/master/hybrid_data.c
InformationsquelleAutor
Dank @Caf. Dein Beitrag geholfen hat. Allerdings habe ich
Das Programm "[7056] Encryption2.exe: Muttersprache' has exited with code -1073741811 (0xc000000d) für die Linie
Änderte ich
Wo Daten hat die PEM-Datei mit nur den öffentlichen Schlüssel. Meine Herausforderung war, zu verschlüsseln, in C++ und entschlüsseln in java. Ich übermittelte die base64-codierte ek Größe eklen (ich habe nicht mit eklen_n) und entschlüsselt, um den AES-Schlüssel mit dem privaten RSA-Schlüssel. Dann habe ich entschlüsselt die Chiffre-Datei mit dieser AES-Schlüssel. Es hat gut funktioniert.
InformationsquelleAutor