//rsa.cpp #include "rsa.h" #include #include void euclideEtendu (mpz_t c, mpz_t m, mpz_t* u, mpz_t* v) { mpz_t a, b, q, r, s, t, tmp, tmp2; mpz_init(a); mpz_init(b); mpz_init(q); mpz_init(r); mpz_init(s); mpz_init(t); mpz_init(tmp); mpz_init(tmp2); mpz_set(a, c); mpz_set(b, m); mpz_set_str(*u, "1", 10); mpz_set_str(*v, "0", 10); mpz_set_str(s, "0", 10); mpz_set_str(t, "1", 10); while(mpz_cmp_ui(b, 0) > 0) { mpz_fdiv_q(q, a, b); mpz_mod (r, a, b); mpz_set(a, b); mpz_set(b, r); mpz_set(tmp, s); mpz_mul(tmp2, q, s); mpz_sub(s, *u, tmp2); mpz_set(*u, tmp); mpz_set(tmp, t); mpz_mul(tmp2, q, t); mpz_sub(t, *v, tmp2); mpz_set(*v, tmp); } //return a; } Rsa::Rsa() { this->state = new gmp_randstate_t; static bool aleatoireInitialise = false; if (false == aleatoireInitialise) { // Initialisation de rand gmp_randinit_default(*(gmp_randstate_t*)this->state); gmp_randseed_ui(*(gmp_randstate_t*)this->state, time(0)); aleatoireInitialise = true; } c = new mpz_t; n = new mpz_t; u = new mpz_t; mpz_init(*(mpz_t*)c); mpz_init(*(mpz_t*)n); mpz_init(*(mpz_t*)u); } void Rsa::genererCles(unsigned int tailleCle) { // Creation d'un nombre P fort probablement premier mpz_t p; mpz_init(p); do { mpz_urandomb (p, *(gmp_randstate_t*)this->state, tailleCle / 2); } while(mpz_probab_prime_p(p, 10) < 1); // Creation d'un nombre Q fort probablement premier mpz_t q; mpz_init(q); do { mpz_urandomb (q, *(gmp_randstate_t*)this->state, tailleCle / 2); } while(mpz_probab_prime_p(q, 10) < 1); // Creation du nombre n = p x q mpz_mul(*(mpz_t*)n, p, q); // Creation du nombre M = (P-1)x(Q-1) mpz_t pMoinsUn; mpz_init(pMoinsUn); mpz_sub_ui(pMoinsUn, p, 1); // P-1 mpz_t qMoinsUn; mpz_init(qMoinsUn); mpz_sub_ui(qMoinsUn, q, 1); // Q-1 mpz_t m; mpz_init(m); mpz_mul(m, pMoinsUn, qMoinsUn); // M = (P-1)x(Q-1) mpz_clear(pMoinsUn); // Liberation des variables provisoirs mpz_clear(qMoinsUn); // Creation du nombre C premier avec M mpz_t pgcd; mpz_init(pgcd); do { mpz_urandomb (*(mpz_t*)c, *(gmp_randstate_t*)state, tailleCle / 2); //! Essayer sans la division par deux mpz_gcd(pgcd, m, *(mpz_t*)c); } while (mpz_cmp_ui(pgcd, 1) != 0); mpz_clear(pgcd); // Determination de U mpz_t v; mpz_init(v); euclideEtendu (*(mpz_t*)c, m, (mpz_t*)u, &v); // Recherche d'une valeur de U acceptable mpz_t uZero; mpz_init(uZero); mpz_set(uZero, *(mpz_t*)u); mpz_t k; mpz_init(k); mpz_set_str(k, "0", 10); mpz_t uFinal; mpz_init(uFinal); while(mpz_cmp_ui(uFinal, 2) < 0) { mpz_sub_ui(k, k, 1); mpz_t kFoisM; mpz_init(kFoisM); mpz_mul(kFoisM, k, m); mpz_sub(uFinal, uZero, kFoisM); mpz_clear(kFoisM); } mpz_set(*(mpz_t*)u, uFinal); mpz_clear(uFinal); // Liberation des variables temporaires mpz_clear(uZero); mpz_clear(k); // Liberation des nombres GMP mpz_clear(p); mpz_clear(q); mpz_clear(m); } Rsa::~Rsa() { mpz_clear(*(mpz_t*)c); mpz_clear(*(mpz_t*)n); mpz_clear(*(mpz_t*)u); delete (mpz_t*)c; delete (mpz_t*)n; delete (mpz_t*)u; } /*void Rsa::euclideEtendu (mpz_t c, mpz_t m, mpz_t* u, mpz_t* v) { mpz_t a, b, q, r, s, t, tmp, tmp2; mpz_init(a); mpz_init(b); mpz_init(q); mpz_init(r); mpz_init(s); mpz_init(t); mpz_init(tmp); mpz_init(tmp2); mpz_set(a, c); mpz_set(b, m); mpz_set_str(*u, "1", 10); mpz_set_str(*v, "0", 10); mpz_set_str(s, "0", 10); mpz_set_str(t, "1", 10); while(mpz_cmp_ui(b, 0) > 0) { mpz_fdiv_q(q, a, b); mpz_mod (r, a, b); mpz_set(a, b); mpz_set(b, r); mpz_set(tmp, s); mpz_mul(tmp2, q, s); mpz_sub(s, *u, tmp2); mpz_set(*u, tmp); mpz_set(tmp, t); mpz_mul(tmp2, q, t); mpz_sub(t, *v, tmp2); mpz_set(*v, tmp); } //return a; }*/ std::string Rsa::clePrivee() { // Lecture de N dans bufferChaine (base 16) unsigned int taille = mpz_sizeinbase(*(mpz_t*)n, 16); char* bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, *(mpz_t*)n); std::string chaineFinale(bufferChaine); free(bufferChaine); chaineFinale += "-"; // Lecture de C dans bufferChaine (base 16) taille = mpz_sizeinbase(*(mpz_t*)u, 16); bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, *(mpz_t*)u); chaineFinale += bufferChaine; free(bufferChaine); return chaineFinale; } std::string Rsa::clePublique() { // Lecture de N dans bufferChaine (base 16) unsigned int taille = mpz_sizeinbase(*(mpz_t*)n, 16); char* bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, *(mpz_t*)n); std::string chaineFinale(bufferChaine); free(bufferChaine); chaineFinale += "-"; // Lecture de C dans bufferChaine (base 16) taille = mpz_sizeinbase(*(mpz_t*)c, 16); bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, *(mpz_t*)c); chaineFinale += bufferChaine; free(bufferChaine); return chaineFinale; } void Rsa::clePrivee(std::string cle) { // Reconstruction de N mpz_clear(*(mpz_t*)n); mpz_init(*(mpz_t*)n); mpz_set_str(*(mpz_t*)n, cle.substr(0, cle.find_first_of("-")).c_str(), 16); // Reconstruction de U mpz_clear(*(mpz_t*)u); mpz_init(*(mpz_t*)u); mpz_set_str(*(mpz_t*)u, cle.substr(cle.find_first_of("-") + 1, cle.size()).c_str(), 16); } void Rsa::clePublique(std::string cle) { // Reconstruction de N mpz_clear(*(mpz_t*)n); mpz_init(*(mpz_t*)n); mpz_set_str(*(mpz_t*)n, cle.substr(0, cle.find_first_of("-")).c_str(), 16); // Reconstruction de C mpz_clear(*(mpz_t*)c); mpz_init(*(mpz_t*)c); mpz_set_str(*(mpz_t*)c, cle.substr(cle.find_first_of("-") + 1, cle.size()).c_str(), 16); } std::string Rsa::coderMessage(std::string message) { std::string messageCode; for(unsigned int i = 0; i < message.size()*2; i++) { if (1 == i % 2) { unsigned char nb = (unsigned char)message[i/2] & 0x0F; nb += (nb <= 9) ? '0' : 'a' - 10; messageCode += nb; } else { unsigned char nb = (unsigned char)message[i/2] >> 4; nb += (nb <= 9) ? '0' : 'a' - 10; messageCode += nb; } } return messageCode; } std::string Rsa::decoderMessage(std::string messageCode) { std::string messageDecode; for(unsigned int i = 0; i < messageCode.size() / 2; i++) { unsigned char n1 = messageCode[i*2]; unsigned char n2 = messageCode[(i*2)+1]; if (n1 <= '9') { n1 -= '0'; } else { n1 -= 'a'; n1 += 10; } if (n2 <= '9') { n2 -= '0'; } else { n2 -= 'a'; n2 += 10; } messageDecode += (n1 << 4) + n2; } return messageDecode; } std::string Rsa::chiffrerAvecClePrivee(std::string message) { message = message.substr(0, this->tailleMaxChiffrable()); // Adaptation du message std::string messageCode = this->coderMessage(message); mpz_t messageAChiffrer; mpz_init(messageAChiffrer); mpz_set_str(messageAChiffrer, messageCode.c_str(), 16); // Chiffrage avec la cle privee mpz_t messageChiffre; mpz_init(messageChiffre); mpz_powm(messageChiffre, messageAChiffrer, *(mpz_t*)u,*(mpz_t*)n); // Construction du message chiffre (base 16) unsigned int taille = mpz_sizeinbase(messageChiffre, 16); char* bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, messageChiffre); std::string chaineFinale = bufferChaine; free(bufferChaine); return chaineFinale; } std::string Rsa::dechiffrerAvecClePrivee(std::string messageChiffre) { mpz_t messageChiffreNombre; mpz_init(messageChiffreNombre); mpz_set_str(messageChiffreNombre, messageChiffre.c_str(), 16); mpz_t messageDechiffre; mpz_init(messageDechiffre); mpz_powm(messageDechiffre, messageChiffreNombre, *(mpz_t*)u,*(mpz_t*)n); // Construction du message dechiffre (base 16) unsigned int taille = mpz_sizeinbase(messageDechiffre, 16); char* bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, messageDechiffre); std::string chaineFinale = bufferChaine; free(bufferChaine); return this->decoderMessage(chaineFinale); } std::string Rsa::chiffrerAvecClePublique(std::string message) { message = message.substr(0, this->tailleMaxChiffrable()); // Adaptation du message std::string messageCode = this->coderMessage(message); mpz_t messageAChiffrer; mpz_init(messageAChiffrer); mpz_set_str(messageAChiffrer, messageCode.c_str(), 16); // Chiffrage avec la cle privee mpz_t messageChiffre; mpz_init(messageChiffre); mpz_powm(messageChiffre, messageAChiffrer, *(mpz_t*)c,*(mpz_t*)n); // Construction du message chiffre (base 16) unsigned int taille = mpz_sizeinbase(messageChiffre, 16); char* bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, messageChiffre); std::string chaineFinale = bufferChaine; free(bufferChaine); return chaineFinale; } std::string Rsa::dechiffrerAvecClePublique(std::string messageChiffre) { mpz_t messageChiffreNombre; mpz_init(messageChiffreNombre); mpz_set_str(messageChiffreNombre, messageChiffre.c_str(), 16); mpz_t messageDechiffre; mpz_init(messageDechiffre); mpz_powm(messageDechiffre, messageChiffreNombre, *(mpz_t*)c,*(mpz_t*)n); // Construction du message dechiffre (base 16) unsigned int taille = mpz_sizeinbase(messageDechiffre, 16); char* bufferChaine = (char*)malloc (taille + 1); mpz_get_str(bufferChaine, 16, messageDechiffre); std::string chaineFinale = bufferChaine; free(bufferChaine); return this->decoderMessage(chaineFinale); } unsigned int Rsa::tailleMaxChiffrable() { return mpz_sizeinbase(*(mpz_t*)n, 2) / 8; } // rsa.h #ifndef RSA_H_INCLUDED #define RSA_H_INCLUDED #include class Rsa { public: Rsa(); ~Rsa(); void genererCles(unsigned int tailleCle); std::string clePrivee(); void clePrivee(std::string cle); std::string clePublique(); void clePublique(std::string cle); std::string chiffrerAvecClePrivee(std::string message); std::string dechiffrerAvecClePrivee(std::string message); std::string chiffrerAvecClePublique(std::string message); std::string dechiffrerAvecClePublique(std::string message); unsigned int tailleMaxChiffrable(); private: /*mpz_t c, n, u; gmp_randstate_t state;*/ void* c; void* n; void* u; void* state; //void euclideEtendu (mpz_t c, mpz_t m, mpz_t* u, mpz_t* v); std::string coderMessage(std::string message); std::string decoderMessage(std::string message); }; #endif // RSA_H_INCLUDED // mine.cpp my app #include #include using namespace std; int main() { Rsa rsa; // Generation d'une paire de cles rsa.genererCles(1024); // Recuperation de chacune des cles string clePrivee = rsa.clePrivee(); string clePublique = rsa.clePublique(); // Creation du message secret string messageSecret = "Je t'aime Alice"; // Cryptage du message string messageCrypte; messageCrypte = rsa.chiffrerAvecClePublique(messageSecret); // Affichage du message crypte cout << "Message crypte : " << endl; cout << messageCrypte << ; // Decryptage du message string messageDecrypte; messageDecrypte = rsa.dechiffrerAvecClePrivee(messageCrypte); // Affichage du message decrypte cout << "Message decrypte : " << endl; cout << messageDecrypte << endl; return 0; }