RSA加密算法原理及其Java实现

  • RSA加密算法的基本原理
    • 主要步骤
    • 解密过程证明
  • java实现

简单介绍了RSA加密算法的原理及其Java实现:原文过长时,进行了分段加密。

RSA加密算法的基本原理

主要步骤

本文所有的字母都为正整数。
其主要步骤如下:
1、取两个不相等的质数p、q,一般都比较大。例如:p=67,q=79。
2、n=p×q,其中n所对应的二进制长度即为密钥的长度,一般为1024位或2048位。n=67×79=5293,转化为二进制数为1 0100 1010 1101,共13位。
3、计算n的欧拉函数f(n):
欧拉函数f(n)定义为:小于n的正整数中和n组成互斥关系的正整数的个数。由欧拉函数的性质:(1)如果正整数可以分解为两个互斥整数之积,则有该正整数的欧拉函数等于两个互斥整数的欧拉函数之积;(2)如果整数为质数,其欧拉函数为该整数减一。则有:
f(n)=f(p)∗f(q)=(p−1)∗(q−1)(1)f(n)=f(p)*f(q)=(p-1)*(q-1)\tag{1}f(n)=f(p)∗f(q)=(p−1)∗(q−1)(1)
f(n)=66×78=5148
4、任选一整数x满足1<x<f(n),且x与f(n)互斥。选x=19
5、计算x关于f(n)的模反元素y,即满足:
(x∗y)%f(n)=1xy=hf(n)+1(2)(x*y)\%f(n)=1\tag{2}\\ xy=hf(n)+1(x∗y)%f(n)=1xy=hf(n)+1(2)
%为取余。
通过扩展欧几里得算法求解19y=5148h+1:

求得y=271,h=-1。
则(n,x)为公钥,(n,y)为私钥,假设原文为a(这里的原文是要转换为ascii码或者其他编码方式,用数字表示),且a小于n,则获取密文b的加密过程为:
b=ax%n(3)b=a^{x}\%n\tag{3}b=ax%n(3)
解密过程为:
a=by%n(4)a=b^{y}\%n\tag{4}a=by%n(4)
假设传递字符A,其ascii码值为65,则通过(3)式计算得到b=1863,通过(4)式解密得到a=65。注意这里数字足够大,以至于使用普通整数计算得到的结果是错误的。

BigInteger num1 = new BigInteger("65");
BigInteger num2 = new BigInteger("5293");
BigInteger b = num1.pow(19).mod(num2);
System.out.println(b);
System.out.println("普通的整数运算是错误的:"+Math.pow(65, 19)%5293);
BigInteger a = b.pow(271).mod(num2);
System.out.println(a);
// 输出为:
1863
普通的整数运算是错误的:4055.0
65

可靠性说明:因为公钥是公开的,所以破解的方法就是获取y,那么在已知n和x的情况下能否求解出y呢?
(1)通过步骤5可知,只有知道x和f(n)才能求解y;
(2)要计算f(n)需要得到p和q;
(3)n=pq,只有将n进行因式分解才能算出p和q。
大整数的因式分解是很难的,所以RSA加密算法可靠。

解密过程证明

