RSA

RSA加密利用了单向函数正向求解很简单,反向求解很复杂的特性


基本概念


一、 什么是“素数”?
  素数是这样的整数,它除了能表示为它自己和1的乘积以外,不能表示为任何其它两个整数的乘积。例如,15=3*5,所以15不是素数;又如,12=6*2=4*3,所以12也不是素数。另一方面,13除了等于13*1以外,不能表示为其它任何两个整数的乘积,所以13是一个素数。素数也称为“质数”。

二、什么是“互质数”(或“互素数”)?
  小学数学教材对互质数是这样定义的:“公约数只有1的两个数,叫做互质数。”这里所说的“两个数”是指自然数。
  判别方法主要有以下几种(不限于此):
(1)两个质数一定是互质数。例如,2与7、13与19。
(2)一个质数如果不能整除另一个合数,这两个数为互质数。例如,3与10、5与 26。
(3)1不是质数也不是合数,它和任何一个自然数在一起都是互质数。如1和9908。
(4)相邻的两个自然数是互质数。如 15与 16。
(5)相邻的两个奇数是互质数。如 49与 51。
(6)大数是质数的两个数是互质数。如97与88。
(7)小数是质数,大数不是小数的倍数的两个数是互质数。如 7和 16。
(8)两个数都是合数(二数差又较大),小数所有的质因数,都不是大数的约数,这两个数是互质数。如357与715,357=3×7×17,而3、7和17都不是715的约数,这两个数为互质数。等等。

三、什么是模指数运算?
  指数运算谁都懂,不必说了,先说说模运算。模运算是整数运算,有一个整数m,以n为模做模运算,即m mod n。怎样做呢?让m去被n整除,只取所得的余数作为结果,就叫做模运算。例如,10 mod 3=1;26 mod 6=2;28 mod 2 =0等等。
  模指数运算就是先做指数运算,取其结果再做模运算。如(5^3) mod 7 = (125 mod 7) = 6。

RSA加解密


RSA属于公钥加密算法中的一个重要应用。RSA加密算法由五个部分组成:

  • 原文(Message):需要加密的信息,可以是数字、文字、视频、音频等,用 MMM 表示。
  • 密文(Ciphertext):加密后得到的信息,用 CCC表示。
  • 公钥(Public Key)和私钥(Secret Key),用PKPKPK 和 SKSKSK表示。
  • 加密算法(Encryption):若E(x)E(x)E(x) 为加密算法,加密过程可以理解为C=E(M)C = E(M)C=E(M)根据原文和加密算法得到密文。
  • 解密算法(Decryption):若D(x)D(x)D(x)为解密算法,解密过程可以理解为M=D(C)M = D(C)M=D(C)据密文和解密算法得到原文。

假设Alice和Bob要在网上进行加密通信,他们要怎么应用RSA来加密和解密信息呢?步骤如下:

  1. 随机选择两个不相同的素数 p,qp,qp,q 。
  2. 将p,qp,qp,q相乘,记为n=p×qn = p\times qn=p×q 。
  3. 计算nnn的欧拉函数φ(n)\varphi(n)φ(n) ,欧拉函数证明,当 p,qp,qp,q为不相同的素数时,φ(n)=(p−1)(q−1)\varphi(n)=(p-1)(q-1)φ(n)=(p−1)(q−1) 。
  4. 随机选择一个整数 eee,满足两个条件:φ(n)\varphi(n)φ(n) 与 eee互质,且1<e<φ(n)1<e<\varphi(n)1<e<φ(n) 。
  5. 计算 eee对于φ(n)\varphi(n)φ(n) 的模反元素ddd,也就是说找到一个ddd满足 ed=1modφ(n)ed = 1 mod\varphi(n)ed=1modφ(n)。这个式子等价于ed−1=kφ(n)ed-1 = k\varphi(n)ed−1=kφ(n),实际上就是对于方程ed−kφ(n)=1ed-k\varphi(n) = 1ed−kφ(n)=1求(d,k)(d,k)(d,k)的整数解。这个方程可以用扩展欧几里得算法求解。
  6. 最终把(e,n)(e,n)(e,n)封装成公钥,(d,n)(d,n)(d,n)封装成私钥。

