RSA加密C++大數實現

C++和python混編,編譯器爲64位mingw。具體配置請參考網上相應技術博客。 

代碼爲一個C++工程

ClassBigInteger.h


#ifndef CLASSBIGINT
#define CLASSBIGINT
#include <bits/stdc++.h>
class BigInteger
{
public:
	BigInteger();
	BigInteger(const BigInteger &);
	BigInteger(std::string num1);
	BigInteger(char num1);
	~BigInteger();
private:
	std::string _num1;
public:

	//friend std::istream& operator>>(istream& in, const BigInteger& a);
//	friend std::ostream& operator<<(ostream& ,const BigInteger& );
    //靜態方法
	static int compare(std::string num1,std::string num2);//if num1>num2,return 1,else if num1=num2,return 0,else return -1;
	static std::string add(std::string num1,std::string num2);//num1+num2
	static std::string minus(std::string num1,std::string num2);//num1-num2
	static std::string multiply(std::string num1,std::string num2);//num1*num2
	static std::string divide(std::string num1,std::string num2,int floatpoint);//num1/num2
	static std::string mod(std::string num1,std::string num2);//num1 mod num2
	static std::string gcd(std::string num1,std::string num2);//gcd(num1,num2)
	static std::string exgcd(std::string a,std::string b,std::string &x,std::string &y);//if gcd(a,b)=1,a*x+b*y=1,return gcd(a,b),x is inverse of a

	//重載操作符
	std::string toString() const;
	void init();
	void setnum(std::string );
	BigInteger operator+(const BigInteger&);//+
	BigInteger operator-(const BigInteger&);//-
	BigInteger operator*(const BigInteger&);//*
	BigInteger operator/(const BigInteger&);///
	BigInteger operator%(const BigInteger&);//mod
	bool operator==(const BigInteger&)const;//==
	bool operator>(const BigInteger&)const;//>
	bool operator<(const BigInteger&)const;//<
};

#endif CLASSBIGINT

ClassBigInteger.cpp 

#include "ClassBigInteger.h"
#include<bits/stdc++.h>
BigInteger::BigInteger()
{

}

BigInteger::BigInteger(std::string num1):_num1(num1)
{

}
BigInteger::BigInteger(char num1)
{
     std::string cc="";
     cc+=num1;
     _num1=cc;
}
BigInteger::BigInteger(const BigInteger &bi)
{
	_num1=bi._num1;
}

BigInteger::~BigInteger()
{

}

void BigInteger::setnum(std::string c){
    this->_num1+=c;
}
void BigInteger::init(){
    this->_num1="";
}
std::string BigInteger::toString() const
{
	return _num1;
}
/*std::ostream& operator<<(ostream& out, const BigInteger& obj)
{
    out <<obj.toString();
    return out;
}*/
/*std::istream& operator<<(istream& in, const BigInteger& obj)
{
    in>>obj.toString();
    return in;
}*/
BigInteger BigInteger::operator+(const BigInteger &bi)
{
    BigInteger t(*this);
	t._num1=add(t._num1,bi._num1);
	return t;
}

BigInteger BigInteger::operator-(const BigInteger &bi)
{
    BigInteger t(*this);
	t._num1=minus(t._num1,bi._num1);
	return t;
}

BigInteger BigInteger::operator*(const BigInteger &bi)
{
    BigInteger t(*this);
	t._num1=multiply(t._num1,bi._num1);
	return t;
}

BigInteger BigInteger::operator/(const BigInteger &bi)
{
    BigInteger t(*this);
	t._num1=divide(t._num1,bi._num1,0);
	return t;
}