下面给出解密公式正确性的证明,即证明(4)式成立:
通过(3)式得:
b=ax−kn(5)b=a^{x}-kn\tag{5}b=ax−kn(5)
将(5)式代入到(4)式等号右边得:
by%n=(ax−kn)y%n=(axy+nK(n))%n=axy%n(6)b^{y}\%n=(a^{x}-kn)^{y}\%n=(a^{xy}+nK(n))\%n=a^{xy}\%n\tag{6}by%n=(ax−kn)y%n=(axy+nK(n))%n=axy%n(6)
这里用到了多项式的因式分解:
(x+y)n=xn+(n1)xyn−1+...+(nn−1)xn−1y+yn(7)(x+y)^n=x^n+\binom{n}{1}xy^{n-1}+...+\binom{n}{n-1}x^{n-1}y+y^{n}\tag{7}(x+y)n=xn+(1n​)xyn−1+...+(n−1n​)xn−1y+yn(7)
其中只有第一项不包含y。
将(2)式代入到(6)式,则只需要证明:
ahf(n)+1%n=a(8)a^{hf(n)+1}\%n=a\tag{8}ahf(n)+1%n=a(8)
下面分情况进行讨论:
情况1、a和n互斥。
这里引入欧拉定理:如果a和n互斥,n的欧拉函数为f(n),则
af(n)%n=1(9)a^{f(n)}\%n=1\tag{9}af(n)%n=1(9)
根据欧拉定理:
af(n)=1+gn→ahf(n)=(1+gn)hahf(n)+1=af(n)∗a=(1+gn)h∗a=(1+hgn+...+hgh−1nh−1+ghnh)a(10)a^{f(n)}=1+gn→a^{hf(n)}=(1+gn)^{h}\\ a^{hf(n)+1}=a^{f(n)}*a=(1+gn)^{h}*a=(1+hgn+...+hg^{h-1}n^{h-1}+g^{h}n^{h})a\tag{10}af(n)=1+gn→ahf(n)=(1+gn)hahf(n)+1=af(n)∗a=(1+gn)h∗a=(1+hgn+...+hgh−1nh−1+ghnh)a(10)
将(10)式代入到(8)式,则可证明(8)式成立。
情况2、a和n不互斥。
由于n为两个质数的乘积,a<n,所以必有a=kp或a=kq,不妨假设a=kp,此时a与q互斥。根据欧拉定理:
af(q)%q=1→af(q)=1+gq(11)a^{f(q)}\%q=1→a^{f(q)}=1+gq\tag{11} af(q)%q=1→af(q)=1+gq(11)
ahf(n)+1%q=(af(q))f(p)∗a%q=(1+gq)f(p)∗a%q=aahf(n)+1=a+tq(12)a^{hf(n)+1}\%q=(a^{f(q)})^{f(p)}*a\%q=(1+gq)^{f(p)}*a\%q=a\tag{12}\\ a^{hf(n)+1}=a+tqahf(n)+1%q=(af(q))f(p)∗a%q=(1+gq)f(p)∗a%q=aahf(n)+1=a+tq(12)
因为a=kp,所以必然有:
ahf(n)+1%p=0(13)a^{hf(n)+1}\%p=0\tag{13}ahf(n)+1%p=0(13)

(a+tq)%p=tq%p=0(14)(a+tq)\%p=tq\%p=0\tag{14}(a+tq)%p=tq%p=0(14)
又因为pq互斥,则由t=rp,代入到式(12)得:
ahf(n)+1=a+rpq=a+rn(a+rn)%n=a→ahf(n)+1%n=aa^{hf(n)+1}=a+rpq=a+rn\\ (a+rn)\%n=a→a^{hf(n)+1}\%n=aahf(n)+1=a+rpq=a+rn(a+rn)%n=a→ahf(n)+1%n=a
得证(8)式。
结合情况1、2,则可证明解密公式得正确性。

java实现

