RSA演算法

来源:http://www.cnblogs.com/first-001/archive/2017/01/04/6250500.html
-Advertisement-
Play Games

RSA.h #ifndef _RSA_H #define _RSA_H #include #include #include /* 密鑰產生: 1.隨機選定兩個大素數p, q. 2.計算公鑰和私鑰的公共模數 n = pq . 3.計算模數n的歐拉函數 φ(n) . 4.選定一個正整數e, 使1 e,... ...


RSA.h
#ifndef _RSA_H
#define _RSA_H
#include<stdio.h>
#include<iostream>
#include<math.h>
/*
密鑰產生:
1.隨機選定兩個大素數p, q.
2.計算公鑰和私鑰的公共模數 n = pq .
3.計算模數n的歐拉函數 φ(n) .
4.選定一個正整數e, 使1 < e < φ(n) , 且e與φ(n)互質.
5.計算d, 滿足 de ≡ 1  (mod φ(n) ), (k為某個正整數).
6.n與e決定公鑰, n與d決定私鑰.
*/
/*
加密:C=M^e mod n
*/
/*
解密:C=M^d mod n
*/
//#define RAND_MAX_64 9223372036854775807//最大素數2^63-1
//#define RAND_MIN_64 2147483647//最小素數2^31-1
#define RAND_MAX_64 1000000
#define RAND_MIN_64 1000
#define Max_64 9223372036854775807
#define Times 10//測試素數次數

class RSA
{
public:
    RSA();
    ~RSA(void);
    void encryption(__int64 *M,__int64 *C);
    void decryption(__int64 *C,__int64 *M);
        void getKey();//生成密鑰
    __int64 get_p(){return p;};
    __int64 get_q(){return q;};
    __int64 get_n(){return n;};
    __int64 get_o(){return o;};
    __int64 get_e(){return e;};
    __int64 get_d(){return d;};
private:
    __int64 Sqrt(__int64 num);                 //大數開平方根
    __int64 get_Prime();                       //得到大素數
    __int64 mod(__int64 a,__int64 m,__int64 n);//快速求模
    __int64 Euclid(__int64 a,__int64 b);       //歐幾里德演算法
    bool Prime_test(__int64 n);                //確定性測試
        bool Witness(__int64 a,__int64 n);         //概率測試
    bool Extended_Euclid(__int64 a,__int64 n,__int64 *d);  //擴展的歐幾里德演算法    
    //公鑰KU={e,n}
    //私鑰KR={d,p,q}/{d,n}
    __int64 p;//素數p
    __int64 q;//素數q
    __int64 n;//n=p*q
    __int64 o;//φ(n)=(p-1)(q-1)
    __int64 e;//隨機整數
    __int64 d;//d=e^-1
};
#endif
RSA.cpp
#include"RSA.h"
//構造函數
RSA::~RSA(){};
//析構函數
RSA::RSA(){};
//加密
void RSA::encryption(__int64 *M,__int64 *C){
    *C=RSA::mod(*M,this->e,this->n);
}
//解密
void RSA::decryption(__int64 *C,__int64 *M){
    *M=RSA::mod(*C,this->d,this->n);
}
//快速求模
//d=a^m mod n  b[k]=m=(101010010)
__int64 RSA::mod(__int64 a,__int64 m,__int64 n){
    __int64 b[500],k=0,i;
    __int64 c, d;
    for(;m!=0;m>>=1){
        if(m%2==0)
            b[k]=0;
        else
            b[k]=1;
        k++;
    }
    c=0;
    d=1;
    for(i=k;i>=0;i--){
        c=2*c;
        d=(d*d)%n;
        if(b[i]==1){
            c=c+1;
            d=(d*a)%n;
        }
        //printf("%lld ",c);
        //printf("%lld\n",d);
    }
    return d;
}
//確定性測試
//n素數
bool RSA::Prime_test(__int64 n){
    __int64 r=2;
    while(r<Sqrt(n)){
        if(n%r==0)
            return false;
        r=r+1;
    }
    return true;
}
//概率測試
//n為素數,a<n
bool RSA::Witness(__int64 a,__int64 n){
    __int64 m=n-1;
    __int64 b[500],k=0,i;
    __int64 d,x;
    for(;m!=0;m>>=1){
        if(m%2==0)
            b[k]=0;
        else
            b[k]=1;
        k++;
    }
    d=1;
    for(i=k;i>=0;i--){
        x=d;
        d=(d*d)%n;
        if(d==1&&x!=1&&x!=n-1)
            return true;//合數
        if(b[i]==1)
            d=(d*a)%n;
    }
    if(d!=1)
        return true;//合數
    return false;//可能是素數
}
//歐幾里德演算法
__int64 RSA::Euclid(__int64 a,__int64 b){
    __int64 x=b,y=a,r=0;
    if(y>0){
        r=x%y;
        x=y;
        y=r;
    }
    return x;
}
//擴展的歐幾里德演算法
//d=e^-1 mod n
bool RSA::Extended_Euclid(__int64 a,__int64 n,__int64 *d){
    __int64 x1=1,x2=0,x3;
    __int64 y1=0,y2=1,y3;
    __int64 t1,t2,t3,q;
    x3=(n>=a)?n:a;//大的數
    y3=(n>=a)?a:n;//小的數
    while(1){
        if(y3==0){
            *d=x3;
            return false;
        }
        if(y3==1){
            *d=y2;
            return true;
        }
        q=x3/y3;
        t1=x1-q*y1;
        t2=x2-q*y2;
        t3=x3-q*y3;
        x1=y1;x2=y2;x3=y3;
        y1=t1;y2=t2;y3=t3;
    }    
}
//得到大素數
__int64 RSA::get_Prime(){
    int flag=0; //
    int times=0;//測試素數次數
    __int64 a,n=0;
    while(flag==0){
        //步驟1
        step_1:flag=0;
        n = (__int64)(rand()%(RAND_MAX_64 - RAND_MIN_64+1))+RAND_MIN_64;    
        n=(n/2)*2+1;
            printf("%lld%\r",n);
        //步驟2
        if(Prime_test(n)==false){
            //返回步驟1
            goto step_1;
        }
        else{
            //步驟3
            step_3:a = (__int64)(rand()%(n-1-0+1))+1;//0<a<n
            //步驟4
            if(Witness(a,n)==true){
                //返回步驟1
                goto step_1;
            }
            else{
                times++;
                if(times>=Times){
                    flag=1;
                    return n;
                }
                else{
                    //返回步驟3
                    goto step_3;
                }
            }
        }
    }
    return 0;
}
//密鑰的生成
void RSA::getKey(){
    this->p = get_Prime();
    this->q = get_Prime();
    this->n = this->p*this->q;//n=p*q
    this->o = (this->p-1)*(this->q-1);//φ(n)=(p-1)(q-1)
    do{
        this->e = (__int64)(rand()%(this->o+1));//0<e<φ(n)
    }while(1==Euclid(this->e,this->o));//e與φ(n)互質
    //this->e = 3;
    if(true==Extended_Euclid(this->e,this->o,&(this->d))){
        while(this->d<=Sqrt(Sqrt(this->n))){
            Extended_Euclid(this->e,this->o,&(this->d));
        }
        printf("密鑰生成成功:%lld\n",this->d);        
    }
    else{
        RSA::getKey();
    }
}
//大數開根
__int64 RSA::Sqrt(__int64 num){
   __int64 low ,mid ,up;
   low = 1 ,up = num;
   if(up > Max_64) up = Max_64;
   __int64 mk = 0;
   while(low <= up){
      mid = (low + up) / 2;
      if(mid * mid > num){
         up = mid - 1;
      }
      else{
         low = mid + 1;
         mk = mid;
      }
   }
   return mk;
}
TEST.cpp
#include"RSA.h"
#include<stdio.h>

