四種密碼編譯演算法之RSA原始碼-C++

來源:互聯網
上載者:User

RSA.h檔案:

//! RSA 動態連結程式庫實現   H檔案/*! @author 朱孟斌 @e-mail  zmb.tsubasa@gmail.com @version 1.0 @date 2011-03 @{*/#ifndef RSA_H#define RSA_H#include <stdio.h>#include <string>#include <stdlib.h>   #include <time.h>  #include <math.h>#include <malloc.h>#include <iostream>#include <ppl.h>using namespace std;using namespace Concurrency;//! MAX是數組的最大個數,LEN為結構體slink的佔用記憶體空間大小 */#define MAX 100#define LEN sizeof(struct slink)//!   #能夠進行動態連結程式庫編譯的RSA類 /*!         @see class _declspec(dllexport) RSA       將RSA演算法寫成動態連結程式庫的形式方便調用,其中有公開金鑰,私密金鑰和明文   就可以進行明文的加密和解密 */class _declspec(dllexport) RSA{public://! # 新定義的資料結構slink/*!   @see struct slink 資料結構中,bignum儲存的是隨機產生的大數,next是指向後面的指標 @see int bignum[MAX] */typedef struct slink{int  bignum[MAX];/*!< bignum[98]用來標記加號或減號,1正,0負bignum[99]來標記實際長度*/struct slink *next;}slink;public://! #RSA 的建構函式    /*! @see RSA()      其中應該對RSA類中的一些變數進行相應的初始化    */RSA();//! #RSA的解構函式    /*!@see ~RSA()      釋放記憶體    */~RSA();public://! #RSA的大數運算函數庫    /** @大數比較函數@see int cmp(int, int)*/int cmp(int a1[MAX],int a2[MAX]);/** @大數類型轉換函式@see void mov(int a[MAX],int *b);*/void mov(int a[MAX],int *b); /** @大數乘積函數 @see void mul(int a1[MAX],int a2[MAX],int *c); */void mul(int a1[MAX],int a2[MAX],int *c); /** @大數相加函數 @see void add(int a1[MAX],int a2[MAX],int *c); */    void add(int a1[MAX],int a2[MAX],int *c); /** @大數大數相減函數 @see  void sub(int a1[MAX],int a2[MAX],int *c); */    void sub(int a1[MAX],int a2[MAX],int *c); /*! @大數模數函數 @see void mod(int a[MAX],int b[MAX],int  *c); @attention /c=a mod b//注意:經檢驗知道此處A和C的數組都改變了。 */void mod(int a[MAX],int b[MAX],int  *c);/*! @大數相除函數@see void divt(int t[MAX],int b[MAX],int  *c ,int *w);@attention //試商法//調用以後w為a mod b, C為a  div b;*/void divt(int t[MAX],int b[MAX],int  *c ,int *w);/*! @解決 了 m=a*b mod n;/*!@see void mulmod(int a[MAX] ,int b[MAX] ,int n[MAX],int *m);*/void mulmod(int a[MAX] ,int b[MAX] ,int n[MAX],int *m);/*! @解決 m=a^p  mod n的函數問題/*!@see void expmod(int a[MAX] ,int p[MAX] ,int n[MAX],int *m);*/void expmod(int a[MAX] ,int p[MAX] ,int n[MAX],int *m);/*!  @判斷是否為素數@see int   is_prime_san(int p[MAX] );*/int   is_prime_san(int p[MAX] );/*! @判斷兩個大數之間是否互質@see int coprime(int e[MAX],int s[MAX]);*/int coprime(int e[MAX],int s[MAX]);/*!  @隨機產生素數@see void prime_random(int *p,int *q);*/void prime_random(int *p,int *q);/*! @產生素數e@see void erand(int e[MAX],int m[MAX]);*/void erand(int e[MAX],int m[MAX]);/*! @根據規則產生其他的數@see void rsad(int e[MAX],int g[MAX],int *d);*/void rsad(int e[MAX],int g[MAX],int *d);/*! @求解密密鑰d的函數(根據Euclid演算法)@see unsigned long  rsa(unsigned long p,unsigned long q,unsigned long e);*/unsigned long  rsa(unsigned long p,unsigned long q,unsigned long e);   //! #RSA的產生大數的公開金鑰和私密金鑰的函數    /*!  @see bool RSAKey();  @param 沒有任何輸入,      @param 隨機產生e,d,n的函數,其已耗用時間比較長,需要等待  @return[bool] 成功返回true,失敗返回false    */bool RSAKey();//!  #RSA的進行檔案加密的函數    /*!  @see string tencrypto(int e[MAX], int n[MAX], char* text);  @param[int[] e,n為隨機產生的公開金鑰,利用公開金鑰進行加密      @param[char* text為明文,明文以char*的格式儲存  @return[string] 傳回值為加密成功之後的密文,採用string類型進行儲存    */string tencrypto(int e[MAX], int n[MAX], char* text);    //! #RSA的進行檔案解密的函數    /*!  @see string tdecrypto(int d[MAX], int n[MAX], string text);  @param[int[] d,n為私密金鑰,由函數RSAKey()產生      @param[string text為密文,對應加密函數,密文的格式為string  @return[string] 解密之後的明文採用string進行儲存    */string tdecrypto(int d[MAX], int n[MAX], string text);public:/** @brief 定義的全域變數,儲存體金鑰 */int  p[MAX],q[MAX],n[MAX],d[MAX],e[MAX],m[MAX],p1[MAX],q1[MAX];private:int  i;char  c;//struct slink *head,*h1,*h2;};#endif // RSA_H