package mytest;import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;import javax.crypto.Cipher;public class RSAUtil {// 密钥长度,可调public static int keyLength = 1025;// 注意这里1024对应128byte,其中11byte用来存储相关信息,所以1024最多加密117Byte数据// 若超过117Byte需要分段,计算公式为keyLength/8并向上取整再减去11// 解密时候长度为keyLength/8向上取整// 存储密钥public static Map<String, String> keyMap = new HashMap<String, String>();public static void main(String[] args) throws Exception {//生成公钥和私钥geneKeyPair();// 输入原文System.out.print("输入原文:");Scanner in = new Scanner(System.in);String message = in.nextLine();//String message = "1aa";System.out.println("随机生成的公钥为:" + keyMap.get("publicKey"));System.out.println("随机生成的私钥为:" + keyMap.get("privateKey"));//加密字符串String messageEnctypt = encrypt(message, keyMap.get("publicKey"));System.out.println("原文:"+message + "\n加密后的字符串为:" + messageEnctypt);String messageDecrypt = decrypt(messageEnctypt, keyMap.get("privateKey"));System.out.println("还原后的字符串为:" + messageDecrypt);in.close();}/*** function:随机生成密钥对并存放在keyMap中* 也可以直接保存RSAPublicKey对象和RSAPrivateCrtKey对象* 一般情况下密钥可能会保存在本地或者其他地方,然后直接读取密钥,这时候存储的一般是密钥字符串* @throws NoSuchAlgorithmException */public static void geneKeyPair() throws NoSuchAlgorithmException {// RSA密钥生成器KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");// 初始化密钥生成器keyPairGenerator.initialize(keyLength, new SecureRandom());// 生成密钥对并保存KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 公钥RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyPair.getPrivate();  // 私钥String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());  // 公钥字符串String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());  // 私钥字符串// 存放keyMap.put("publicKey", publicKeyString);keyMap.put("privateKey", privateKeyString);}/** function:加密* @param 明文* @param 公钥字符串,十六进制字符串* @return 密文* @throws Exception*/public static String encrypt(String input, String publicKeyString) throws Exception {// 从字符串获取公钥byte[] decoded = Base64.getDecoder().decode(publicKeyString.getBytes());RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); // 加密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] inputArr = input.getBytes();StringBuilder output = new StringBuilder();int splitLength = (int) Math.ceil((float)keyLength/8) - 11;  // 分段长度for(int i = 0; i < inputArr.length; i += splitLength) {  // 分段加密int len = inputArr.length-i >= splitLength ? splitLength :  inputArr.length-i;output.append(byteArray2HexString(cipher.doFinal(Arrays.copyOfRange(inputArr, i, i+len))));}return output.toString();}/** function:私钥解密* @param 密文* @param 私钥字符串* @return 明文* @throws Exception*/public static String decrypt(String input, String privateKeyString) throws Exception {// 从字符串获取私钥byte[] decoded = Base64.getDecoder().decode(privateKeyString.getBytes());RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); // 解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);int splitLength = (int) Math.ceil((float)privateKey.getModulus().bitLength()/8);  // 分段长度byte[] inputArr = hexString2byteArray(input);StringBuilder output = new StringBuilder();for(int i = 0; i < inputArr.length; i += splitLength) {  // 分段解密int len = inputArr.length-i >= splitLength ? splitLength :  inputArr.length-i;output.append(new String(cipher.doFinal(Arrays.copyOfRange(inputArr, i, i+len))));}return output.toString();}public static int getKeyLength() {return keyLength;}/** function:设置密钥长度*/public static void setKeyLength(int keyLength) {// RSA keys must be at least 512 bits longif(keyLength < 512) {keyLength = 512;}RSAUtil.keyLength = keyLength;}/** function:byte[]转换为十六进制字符串* byte占8位,可以用两位16进制数表示* @param byte[]* @return String*/public static String byteArray2HexString(byte[] bytes) {StringBuilder output = new StringBuilder();String temp;for(byte b : bytes) {temp = Integer.toHexString(0xff & b);if(temp.length() == 1) {output.append(0);}output.append(temp);}return output.toString();}/** function:十六进制字符串转换位byte[]* @param String* @return byte[]*/public static byte[] hexString2byteArray(String hexString) {int len = hexString.length() / 2;byte[] output = new byte[len];for(int i = 0; i < len; i++) {int pos = i * 2;output[i] = (byte) (char2Byte(hexString.charAt(pos)) << 4 | char2Byte(hexString.charAt(pos+1)));}return output;}/** function: char转换位byte,这里的char只包含0123456789abcdef* @param char* @return byte*/private static byte char2Byte(char c) {byte b = (byte)"0123456789abcdef".indexOf(c);return b;}
}

测试结果:

