加密算法(二,RSA算法)
2019-04-16 本文已影响0人
腊鸡程序员
timg (4).jpg
image.png image.png image.png image.png image.png
image.png image.png
简介
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年7月首次在美国公布,当时他们三人都在麻省理工学院工作实习。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
今天只有短的RSA钥匙才可能被强力方式解破。
到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。
只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战和质疑。
算法思想
- 问题提出
1970年以前,密码学一直使用对称密钥,
如果一个人需要和多个人分享信息,比如银行需要存放所有人的密码,来进行信息交换,必然需要管理所有的密钥.
能否有一种更简单的方法呢?
1970年一个英国工程师和数学家James H.Ellis 在研究一个非秘密的加密想法,基于一个简单又聪明的想法,上锁和解锁是相反的操作
他可以把锁打开,交给对方后,由对方上好锁,再还给他,由他自己开锁
这样他可以大量发出他的信息,而只需要保留单个钥匙
当然他给出了工作原理,但不知如何用数学方法解决
- 解决
被另一个数学家和密码专家Cocks发现
他需要一个特殊的单向函数,正推容易,求逆很难
求素数的因子分解589=19*31,计算很难,如果是个1000位数呢?
欧拉发现了一个重要的函数phi(n),用于找到整数的可分解性
image.pngimage.png image.png image.png image.png image.png
RSA算法推论:
image.png image.png
实现:
image.png代码:
import org.junit.Test;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
public class RSA {
public static String ALGORITHM = "RSA";
//指定key的位数 N的位数
public static int keySize = 1024;
//指定公钥的存放文件
public static String PUBLIC_KEY_FILE = "public_key.dat";
//指定私钥的存放文件
public static String PRIVATE_KEY_FILE = "private_key.dat";
/**
* 生成秘钥对 公钥(e,n) 私钥(d,n)
*/
public static void generateKeyPair() throws Exception{
SecureRandom sr = new SecureRandom();
//初始化KeyPairGenerator对象
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGenerator.initialize(keySize,sr);
//生成秘钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//得到公钥
Key publicKey = keyPair.getPublic();
//得到私钥
Key privateKey = keyPair.getPrivate();
//可以写入文件后,这两个文件分别放在客户端和服务器
ObjectOutputStream outputStream1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
ObjectOutputStream outputStream2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
outputStream1.writeObject(publicKey);
outputStream2.writeObject(privateKey);
outputStream1.close();
outputStream2.close();
}
/**
* 加密
* @param source 明文
* @return
* @throws Exception
*/
public static String encrypt(String source) throws Exception{
generateKeyPair();
//取出公钥
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
Key key = (Key) ois.readObject();
ois.close();
//开始使用公钥
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[] b = source.getBytes();
byte[] b1 = cipher.doFinal(b);
//用BASE64编码,二进制和字符串的转化的一种方式
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(b1);
}
/**
* 解密
* @param cryptText 密文
* @return
*/
public static String decrypt(String cryptText) throws Exception{
//读文件,获取私钥
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
Key key = (Key) ois.readObject();
ois.close();
//解密
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,key);
BASE64Decoder decoder = new BASE64Decoder();
byte[] b = decoder.decodeBuffer(cryptText);
byte[] b1 = cipher.doFinal(b);
return new String(b1);
}
@Test
public void test() throws Exception{
String source = "jett";
String encryptText = encrypt(source);
System.out.println("加密后:" +encryptText);
String decryptText = decrypt(encryptText);
System.out.println("解密后:" + decryptText);
}
}