int main(){
         __int64 M=0,C=0;
        RSA rsa = RSA();
    printf("----------生成密鑰----------\n");
        rsa.getKey();
    printf("----------輸出密鑰----------\n");
    printf("p:%lld\n",rsa.get_p());
    printf("q:%lld\n",rsa.get_q());
    printf("n:%lld\n",rsa.get_n());
    printf("o:%lld\n",rsa.get_o());
    printf("e:%lld\n",rsa.get_e());
    printf("d:%lld\n",rsa.get_d());
    printf("----------加密信息----------\n");
    printf("請輸入明文:\n");
    scanf("%lld",&M);
    rsa.encryption(&M,&C);
    printf("加密後密文:%lld\n",C);
    printf("----------解密信息----------\n");
    printf("請輸入密文:\n");
    scanf("%lld",&C);
    rsa.decryption(&C,&M);
    printf("解密後明文:%lld\n",M);

    system("pause");
    return 0;
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • FullCalendar提供了豐富的屬性設置和方法調用,開發者可以根據FullCalendar提供的API快速完成一個日曆日程的開發,本文將FullCalendar的常用屬性和方法、回調函數等整理成中文文檔,以供參閱。當前版本1.6.4。 普通顯示設置 屬性 描述 預設值 header 設置日曆頭部 ...
  • AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); WindowsPrincipal principal = (WindowsPrincipal)Thread.CurrentPrincipal; ...
  • C# 基礎回顧 - 匿名方法 目錄 簡介 匿名方法的參數使用範圍 委托示例 簡介 在 C# 2.0 之前的版本中,我們創建委托的唯一形式 -- 命名方法。 而 C# 2.0 -- 引進了匿名方法,在 ≥ C# 3.0 的版本中,我們會用 Lambda 表達式進行取代匿名方法,並且用 Lambda 表 ...
  • 在《ASP.NET Core應用的錯誤處理[1]:三種呈現錯誤頁面的方式》中,我們通過幾個簡單的實例演示瞭如何呈現一個錯誤頁面,這些錯誤頁面的呈現分別由三個對應的中間件來完成,接下來我們將對這三個中間件進行詳細介紹。在開發環境呈現的異常頁面是通過一個類型為DeveloperExceptionPage... ...
  • 2009 年我讀了李笑來老師的《把時間當朋友》,知識了柳比歇夫的時間記錄法。當時激動壞了,馬上動手實踐起來。一開始的時候,是用一個小本子,走到哪兒都帶著。完成一件事,就記錄一下花費的時間。這樣的做法持續了一周多的時間,我發現每天浪費在 Google Reader 上的時間大幅度減少了。那個時候,我使 ...
  • 什麼是Servlet?① Servlet就是JAVA 類② Servlet是一個繼承HttpServlet類的類③ 這個在伺服器端運行,用以處理客戶端的請求 Servlet相關包的介紹--javax.servlet.* :存放與HTTP 協議無關的一般性Servlet 類;--javax.servl ...
  • 直接插入排序是將一個記錄插入到已經排好序的有序表中,從而得到一個新的記錄數加1的有序表。 下麵的代碼中會先假設數組的第一個元素是已經拍好序的有序表,然後從第二個元素開始遍歷剩下的元素。 所以呢,第一個for迴圈是遍歷待插入的元素,第二個for迴圈是遍歷被插入的有序表,並將待插入元素與有序表的元素比較 ...
  • 參考 http://www.cnblogs.com/chengmo/archive/2010/10/02/1841355.html 問題:bash怎麼提取字元串的最後一位?例如python中string[-1]就是python字元串最後一位。 echo ${PATH:((${#PATH} - 1)) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...