输入原文:sadjhfkkjasdghjkhadkjsdhgksdhgjkshgdweuosyhjkhfsdg5sd4g5s4dg1564h56d4as1gd521f56a1sa3f54a654g5s6d41fg56ha456sd41f23g1h5a6s4dg1gf2asd5g45
随机生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo+UfWVK/CQVayLR5DRy9ydyahLUjr0Eq4xD6pXmMouNWgSjWkiEiQ2eWE3RfAVI89qGYwvD76VvBd+uO9lMLZmh3aVk+Iu0ajTwEt4UxI3T3oGpirYYHWIBHNmcKrRyuGPpQZd+klNzzJeiS+/4Ee5mOPEKun5kJs33D61o4kKwIDAQAB
随机生成的私钥为:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKj5R9ZUr8JBVrItHkNHL3J3JqEtSOvQSrjEPqleYyi41aBKNaSISJDZ5YTdF8BUjz2oZjC8PvpW8F36472UwtmaHdpWT4i7RqNPAS3hTEjdPegamKthgdYgEc2ZwqtHK4Y+lBl36SU3PMl6JL7/gR7mY48Qq6fmQmzfcPrWjiQrAgMBAAECgYBZKkodMM0abc4o8aQRjoPcHEH3NWVQgrabb3s9dsBOodKg5egOrZfVUBZMmTrKVBTOTYm3V+7HvY7TmOwKg3CZ9UzxYrhhIbh7p42gAIlpnyiq7YCz3X0hz+FrRKEOJJ5eLINKxl6w3jOG1ZeY9FIHUrGIb0KJe/a5m1gkG8zFoQJBAN0zS/DPpDNJKCrnxRs1TijtLdL9JgOle7ecPKp2kbJQB6RLmJ5/675JrlR1SD5N9E4KUdgEsyF4uUr3cew6XlsCQQDDjpcTHn3wgjZOGU8WAuNHV132TSfT1YiCttFjRuXNtGVrmYdbyZh77g6qbk+DxjJ1Zw0dNh1WhsGyLOTCI9pxAkAJxW1SWunG9jFXC9vyIr2sIyYGDvax7Ip1hupLIWe4N77OrCQ2xDHWuwx/YJrrXagwFladMz/yd5G/1QRsSfvHAkB50wuEapt0R/oCnzuob7YczG2Jsbkc+0pme/NnUFR62GXSKTusz6LBmaTjQYMhiUgH4WHHD94o+BwUnmkIFIPRAkAr5ToL9zeevlwYvIxqd4++Vdcfm+1uDbxa0Rjm00ay5S3fS/3jXHs0j+CB2faxakVUYueMKmdUoYpWKfgOOk7A
原文:sadjhfkkjasdghjkhadkjsdhgksdhgjkshgdweuosyhjkhfsdg5sd4g5s4dg1564h56d4as1gd521f56a1sa3f54a654g5s6d41fg56ha456sd41f23g1h5a6s4dg1gf2asd5g45
加密后的字符串为:9186b953a69941d47b35e0abff66356c03b29e3b0be1b1187f845fd212f2bf14e9fe56484fd5b15b23782d960545bb6cb1a992142315857a6f2854e81f89c20216b5e15cf9b5496350c17224f1820fe4445044ce0adf10eba16d130dd63885b6ede13a3670009e2493f1eeaaee35e67fdcd8373692449dab4382196d85ee84861680fc1613ce132c731d6be0d34e00c7ed04a6a0c8b695a0f91983931de47ec2221575d60023cf223ac5b70c047c9c6b155e20723770cbdb13f45014656244f1894205cb8a2a4d029b3cdd2de9b1cbf1729e5ddcdf3314145c6db93a593b8e1f38c70dc064147a3d6ffaf9a21d338fa5d9a676a9449e37c8d9446abea15f1dfc
还原后的字符串为:sadjhfkkjasdghjkhadkjsdhgksdhgjkshgdweuosyhjkhfsdg5sd4g5s4dg1564h56d4as1gd521f56a1sa3f54a654g5s6d41fg56ha456sd41f23g1h5a6s4dg1gf2asd5g45

