RSA算法Java的简单实现

RSA简介

RSA算法据说是目前地球上最重要的加密算法。维基百科是这么介绍的:“对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法,那么RSA的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA密钥才可能被暴力破解。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要密钥长度足够长,用RSA加密的信息实际上是不能被解破的。”

看上去很神奇是吧,其实在学习网络安全和密码学这门课的时候,都接触过。毕业近一年了,数论方面的知识忘的差不多了。如果大家对RSA算法原理很感兴趣,推荐下面这两篇文章:

http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

本文描述下,我自己实现的一个简单的RSA算法。

RSA密钥生成和加密解密过程

RSA的具体实现

RSA具体实现的难点在于质数的生成。好在Java提供了一个强大的工具类BigInteger。具体的实现如下

(不过百行):

public class RSA {
	private BigInteger p = null;
	private BigInteger q = null;
	private BigInteger n = null;
	private BigInteger totient = null;
	private BigInteger e = null;
	private BigInteger d = null;
	public RSA(BigInteger p, BigInteger q) {
		this.p = p;
		this.q = q;
		n = p.multiply(q); // n = p * q;//totient =(p-1)*(q-1)即 (n)
		totient = (p.subtract(BigInteger.valueOf(1)).multiply((q
				.subtract(BigInteger.valueOf(1)))));
                e = getE();//选择公钥
		BigInteger y = egcd(totient, e)[1];
                d = y.mod(totient); //产生私钥
	}
	public BigInteger getE() {
		// 这里以totient/4为种子,选取一个素数作为公钥
		return totient.divide(BigInteger.valueOf(4)).nextProbablePrime();
	}
        // 扩展的Euclid算法,目的:算出e-1 mod n
	public static BigInteger[] egcd(BigInteger d1, BigInteger d2) {
		BigInteger[] ret = new BigInteger[3];
		BigInteger u = BigInteger.valueOf(1), u1 = BigInteger.valueOf(0);
		BigInteger v = BigInteger.valueOf(0), v1 = BigInteger.valueOf(1);
		if (d2.compareTo(d1) > 0) {
			BigInteger tem = d1;
			d1 = d2;
			d2 = tem;
		}
		while (d2.compareTo(BigInteger.valueOf(0)) != 0) {
			BigInteger tq = d1.divide(d2); // tq = d1 / d2
			BigInteger tu = u;
			u = u1;
			u1 = tu.subtract(tq.multiply(u1)); // u1 =tu - tq * u1
			BigInteger tv = v;
			v = v1;
			v1 = tv.subtract(tq.multiply(v1)); // v1 = tv - tq * v1
			BigInteger td1 = d1;
			d1 = d2;
			d2 = td1.subtract(tq.multiply(d2)); // d2 = td1 - tq * d2
			ret[0] = u;
			ret[1] = v;
			ret[2] = d1;
		}
		return ret;
	}
        // 加密
	public BigInteger encode(BigInteger d) {
		return d.modPow(this.e, this.n);
	}
        // 解密
	public BigInteger decode(BigInteger c) {
		return c.modPow(this.d, this.n);
	}
}

RSA的缺点

RSA算法使用乘方运算,明文以分组为单位进行加密,每个分组的二进制值均小于n也就是说分组的大

小必须小于或等于log2(n)+1位。如果明文分组大于此长度,则需要进一步细分,或者借助另外一种对

称的加密算法来进行加密。此外,RSA加密解密效率不高,特别是密钥长度很长的时候,不适合对大

量信息进行加密。所以一般RSA会和其他对称的加密算法配合使用。

下面是我本科毕设中设计的一个简单的加密方案,以及前几天根据这个方案写的一个demo。

假设客户端要向服务发送数据,首先客户端需要通过用户名和密码生成自己的RSA密钥(用于解密的私

钥cPR),然后通过一个随机数生成这次数据传输的DES密钥deskey_c,除此之外我们还知道服务端的

RSA公钥sPU(服务端的RSA密钥是固定的)。有了这次数据传输的密钥信息之后,客户端就可以将数

据M1通过DES算法用deskey_c加密得到密文C1,然后将客户端生成的DES密钥deskey_c通过RSA算法

用服务端的公钥sPU加密得到加密后的DES密钥c_deskey_c。最后将加密后的信息(密文C1和加密后的

DES密钥c_deskey_c)通过http协议发送到服务端。服务端接收后,先通过自己的私钥sPR将DES密钥

解密出来,得到之前客户端生成的deskey_c,然后通过DES算法用deskey_c解密C1,得到原来的数据

M1。至此,客户端加密服务端解密的过程结束。在加密解密过程中,DES密钥为50位10进制数,RSA

算法中的p和q的范围是0到150位十进制整数。而当服务端向客户端发送数据的时候,同样需要生成密钥

信息。首先服务端通过客户端的用户名和密码得到客户端的RSA公钥cPU,然后通过一个随机数得到这

