RSA非对称加密算法原理和代码实现 信息安全 密码学

一 欧拉数论定理

1. 欧拉函数

      设n为一正整数,则欧拉函数 φ ( n ) \varphi (n) φ(n)等于 0 ∼ n − 1 0\sim n-1 0n1中与n互素的整数个数
      比如 φ ( 5 ) = 4 \varphi (5) = 4 φ(5)=4,因为0~5中, 1,2,3,4均与5互素,即最大公约数为1

2. 欧拉定理

      设a,n为两个正整数,且(a,n)=1,则有: a φ ( n ) ≡ 1   m o d ( n ) a^{\varphi (n)} \equiv 1 \, mod (n) aφ(n)1mod(n)

二 RSA数学原理

      给定两个不同的素数p,q,令n=p*q,则 φ ( n ) = ( p − 1 ) ( q − 1 ) \varphi (n) = (p-1)(q-1) φ(n)=(p1)(q1),对于满足 c d ≡ 1 m o d ( φ ( n ) ) cd \equiv 1 mod (\varphi (n)) cd1mod(φ(n))的两个正整数c,d,显然满足: a c d ≡ a   m o d ( n ) a^{cd} \equiv a \, mod (n) acdamod(n)

(1) 对于明文M,则有密文C=M^e mod n  (获得密文是明文的e次方再模n)    
(2) 对于密文C,则有明文M=C^d mod n  (获得明文是密文的d次方再模n)

      明文和密文的产生是建立在一对密钥的基础上的,即(e,n)和(d,n) 。其中,(e,n)称为公钥 , (d,n)称为私钥。公钥在网络中公开,谁都可以使用;私钥在本地保存,仅限自己使用。根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因而在大素数条件下根据公钥去计算私钥是比较耗时的过程,由此保证了信息的安全。

三 Python实现RSA

import random

'''
计算两个整数的最大公因数,采用欧几里得算法,其原理具体描述为:
假设 a = t*b + r ,那么a与b最大公约数等于b与r最大公约数
gcd(a,b) = gcd(b,r)
'''


def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a


'''
当满足 ab同余1模m 时,b即为 a模m 下的逆,采用欧几里得算法反推计算
A1 = T1*A2 + A3
A2 = T2*A3 + A4
......
An = Tn*A(n+1) + A(n+2)
结束时,A(n+2) = 1
'''