RSA加密算法原理及其Java实现相关推荐

  1. RSA加密算法原理和java简单实现

    数学 RSA加密算法中,用到素数.互质数.指数运算.模运算等几个数学知识. 素数 素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数. 互质数 百度百科:公因数只有 ...

  2. RSA加密算法原理及RES签名算法简介(转载)

    第一部分:RSA算法原理与加密解密 一.RSA加密过程简述 A和B进行加密通信时,B首先要生成一对密钥.一个是公钥,给A,B自己持有私钥.A使用B的公钥加密要加密发送的内容,然后B在通过自己的私钥解密 ...

  3. java的rsa加密算法_用java编程实现RSA加密算法

    RSA加密算法是目前应用最广泛的公钥加密算法,特别适用于通过Internet传送的数据,常用于数字签名和密钥交换.那么我今天就给大家介绍一下如何利用Java编程来实现RSA加密算法. 一.RSA加密算 ...

  4. RSA 加密算法原理简述

    概述 本文旨在说明RSA加密算法的原理及实现,而其相关的数学部分的证明则不是本文内容. 版权说明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Q-WHai 发表日期: ...

  5. RSA加密算法介绍及Java工具类

    一.RSA加密算法介绍 当今重要的三类加密算法:非对称加密.对称加密以及哈希算法(HASH严格说不是加密算法,但由于其不可逆性,已成为加密算法中的一个重要构成部分). 1976年以前,所有的加密方法都 ...

  6. 密码学——RSA加密算法原理

    前言:之前在做密码学题的时候了解了一下RSA,但总感觉那时总结的过少,而且也理解的不到位,这次就再来详细的了解一下,并通过做题来巩固一下. 一.对称加密与非对称加密 对称加密: 加密和解密用的是同一密 ...

  7. AES加密算法原理及java android实现

    AES当今最流行的对称加密算法之一,是DES的替代者. 密钥是AES算法实现加密和解密的根本.对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥. AES支持三种长度的密钥: ...

  8. AES加密算法原理分析

    明文:任何人见字符(文)知意:暗文:没有密钥解码则见字符(文)不知意. AES(Advanced Encryption Standard)高级加密标准为常见的对称型加密算法(微信小程序加密传输是用AE ...

  9. AES加密算法原理解析

    转自: https://blog.csdn.net/qq_28205153/article/details/55798628 AES简介 高级加密标准(AES,Advanced Encryption ...

最新文章

  1. java安装好了打不开机_劝告大家!早餐打豆浆,黄豆泡好直接打不对,教你1招,豆浆香浓更丝滑...
  2. 好雨云帮近期问答集锦(1.16~2.5)
  3. 斯坦福李飞飞团队「最惨」在读博士:论文被拒,项目被砍,本文教你如何正视失败!...
  4. Spring-AOP 静态普通方法名匹配切面
  5. DayDayUp:今天早上看到一条朋友圈——《吃苦与穷的深刻认知》
  6. 安全是一个系统问题包括服务器安全,信息安全技术题库:信息泄露对于Web服务器的危害在于( )。...
  7. android studio windows,AndroidStudio的使用(Windows)
  8. bert 多义词_广告行业中那些趣事系列15:超实用的基于BERT美团搜索实践
  9. python的kite下载安装及使用_Kite下载|Kite Python编程工具 V1.2020.1203.0 最新版下载 - 下载银行...
  10. 利用R、Octave和NumPy求解线性方程组
  11. CCPC-Wannafly Comet OJ 夏季欢乐赛(2019)E
  12. 蚂蚁金服推出分布式的图神经知识表示框架,性能和可扩展性俱佳
  13. 4、matplotlib中的子图相关subplot
  14. switchhost使用记录
  15. UML之用例图转类图
  16. 如何配置NSSA区域?
  17. Git学习8:Git分支操作
  18. 微软新的邮件帐户域名 @live.com和@windowslive.com
  19. 第二次项目《吃货联盟Plus》
  20. [Swift]求最大公约数和最小公倍数【用微信查看本文链接可查看到引用图片】

热门文章

  1. 关键字抽取论文阅读笔记
  2. html中表格内边框颜色,html表格边框颜色 Word中的表格如何设置表格内边框的颜色...
  3. index2.php,index2.php
  4. 苹果CMS Mxone Pro开源版无加密v7.2
  5. 浏览器如何赚钱:谷歌​需要火狐
  6. java输入流和输出流
  7. R语言中的基础作图和ggplot2配色系统
  8. 近现代史复习重点(第九、十章太少,直接刷题)
  9. mysql全文检索_Mysql的全文检索
  10. mysql like全文检索_MySQL全文检索中Like索引的实现