我们举个实际例子运行一遍这个算法。



RSA算法

Java版本

package com.tencent.blue.utils;import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.IOUtils;import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;/*** Created by cuiran on 19/1/9.*/
public class RSAUtils {public static final String CHARSET = "UTF-8";public static final String RSA_ALGORITHM = "RSA";public static Map<String, String> createKeys(int keySize){//为RSA算法创建一个KeyPairGenerator对象KeyPairGenerator kpg;try{kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);}catch(NoSuchAlgorithmException e){throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");}//初始化KeyPairGenerator对象,密钥长度kpg.initialize(keySize);//生成密匙对KeyPair keyPair = kpg.generateKeyPair();//得到公钥Key publicKey = keyPair.getPublic();String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());//得到私钥Key privateKey = keyPair.getPrivate();String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());Map<String, String> keyPairMap = new HashMap<String, String>();keyPairMap.put("publicKey", publicKeyStr);keyPairMap.put("privateKey", privateKeyStr);return keyPairMap;}/*** 得到公钥* @param publicKey 密钥字符串(经过base64编码)* @throws Exception*/public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {//通过X509编码的Key指令获得公钥对象KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);return key;}/*** 得到私钥* @param privateKey 密钥字符串(经过base64编码)* @throws Exception*/public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {//通过PKCS#8编码的Key指令获得私钥对象KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);return key;}/*** 公钥加密* @param data* @param publicKey* @return*/public static String publicEncrypt(String data, RSAPublicKey publicKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicKey);return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));}catch(Exception e){throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);}}/*** 私钥解密* @param data* @param privateKey* @return*/public static String privateDecrypt(String data, RSAPrivateKey privateKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);}catch(Exception e){throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);}}/*** 私钥加密* @param data* @param privateKey* @return*/public static String privateEncrypt(String data, RSAPrivateKey privateKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, privateKey);return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));}catch(Exception e){throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);}}/*** 公钥解密* @param data* @param publicKey* @return*/public static String publicDecrypt(String data, RSAPublicKey publicKey){try{Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, publicKey);return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);}catch(Exception e){throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);}}private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){int maxBlock = 0;if(opmode == Cipher.DECRYPT_MODE){maxBlock = keySize / 8;}else{maxBlock = keySize / 8 - 11;}ByteArrayOutputStreamout = new ByteArrayOutputStream();int offSet = 0;byte[] buff;int i = 0;try{while(datas.length > offSet){if(datas.length-offSet > maxBlock){buff = cipher.doFinal(datas, offSet, maxBlock);}else{buff = cipher.doFinal(datas, offSet, datas.length-offSet);}out.write(buff, 0, buff.length);i++;offSet = i * maxBlock;}}catch(Exception e){throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);}byte[] resultDatas = out.toByteArray();IOUtils.closeQuietly(out);return resultDatas;}public static void main (String[] args) throws Exception {Map<String, String> keyMap = RSAUtils.createKeys(1024);String  publicKey = keyMap.get("publicKey");String  privateKey = keyMap.get("privateKey");System.out.println("公钥: \n\r" + publicKey);System.out.println("私钥: \n\r" + privateKey);System.out.println("公钥加密——私钥解密");String str = "code_cayden";System.out.println("\r明文:\r\n" + str);System.out.println("\r明文大小:\r\n" + str.getBytes().length);String encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(publicKey));System.out.println("密文:\r\n" + encodedData);String decodedData = RSAUtils.privateDecrypt(encodedData, RSAUtils.getPrivateKey(privateKey));System.out.println("解密后文字: \r\n" + decodedData);}}

C++

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include<string.h>
#include <math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int e, d, n;int gcd(int a, int b)  //求最大公约数
{int c = 0;if(a<b) swap(a,b);c = b;do{b = c;c = a%b;a = b;}while (c != 0);return b;
}int PrimarityTest(int a, int i) //判断i是否是素数
{int flag=0;for(a;a<i;a++){if(i%a==0){flag=1;break;}}if(flag) return 0;return 1;// complete this part
}int ModularExponention(int a, int b, int n)  //求a^bmodn
{int y;/*使用二进制平方乘法计算 pow(a,b) % n*/y=1;while(b != 0){/*对于b中的每个1,累加y*/if(b & 1)y = (y*a) % n;/*对于b中的每一位,计算a的平方*/a = (a*a) % n;/*准备b中的下一位*/b = b>>1;}return y;// complete this part
}void extgcd(ll a,ll b,ll& d,ll& x,ll& y) //获取(1/a)modb得结果
{if(!b){d=a;x=1;y=0;}else{extgcd(b,a%b,d,y,x);y-=x*(a/b);}
}int ModularInverse(int a,int b)  //获取(1/a)modb得结果
{ll d,x,y;extgcd(a,b,d,x,y);return d==1?(x+b)%b:-1;// complete this part
}void KeyGeneration()  //获取公钥密钥
{int p, q;int phi_n;do{dop = rand();while (p % 2 == 0);}while (!PrimarityTest(2, p));do{doq = rand();while (q % 2 == 0);}while (!PrimarityTest(2, q));n = p * q;phi_n = (p - 1) * (q - 1);doe = rand() % (phi_n - 2) + 2; // 1 < e < phi_nwhile (gcd(e, phi_n) != 1);d = ModularInverse(e,phi_n);
}void Encryption(int value, FILE* out)  //加密
{int cipher;cipher = ModularExponention(value, e, n);fprintf(out, "%d ", cipher);
}void Decryption(int value, FILE* out)  //解密
{int decipher;decipher = ModularExponention(value, d, n);fprintf(out, "%c", decipher);
}
int main(void)
{FILE* inp, * out;char filepath[15], filename[100];strcpy(filepath, "F:\Desktop\\");  //文件路径sprintf(filename, "%s%s", filepath, "cipher.txt");out = fopen(filename, "w+");  //打开文件fclose(out);sprintf(filename, "%s%s", filepath, "decipher.txt");out = fopen(filename, "w+");  //打开文件fclose(out);KeyGeneration();  //获取公钥密钥sprintf(filename, "%s%s", filepath, "plain.txt");inp = fopen(filename, "r+");  //读取原文件if (inp == NULL){printf("Error opening Source File.\n");exit(1);}sprintf(filename, "%s%s", filepath, "cipher.txt");out = fopen(filename, "w+");if (out == NULL){printf("Error opening Destination File.\n");exit(1);}// encryption startswhile (1){char ch = getc(inp);  //读取文件字符,一个字符一个字符的读取输出if (ch == -1)break;int value = toascii(ch);  //toascii将字符转化成对应ascall值Encryption(value, out);  //加密输出}fclose(inp);fclose(out);// decryption startssprintf(filename, "%s%s", filepath, "cipher.txt");inp = fopen(filename, "r");if (inp == NULL){printf("Error opening Cipher Text.\n");exit(1);}sprintf(filename, "%s%s", filepath, "decipher.txt");out = fopen(filename, "w+");if (out == NULL){printf("Error opening File.\n");exit(1);}while (1){int cip;if (fscanf(inp, "%d", &cip) == -1)break;Decryption(cip, out);  //解密}fclose(out);return 0;
}

密码为什么一定要用到素数(质数)?

这个问题谁能回答我一下?

密码学—RSA(非对称加密)相关推荐

