๋ฌธ์
๊ณต๊ฐํค ์๊ณ ๋ฆฌ์ฆ ์ค Rivest, Shamir, Adleman์ ์ํด ์ค๊ณ๋ RSA ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ๋ผ
๋ก์ง
- 2๊ฐ์ ์์ (p, q)๊ฐ ํ์ํ๋ค
- n = p * q
- ฯ(n) = (p-1) * (q-1)
- e = e์ ฯ(n)์ ์๋ก์
- d = e*d mod ฯ(n) = 1
- c = m^e mod n
- m = c^d mod n
์ฃผ์ ์ฌํญ
- ์ํธํํ๋ ํ๋ฌธ์ n์ ์๋ฆฟ์๋ณด๋ค ์์ ์๋ฆฟ์๋ฅผ ๊ฐ์ ธ์ผํ๋ค.
a. ํ๋ฌธ์ด '123456789'์ด๊ณ , n์ด '1234'์ด๋ฉด ํ๋ฌธ์ '123', '456', 789'๋ก ๋๋ ์ ์ํธํํด์ผํ๋ค.
- p์ q๋ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํด์ผ ํ๋ค.
a. p์ q๋ ๊ฐ์ง ์๊ณ ๊ฑฐ์ ๊ฐ์ ํฌ๊ธฐ์ ์๋ฆฟ์์ผ์ผ ํ๋ค.
b. p-1๊ณผ q-1์ ์ปค๋ค๋ ์์ธ์๋ฅผ ๊ฐ๊ฐ ๊ฐ์ ธ์ผ ํ๋ค.
c. p-1๊ณผ q-1์ ์ต๋ ๊ณต์ฝ์๋ ์์ ์์ฌ์ผ ํ๋ค
๊ตฌํํ์ง ์์์ง๋ง, TMI
- ์ค์ RSA์์ ์ฌ์ฉํ๋ p์ q๋ 100์๋ฆฌ ์ ๋์ ์์๋ก ๊ฑฐ์ ๊ฐ์ ํฌ๊ธฐ์ ์๋ฆฟ์๋ฅผ ๊ฐ์ง๋ ์๋ฅผ ์ ํํ๋ค.
์ฝ๋
rsa.h
#ifndef _RSA
#define _RSA
typedef struct key
{
long pkey; // ์ด๊ธฐ 2๊ฐ์ ์์ p์ q๊ฐ ๊ณฑํด์ ๋์ค๋ n์ด ์ ์ฅ๋ ๋ณ์
long ekey; // public-key
long dkey; // private-key
int pkey_size;
} Key;
class Rsa
{
public:
Rsa();
virtual ~Rsa();
public:
Key produce_keys();
long endecrypt(const long msg, const long key, const long pkey);
int sizeof_int(long data);
private:
long produce_pkey(const long prime1, const long prime2);
long produce_ekey(const long orla);
long produce_dkey(const long ekey, const long orla);
long produce_prime();
long produce_orla(const long prime1, const long prime2);
long produce_gcd(const long a, const long b);
bool is_prime(const long digit);
};
#endif
main.cpp
#include "rsa.h"
#include <iostream>
using namespace std;
int main(void)
{
Rsa rsa;
Key key = rsa.produce_keys();
cout << "=============================" << endl;
cout << "=========== R S A ===========" << endl;
cout << "=============================\n" << endl;
cout << "=====================================" << endl;
cout << "์ํธํ ํ ์ป์ ํค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค."<< endl;
cout << "n ํค : " << key.pkey << endl;
cout << "์ํธํ ํค (๊ณต๊ฐํค) : " << key.ekey << endl;
cout << "์ํธ ํด๋
ํค (๊ฐ์ธํค) : " << key.dkey << endl;
cout << "=====================================\n" << endl;
long msg;
cout << "์ํธํํ ์ ๋ณด๋ฅผ ์
๋ ฅํ์ญ์์ค (์ซ์, ๋๋ฌด ํด ์ ์์) : ";
cin >> msg;
cout << "\n=====================================" << endl;
long msg_des = rsa.endecrypt(msg, key.ekey, key.pkey);
cout << "์ํธํ๋ ์ ๋ณด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
msg_des = rsa.endecrypt(msg_des, key.dkey, key.pkey);
cout << "์ํธ ํด๋
๋ ๋ฉ์์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
cout << "=====================================" << endl;
return 0;
}
rsa.cpp
#include "rsa.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
Rsa::Rsa()
{
}
Rsa::~Rsa()
{
}
/***********************************************************************
์ํธํ ๋ณตํธํ๋ฅผ ๋์์ ์งํํ๋ ๋ฉ์๋
c = m^e mod n
m = c^d mod n
๋ผ๋ ์์ ๊ฐ๊ณ ๋ณ์๋ง ๋งค๊ฐ๊ฐ๋ง ๋ฐ๋๋ฉด ๋๋ฏ๋ก ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํจ
***********************************************************************/
long Rsa::endecrypt(const long msg, const long key, const long pkey)
{
long msg_des = 1;
long root = msg;
long index = key;
//int n_size = sizeof_int(pkey);
//int msg_size = sizeof_int(msg);
//int size = msg_size / n_size;
//if (msg_size % n_size)
// size = size + 1;
while (index)
{
//cout << bitset<32>(index) << endl;
if (index & 1) {
msg_des = (msg_des * root) % pkey;
//cout << "msg_des : " << msg_des << endl;
}
index >>= 1;
//cout << "b root : " << root << endl;
root = (root * root) % pkey;
//cout << "a root : " << root << endl;
}
return msg_des;
}
/************************************
p์ q๋ฅผ ์์ฑํด์
n, e, d ํค๋ฅผ ์์ฑ
* *********************************/
Key Rsa::produce_keys()
{
long prime1 = produce_prime(); // p
long prime2 = produce_prime(); // q
while (prime2 == prime1) // p์ q๋ n์ ๋ง๋ค๊ณ ํ๊ธฐํด์ผ ํ๊ธฐ ๋๋ฌธ์
prime2 = produce_prime(); // ๋ฐ๋ก ์ ์ฅํด์ ๋ฉ์๋ ๋ฐ์ผ๋ก ๋นผ์ง ์์
Key key;
long orla = produce_orla(prime1, prime2); // ์ค์ผ๋ฌ n ์์ฑ
key.pkey = produce_pkey(prime1, prime2); // n ์์ฑ
key.ekey = produce_ekey(orla); // e ์์ฑ
key.dkey = produce_dkey(key.ekey, orla); // d ์์ฑ
return key;
}
/************************************
N ํค ์์ฑ
p * q
* *********************************/
long Rsa::produce_pkey(const long prime1, const long prime2)
{
return prime1 * prime2;
}
/************************************
์ค์ผ๋ฌ n ์์ฑ
************************************/
long Rsa::produce_orla(const long prime1, const long prime2)
{
return (prime1 - 1) * (prime2 - 1);
}
/************************************
์ํธํ ํค (๊ณต๊ฐํค) e ์์ฑ
* *********************************/
long Rsa::produce_ekey(const long orla)
{
long ekey;
while (true)
{
ekey = rand() % orla; // ๋๋ค ์๋ฅผ ์ค์ผ๋ฌ n์ผ๋ก ๋๋จธ์ง ์ฐ์ฐ
if (ekey >= 2 && produce_gcd(ekey, orla) == 1) // e-key์ ์ค์ผ๋ฌ n์ด ์๋ก์์ธ์ง ํ๋ณ
break;
}
return ekey;
}
/************************************
๋ณตํธํ ํค (๊ฐ์ธํค) d ์์ฑ
* *********************************/
long Rsa::produce_dkey(const long ekey, const long orla)
{
long dkey = orla / ekey;
while (true)
{
if (((dkey * ekey) % orla) == 1)
break;
else
++dkey;
}
return dkey;
}
/************************************
[100, 200] ๋ฒ์์์ ์์์ ์์ ์์ฑ
* *********************************/
long Rsa::produce_prime()
{
long prime = 0;
srand(time(0));
while (true)
{
prime = rand() % 100 + 100;
if (is_prime(prime))
break;
}
return prime;
}
/************************************
๋ ์ซ์์ ์ต๋ ๊ณต์ฝ์ ์์ฑ
* *********************************/
long Rsa::produce_gcd(const long a, const long b)
{
long dividend = a;
long divisor = b;
long residual = dividend % divisor;
while (residual)
{
dividend = divisor;
divisor = residual;
residual = dividend % divisor;
}
return divisor;
}
/************************************
์์์ธ์ง ํ๋จ
* *********************************/
bool Rsa::is_prime(const long digit)
{
int tmp = 2;
while (tmp < digit)
if (!(digit % tmp++))
break;
if (tmp == digit)
return true;
return false;
}
/************************************
์
๋ ฅ๊ฐ์ ์๋ฆฟ์ ํ๋จ
* *********************************/
int Rsa::sizeof_int(long data)
{
int pos = 1;
if (data < 0)
data *= (-1);
for (int i = 0; ; i++, pos++) {
if ((data /= 10) <= 0)
break;
}
return pos;
}
๊ฒฐ๊ณผ
- ์ํธํํ๋ ํ๋ฌธ์ n์ ์๋ฆฟ์๋ณด๋ค ์์ ์๋ฆฟ์๋ฅผ ๊ฐ์ ธ์ผํ๋ค. a. ํ๋ฌธ์ด '123456789'์ด๊ณ , n์ด '1234'์ด๋ฉด ํ๋ฌธ์ '123', '456', 789'๋ก ๋๋ ์ ์ํธํํด์ผํ๋ค.
- p์ q๋ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํด์ผ ํ๋ค. a. p์ q๋ ๊ฐ์ง ์๊ณ ๊ฑฐ์ ๊ฐ์ ํฌ๊ธฐ์ ์๋ฆฟ์์ผ์ผ ํ๋ค. b. p-1๊ณผ q-1์ ์ปค๋ค๋ ์์ธ์๋ฅผ ๊ฐ๊ฐ ๊ฐ์ ธ์ผ ํ๋ค. c. p-1๊ณผ q-1์ ์ต๋ ๊ณต์ฝ์๋ ์์ ์์ฌ์ผ ํ๋ค
๊ตฌํํ์ง ์์์ง๋ง, TMI
- ์ค์ RSA์์ ์ฌ์ฉํ๋ p์ q๋ 100์๋ฆฌ ์ ๋์ ์์๋ก ๊ฑฐ์ ๊ฐ์ ํฌ๊ธฐ์ ์๋ฆฟ์๋ฅผ ๊ฐ์ง๋ ์๋ฅผ ์ ํํ๋ค.
์ฝ๋
rsa.h
#ifndef _RSA
#define _RSA
typedef struct key
{
long pkey; // ์ด๊ธฐ 2๊ฐ์ ์์ p์ q๊ฐ ๊ณฑํด์ ๋์ค๋ n์ด ์ ์ฅ๋ ๋ณ์
long ekey; // public-key
long dkey; // private-key
int pkey_size;
} Key;
class Rsa
{
public:
Rsa();
virtual ~Rsa();
public:
Key produce_keys();
long endecrypt(const long msg, const long key, const long pkey);
int sizeof_int(long data);
private:
long produce_pkey(const long prime1, const long prime2);
long produce_ekey(const long orla);
long produce_dkey(const long ekey, const long orla);
long produce_prime();
long produce_orla(const long prime1, const long prime2);
long produce_gcd(const long a, const long b);
bool is_prime(const long digit);
};
#endif
main.cpp
#include "rsa.h"
#include <iostream>
using namespace std;
int main(void)
{
Rsa rsa;
Key key = rsa.produce_keys();
cout << "=============================" << endl;
cout << "=========== R S A ===========" << endl;
cout << "=============================\n" << endl;
cout << "=====================================" << endl;
cout << "์ํธํ ํ ์ป์ ํค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค."<< endl;
cout << "n ํค : " << key.pkey << endl;
cout << "์ํธํ ํค (๊ณต๊ฐํค) : " << key.ekey << endl;
cout << "์ํธ ํด๋
ํค (๊ฐ์ธํค) : " << key.dkey << endl;
cout << "=====================================\n" << endl;
long msg;
cout << "์ํธํํ ์ ๋ณด๋ฅผ ์
๋ ฅํ์ญ์์ค (์ซ์, ๋๋ฌด ํด ์ ์์) : ";
cin >> msg;
cout << "\n=====================================" << endl;
long msg_des = rsa.endecrypt(msg, key.ekey, key.pkey);
cout << "์ํธํ๋ ์ ๋ณด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
msg_des = rsa.endecrypt(msg_des, key.dkey, key.pkey);
cout << "์ํธ ํด๋
๋ ๋ฉ์์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
cout << "=====================================" << endl;
return 0;
}
rsa.cpp
#include "rsa.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
Rsa::Rsa()
{
}
Rsa::~Rsa()
{
}
/***********************************************************************
์ํธํ ๋ณตํธํ๋ฅผ ๋์์ ์งํํ๋ ๋ฉ์๋
c = m^e mod n
m = c^d mod n
๋ผ๋ ์์ ๊ฐ๊ณ ๋ณ์๋ง ๋งค๊ฐ๊ฐ๋ง ๋ฐ๋๋ฉด ๋๋ฏ๋ก ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํจ
***********************************************************************/
long Rsa::endecrypt(const long msg, const long key, const long pkey)
{
long msg_des = 1;
long root = msg;
long index = key;
//int n_size = sizeof_int(pkey);
//int msg_size = sizeof_int(msg);
//int size = msg_size / n_size;
//if (msg_size % n_size)
// size = size + 1;
while (index)
{
//cout << bitset<32>(index) << endl;
if (index & 1) {
msg_des = (msg_des * root) % pkey;
//cout << "msg_des : " << msg_des << endl;
}
index >>= 1;
//cout << "b root : " << root << endl;
root = (root * root) % pkey;
//cout << "a root : " << root << endl;
}
return msg_des;
}
/************************************
p์ q๋ฅผ ์์ฑํด์
n, e, d ํค๋ฅผ ์์ฑ
* *********************************/
Key Rsa::produce_keys()
{
long prime1 = produce_prime(); // p
long prime2 = produce_prime(); // q
while (prime2 == prime1) // p์ q๋ n์ ๋ง๋ค๊ณ ํ๊ธฐํด์ผ ํ๊ธฐ ๋๋ฌธ์
prime2 = produce_prime(); // ๋ฐ๋ก ์ ์ฅํด์ ๋ฉ์๋ ๋ฐ์ผ๋ก ๋นผ์ง ์์
Key key;
long orla = produce_orla(prime1, prime2); // ์ค์ผ๋ฌ n ์์ฑ
key.pkey = produce_pkey(prime1, prime2); // n ์์ฑ
key.ekey = produce_ekey(orla); // e ์์ฑ
key.dkey = produce_dkey(key.ekey, orla); // d ์์ฑ
return key;
}
/************************************
N ํค ์์ฑ
p * q
* *********************************/
long Rsa::produce_pkey(const long prime1, const long prime2)
{
return prime1 * prime2;
}
/************************************
์ค์ผ๋ฌ n ์์ฑ
************************************/
long Rsa::produce_orla(const long prime1, const long prime2)
{
return (prime1 - 1) * (prime2 - 1);
}
/************************************
์ํธํ ํค (๊ณต๊ฐํค) e ์์ฑ
* *********************************/
long Rsa::produce_ekey(const long orla)
{
long ekey;
while (true)
{
ekey = rand() % orla; // ๋๋ค ์๋ฅผ ์ค์ผ๋ฌ n์ผ๋ก ๋๋จธ์ง ์ฐ์ฐ
if (ekey >= 2 && produce_gcd(ekey, orla) == 1) // e-key์ ์ค์ผ๋ฌ n์ด ์๋ก์์ธ์ง ํ๋ณ
break;
}
return ekey;
}
/************************************
๋ณตํธํ ํค (๊ฐ์ธํค) d ์์ฑ
* *********************************/
long Rsa::produce_dkey(const long ekey, const long orla)
{
long dkey = orla / ekey;
while (true)
{
if (((dkey * ekey) % orla) == 1)
break;
else
++dkey;
}
return dkey;
}
/************************************
[100, 200] ๋ฒ์์์ ์์์ ์์ ์์ฑ
* *********************************/
long Rsa::produce_prime()
{
long prime = 0;
srand(time(0));
while (true)
{
prime = rand() % 100 + 100;
if (is_prime(prime))
break;
}
return prime;
}
/************************************
๋ ์ซ์์ ์ต๋ ๊ณต์ฝ์ ์์ฑ
* *********************************/
long Rsa::produce_gcd(const long a, const long b)
{
long dividend = a;
long divisor = b;
long residual = dividend % divisor;
while (residual)
{
dividend = divisor;
divisor = residual;
residual = dividend % divisor;
}
return divisor;
}
/************************************
์์์ธ์ง ํ๋จ
* *********************************/
bool Rsa::is_prime(const long digit)
{
int tmp = 2;
while (tmp < digit)
if (!(digit % tmp++))
break;
if (tmp == digit)
return true;
return false;
}
/************************************
์
๋ ฅ๊ฐ์ ์๋ฆฟ์ ํ๋จ
* *********************************/
int Rsa::sizeof_int(long data)
{
int pos = 1;
if (data < 0)
data *= (-1);
for (int i = 0; ; i++, pos++) {
if ((data /= 10) <= 0)
break;
}
return pos;
}
๊ฒฐ๊ณผ
rsa.h
#ifndef _RSA
#define _RSA
typedef struct key
{
long pkey; // ์ด๊ธฐ 2๊ฐ์ ์์ p์ q๊ฐ ๊ณฑํด์ ๋์ค๋ n์ด ์ ์ฅ๋ ๋ณ์
long ekey; // public-key
long dkey; // private-key
int pkey_size;
} Key;
class Rsa
{
public:
Rsa();
virtual ~Rsa();
public:
Key produce_keys();
long endecrypt(const long msg, const long key, const long pkey);
int sizeof_int(long data);
private:
long produce_pkey(const long prime1, const long prime2);
long produce_ekey(const long orla);
long produce_dkey(const long ekey, const long orla);
long produce_prime();
long produce_orla(const long prime1, const long prime2);
long produce_gcd(const long a, const long b);
bool is_prime(const long digit);
};
#endif
main.cpp
#include "rsa.h"
#include <iostream>
using namespace std;
int main(void)
{
Rsa rsa;
Key key = rsa.produce_keys();
cout << "=============================" << endl;
cout << "=========== R S A ===========" << endl;
cout << "=============================\n" << endl;
cout << "=====================================" << endl;
cout << "์ํธํ ํ ์ป์ ํค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค."<< endl;
cout << "n ํค : " << key.pkey << endl;
cout << "์ํธํ ํค (๊ณต๊ฐํค) : " << key.ekey << endl;
cout << "์ํธ ํด๋
ํค (๊ฐ์ธํค) : " << key.dkey << endl;
cout << "=====================================\n" << endl;
long msg;
cout << "์ํธํํ ์ ๋ณด๋ฅผ ์
๋ ฅํ์ญ์์ค (์ซ์, ๋๋ฌด ํด ์ ์์) : ";
cin >> msg;
cout << "\n=====================================" << endl;
long msg_des = rsa.endecrypt(msg, key.ekey, key.pkey);
cout << "์ํธํ๋ ์ ๋ณด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
msg_des = rsa.endecrypt(msg_des, key.dkey, key.pkey);
cout << "์ํธ ํด๋
๋ ๋ฉ์์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
cout << "=====================================" << endl;
return 0;
}
rsa.cpp
#include "rsa.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
Rsa::Rsa()
{
}
Rsa::~Rsa()
{
}
/***********************************************************************
์ํธํ ๋ณตํธํ๋ฅผ ๋์์ ์งํํ๋ ๋ฉ์๋
c = m^e mod n
m = c^d mod n
๋ผ๋ ์์ ๊ฐ๊ณ ๋ณ์๋ง ๋งค๊ฐ๊ฐ๋ง ๋ฐ๋๋ฉด ๋๋ฏ๋ก ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํจ
***********************************************************************/
long Rsa::endecrypt(const long msg, const long key, const long pkey)
{
long msg_des = 1;
long root = msg;
long index = key;
//int n_size = sizeof_int(pkey);
//int msg_size = sizeof_int(msg);
//int size = msg_size / n_size;
//if (msg_size % n_size)
// size = size + 1;
while (index)
{
//cout << bitset<32>(index) << endl;
if (index & 1) {
msg_des = (msg_des * root) % pkey;
//cout << "msg_des : " << msg_des << endl;
}
index >>= 1;
//cout << "b root : " << root << endl;
root = (root * root) % pkey;
//cout << "a root : " << root << endl;
}
return msg_des;
}
/************************************
p์ q๋ฅผ ์์ฑํด์
n, e, d ํค๋ฅผ ์์ฑ
* *********************************/
Key Rsa::produce_keys()
{
long prime1 = produce_prime(); // p
long prime2 = produce_prime(); // q
while (prime2 == prime1) // p์ q๋ n์ ๋ง๋ค๊ณ ํ๊ธฐํด์ผ ํ๊ธฐ ๋๋ฌธ์
prime2 = produce_prime(); // ๋ฐ๋ก ์ ์ฅํด์ ๋ฉ์๋ ๋ฐ์ผ๋ก ๋นผ์ง ์์
Key key;
long orla = produce_orla(prime1, prime2); // ์ค์ผ๋ฌ n ์์ฑ
key.pkey = produce_pkey(prime1, prime2); // n ์์ฑ
key.ekey = produce_ekey(orla); // e ์์ฑ
key.dkey = produce_dkey(key.ekey, orla); // d ์์ฑ
return key;
}
/************************************
N ํค ์์ฑ
p * q
* *********************************/
long Rsa::produce_pkey(const long prime1, const long prime2)
{
return prime1 * prime2;
}
/************************************
์ค์ผ๋ฌ n ์์ฑ
************************************/
long Rsa::produce_orla(const long prime1, const long prime2)
{
return (prime1 - 1) * (prime2 - 1);
}
/************************************
์ํธํ ํค (๊ณต๊ฐํค) e ์์ฑ
* *********************************/
long Rsa::produce_ekey(const long orla)
{
long ekey;
while (true)
{
ekey = rand() % orla; // ๋๋ค ์๋ฅผ ์ค์ผ๋ฌ n์ผ๋ก ๋๋จธ์ง ์ฐ์ฐ
if (ekey >= 2 && produce_gcd(ekey, orla) == 1) // e-key์ ์ค์ผ๋ฌ n์ด ์๋ก์์ธ์ง ํ๋ณ
break;
}
return ekey;
}
/************************************
๋ณตํธํ ํค (๊ฐ์ธํค) d ์์ฑ
* *********************************/
long Rsa::produce_dkey(const long ekey, const long orla)
{
long dkey = orla / ekey;
while (true)
{
if (((dkey * ekey) % orla) == 1)
break;
else
++dkey;
}
return dkey;
}
/************************************
[100, 200] ๋ฒ์์์ ์์์ ์์ ์์ฑ
* *********************************/
long Rsa::produce_prime()
{
long prime = 0;
srand(time(0));
while (true)
{
prime = rand() % 100 + 100;
if (is_prime(prime))
break;
}
return prime;
}
/************************************
๋ ์ซ์์ ์ต๋ ๊ณต์ฝ์ ์์ฑ
* *********************************/
long Rsa::produce_gcd(const long a, const long b)
{
long dividend = a;
long divisor = b;
long residual = dividend % divisor;
while (residual)
{
dividend = divisor;
divisor = residual;
residual = dividend % divisor;
}
return divisor;
}
/************************************
์์์ธ์ง ํ๋จ
* *********************************/
bool Rsa::is_prime(const long digit)
{
int tmp = 2;
while (tmp < digit)
if (!(digit % tmp++))
break;
if (tmp == digit)
return true;
return false;
}
/************************************
์
๋ ฅ๊ฐ์ ์๋ฆฟ์ ํ๋จ
* *********************************/
int Rsa::sizeof_int(long data)
{
int pos = 1;
if (data < 0)
data *= (-1);
for (int i = 0; ; i++, pos++) {
if ((data /= 10) <= 0)
break;
}
return pos;
}
๊ฒฐ๊ณผ
#ifndef _RSA
#define _RSA
typedef struct key
{
long pkey; // ์ด๊ธฐ 2๊ฐ์ ์์ p์ q๊ฐ ๊ณฑํด์ ๋์ค๋ n์ด ์ ์ฅ๋ ๋ณ์
long ekey; // public-key
long dkey; // private-key
int pkey_size;
} Key;
class Rsa
{
public:
Rsa();
virtual ~Rsa();
public:
Key produce_keys();
long endecrypt(const long msg, const long key, const long pkey);
int sizeof_int(long data);
private:
long produce_pkey(const long prime1, const long prime2);
long produce_ekey(const long orla);
long produce_dkey(const long ekey, const long orla);
long produce_prime();
long produce_orla(const long prime1, const long prime2);
long produce_gcd(const long a, const long b);
bool is_prime(const long digit);
};
#endif
#include "rsa.h"
#include <iostream>
using namespace std;
int main(void)
{
Rsa rsa;
Key key = rsa.produce_keys();
cout << "=============================" << endl;
cout << "=========== R S A ===========" << endl;
cout << "=============================\n" << endl;
cout << "=====================================" << endl;
cout << "์ํธํ ํ ์ป์ ํค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค."<< endl;
cout << "n ํค : " << key.pkey << endl;
cout << "์ํธํ ํค (๊ณต๊ฐํค) : " << key.ekey << endl;
cout << "์ํธ ํด๋
ํค (๊ฐ์ธํค) : " << key.dkey << endl;
cout << "=====================================\n" << endl;
long msg;
cout << "์ํธํํ ์ ๋ณด๋ฅผ ์
๋ ฅํ์ญ์์ค (์ซ์, ๋๋ฌด ํด ์ ์์) : ";
cin >> msg;
cout << "\n=====================================" << endl;
long msg_des = rsa.endecrypt(msg, key.ekey, key.pkey);
cout << "์ํธํ๋ ์ ๋ณด๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
msg_des = rsa.endecrypt(msg_des, key.dkey, key.pkey);
cout << "์ํธ ํด๋
๋ ๋ฉ์์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค : " << msg_des << endl;
cout << "=====================================" << endl;
return 0;
}
rsa.cpp
#include "rsa.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
Rsa::Rsa()
{
}
Rsa::~Rsa()
{
}
/***********************************************************************
์ํธํ ๋ณตํธํ๋ฅผ ๋์์ ์งํํ๋ ๋ฉ์๋
c = m^e mod n
m = c^d mod n
๋ผ๋ ์์ ๊ฐ๊ณ ๋ณ์๋ง ๋งค๊ฐ๊ฐ๋ง ๋ฐ๋๋ฉด ๋๋ฏ๋ก ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํจ
***********************************************************************/
long Rsa::endecrypt(const long msg, const long key, const long pkey)
{
long msg_des = 1;
long root = msg;
long index = key;
//int n_size = sizeof_int(pkey);
//int msg_size = sizeof_int(msg);
//int size = msg_size / n_size;
//if (msg_size % n_size)
// size = size + 1;
while (index)
{
//cout << bitset<32>(index) << endl;
if (index & 1) {
msg_des = (msg_des * root) % pkey;
//cout << "msg_des : " << msg_des << endl;
}
index >>= 1;
//cout << "b root : " << root << endl;
root = (root * root) % pkey;
//cout << "a root : " << root << endl;
}
return msg_des;
}
/************************************
p์ q๋ฅผ ์์ฑํด์
n, e, d ํค๋ฅผ ์์ฑ
* *********************************/
Key Rsa::produce_keys()
{
long prime1 = produce_prime(); // p
long prime2 = produce_prime(); // q
while (prime2 == prime1) // p์ q๋ n์ ๋ง๋ค๊ณ ํ๊ธฐํด์ผ ํ๊ธฐ ๋๋ฌธ์
prime2 = produce_prime(); // ๋ฐ๋ก ์ ์ฅํด์ ๋ฉ์๋ ๋ฐ์ผ๋ก ๋นผ์ง ์์
Key key;
long orla = produce_orla(prime1, prime2); // ์ค์ผ๋ฌ n ์์ฑ
key.pkey = produce_pkey(prime1, prime2); // n ์์ฑ
key.ekey = produce_ekey(orla); // e ์์ฑ
key.dkey = produce_dkey(key.ekey, orla); // d ์์ฑ
return key;
}
/************************************
N ํค ์์ฑ
p * q
* *********************************/
long Rsa::produce_pkey(const long prime1, const long prime2)
{
return prime1 * prime2;
}
/************************************
์ค์ผ๋ฌ n ์์ฑ
************************************/
long Rsa::produce_orla(const long prime1, const long prime2)
{
return (prime1 - 1) * (prime2 - 1);
}
/************************************
์ํธํ ํค (๊ณต๊ฐํค) e ์์ฑ
* *********************************/
long Rsa::produce_ekey(const long orla)
{
long ekey;
while (true)
{
ekey = rand() % orla; // ๋๋ค ์๋ฅผ ์ค์ผ๋ฌ n์ผ๋ก ๋๋จธ์ง ์ฐ์ฐ
if (ekey >= 2 && produce_gcd(ekey, orla) == 1) // e-key์ ์ค์ผ๋ฌ n์ด ์๋ก์์ธ์ง ํ๋ณ
break;
}
return ekey;
}
/************************************
๋ณตํธํ ํค (๊ฐ์ธํค) d ์์ฑ
* *********************************/
long Rsa::produce_dkey(const long ekey, const long orla)
{
long dkey = orla / ekey;
while (true)
{
if (((dkey * ekey) % orla) == 1)
break;
else
++dkey;
}
return dkey;
}
/************************************
[100, 200] ๋ฒ์์์ ์์์ ์์ ์์ฑ
* *********************************/
long Rsa::produce_prime()
{
long prime = 0;
srand(time(0));
while (true)
{
prime = rand() % 100 + 100;
if (is_prime(prime))
break;
}
return prime;
}
/************************************
๋ ์ซ์์ ์ต๋ ๊ณต์ฝ์ ์์ฑ
* *********************************/
long Rsa::produce_gcd(const long a, const long b)
{
long dividend = a;
long divisor = b;
long residual = dividend % divisor;
while (residual)
{
dividend = divisor;
divisor = residual;
residual = dividend % divisor;
}
return divisor;
}
/************************************
์์์ธ์ง ํ๋จ
* *********************************/
bool Rsa::is_prime(const long digit)
{
int tmp = 2;
while (tmp < digit)
if (!(digit % tmp++))
break;
if (tmp == digit)
return true;
return false;
}
/************************************
์
๋ ฅ๊ฐ์ ์๋ฆฟ์ ํ๋จ
* *********************************/
int Rsa::sizeof_int(long data)
{
int pos = 1;
if (data < 0)
data *= (-1);
for (int i = 0; ; i++, pos++) {
if ((data /= 10) <= 0)
break;
}
return pos;
}
๊ฒฐ๊ณผ
#include "rsa.h"
#include <cstdlib>
#include <ctime>
#include <string>
#include <bitset>
#include <iostream>
using namespace std;
Rsa::Rsa()
{
}
Rsa::~Rsa()
{
}
/***********************************************************************
์ํธํ ๋ณตํธํ๋ฅผ ๋์์ ์งํํ๋ ๋ฉ์๋
c = m^e mod n
m = c^d mod n
๋ผ๋ ์์ ๊ฐ๊ณ ๋ณ์๋ง ๋งค๊ฐ๊ฐ๋ง ๋ฐ๋๋ฉด ๋๋ฏ๋ก ํ๋์ ๋ฉ์๋์์ ์ฒ๋ฆฌํจ
***********************************************************************/
long Rsa::endecrypt(const long msg, const long key, const long pkey)
{
long msg_des = 1;
long root = msg;
long index = key;
//int n_size = sizeof_int(pkey);
//int msg_size = sizeof_int(msg);
//int size = msg_size / n_size;
//if (msg_size % n_size)
// size = size + 1;
while (index)
{
//cout << bitset<32>(index) << endl;
if (index & 1) {
msg_des = (msg_des * root) % pkey;
//cout << "msg_des : " << msg_des << endl;
}
index >>= 1;
//cout << "b root : " << root << endl;
root = (root * root) % pkey;
//cout << "a root : " << root << endl;
}
return msg_des;
}
/************************************
p์ q๋ฅผ ์์ฑํด์
n, e, d ํค๋ฅผ ์์ฑ
* *********************************/
Key Rsa::produce_keys()
{
long prime1 = produce_prime(); // p
long prime2 = produce_prime(); // q
while (prime2 == prime1) // p์ q๋ n์ ๋ง๋ค๊ณ ํ๊ธฐํด์ผ ํ๊ธฐ ๋๋ฌธ์
prime2 = produce_prime(); // ๋ฐ๋ก ์ ์ฅํด์ ๋ฉ์๋ ๋ฐ์ผ๋ก ๋นผ์ง ์์
Key key;
long orla = produce_orla(prime1, prime2); // ์ค์ผ๋ฌ n ์์ฑ
key.pkey = produce_pkey(prime1, prime2); // n ์์ฑ
key.ekey = produce_ekey(orla); // e ์์ฑ
key.dkey = produce_dkey(key.ekey, orla); // d ์์ฑ
return key;
}
/************************************
N ํค ์์ฑ
p * q
* *********************************/
long Rsa::produce_pkey(const long prime1, const long prime2)
{
return prime1 * prime2;
}
/************************************
์ค์ผ๋ฌ n ์์ฑ
************************************/
long Rsa::produce_orla(const long prime1, const long prime2)
{
return (prime1 - 1) * (prime2 - 1);
}
/************************************
์ํธํ ํค (๊ณต๊ฐํค) e ์์ฑ
* *********************************/
long Rsa::produce_ekey(const long orla)
{
long ekey;
while (true)
{
ekey = rand() % orla; // ๋๋ค ์๋ฅผ ์ค์ผ๋ฌ n์ผ๋ก ๋๋จธ์ง ์ฐ์ฐ
if (ekey >= 2 && produce_gcd(ekey, orla) == 1) // e-key์ ์ค์ผ๋ฌ n์ด ์๋ก์์ธ์ง ํ๋ณ
break;
}
return ekey;
}
/************************************
๋ณตํธํ ํค (๊ฐ์ธํค) d ์์ฑ
* *********************************/
long Rsa::produce_dkey(const long ekey, const long orla)
{
long dkey = orla / ekey;
while (true)
{
if (((dkey * ekey) % orla) == 1)
break;
else
++dkey;
}
return dkey;
}
/************************************
[100, 200] ๋ฒ์์์ ์์์ ์์ ์์ฑ
* *********************************/
long Rsa::produce_prime()
{
long prime = 0;
srand(time(0));
while (true)
{
prime = rand() % 100 + 100;
if (is_prime(prime))
break;
}
return prime;
}
/************************************
๋ ์ซ์์ ์ต๋ ๊ณต์ฝ์ ์์ฑ
* *********************************/
long Rsa::produce_gcd(const long a, const long b)
{
long dividend = a;
long divisor = b;
long residual = dividend % divisor;
while (residual)
{
dividend = divisor;
divisor = residual;
residual = dividend % divisor;
}
return divisor;
}
/************************************
์์์ธ์ง ํ๋จ
* *********************************/
bool Rsa::is_prime(const long digit)
{
int tmp = 2;
while (tmp < digit)
if (!(digit % tmp++))
break;
if (tmp == digit)
return true;
return false;
}
/************************************
์
๋ ฅ๊ฐ์ ์๋ฆฟ์ ํ๋จ
* *********************************/
int Rsa::sizeof_int(long data)
{
int pos = 1;
if (data < 0)
data *= (-1);
for (int i = 0; ; i++, pos++) {
if ((data /= 10) <= 0)
break;
}
return pos;
}
์ฐธ๊ณ ๋ฌธํ
GitHub, "RSA Encryption Decryption", https://github.com/cassvin/Rsa, (2020.06.05.)
GitHub, "RSA Encryption Decryption", https://github.com/cassvin/Rsa, (2020.06.05.)
Ghost