次数据传输的DES密钥deskey_s,然后通过DES算法用deskey_s将数据M2加密为密文C2,然后通过

RSA算法用客户端的公钥cPU将deskey_s加密为c_deskey_s。最后服务端将密文C2和加密后的DES

密钥c_deskey_s发送给客户端。客户端接收后,先通过RSA算法用自己的私钥cPR解密c_deskey_s,

得到原来服务端生成的DES密钥deskey_s,然后通过DES算法用该密钥解密出原来的数据M2。这样

就完成了服务端加密,客户端解密的过程。

Demo:

附上工程源码(最近加班紧,代码写的不是很好-_-||):

http://download.csdn.net/detail/he_qiao_2010/8548675

时间: 2024-10-22 12:35:49

RSA算法Java的简单实现的相关文章

AES算法,DES算法,RSA算法JAVA实现

1     AES算法 1.1    算法描述 1.1.1      设计思想 Rijndael密码的设计力求满足以下3条标准: ① 抵抗所有已知的攻击. ② 在多个平台上速度快,编码紧凑. ③ 设计简单. 当前的大多数分组密码,其轮函数是Feistel结构. Rijndael没有这种结构. Rijndael轮函数是由3个不同的可逆均匀变换 1.1.2      密码说明 严格地说,AES和Rijndael加密法并不完全一样(虽然在实际应用中二者可以互换),因为Rijndael加密法可以支持更大

RSA算法原理(简单易懂)

1. 什么是RSA RSA算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法.在了解RSA算法之前,先熟悉下几个术语 根据密钥的使用方法,可以将密码分为对称密码和公钥密码 对称密码:加密和解密使用同一种密钥的方式 公钥密码:加密和解密使用不同的密码的方式,因此公钥密码通常也称为非对称密码. 2. RSA加密 RSA的加密过程可以使用一个通式来表达 密文=明文EmodN密文=明文EmodN 也就是说RSA加密是对明文的E次方后除以N后求余数的过程.就这么简单?对,就是这么简单. 从

RSA算法 Android JAVA C#互通

RSA算法属非对称加密算法,在实际使用中,往往客户端使用公钥进行加密传递敏感数据,服务端server使用私钥进行解密,这样防止中间人从网络获取敏感数据的明文. Android端主要代码如下: 1 package com.example.rsatest; 2 3 import java.io.UnsupportedEncodingException; 4 import java.math.BigInteger; 5 import java.security.KeyFactory; 6 import

ios下使用RSA算法加密与java后台解密配合demo

首先了解一下几个相关概念,以方便后面遇到的问题的解决: 原网址:http://blog.csdn.net/jinglijun/article/details/7770315RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥

一个基于RSA算法的Java数字签名例子

原文地址:一个基于RSA算法的Java数字签名例子 一.前言: 网络数据安全包括数据的本身的安全性.数据的完整性(防止篡改).数据来源的不可否认性等要素.对数据采用加密算法加密可以保证数据本身的安全性,利用消息摘要可以保证数据的完整性,但是还有一点就是数据来源的不可否认性(也就是数据来自哪里接收者是清楚的,而且发送数据者不可抵赖). 有些方案曾经使用消息认证码(MAC)来保证数据来源于合法的发送着,但是利用消息认证码会带来一个问题,就是通讯双方必须事先约定两者之间的通讯用共享密码.在我们的互联网

RSA算法使用介绍

http://www.cnblogs.com/AloneSword/p/3326750.html RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥.公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用. 解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者.加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文.

RSA算法原理1

必备数学知识 RSA加密算法中,只用到素数.互质数.指数运算.模运算等几个简单的数学知识.所以,我们也需要了解这几个概念即可. 素数 素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数.这个概念,我们在上初中,甚至小学的时候都学过了,这里就不再过多解释了. 互质数 百度百科上的解释是:公因数只有1的两个数,叫做互质数.:维基百科上的解释是:互质,又称互素.若N个整数的最大公因子是1,则称这N个整数互质. 常见的互质数判断方法主要有以下几种: 两个不同的质数一定

springmvc使用RSA算法加密表单

今天被吐槽在客户端用js对密码进行md5加密其实也不见得安全.这种做法其实不见得有什么作用,学过计算机网络都知道,在网上抓一个包是很简单的事,就算别人抓包抓不到你原始密码,用这个md5后的密码一样可以模拟登录系统.这样做无非就是直接通过登录页没法直接输入用户名密码,但用个程序模拟登陆也不是什么太难的事情.以前一直写那么多,一直没有注意,直到今天被吐槽,才发现以前自己的做法是多么的幼稚. 加密数据的方式当然不止一种,也可以通过https加密数据,但是对于一般应用来说,还需要花钱拿去给那些认证机构签

RSA算法(一)

转载:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 作者: 阮一峰 日期: 2013年6月27日 如果你问我,哪一种算法最重要? 我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先简单介绍一下,什么是"公钥加密算法". 一.一点历史 1976年以前,所有的加密方法都是同一种模式: (