  1. JSON 接口如何实现 RSA 非对称加密与签名

    代码地址如下: http://www.demodashi.com/demo/14000.html 一.概述 1. 数字签名的作用:保证数据完整性,机密性和发送方角色的不可抵赖性,加密与签字结合时,两套 ...

  2. CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互

    (以下代码中都只做测试用,有些地方没有释放内存...这个自己解决下) 1.RSA非对称的,首先提供一个供测试用的证书和私钥的数据 1)pem格式的证书和私钥(公私钥是对应的)的base64编码 [cp ...

  3. php利用openssl实现RSA非对称加密签名

    来源:http://www.webiji.com/archives/412 php利用openssl实现RSA非对称加密签名 1. 先用php生成一对公钥和私钥 $res = openssl_pkey ...

  4. Atitit RSA非对称加密原理与解决方案

    Atitit RSA非对称加密原理与解决方案 1.1. 一.一点历史 1 1.2. 八.加密和解密 2 1.3. 二.基于RSA的消息传递机制  3 1.4. 基于rsa的授权验证机器码 4 1.5. ...

  5. java rsa 117_java实现RSA非对称加密解密

    之前写过一篇java实现AES对称加密解密 在对密码加密传输的场景下 RSA非对称加密解密可能会更加适合. 原理就是后台生成一对公钥和私钥,公钥给前端用来加密,后台用私钥去解密,保证了传输过程中就算被 ...

  6. 前后端数据加密传输 RSA非对称加密

    任务需求:要求登陆时将密码加密之后再进行传输到后端. 经过半天查询摸索折腾,于是有了如下成果: 加密方式:RSA非对称加密. 实现方式:公钥加密,私钥解密. 研究进度:javascript与java端 ...

  7. Springboot+RSA非对称加密

    这是百度百科对(对称加密丶非对称加密)的解释: (1)对称加密算法在加密和解密时使用的是同一个秘钥. (2)非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称 ...

  8. 微信小程序RSA非对称加密。

    因公司做的产品为金融项目,所以对数据安全性有很高要求,因为项目中的数据都会通过3DES 对称加密,和RSA非对称加密进行数据传输. 在这里先简单介绍一下什么是对称加密和非对称加密 对称加密:对称加密采 ...

  9. 数据加密 RSA非对称加密篇

    先把代码贴上来,理论后续补充,暂时可先参考数据加密 总篇 package com.jlpay.partner.utils;import android.util.Base64;import java. ...

最新文章

  1. 需要注意变量作用域的使用
  2. vscode配置C/C++ windows编译环境。
  3. layui父页面调用子页面的渲染_layUI ajax加载html页面后重新渲染的方法
  4. Tomcat类加载器为何违背双亲委派模型
  5. python socket tcp实战_python socket 实战
  6. img默认图片的问题
  7. 有序充电matlab仿真,电动汽车有序充电策略研究
  8. JS 中的call,apply,bind 和 caller, callee
  9. 现有Android项目中集成Flutter/Flutter混合开发实战(一)
  10. Android Textview控件基础属性
  11. 手工做迷宫_手工DIY好玩双人大型立体迷宫玩具
  12. linux启动和grub修复
  13. html银河特效编码,html5 canvas银河星系动画特效
  14. Method threw ‘feign.codec.DecodeException‘ exception.
  15. 仿微信、qq聊天,@好友功能
  16. Hbuilder 运行到手机上找不到真机 解决办法
  17. Core Data概述
  18. 构建属于自己的 jre Docker 镜像
  19. 【递归】进制转换、字符串反转、判断回文
  20. 关于“sin(10°)是无理数”的一个证明

热门文章

  1. 微博掘金旅游大数据,商业化的好选择?
  2. php 同步代码,PHP进程同步代码实例_PHP
  3. 挖宝AI语音芯片:语音公司大爆发还是集体作秀?
  4. python数据科学包第二天
  5. 病床呼叫系统有显示屏c语言,病床呼叫系统毕业设计
  6. i3处理器_i3-8100F是什么意思?i3-8100F和8100的区别
  7. 中兴手机发布Blade V9系列,这是首款集成FOTONATION和DTS解决方案的移动设备
  8. 原画分享图文教程(含胶囊,小猫,饮料,水珠,皮毛)
  9. 连接两个路由器在同一网段
  10. form表单文件上传