RSA.c檔案:

/*!* @ RSA 動態連結程式庫實現   CPP檔案* @author 朱孟斌* @e-mail  zmb.tsubasa@gmail.com* @version 1.0* @date 2011-03* @{*/#include "RSA.h"RSA::RSA(){}RSA::~RSA(){}/*----------------------------建立自己的大數運算庫---------------------------------*/int RSA::cmp(int a1[MAX],int a2[MAX]){int l1, l2;int i;l1=a1[99];l2=a2[99];if (l1>l2)return 1;if (l1<l2)return -1;for(i=(l1-1);i>=0;i--){if (a1[i]>a2[i])return 1 ;if (a1[i]<a2[i])return -1;}return 0;}void RSA::mov(int a[MAX],int *b){int j;for(j=0;j<MAX;j++)b[j]=a[j];return ;}void RSA::mul(int a1[MAX],int a2[MAX],int *c){int i,j;int y;int x;int z;int w;int l1, l2;l1=a1[MAX-1];l2=a2[MAX-1];if (a1[MAX-2]=='-'&& a2[MAX-2]=='-')c[MAX-2]=0;else if (a1[MAX-2]=='-')c[MAX-2]='-';else if (a2[MAX-2]=='-')c[MAX-2]='-';for(i=0;i<l1;i++){for(j=0;j<l2;j++){x=a1[i]*a2[j];y=x/10;z=x%10;w=i+j;c[w]=c[w]+z;c[w+1]=c[w+1]+y+c[w]/10;c[w]=c[w]%10;}}w=l1+l2;if(c[w-1]==0)w=w-1;c[MAX-1]=w;return;} void RSA::add(int a1[MAX],int a2[MAX],int *c){int i,l1,l2;int len,temp[MAX];int k=0;l1=a1[MAX-1];l2=a2[MAX-1];if((a1[MAX-2]=='-')&&(a2[MAX-2]=='-')){c[MAX-2]='-';}else if (a1[MAX-2]=='-'){mov(a1,temp);temp[MAX-2]=0;sub(a2,temp,c);return;}else if (a2[MAX-2]=='-'){mov(a2,temp);temp[98]=0;sub(a1,temp,c);return;}if(l1<l2)len=l1;else len=l2;for(i=0;i<len;i++){c[i]=(a1[i]+a2[i]+k)%10;k=(a1[i]+a2[i]+k)/10;}if(l1>len){for(i=len;i<l1;i++){c[i]=(a1[i]+k)%10;k=(a1[i]+k)/10;   }if(k!=0){c[l1]=k;len=l1+1;}else len=l1;}else{for(i=len;i<l2;i++){c[i]=(a2[i]+k)%10;k=(a2[i]+k)/10;   }if(k!=0){c[l2]=k;len=l2+1;}else len=l2;}c[99]=len;return;} void RSA::sub(int a1[MAX],int a2[MAX],int *c){int i,l1,l2;int len,t1[MAX],t2[MAX];int k=0;l1=a1[MAX-1];l2=a2[MAX-1];if ((a1[MAX-2]=='-') && (a2[MAX-2]=='-')){mov(a1,t1);mov(a2,t2);t1[MAX-2]=0;t2[MAX-2]=0;sub(t2,t1,c);return;}else if( a2[MAX-2]=='-'){mov(a2,t2);t2[MAX-2]=0;add(a1,t2,c);return;}else if (a1[MAX-2]=='-'){mov(a2,t2);t2[MAX-2]='-';add(a1,t2,c);return;}if(cmp(a1,a2)==1){len=l2;for(i=0;i<len;i++){if ((a1[i]-k-a2[i])<0){c[i]=(a1[i]-a2[i]-k+10)%10;k=1;}else {c[i]=(a1[i]-a2[i]-k)%10;k=0;}}for(i=len;i<l1;i++){if ((a1[i]-k)<0){c[i]=(a1[i]-k+10)%10;k=1;}else {c[i]=(a1[i]-k)%10;k=0;} }if(c[l1-1]==0)/*使得數組C中的前面所以0字元不顯示了,如1000-20=0980--->顯示為980了*/{len=l1-1;i=2;while (c[l1-i]==0)/*111456-111450=00006,消除0後變成了6;*/{len=l1-i;i++;}}else {len=l1;}}elseif(cmp(a1,a2)==(-1)){c[MAX-2]='-';len=l1;for(i=0;i<len;i++){if ((a2[i]-k-a1[i])<0){c[i]=(a2[i]-a1[i]-k+10)%10;k=1;}else {c[i]=(a2[i]-a1[i]-k)%10;k=0;}}for(i=len;i<l2;i++){if ((a2[i]-k)<0){c[i]=(a2[i]-k+10)%10;k=1;}else {c[i]=(a2[i]-k)%10;k=0;}   }if(c[l2-1]==0){  len=l2-1;i=2;while (c[l1-i]==0){len=l1-i;i++;}}else len=l2;}else if(cmp(a1,a2)==0){len=1;c[len-1]=0;}c[MAX-1]=len;return;}void  RSA::mod(int a[MAX],int b[MAX],int  *c)/*/c=a mod b//注意:經檢驗知道此處A和C的數組都改變了。*/{int d[MAX];mov (a,d);while (cmp(d,b)!=(-1))/*/c=a-b-b-b-b-b.......until(c<b)*/{sub(d,b,c);mov(c,d);/*/c複製給a*/}return ;}void  RSA::divt(int t[MAX],int b[MAX],int  *c ,int *w)/*//試商法//調用以後w為a mod b, C為a  div b;*/{int a1,b1,i,j,m;/*w用於暫時儲存資料*/int d[MAX],e[MAX],f[MAX],g[MAX],a[MAX];mov(t,a);for(i=0;i<MAX;i++)e[i]=0;for(i=0;i<MAX;i++)d[i]=0;for(i=0;i<MAX;i++) g[i]=0;a1=a[MAX-1];b1=b[MAX-1];if (cmp(a,b)==(-1)){c[0]=0;c[MAX-1]=1;mov(t,w);return;}else if (cmp(a,b)==0){c[0]=1;c[MAX-1]=1;w[0]=0;w[MAX-1]=1;return;}m=(a1-b1);for(i=m;i>=0;i--)/*341245/3=341245-300000*1--->41245-30000*1--->11245-3000*3--->2245-300*7--->145-30*4=25--->25-3*8=1*/{for(j=0;j<MAX;j++)d[j]=0;d[i]=1;d[MAX-1]=i+1;mov(b,g);mul(g,d,e);while (cmp(a,e)!=(-1)){c[i]++;sub(a,e,f);mov(f,a);/*f複製給g*/}for(j=i;j<MAX;j++)/*高位清零*/e[j]=0;}mov(a,w);if (c[m]==0) c[MAX-1]=m;else c[MAX-1]=m+1;return;}void RSA::mulmod(int a[MAX] ,int b[MAX] ,int n[MAX],int *m)/*解決 了 m=a*b mod n;*/{int c[MAX],d[MAX];int i;for(i=0;i<MAX;i++)d[i]=c[i]=0;mul(a,b,c);divt(c,n, d,m);//for(i=0;i<m[MAX-1];i++)//printf("%d",m[m[MAX-1]-i-1]);//printf("\nm  length is :  %d \n",m[MAX-1]);}/*-------------接下來的重點任務是要著手解決 m=a^p  mod n的函數問題------------*/void RSA::expmod(int a[MAX] ,int p[MAX] ,int n[MAX],int *m){int t[MAX],l[MAX],temp[MAX]; /*/t放入2,l放入1;*/int w[MAX],s[MAX],c[MAX],b[MAX],i;for(i=0;i<MAX-1;i++)b[i]=l[i]=t[i]=w[i]=0;t[0]=2;t[MAX-1]=1;l[0]=1;l[MAX-1]=1;mov(l,temp);mov(a,m);mov(p,b);while(cmp(b,l)!=0){for(i=0;i<MAX;i++)w[i]=c[i]=0;divt(b,t,w,c);/*// c=p mod 2  w= p /2*/mov(w,b);/*//p=p/2*/if(cmp(c,l)==0) /*/餘數c==1*/{for(i=0;i<MAX;i++)w[i]=0;mul(temp,m,w);mov(w,temp);for(i=0;i<MAX;i++)w[i]=c[i]=0;divt(temp,n,w,c);/* /c為餘c=temp % n,w為商w=temp/n */mov(c,temp);}for(i=0;i<MAX;i++)s[i]=0;mul(m,m,s);//s=a*afor(i=0;i<MAX;i++)c[i]=0;divt(s,n,w,c);/*/w=s/n;c=s mod n*/mov (c,m);}for(i=0;i<MAX;i++)s[i]=0;mul(m,temp,s);for(i=0;i<MAX;i++)c[i]=0;divt(s,n,w,c);mov (c,m);/*餘數s給m*/m[MAX-2]=a[MAX-2];/*為後面的漢字顯示需要,用第99位做為標記*/return;/*/k=temp*k%n;*/}int   RSA::is_prime_san(int p[MAX] ){int i,a[MAX],t[MAX],s[MAX],o[MAX]; for(i=0;i<MAX;i++)s[i]=o[i]=a[i]=t[i]=0;t[0]=1;t[MAX-1]=1;a[0]=2;// { 2,3,5,7 }a[MAX-1]=1;sub(p,t,s);expmod ( a, s, p ,o);if ( cmp(o,t) != 0 ) {return 0;}a[0]=3;for(i=0;i<MAX;i++)  o[i]=0;expmod ( a, s, p ,o);if ( cmp(o,t) != 0 )    {return 0;}a[0]=5;for(i=0;i<MAX;i++)  o[i]=0;expmod ( a, s, p ,o);if ( cmp(o,t) != 0 ) {   return 0;}a[0]=7;for(i=0;i<MAX;i++)  o[i]=0;expmod ( a, s, p ,o);if ( cmp(o,t) != 0 ) {return 0;}return 1;}int RSA::coprime(int e[MAX],int s[MAX]) /*//// 判斷兩個大數之間是否互質////*/{int a[MAX],b[MAX],c[MAX],d[MAX],o[MAX],l[MAX];int i;for(i=0;i<MAX;i++)l[i]=o[i]=c[i]=d[i]=0;o[0]=0;o[MAX-1]=1;l[0]=1;l[MAX-1]=1;mov(e,b);mov(s,a);do{if(cmp(b,l)==0){return 1;}for(i=0;i<MAX;i++)c[i]=0;divt(a,b,d,c);mov(b,a);/*b--->a*/mov(c,b);/*c--->b*/}while(cmp(c,o)!=0);/*printf("Ihey are  not coprime!\n");*/return 0;}void RSA::prime_random(int *p,int *q){int i,k;time_t t; p[0]=1;q[0]=3;p[MAX-1]=10;q[MAX-1]=11;do{t=time(NULL);srand((unsigned long)t);for(i=1;i<p[MAX-1]-1;i++){k=rand()%10;p[i]=k;}k=rand()%10;while (k==0){k=rand()%10;}p[p[MAX-1]-1]=k;}while((is_prime_san(p))!=1);do{t=time(NULL);srand((unsigned long)t);for(i=1;i<q[MAX-1];i++){k=rand()%10;q[i]=k;}}while((is_prime_san(q))!=1);return;}void  RSA::erand(int e[MAX],int m[MAX]){int i,k;time_t t;e[MAX-1]=5;do{t=time(NULL);srand((unsigned long)t);for(i=0;i<e[MAX-1]-1;i++){k=rand()%10;e[i]=k;}while((k=rand()%10)==0)k=rand()%10;e[e[MAX-1]-1]=k;}while(coprime( e, m)!=1);return ;}void RSA::rsad(int e[MAX],int g[MAX],int *d){int r[MAX],n1[MAX],n2[MAX],k[MAX],w[MAX];int i,t[MAX],b1[MAX],b2[MAX],temp[MAX];mov(g,n1);mov(e,n2);for(i=0;i<MAX;i++)k[i]=w[i]=r[i]=temp[i]=b1[i]=b2[i]=t[i]=0;b1[MAX-1]=0;b1[0]=0;/*/b1=0;*/b2[MAX-1]=1;b2[0]=1;/*/b2=1;*/while(1){for(i=0;i<MAX;i++)k[i]=w[i]=0;divt(n1,n2,k,w);/*/k=n1/n2;*/for(i=0;i<MAX;i++)temp[i]=0;mul(k,n2,temp);/*/temp=k*n2;*/for(i=0;i<MAX;i++)r[i]=0;sub(n1,temp,r);if((r[MAX-1]==1) && (r[0]==0))/*/r=0*/{break;}else{mov(n2,n1);/*/n1=n2;*/mov( r,n2);/*/n2=r;*/mov(b2, t);/*/t=b2;*/for(i=0;i<MAX;i++)temp[i]=0;mul(k,b2,temp);/*/b2=b1-k*b2;*/for(i=0;i<MAX;i++)b2[i]=0;sub(b1,temp,b2);mov(t,b1);}}for(i=0;i<MAX;i++)t[i]=0;add(b2,g,t);for(i=0;i<MAX;i++)temp[i]=d[i]=0;divt(t,g,temp,d);}/*/求解密密鑰d的函數(根據Euclid演算法)96403770511368768000*/unsigned long  RSA::rsa(unsigned long p,unsigned long q,unsigned long e)  /*/求解密密鑰d的函數(根據Euclid演算法)*/{unsigned long g,k,r,n1,n2,t;unsigned long b1=0,b2=1;g=(p-1)*(q-1);n1=g;n2=e;while(1){k=n1/n2;r=n1-k*n2;if(r!=0){n1=n2;n2=r;t=b2;b2=b1-k*b2;b1=t;}else{break;}}return (g+b2)%g;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////! RSA的進行檔案加密的函數/*!   * @param[in] e,n為隨機產生的公開金鑰,利用公開金鑰進行加密   * @param[in] text為明文,明文以char*的格式儲存   * @return[string] 傳回值為加密成功之後的密文,採用string類型進行儲存   * @pre \e 進行加密的過程中進行了資料類型的轉換   * @see e,d,n & text*/string  RSA::tencrypto(int e[MAX], int n[MAX], char* text)/*//對有需要的檔案進行加密*/{int i,k,count,temp,c;char ch;struct slink  *p,*p1,*p2;struct slink  *h;h=p=p1=p2=(struct slink * )malloc(LEN);h=NULL;if (text == NULL){return NULL;}count=0;int j;for (j = 0 ; j < strlen(text); j++){  ch = text[j];c=ch;k=0;if(c<0){c=abs(c);/*/把負數取正並且做一個標記*/p1->bignum[MAX-2]='0';}else{p1->bignum[MAX-2]='1';}while(c/10!=0){temp=c%10;c=c/10;p1->bignum[k]=temp;k++;}p1->bignum[k]=c;p1->bignum[MAX-1]=k+1;count=count+1;if(count==1)h=p1;else p2->next=p1;p2=p1;p1=(struct slink * )malloc(LEN);}p2->next=NULL; string res;p=p1=(struct slink * )malloc(LEN);p=h;if(h!=NULL)do { expmod( p->bignum , e ,n ,p1->bignum);ch=p1->bignum[MAX-2];res += ch;if ((p1->bignum[MAX-1]/10) ==0)/*/判斷p1->bignum[99]的是否大於十;*/{ch=0+48;res += ch;ch=p1->bignum[MAX-1]+48;res += ch;}else{ch=p1->bignum[MAX-1]/10+48;res += ch;ch=p1->bignum[MAX-1]%10+48;res += ch;}for(i=0;i<p1->bignum[MAX-1];i++){ch=p1->bignum[i]+48;res += ch;}p=p->next;p1=(struct slink * )malloc(LEN);}while(p!=NULL);return res;}//! RSA的進行檔案解密的函數/*!   * @param[in] d,n為私密金鑰,由函數RSAKey()產生   * @param[in] text為密文,對應加密函數,密文的格式為string   * @return[string] 解密之後的明文採用string進行儲存   * @pre \e 進行解密的過程中進行了資料類型的轉換   * @see e,d,n & text*/string RSA::tdecrypto(int d[MAX], int n[MAX], string text){struct slink *h,*p1,*p2;char ch;int i,j,k,c,count,temp;i=0;j=3;count=0;h=p1=p2=(struct slink * )malloc(LEN);int kk;for (kk = 0; kk < text.length(); kk++){  ch = text.at(kk);c=ch;   if(j==3){p1->bignum[MAX-2]=c;j--;}else if(j==2){temp=c-48;j--;}else if(j==1){p1->bignum[MAX-1]=temp*10+c-48;j--;}else if (j==0){p1->bignum[i]=c-48;i++;if(i==p1->bignum[MAX-1]){ i=0;j=3;count++;if (count==1)h=p1;else p2->next=p1;p2=p1;p1=(struct slink * )malloc(LEN);}}}p2->next=NULL; p2=(struct slink * )malloc(LEN);p1=h;k=0;string res;if(h!=NULL)/*/temp為暫存ASIIC碼的int值*/do{for(i=0;i<MAX;i++)p2->bignum[i]=0;expmod( p1->bignum , d ,n ,p2->bignum);  temp=p2->bignum[0]+p2->bignum[1]*10+p2->bignum[2]*100;if (( p2->bignum[MAX-2])=='0'){temp=0-temp;}/*/轉化為正確的ASIIC碼,如-78-96形成漢字*/ ch=temp;/*  str[k]--->ch */res += ch;k++;p1=p1->next;p2=(struct slink * )malloc(LEN);}while (p1!=NULL);return res;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////** 產生密鑰,公開金鑰和私密金鑰* @param[in] 隨機產生大數密鑰* @param[in] 利用自訂的大數運算規則進行計算* @return 返回產產生功與否* – false 表示產生密鑰失敗* @pre \e 產生的金鑰儲存區在定義的類中變數中* @see e,d,n*/bool RSA::RSAKey(){for(i=0;i<MAX;i++)m[i]=p[i]=q[i]=n[i]=d[i]=e[i]=0;/*/簡單初始化一下*/prime_random(p,q);/*/隨機產生兩個大素數*/mul(p,q,n);mov(p,p1);p1[0]--;      mov(q,q1);q1[0]--;      /*/q-1;*/mul(p1,q1,m);//m=(p-1)*(q-1)erand(e,m);rsad(e,m,d);return true;}//////////////////////////

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.