def inverse(e, phi):
    a, b, t = phi, e, 0
    x, y = 0, 0
    x1, y1 = 1, 0
    x2, y2 = 0, 1
    while (a % b) != 1:
        t = a // b
        x, y = x2, y2
        x2, y2 = x1 - t * x2, y1 - t * y2
        x1, y1 = x, y
        a, b = b, a % b
    t = a // b
    x, y = x1 - t * x2, y1 - t * y2
    return (y + ((abs(y)) // phi + 1) * phi) % phi


'''
测试所选整数是不是质数
'''


def is_prime(num):
    if num == 2:
        return True
    if num < 2 or num % 2 == 0:
        return False
    for n in range(3, int(num ** 0.5) + 2, 2):
        if num % n == 0:
            return False
    return True


'''
生成公钥和私钥
'''


def generate_key_pair(p, q):
    if not (is_prime(p) and is_prime(q)):
        raise ValueError('Both numbers must be prime.')
    elif p == q:
        raise ValueError('p and q cannot be equal')
    if p < 11 or q < 11:
        raise ValueError('p or q should larger than 10')  # 保证n大于128,容纳ASCII字符
    n = p * q
    phi = (p - 1) * (q - 1)
    e = random.randrange(1, phi)
    g = gcd(e, phi)
    while g != 1:
        e = random.randrange(1, phi)
        g = gcd(e, phi)
    d = inverse(e, phi)
    # Public key is (e, n) and private key is (d, n)
    return ((e, n), (d, n))


def encrypt(pk, plaincode):
    key, n = pk
    ciphercode = [pow(code, key, n) for code in plaincode]
    return ciphercode


def decrypt(pk, ciphercode):
    key, n = pk
    plaincode = [pow(code, key, n) for code in ciphercode]
    plaintext = [chr(code) for code in plaincode]
    return ''.join(plaintext)


if __name__ == '__main__':
    '''
    Detect if the script is being run directly by the user
    '''
    print("===========================================================================================================")
    print("================================== RSA Encryptor / Decrypter ==============================================")
    print(" ")
    p = int(input(" - Enter a prime number (11, 13, 17, 19, 23, etc): "))
    q = int(input(" - Enter another prime number (Not one you entered above): "))
    print(" - Generating your public / private key-pairs now . . .")
    public, private = generate_key_pair(p, q)
    print(" - Your public key is ", public, " and your private key is ", private)
    message = input(" - Enter a message to encrypt with your public key: ")
    plaintext = [char for char in message]
    plaincode = [ord(char) for char in message]
    print(" - Your plaintext is: ", plaintext, "and your plaincode is: ", plaincode)
    print(" - Encrypting message with public key ", public, " . . .")
    ciphercode = encrypt(public, plaincode)
    ciphertext = [chr(code) for code in ciphercode]
    print(" - Your ciphertext is: ", ciphertext, "and your ciphercode is: ", ciphercode)
    print(" - Decrypting message with private key ", private, " . . .")
    print(" - Your message is: ", decrypt(private, ciphercode))
    print(" ")
    print("============================================ END ==========================================================")
    print("===========================================================================================================")

四 C语言实现RSA

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <wchar.h>
using namespace std;
// 计算最大公因数
int gcd(long int a, long int b){
    return b==0?a:gcd(b,a%b);
}
// 计算模phi的逆
int inverse(long int e, long int phi){
    long int a=phi, b=e, t=0;
    long int x=0, y=1;
    while(a%b!=1){
        t = x;
        x = y;
        y = t-y*(a/b);
        t = a;
        a = b;
        b = t%a;
    }
    return ((x-y*(a/b))%phi+phi)%phi;
}
//检测是不是质数
int is_prime(long int num){
    if (num==2) return 1;
    if (num<2||num%2==0) return 0;
    long int n = 3;
    while(1){
        if (n*n>num) return 1;
        if (num%n==0) return 0;
        n += 2;
    }
}
void generate_key_pair(long int p, long int q, long int* r){
    if (!(is_prime(p)&&is_prime(q))){
        printf("Both numbers must be prime.");
        exit(2);
    }
    if (p==q||p+q<24){
        printf("p and q cannot be equal.");
        exit(2);
    }
    long int n = p * q;
    long int phi = (p - 1) * (q - 1);
    srand((unsigned)time(NULL));
    long int e = (rand()+1)%phi;
    long int g = gcd(e, phi);
    while (g != 1){
        e = (e+rand()+1)%phi;
        g = gcd(e, phi);
    }
    long int d = inverse(e, phi);
    // Public key is (e, n) and private key is (d, n)
    r[0] = e;
    r[1] = n;
    r[2] = d;
    r[3] = n;
}
// 指数取模运算
long int ModExp(long int base, long int exp, long int mod){
    long int res = 1;
    while(exp){
        if (exp%2==1) res = (res*base) % mod;
        exp /= 2;
        base = (base*base) % mod;//底数平方
    }
    return res;
}
void encrypt(long int* pk, long int* plaincode, long int* ciphercode, int length){
    int key=pk[0], n=pk[1];
    for (int i=0;i<length;i++) ciphercode[i] = ModExp(plaincode[i],key,n);
}
wstring decrypt(long int* pk, long int* ciphercode, int length){
    int key=pk[0], n=pk[1];
    wstring result;
    long int* plaincode = (long int*)malloc(length*sizeof(long int));
    for (int i=0;i<length;i++) plaincode[i] = ModExp(ciphercode[i],key,n);
    for (int i=0;i<length;i++) result = result + wchar_t(plaincode[i]);
    return result;
}
int main(){
    printf("===========================================================================================================\n");
    printf("================================== RSA Encryptor / Decrypter ==============================================\n");
    long int p,q;
    printf(" - Enter a prime number (11, 13, 17, 19, 23, etc): ");
    cin >> p;
    printf(" - Enter another prime number (Not one you entered above): ");
    cin >> q;
    long int* key_pairs = (long int*)malloc(4*sizeof(long int));
    printf(" - Generating your public / private key-pairs now . . .\n");
    generate_key_pair(p,q,key_pairs);
    long int* key_public = (long int*)malloc(2*sizeof(long int));
    long int* key_private = (long int*)malloc(2*sizeof(long int));
    key_public[0]=key_pairs[0];
    key_public[1]=key_pairs[1];
    key_private[0]=key_pairs[2];
    key_private[1]=key_pairs[3];
    printf(" - Your public key is (%ld,%ld) and your private key is (%ld,%ld)\n",key_public[0],key_public[1],key_private[0],key_private[1]);
    printf(" - Enter a message to encrypt with your public key: ");
    wstring message;
    wcin >> message;
    int length = message.size();
    long int* plaincode = (long int*)malloc(length*sizeof(long int));
    long int* ciphercode = (long int*)malloc(length*sizeof(long int));
    for (int i=0;i<length;i++) plaincode[i] = message[i];
    cout << " - Your plaintext is: [";
    for (int i=0;i<length;i++) wcout << " " << message[i] << " ";
    cout << "]    and your plaincode is: [";
    for (int i=0;i<length;i++) cout << " " << plaincode[i] << " ";
    cout << " ]" << endl;
    printf(" - Encrypting message with public key (%ld, %ld) . . .\n", key_public[0], key_public[1]);
    encrypt(key_public,plaincode,ciphercode,length);
    cout << " - Your ciphertext is: [";
    for (int i=0;i<length;i++) wcout << " " << wchar_t(ciphercode[i]) << " ";
    cout << "]    and your ciphercode is: [";
    for (int i=0;i<length;i++) cout << " " << ciphercode[i] << " ";
    cout << " ]" << endl;
    printf(" - Decrypting message with private key (%ld, %ld) . . .\n", key_private[0], key_private[1]);
    wstring ws = decrypt(key_private, ciphercode,length);
    wcout << " - Your message is: " << ws << endl;
    printf("============================================ END ==========================================================\n");
    printf("===========================================================================================================\n");
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦星辰.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值