加密和解密使用不同的密钥,这种算法称为非对称加密算法
特点:
必须有两个密钥,一个公钥,一个私钥公钥和私钥是一对,称为密钥对如果使用公钥加密,必须使用私钥解密如果使用私钥加密,必须使用公钥解密处理数据速度慢安全级别高-举个例子:
首先生成密钥对, 公钥为(5,14), 私钥为(11,14)
现在A希望将原文2发送给B
A使用公钥加密数据. 2的5次方mod 14 = 4 , 将密文4发送给B
B使用私钥解密数据. 4的11次方mod14 = 2, 得到原文2
-分类:
RSAECC开始代码讲解!!
1.怎样生成公钥和私钥?
准备工作:
定义加密算法String algorithm = “RSA”;
创建密钥对生成器对象KeyPairGenerator类用于生成公钥和私钥对。密钥对生成器使用getInstance工厂方法构造。其参数为算法algorithm
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
调用keyPairGenerator的generateKeyPair()方法生成一个密钥对KeyPair keyPair = keyPairGenerator.generateKeyPair();
调用keyPair的getPrivate()方法 开始生成私钥PrivateKey privateKey = keyPair.getPrivate();
调用keyPair的getPublic()方法 开始生成公钥PublicKey publicKey = keyPair.getPublic();
接着一一获取私钥公钥字节数组byte[] privateKeyEncoded = privateKey.getEncoded();
byte[] publicKeyEncoded = publicKey.getEncoded();
最后再对公钥私钥进行Base64编码String privateKeyString = Base64.encode(privateKeyEncoded);
String publicKeyString = Base64.encode(publicKeyEncoded);
把私钥公钥打印康康~~System.out.println(privateKeyString);
System.out.println(publicKeyString);
2.怎么用私钥/公钥进行加密?
准备工作:
设置原文String input = “aa”;
创建加密对象,参数为加密算法Cipher cipher = Cipher.getInstance(algorithm);
初始化加密,第一个参数为加密模式,第二个参数为使用私钥加密cipher.init(Cipher.ENCRYPT_MODE,privateKey);
接着调用cipher的doFinal()方法去执行加密算法,其参数为原文的字节数组byte[] bytes = cipher.doFinal(input.getBytes());
最后使用Base64编码输出就ok辣!!System.out.println(Base64.encode(bytes));
让我们看看输出结果
3.我们试试使用私钥能不能解密呢?
解密也需要调用cipher的初始化方法init(),其第一个参数为解密模式,第二个参数为私钥 cipher.init(Cipher.DECRYPT_MODE,publicKey);对密文进行解密,不需要使用base64,因为原文不会乱码byte[] bytes1 = cipher.doFinal(bytes);
System.out.println(new String(bytes1));
让我们看看输出结果~~
出错,所以只能使用私钥加密,公钥解密!
4.使用公钥解密!
解密也需要调用cipher的初始化方法init(),其第一个参数为解密模式,第二个参数为公钥cipher.init(Cipher.DECRYPT_MODE,publicKey);
调用cipher的doFinal()方法来进行解密,其参数为密文的字节数组byte[] bytes1 = cipher.doFinal(bytes);
System.out.println(new String(bytes1));
让我们来看看输出结果~~
嚯!原文出来啦!
同理,用公钥加密还用公钥解密还是会报错,所以只能使用一个加密,另一个解密哈!
5.保存私钥公钥
前面代码每次都会生成 加密和解密 ,咱们需要把加密和解密的方法全部到本地的根目录下面。
使用到FileUtils.writeStringToFile()将字符串写入文件,传入三个参数,第一个参数为new File(私钥文件的路径),第二个参数为私钥Base64编码,第三个参数为使用到UTF-8编码FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName(“UTF-8”));
同理,保存公钥也是这个流程FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName(“UTF-8”));
我们把它抽取为一个函数
generateKeyToFile(algorithm,“a.pub”,“b.pri”)
public static void generateKeyToFile (String algorithm,String pubPath,String priPath) throws Exception{ //创建密钥对生成器对象 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm); //生成密钥对 KeyPair keyPair = keyPairGenerator.generateKeyPair(); //生成私钥 PrivateKey privateKey = keyPair.getPrivate(); //生成公钥 PublicKey publicKey = keyPair.getPublic(); //获取私钥的字节数组 byte[] privateKeyEncoded = privateKey.getEncoded(); //获取公钥的字节数组 byte[] publicKeyEncoded = publicKey.getEncoded(); //使用Base64进行编码 String privateEncodeString = Base64.encode(privateKeyEncoded); String publiceEncodeString = Base64.encode(publicKeyEncoded); //把公钥和私钥保存到根目录中 FileUtils.writeStringToFile(new File(pubPath),publiceEncodeString,Charset.forName("UTF-8")); FileUtils.writeStringToFile(new File(priPath),privateEncodeString,Charset.forName("UTF-8")); }让我们看看生成结果!!
在本地目录分别生成一个公钥私钥文件!!
6.读取私钥
直接读取使用FileUtils类的readFileToString()方法去读取,传入两个参数,第一个参数为new File(私钥文件的路径),第二个参数为Charset类的defaultCharset()方法去解码
tring privateKey = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());
//读取私钥 String getPri = getPrivateKey("b.pri",algorithm); System.out.println("读取私钥"+getPri); public static String getPrivateKey (String priPath,String algorithm) throws Exception{ String privateKey = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset()); return privateKey; }让我们看看结果!!
读取私钥对象与直接读取区别的是,这里要使用到密钥工厂去实例化,然后在构建一个密钥规范 PKCS8EncodedKeySpec,参数就是使用Base64.decode去解码privateKeyString
PrivateKey privateKey1 = getPrivateKey("b.pri", algorithm); System.out.println("私钥对象"+privateKey1); public static PrivateKey getPrivateKey (String priPath,String algorithm) throws Exception{ String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset()); KeyFactory keyFactory = KeyFactory.getInstance(algorithm); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString)); return keyFactory.generatePrivate(keySpec); }让我们看看结果!!!
7.读取公钥
直接读取 原理与直接读取私钥类似,直接上代码了哈 //读取公钥 String getPub = getPublicKey("a.pub",algorithm); System.out.println("直接读取公钥"+getPub); private static String getPublicKey(String pubPath, String algorithm) throws Exception { String publicKey = FileUtils.readFileToString(new File(pubPath), Charset.defaultCharset()); return publicKey; }让我们看看结果!!!
读取公钥对象与读取私钥对象类型,但要注意有一点不同使用公钥规则不同,私钥使用的是PKCS8EncodedKeySpec规则,而公钥使用的是X509EncodedKeySpec规则;
// 读取公钥对象 PublicKey publicKey1 = getPublicKey("a.pub", algorithm); System.out.println("读取公钥对象"+publicKey1); private static PublicKey getPublicKey(String pubPath, String algorithm) throws Exception { String publicKeyString = FileUtils.readFileToString(new File(pubPath), Charset.defaultCharset()); KeyFactory keyFactory = KeyFactory.getInstance(algorithm); //创建公钥规则 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKeyString)); return keyFactory.generatePublic(keySpec); }让我们看看结果!!!