BigInteger BigInteger::operator%(const BigInteger &bi)
{
    BigInteger t(*this);
	t._num1=mod(t._num1,bi._num1);
	return t;
}
int BigInteger::compare(std::string number1,std::string number2)
{
	if(number1[0]!='-'&&number2[0]!='-'){
		int j;
		int length1 = number1.size();
		int length2 = number2.size();

		if(number1.size() == 0)
			number1 = "0";
		if(number2.size() == 0)
			number2 = "0";

		j = 0;
		for(int i = 0; i < length1; ++i)
		{
			if(number1[i] == '0')
				++j;
			else
				break;
		}
		number1 = number1.substr(j);
		j = 0;
		for(int i = 0; i < length2; ++i)
		{
			if(number2[i] == '0')
				++j;
			else
				break;
		}
		number2 = number2.substr(j);
		length1 = number1.size();
		length2 = number2.size();
		if(length1 > length2)
		{
			return 1;
		}
		else if(length1 == length2)
		{
			if(number1.compare(number2) > 0)
			{
				return 1;
			}
			else if(number1.compare(number2) == 0)
			{
				return 0;
			}
			else
			{
				return -1;
			}
		}
		else
		{
			return -1;
		}
	}
	else if(number1[0]=='-'&&number2[0]!='-')
	{
		return -1;
	}
	else if(number1[0]!='-'&&number2[0]=='-')
	{
		return 1;
	}
	else{
		std::string absnumber1="";
		std::string absnumber2="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		int result=compare(absnumber1,absnumber2);
		if(result==1)
		{
			return -1;
		}
		else if(result==-1)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
}
bool BigInteger::operator==(const BigInteger &a)const{
    std::string s1=this->toString();
    std::string s2=a.toString();
    if(this->compare(s1,s2)==0)return true;
    else return false;
}
bool BigInteger::operator>(const BigInteger &a)const{
    std::string s1=this->toString();
    std::string s2=a.toString();
    if(this->compare(s1,s2)==1)return true;
    else return false;
}
bool BigInteger::operator<(const BigInteger &a)const{
    std::string s1=this->toString();
    std::string s2=a.toString();
    if(this->compare(s1,s2)==-1)return true;
    else return false;
}
std::string BigInteger::add(std::string number1,std::string number2)
{
	if(number1[0]!='-'&&number2[0]!='-'){
		int i;
		int length1 = number1.size();
		int length2 = number2.size();

		std::string result="";

		reverse(number1.begin(), number1.end());
		reverse(number2.begin(), number2.end());

		for(i = 0; i < length1 && i < length2; i++)
		{
			char c = (char)(number1[i] + number2[i] - 48);//每一位相加,-48減去ascii的'0'
			result = result + c;//把結果給result
		}

		//加上剩餘比較長的數
		while(i < length1)
		{
			result = result + number1[i];
			++i;
		}

		while(i < length2)
		{
			result = result + number2[i];
			++i;
		}
		//轉化
		int carry = 0;
		for(i = 0; i < (int)result.size(); ++i)
		{
			int value = result[i] - 48 + carry;
			result[i] = (char)(value % 10 + 48);
			carry = value / 10;
		}

		if(carry !=0 )
		{
			result = result + (char)(carry + 48);
		}

		for(i = result.size() - 1; i >= 0; i--)
		{
			if(result[i] != '0')
				break;
		}
		//截取有效位,有的數前面是用0來填充的
		result = result.substr(0, i + 1);
		//翻轉回來
		reverse(result.begin(), result.end());
		if(result.length() == 0)
			result = "0";
		return result;
	}
	else if(number1[0]=='-'&&number2[0]!='-'){
		std::string absnumber1="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		std::string result=minus(number2,absnumber1);
		return result;
	}
	else if(number1[0]!='-'&&number2[0]=='-'){
		std::string absnumber2="";
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		std::string result=minus(number1,absnumber2);
		return result;
	}
	else
	{
		std::string absnumber1="";
		std::string absnumber2="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		return "-"+add(absnumber1,absnumber2);
	}
}

std::string BigInteger::minus(std::string number1,std::string number2)
{
	if(number1[0]!='-'&&number2[0]!='-'){
		int i;
		std::string result = "";

		int length1 = number1.size();
		int length2 = number2.size();

		if(compare(number2,number1) > 0)
		{
			return "-" + minus(number2, number1);
		}

		reverse(number1.begin(),number1.end());
		reverse(number2.begin(),number2.end());

		for(i = 0; i < length1 && i < length2; i++)
		{
			char c = number1[i] - number2[i] + 48;
			result = result + c;
		}

		if(i < length1)
		{
			for(; i < length1; i++)
			{
				result = result + number1[i];
			}
		}

		int carry = 0;
		for(i = 0; i < (int)result.length(); i++)
		{
			int value = result[i] - 48 + carry;
			if(value < 0)
			{
				value = value + 10;
				carry = -1;
			}
			else
				carry = 0;
			result[i]=(char)(value + 48);
		}

		for(i = result.size() - 1; i >= 0; i--)
		{
			if(result[i] != '0')break;
		}

		result = result.substr(0, i+1);

		reverse(result.begin(), result.end());
		if(result.length()==0) result = "0";
		return result;
	}
	else if(number1[0]=='-'&&number2[0]!='-'){
		std::string absnumber1="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		std::string result=add(number2,absnumber1);
		return "-"+result;
	}
	else if(number1[0]!='-'&&number2[0]=='-'){
		std::string absnumber2="";
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		std::string result=add(number1,absnumber2);
		return result;
	}
	else
	{
		std::string absnumber1="";
		std::string absnumber2="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		return minus(absnumber2,absnumber1);
	}
}

std::string BigInteger::multiply(std::string number1,std::string number2)
{
	if(number1[0]!='-'&&number2[0]!='-'){
		int i, j;
		int *iresult;
		int length1 = number1.size();
		int length2 = number2.size();
		std::string result = "";

		reverse(number1.begin(), number1.end());
		reverse(number2.begin(), number2.end());

		iresult = (int*)malloc(sizeof(int) * (length1 + length2 + 1));
		memset(iresult, 0, sizeof(int) * (length1 + length2 + 1));

		for(i = 0; i < length1; i++)
		{
			for(j = 0; j < length2; j++)
			{
				iresult[i+j] += ((number1[i] - 48) * (number2[j] - 48));
			}
		}

		int carry = 0;
		for(i = 0; i < length1 + length2; i++)
		{
			int value = iresult[i] + carry;
			iresult[i] = value % 10;
			carry = value / 10;
		}

		for(i = length1 + length2 - 1; i >= 0; i--)
		{
			if(iresult[i] != 0)
				break;
		}

		for(; i >= 0; i--)
		{
			result = result + (char)(iresult[i]+48);
		}

		free(iresult);

		if(result == "") result = "0";
		return result;
	}
	else if(number1[0]=='-'&&number2[0]!='-'){
		std::string absnumber1="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		std::string result=multiply(number2,absnumber1);
		return "-"+result;
	}
	else if(number1[0]!='-'&&number2[0]=='-'){
		std::string absnumber2="";
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		std::string result=multiply(number1,absnumber2);
		return "-"+result;
	}
	else
	{
		std::string absnumber1="";
		std::string absnumber2="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		return multiply(absnumber2,absnumber1);
	}
}

std::string BigInteger::divide(std::string number1,std::string number2,int floatpoint = 0)
{
	if(number1[0]!='-'&&number2[0]!='-'){
		int i, j, pos;
		std::string result = "";
		std::string tempstr = "";
		int length1 = number1.size();
		int length2 = number2.size();

		if((compare(number2, number1) > 0) && (floatpoint == 0))
		{
			return "0";
		}

		tempstr = number1.substr(0, length2);
		pos = length2 - 1;

		while(pos < length1)
		{
			int quotient = 0;
			while(compare(tempstr, number2) >= 0)
			{
				quotient++;
				tempstr = minus(tempstr, number2);
			}

			result = result + (char)(quotient + 48);
			pos++;
			if(pos < length1)
			{
				tempstr += number1[pos];
			}
		}

		if(floatpoint > 0)
		{
			result += '.';
			std::string stmp = "1";
			int itmp = 0;
			for(int k = 0; k < floatpoint; ++k)
			{
				stmp += '0';
				if(compare(multiply(minus(number1, multiply(divide(number1, number2), number2)), stmp), number2) < 0)
				{
					result += '0';
					++itmp;
				}
			}

			std::string temp = divide(multiply(minus(number1, multiply(divide(number1, number2), number2)), stmp), number2);
			if(temp[0] != '0') result += temp;
		}

		j = result.size();
		for(i = 0; i < j; i++)
		{
			if(result[i] != '0') break;
		}

		result = result.substr(i, j);

		return result;
	}
	else if(number1[0]=='-'&&number2[0]!='-'){
		std::string absnumber1="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		std::string result=divide(absnumber1,number2);
		return "-"+result;
	}
	else if(number1[0]!='-'&&number2[0]=='-'){
		std::string absnumber2="";
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		std::string result=divide(number1,absnumber2);
		return "-"+result;
	}
	else
	{
		std::string absnumber1="";
		std::string absnumber2="";
		for(size_t i=1;i<number1.size();i++)
		{
			absnumber1+=number1[i];
		}
		for(size_t i=1;i<number2.size();i++)
		{
			absnumber2+=number2[i];
		}
		return divide(absnumber1,absnumber2);
	}
}

std::string BigInteger::mod(std::string number1,std::string number2)
{
	if(compare(number1, number2) == 0)
	{
		return "0";
	}
	else if(number2[0]=='-')
	{
		return "error";
	}
	else{
		std::string result=minus(number1, multiply(divide(number1, number2), number2));
		if(compare("0",result)>0)
		{
			result=add(result,number2);
		}
		return result;
	}
}

std::string BigInteger::gcd(std::string num1,std::string num2)
{
	if (num1 == "0")
	{
		return num2;
	}
	if (num2 == "0")
	{
		return num1;
	}
	if (compare(num1,num2)==0)
	{
		std::string temp=num1;
		num1=num2;
		num2=temp;
	}

	std::string result = mod(num1,num2);
	while(result != "0")
	{
		num1 = num2;
		num2 = result;
		result = mod(num1,num2);
	}
	return num2;
}

std::string BigInteger::exgcd(std::string a,std::string b,std::string &x,std::string &y)
{
	if( b == "0" ) {
		x = "1";
		y = "0";
		return a;
	}
	else{
		std::string x1,y1;
		if(mod(a,b)=="error")
		{
			return "error";
		}
		std::string d = exgcd ( b ,mod(a,b),x1,y1);
		x = y1;
		std::string temp=divide(a,b);
		std::string temp2=multiply(temp,y1);
		y=minus(x1,temp2);
		return d;
	}
}

main.cpp 

#include<bits/stdc++.h>
#include<iostream>
//#include <python3.5m>
#include <Python.h>
#include <Python-ast.h>
#include "ClassBigInteger.h"
#include <string>
using namespace std;
#define MAXSIZE 1024
ostream& operator<<(ostream& out, const BigInteger& obj)
{
    out <<obj.toString();
    return out;
}
istream& operator>>(istream & in, BigInteger& b)   //重載輸入運算符
{
    b.init();
    std::string ch;
    in>>ch;
    b.setnum(ch);
    return in;

}
BigInteger zero("0"),one("1");
BigInteger xx,yy;
void ExtendedEuclid(BigInteger a,BigInteger b)
{
    if(b==zero)
    {
        xx=one,yy=zero;
        return ;
    }
    ExtendedEuclid(b,a%b);
    //cout<<xx<<" "<<yy<<" "<<a/b<<endl;
    BigInteger tmp = xx;
    xx = yy;
    yy = tmp - ((a/b)*yy);
    //cout<<xx<<" "<<yy<<" "<<tmp<<endl;
    return ;
}
BigInteger encode(BigInteger m,BigInteger e,BigInteger n)
{
    BigInteger t,ret("1"),two("2");
    if(e<zero)
        exit(-1);
    if(e==zero)
        return one;
    if(e==one)
        return m;
    while(e>zero)
    {
        if(e%two==one)
        {
            ret = (ret*m)%n;
        }
        m = (m*m)%n;
        e=e/two;
    }
    return ret%n;
}
BigInteger decode(BigInteger c,BigInteger d,BigInteger n)
{
    BigInteger t,ret("1"),two("2");
    if(d<zero)
        exit(-1);
    if(d==zero)
        return one;
    if(d==one)
        return c;
    while(d>zero)
    {
        if(d%two==one)
        {
            ret = (ret*c)%n;
        }
        c = (c*c)%n;
        d=d/two;
    }
    return ret%n;
}
int main(int argc, char* argv[])
{
    Py_Initialize();              //使用python之前,要調用Py_Initialize();這個函數進行初始化
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import random");
    PyRun_SimpleString("sys.path.append('./')");
    PyObject * pModule = NULL;    //聲明變量
    PyObject * pFunc = NULL;      //聲明變量
    pModule =PyImport_ImportModule("sjss");              //這裏是要調用的Python文件名

    if(pModule==NULL)
    {
        cout<<"Cant not open the file"<<endl;
        return 0;
    }
    pFunc= PyObject_GetAttrString(pModule, "cxf");   //這裏是要調用的函數名

    PyObject *pReturn = NULL;
    pReturn =PyEval_CallObject(pFunc, NULL);      //調用函數
    //PyEval_CallObject(pFunc, NULL);    //調用函數,NULL表示參數爲空
    char* result1=NULL;
    char* result2=NULL;
    char* result3=NULL;
    PyArg_Parse(pReturn, "s", &result1);    //i表示轉換成int型變量
    //cout << result << endl;
    pReturn =PyEval_CallObject(pFunc, NULL);      //調用函數
    PyArg_Parse(pReturn, "s", &result2);    //i表示轉換成int型變量

    pReturn =PyEval_CallObject(pFunc, NULL);      //調用函數
    PyArg_Parse(pReturn, "s", &result3);    //i表示轉換成int型變量

    std::string str1(result1);
    std::string str2(result2);
    std::string str3(result3);
    //printf("%s\n",result1);
    cout<<"the prime number P is:"<<endl;
    cout<<str1<<endl;
    cout<<"the prime number Q is:"<<endl;
    cout<<str2<<endl;
    cout<<"the prime number E is:"<<endl;
    cout<<str3<<endl;
    Py_Finalize();                //調用Py_Finalize,這個和Py_Initialize相對應的.
    BigInteger p(str1);
    BigInteger q(str2);
    BigInteger n=p*q,r=(p-one)*(q-one);
    cout<<"the number N=p*q is:"<<endl;
    cout<<n<<endl;
    cout<<"the number R=(p-1)*(q-1) is:"<<endl;
    cout<<r<<endl;
    //cout<<p.toString()<<" "<<q.toString()<<endl;
    BigInteger e(str3);
    ExtendedEuclid(e,r);
    //cout<<xx.toString()<<" "<<yy.toString()<<endl;
    cout<<"the number D=>(D*E=1 mod R) is:"<<endl;
    BigInteger d=(xx%r+r)%r;
    cout<<d.toString()<<endl;
    BigInteger m("123456789");//明文
    cout<<"the Plaintext is:"<<endl;
    cout<<m<<endl;
    BigInteger c=encode(m,e,n);
    cout<<"the Ciphertext is:"<<endl;
    cout<<c<<endl;
    cout<<"the result is:"<<endl;
    cout<<decode(c,d,n)<<endl;
    //system("pause");
    return 0;
}

大素數生成和檢測用的python腳本 

#!/usr/bin/python
#coding:utf-8
import random
import sys
def proBin(w):  # w表示希望產生位數
    list = []
    list.append(1)  #最高位定爲1
    for i in range(w - 2):
        c = random.randint(0, 1)
        list.append(c)
    list.append(1)
    ls2 = [str(j) for j in list]
    ls3 = ''.join(ls2)
    b = int(ls3[0])
    for i2 in range(len(ls3) - 1):
        b = b << 1
        b = b + int(ls3[i2 + 1])
    d = int(b)
    return d

def X_n_mod_P(x, n, p):  # x^n mod P 遞歸求法 (x*x)^(n/2) mod P = ((x*x)mod P)^(n/2) mod P
    if n == 0:
        return 1
    res = X_n_mod_P((x * x) % p, n >> 1, p)
    if n & 1 != 0:
        res = (res * (x)) % p # x是較小數,x%p的結果就是本身
    return res

def MillerRabin(a, p):  
    if X_n_mod_P(a, p - 1, p) == 1:
        u = (p-1) >> 1
        while (u & 1) == 0:
            t = X_n_mod_P(a, u, p)
            if t == 1:
                u = u >> 1
            else:
                if t == p - 1:
                    return True
                else:
                    return False
        else:
            t = X_n_mod_P(a, u, p)
            if t == 1 or t == p - 1:
                return True
            else:
                return False
    else:
        return False

def testMillerRabin(p, k):  # k爲測試次數,p爲待測奇數
    while k > 0:
        a = random.randint(2, p - 1)
        if not MillerRabin(a, p):
            return False
        k = k - 1
    return True

def pro512():           # 產生512位素數
    while 1:
        d = proBin(512)
        for i in range(50):  # 僞素數附近50個奇數都沒有真素數的話,重新再產生一個僞素數
            u = testMillerRabin(d+2*(i), 5)
            if u:
                b = d + 2*(i)
                break
            else:
                continue
        if u:
            return b
        else:
            continue
            
def cxf():
    t1 = str(pro512())
    #t2 = str(pro512())
    #t3 = str(pro512())
    #f1.open('test.txt','w')
    #f1.write(t1)
    #f1.close()
    #print(t1)
    #print(t2)
    #print(t3)
    return t1
#cxf()
# while 1:                    
    # t1 = int(pro512())
    # for k in range(4):           #再產生一個512位的合數,判斷乘積是否爲1024位,
        # t2 = proBin(512) - 1     #如果不是,再產生一個512位的合數,循環4次,如果不是,產生一個新的512質數
        # t = t1*t2
        # h = len(bin(t)) - 2
        # if h == 1024:
            # break
        # else:
            # continue
    # if not h == 1024:
        # continue
    # else:
        # for i in range(50):    #循環五十次判斷判斷t3是否爲質數,如果不是t2周圍去嘗試
            # t2 = t2 + 2*i
            # t3 = t1*t2 + 1
            # u = testMillerRabin(t3, 5)
            # if u:
                # break
            # else:
                # continue
        # if u:
            # break
        # else:
            # continue
# print('小質數t1(2) =', bin(t1)[2:])
# print('小質數t1(10) =',t1)
# print('倍數t2(2) =', bin(t2)[2:])
# print('倍數t2(10) =',t2)
# print('大質數t3(2) =', bin(t3)[2:])
# print('大質數t3(10) =',t3)
//優化了大數乘法和取模,15秒可以算512bit大數
#include<bits/stdc++.h>
#include<iostream>
//#include <python3.5m>
#include <Python.h>
#include <Python-ast.h>
#include "ClassBigInteger.h"
#include <string>
using namespace std;
#define MAXSIZE 2048
ostream& operator<<(ostream& out, const BigInteger& obj)
{
    out <<obj.toString();
    return out;
}
istream& operator>>(istream & in, BigInteger& b)   //重載輸入運算符
{
    b.init();
    std::string ch;
    in>>ch;
    b.setnum(ch);
    return in;

}


const int L=2000;
int sub(int *a,int *b,int La,int Lb)
{
    if(La<Lb) return -1;//如果a小於b,則返回-1
    if(La==Lb)
    {
        for(int i=La-1;i>=0;i--)
            if(a[i]>b[i]) break;
            else if(a[i]<b[i]) return -1;//如果a小於b,則返回-1

    }
    for(int i=0;i<La;i++)//高精度減法
    {
        a[i]-=b[i];
        if(a[i]<0) a[i]+=10,a[i+1]--;
    }
    for(int i=La-1;i>=0;i--)
        if(a[i]) return i+1;//返回差的位數
    return 0;//返回差的位數

}
std::string div(std::string n1,std::string n2,int nn)//n1,n2是字符串表示的被除數,除數,nn是選擇返回商還是餘數
{
     std::string s,v;//s存商,v存餘數
     int a[L],b[L],r[L],La=n1.size(),Lb=n2.size(),i,tp=La;//a,b是整形數組表示被除數,除數,tp保存被除數的長度
     fill(a,a+L,0);fill(b,b+L,0);fill(r,r+L,0);//數組元素都置爲0
     for(i=La-1;i>=0;i--) a[La-1-i]=n1[i]-'0';
     for(i=Lb-1;i>=0;i--) b[Lb-1-i]=n2[i]-'0';
     if(La<Lb || (La==Lb && n1<n2)) {
            //cout<<0<<endl;
     return n1;}//如果a<b,則商爲0,餘數爲被除數
     int t=La-Lb;//除被數和除數的位數之差
     for(int i=La-1;i>=0;i--)//將除數擴大10^t倍
        if(i>=t) b[i]=b[i-t];
        else b[i]=0;
     Lb=La;
     for(int j=0;j<=t;j++)
     {
         int temp;
         while((temp=sub(a,b+j,La,Lb-j))>=0)//如果被除數比除數大繼續減
         {
             La=temp;
             r[t-j]++;
         }
     }
     for(i=0;i<L-10;i++) r[i+1]+=r[i]/10,r[i]%=10;//統一處理進位
     while(!r[i]) i--;//將整形數組表示的商轉化成字符串表示的
     while(i>=0) s+=r[i--]+'0';
     //cout<<s<<endl;
     i=tp;
     while(!a[i]) i--;//將整形數組表示的餘數轉化成字符串表示的</span>
     while(i>=0) v+=a[i--]+'0';
     if(v.empty()) v="0";
     //cout<<v<<endl;
     if(nn==1) return s;
     if(nn==2) return v;
}

#define L(x) (1 << (x))
const double PI = acos(-1.0);
const int Maxn = 133015;
double ax[Maxn], ay[Maxn], bx[Maxn], by[Maxn];
char sa[Maxn/2],sb[Maxn/2];
int sum[Maxn];
int x1[Maxn],x2[Maxn];
int revv(int x, int bits)
{
    int ret = 0;
    for (int i = 0; i < bits; i++)
    {
        ret <<= 1;
        ret |= x & 1;
        x >>= 1;
    }
    return ret;
}
void fft(double * a, double * b, int n, bool rev)
{
    int bits = 0;
    while (1 << bits < n) ++bits;
    for (int i = 0; i < n; i++)
    {
        int j = revv(i, bits);
        if (i < j)
            swap(a[i], a[j]), swap(b[i], b[j]);
    }
    for (int len = 2; len <= n; len <<= 1)
    {
        int half = len >> 1;
        double wmx = cos(2 * PI / len), wmy = sin(2 * PI / len);
        if (rev) wmy = -wmy;
        for (int i = 0; i < n; i += len)
        {
            double wx = 1, wy = 0;
            for (int j = 0; j < half; j++)
            {
                double cx = a[i + j], cy = b[i + j];
                double dx = a[i + j + half], dy = b[i + j + half];
                double ex = dx * wx - dy * wy, ey = dx * wy + dy * wx;
                a[i + j] = cx + ex, b[i + j] = cy + ey;
                a[i + j + half] = cx - ex, b[i + j + half] = cy - ey;
                double wnx = wx * wmx - wy * wmy, wny = wx * wmy + wy * wmx;
                wx = wnx, wy = wny;
            }
        }
    }
    if (rev)
    {
        for (int i = 0; i < n; i++)
            a[i] /= n, b[i] /= n;
    }
}
int solve(int a[],int na,int b[],int nb,int ans[])
{
    int len = max(na, nb), ln;
    for(ln=0; L(ln)<len; ++ln);
    len=L(++ln);
    for (int i = 0; i < len ; ++i)
    {
        if (i >= na) ax[i] = 0, ay[i] =0;
        else ax[i] = a[i], ay[i] = 0;
    }
    fft(ax, ay, len, 0);
    for (int i = 0; i < len; ++i)
    {
        if (i >= nb) bx[i] = 0, by[i] = 0;
        else bx[i] = b[i], by[i] = 0;
    }
    fft(bx, by, len, 0);
    for (int i = 0; i < len; ++i)
    {
        double cx = ax[i] * bx[i] - ay[i] * by[i];
        double cy = ax[i] * by[i] + ay[i] * bx[i];
        ax[i] = cx, ay[i] = cy;
    }
    fft(ax, ay, len, 1);
    for (int i = 0; i < len; ++i)
        ans[i] = (int)(ax[i] + 0.5);
    return len;
}
std::string mul(std::string sa,std::string sb)
{
    int l1,l2,l;
    int i;
    std::string ans;
    memset(sum, 0, sizeof(sum));
    l1 = sa.size();
    l2 = sb.size();
    for(i = 0; i < l1; i++)
        x1[i] = sa[l1 - i - 1]-'0';
    for(i = 0; i < l2; i++)
        x2[i] = sb[l2-i-1]-'0';
    l = solve(x1, l1, x2, l2, sum);
    for(i = 0; i<l || sum[i] >= 10; i++) // 進位
    {
        sum[i + 1] += sum[i] / 10;
        sum[i] %= 10;
    }
    l = i;
    while(sum[l] <= 0 && l>0)    l--; // 檢索最高位
    for(i = l; i >= 0; i--)    ans+=sum[i] + '0'; // 倒序輸出
    return ans;
}

BigInteger zero("0"),one("1");
BigInteger xx,yy;
int input[1024];
int output[2048];
int tentobin(std::string a)
{
    memset(input,0,sizeof(input));
    int shang,shang_sum,yu,k,j;
    int len=a.length();
    for(int i=0; i<len; i++)
    {
        input[i]=a[i]-'0';
        //cout<<input[i]<<" ";
    }
    memset(output,0,sizeof(output));
    shang_sum=1;
    k=0;
    shang=0;
    while(shang_sum)
    {
        shang_sum=0;
        //cout<<shang_sum;
        for(int i=0; i<len; i++)
        {
            j=i+1;
            shang=input[i]/2;
            //cout<<i;
            shang_sum+=shang;
            yu=input[i]%2;
            if(i==(len-1))output[k++]=yu;
            else input[j]+=yu*10;
            input[i]=shang;
        }
    }
    return k;
}

void ExtendedEuclid(BigInteger a,BigInteger b)
{
    if(b==zero)
    {
        xx=one,yy=zero;
        return ;
    }
    ExtendedEuclid(b,a%b);
    //cout<<xx<<" "<<yy<<" "<<a/b<<endl;
    BigInteger tmp = xx;
    xx = yy;
    yy = tmp - ((a/b)*yy);
    //cout<<xx<<" "<<yy<<" "<<tmp<<endl;
    return ;
}

std::string encode(BigInteger m,BigInteger e,BigInteger n)
{
    /*BigInteger t,ret("1"),two("2");
    if(e<zero)
        exit(-1);
    if(e==zero)
        return one;
    if(e==one)
        return m;*/
    int len=tentobin(e.toString()),i=0;
    std::string ret="1",mm=m.toString(),nn=n.toString();
    while(i<len)
    {
        if(output[i]==1)
        {
            //ret = (ret*m)%n;
            //cout<<ret<<endl;
            ret=mul(ret,mm);
            ret=div(ret,nn,2);
        }
        mm=mul(mm,mm);
        mm=div(mm,nn,2);
        //m = (m*m)%n;
        //e=e/two;
        //e.divide2(e.toString());
        i++;
    }
    ret=div(ret,nn,2);
    return ret;
}
std::string decode(BigInteger c,BigInteger d,BigInteger n)
{
    /*BigInteger t,ret("1"),two("2");
    if(d<zero)
        exit(-1);
    if(d==zero)
        return one;
    if(d==one)
        return c;
    int len=tentobin(d.toString()),i=0;
    while(i<len)
    {
        if(output[i]==1)
        {
            ret = (ret*c)%n;
            //cout<<ret<<endl;
        }
        c = (c*c)%n;
        //e=e/two;
        //e.divide2(e.toString());
        i++;
    }
    return ret%n;*/
    int len=tentobin(d.toString()),i=0;
    std::string ret="1",cc=c.toString(),nn=n.toString();
    while(i<len)
    {
        if(output[i]==1)
        {
            //ret = (ret*m)%n;
            //cout<<ret<<endl;
            ret=mul(ret,cc);
            ret=div(ret,nn,2);
        }
        cc=mul(cc,cc);
        cc=div(cc,nn,2);
        //m = (m*m)%n;
        //e=e/two;
        //e.divide2(e.toString());
        i++;
    }
    ret=div(ret,nn,2);
    return ret;
}
int main(int argc, char* argv[])
{
    Py_Initialize();              //使用python之前,要調用Py_Initialize();這個函數進行初始化
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("import random");
    PyRun_SimpleString("sys.path.append('./')");
    PyObject * pModule = NULL;    //聲明變量
    PyObject * pFunc = NULL;      //聲明變量
    pModule =PyImport_ImportModule("sjss");              //這裏是要調用的Python文件名

    if(pModule==NULL)
    {
        cout<<"Cant not open the file"<<endl;
        return 0;
    }
    pFunc= PyObject_GetAttrString(pModule, "cxf");   //這裏是要調用的函數名

    PyObject *pReturn = NULL;
    pReturn =PyEval_CallObject(pFunc, NULL);      //調用函數
    //PyEval_CallObject(pFunc, NULL);    //調用函數,NULL表示參數爲空
    char* result1=NULL;
    char* result2=NULL;
    char* result3=NULL;
    PyArg_Parse(pReturn, "s", &result1);    //i表示轉換成int型變量
    //cout << result << endl;
    pReturn =PyEval_CallObject(pFunc, NULL);      //調用函數
    PyArg_Parse(pReturn, "s", &result2);    //i表示轉換成int型變量

    pReturn =PyEval_CallObject(pFunc, NULL);      //調用函數
    PyArg_Parse(pReturn, "s", &result3);    //i表示轉換成int型變量

    std::string str1(result1);
    std::string str2(result2);
    std::string str3(result3);
    //printf("%s\n",result1);
    cout<<"the prime number P is:"<<endl;
    cout<<str1<<endl;
    cout<<"the prime number Q is:"<<endl;
    cout<<str2<<endl;
    cout<<"the prime number E is:"<<endl;
    cout<<str3<<endl;
    Py_Finalize();                //調用Py_Finalize,這個和Py_Initialize相對應的.
    BigInteger p(str1);
    BigInteger q(str2);
    BigInteger n=p*q,r=(p-one)*(q-one);
    cout<<"the number N=p*q is:"<<endl;
    cout<<n<<endl;
    cout<<"the number R=(p-1)*(q-1) is:"<<endl;
    cout<<r<<endl;
    //cout<<p.toString()<<" "<<q.toString()<<endl;
    BigInteger e(str3);
    ExtendedEuclid(e,r);
    //cout<<xx.toString()<<" "<<yy.toString()<<endl;
    cout<<"the number D=>(D*E=1 mod R) is:"<<endl;
    BigInteger d=(xx%r+r)%r;
    cout<<d.toString()<<endl;
    BigInteger m("123456789");//明文
    cout<<"the Plaintext is:"<<endl;
    cout<<m<<endl;
    //BigInteger a("5"),b("3"),tt("7");

    //cout<<qmul(a,b,tt)<<endl;
    std::string c=encode(m,e,n);
    cout<<"the Ciphertext is:"<<endl;
    cout<<c<<endl;
    BigInteger cip(c);
    cout<<"the result is:"<<endl;
    cout<<decode(cip,d,n)<<endl;
    //system("pause");
    //BigInteger two("2");
    //cout<<n/two<<endl;
    return 0;
}

 

實驗截圖

python外掛

最後,如果用16進制加解密,我的最優能到6秒,代碼也不長,改天貼一篇新的。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章