700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > RSA公钥加密与私钥解密算法

RSA公钥加密与私钥解密算法

时间:2020-10-31 04:32:23

相关推荐

RSA公钥加密与私钥解密算法

首先是随机生成一个密钥对(一个公钥和一个私钥)

package com.zy.demo1.secretTest;import lombok.extern.slf4j.Slf4j;import mons.codec.binary.Base64;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.util.HashMap;import java.util.Map;@Slf4jpublic class generateKeys {public static void main(String[] args) throws Exception {String point = "xxx";Map<String, String> keyMap = genKeyPair(point);}/*** 随机生成密钥对** @throws NoSuchAlgorithmException* @param point*/public static Map<String, String> genKeyPair(String point) throws NoSuchAlgorithmException {// log.info("{}|开始生成公私钥",point);// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");// 初始化密钥对生成器,密钥大小为96-1024位keyPairGen.initialize(512, new SecureRandom());// 生成一个密钥对,保存在keyPair中KeyPair keyPair = keyPairGen.generateKeyPair();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));// 得到私钥字符串String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));// 将公钥和私钥保存到MapMap<String, String> map = new HashMap<>();map.put("publicKey", publicKeyString);map.put("privateKey", privateKeyString);// log.info("{}|生成的公私钥|map:{}",point,map);System.out.println("公钥:"+publicKeyString);System.out.println("私钥:"+privateKeyString);return map;}}

然后就是测试公钥加密和私钥解密:

@Slf4jpublic class RSAEncrypt {static String PUBLICKEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJNyGpwXu+iN158lNzZxvQnuhJKwuoisgINUmV/EYRbC6UevLq65/xbzirzHuieCngDwMtzxzHFm1Z6Yv7z8fQ8CAwEAAQ==";static String PRIVATEKEY = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAk3IanBe76I3XnyU3NnG9Ce6EkrC6iKyAg1SZX8RhFsLpR68urrn/FvOKvMe6J4KeAPAy3PHMcWbVnpi/vPx9DwIDAQABAkBVgivqcF06beApXFTbzzRZaSkbRUC4eIoDH/Hety2zG6vpBiKf5yImIrOVuxl5tkKGVVSX18bVAgcwgmM1i9PhAiEA5VFFcyiJaLopgrOm8o3Za0sTb92ziUV6Znd24XfiEnECIQCkmhnudWLXYSC/Vdy1U+wboxBzglDGJZRfIcl+CDhHfwIgLKB+VYTkCN+ByI/Rw45ba4f2xmRs1iARS/OfzQ0Zj+ECIER1Vx2nMsGzQsRxOIct7UAdVMVFyMRwcsISMlQ5pPaPAiEAqK5tUiCtnnDcCDrKhrvblZcB3/+rbri5TPwHtusX1bw=";// static String PUBLICKEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcbvFyyeZrDyZKcRKkzCcRx7/ULLSpCzhNeJHgGHti6VaGrodMFSwVPqo9lcpkTEwvoNi3TjLzq151pZZacI6usz4CcEA3dJmj6XjL4UoowjWGTDLNEmQUmA2QcdhAgi3Mpv3rKjjBVmVjbgsPxME2YrPijArRosOnWfg7GXLHkQIDAQAB";// static String PRIVATEKEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJxu8XLJ5msPJkpxEqTMJxHHv9QstKkLOE14keAYe2LpVoauh0wVLBU+qj2VymRMTC+g2LdOMvOrXnWlllpwjq6zPgJwQDd0maPpeMvhSijCNYZMMs0SZBSYDZBx2ECCLcym/esqOMFWZWNuCw/EwTZis+KMCtGiw6dZ+DsZcseRAgMBAAECgYA1EQ2nOwaHWuRKbIE+lmLKjVBt0ZyXm87FuRkDRErXCwDnP112WdhSfKeTrLSzwY42ugHKbSSrtH6eukV++J/t5+FEgSC2qvJZkyla65lP9+KrKyufj4AGPUIxedfpCIWiLM4kMeV7ZpzNXWEOoFGA7NjhMgYc5UMqukBD4NtagQJBAP83L+yBUmlIqPidxYk1o/u8D+dBt+EVRPfCJHj4DBhXwtwmm/YjhZJm2DibA4Mi7NS80VIQ5qlex9GRPFpT/I0CQQCc6gfTAB4dun9AyBH8dvQKtGI+ud8stOfK8OIF2UM9W5SWmw0+13PRt8APaRfBYvK0c0RRwEN2Tqwo7p3S71AVAkEAiGQl6G70a++43aTzfHB+QnouxZgJfPCw+vd2Jm/phtjf+mdn0hMJv0PXKekt51cy2j5OX11I6BsPDqBfcKaRwQJAct7c1XnLkkXaLKmKiUDnzQJavcLCf278FVQckt2HXN6zO0HNA4kkb43OGzn7OwZd2P5dMF/Iw046uEhe33F0NQJAESYWsj8DtCurAkEOihnr404hRC7dCY7WcSpp30qjRdy1+qgYsZtz87nOdsaKu+DANdfFu6oTZw4rK23X4VECmg==";public static void main(String[] args) {List<String> strings = Arrays.asList("17604897965", "15352438462", "32764838763");List<Object> collect = strings.stream().map(v -> {try {return publicKeyEncrypt(v);} catch (Exception e) {e.printStackTrace();return null;}}).collect(Collectors.toList());collect.stream().forEach(v->{try {System.out.println(v+":::"+privateKeyDecrypt((String) v));} catch (Exception e) {e.printStackTrace();}});}/*** RSA公钥加密** @param str 加密字符串* @return 密文* @throws Exception 加密过程中的异常信息*/public static String publicKeyEncrypt(String str) throws Exception {// log.info("{}|RSA公钥加密前的数据|str:{}|publicKey:{}",point,str,publicKey);//base64编码的公钥byte[] decoded = Base64.decodeBase64(PUBLICKEY);RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));//RSA加密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, pubKey);String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));// log.info("{}|公钥加密后的数据|outStr:{}",point,outStr);return outStr;}/*** RSA私钥解密** @param str 加密字符串* @return 明文* @throws Exception 解密过程中的异常信息*/public static String privateKeyDecrypt(String str) throws Exception {// log.info("{}|RSA私钥解密前的数据|str:{}|privateKey:{}",point,str,privateKey);//64位解码加密后的字符串byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));//base64编码的私钥byte[] decoded = Base64.decodeBase64(PRIVATEKEY);RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));//RSA解密Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, priKey);String outStr = new String(cipher.doFinal(inputByte));// log.info("{}|RSA私钥解密后的数据|outStr:{}",point,outStr);return outStr;}}

然后对于RSA算法密钥的长度则有以下相关说明:

在做RSA加密的时候可能会遇到一个这样的错误:ArrayIndexOutOfBoundsException: too much data for RSA block

该错误是加密数据过长导致的。

加密数据长度 <= 模长-11

解决办法:将要加密的数据截取后分段加密

以下是关于RSA算法密钥长度/密文长度/明文长度的介绍

1.密钥长度

rsa算法初始化的时候一般要填入密钥长度,在96-1024bits间

(1)为啥下限是96bits(12bytes)?因为加密1byte的明文,需要至少1+11=12bytes的密钥(不懂?看下面的明文长度),低于下限96bits时,一个byte都加密不了,当然没意义啦

(2)为啥上限是1024(128bytes)?这是算法本身决定的...当然如果某天网上出现了支持2048bits长的密钥的rsa算法时,你当我废话吧

2.明文长度

明文长度(bytes) <= 密钥长度(bytes)-11.这样的话,对于上限密钥长度1024bits能加密的明文上限就是117bytes了.

这个规定很狗血,所以就出现了分片加密,网上很流行这个版本.很简单,如果明文长度大于那个最大明文长度了,我就分片吧,保证每片都别超过那个值就是了.

片数=(明文长度(bytes)/(密钥长度(bytes)-11))的整数部分+1,就是不满一片的按一片算

3.密文长度

对,就是这个充满了谣言,都说密文长度为密钥长度的一半,经俺验证,密文长度等于密钥长度.当然这是不分片情况下的.

分片后,密文长度=密钥长度*片数

例如96bits的密钥,明文4bytes

每片明文长度=96/8-11=1byte,片数=4,密文长度=96/8*4=48bytes

又例如128bits的密钥,明文8bytes

每片明文长度=128/8-11=5bytes,片数=8/5取整+1=2,密文长度=128/8*2=32

注意,对于指定长度的明文,其密文长度与密钥长度非正比关系.如4bytes的明文,在最短密钥96bites是,密文长度48bytes,128bits米密钥时,密文长度为16bytes,1024bits密钥时,密文长度128bytes.

因为分片越多,密文长度显然会变大,所以有人说,那就一直用1024bits的密钥吧...拜托,现在的机器算1024bits的密钥还是要点时间滴,别以为你的cpu很牛逼...那么选个什么值比较合适呢?个人认为是600bits,因为我们对于一个字符串的加密,一般不是直接加密,而是将字符串hash 后,对hash值加密.现在的hash值一般都是4bytes,很少有8bytes,几十年内应该也不会超过64bytes.那就用64bytes算吧, 密钥长度就是(64+11)*8=600bits了.

用开源rsa算法的时候,还要注意,那个年代的人把long当4bytes用,如今放在64位的机器上,就会死循环啊多悲催....因为有个循环里让一个4bytes做递减....64位机上long是8bytes,这个循环进去后个把小时都出不来....所以要注意下哦....同理对于所有年代久远的开源库都得注意下...

加密算法RSA和Base64的关系

在使用RSA非对称加密的时候,我们会发现里面出现Base64的身影,那他们之间有什么关系呢?

一、RSA是加密算法,非对称加密,拥有两把密钥,一把公钥,一把私钥。

通信双方会分别生成一对公私钥,双方交换公钥。通信过程会传输加密文本和签名。

加密解密过程:服务器会把公钥发送给每一个客户端,客户端在向服务器发送数据时,用公钥进行加密,但是最终解密数据不是用公钥,而是通过私钥解密,私钥不会发给任何人,只会牢牢保护在服务端。

加密:是将数据资料加密,使得非法用户即使取得加密过的资料,也无法获取正确的资料内容,所以数据加密可以保护数据,防止监听攻击,其重点在于数据的安全性。

加签验签过程:客户端在向服务器发送数据时,首先利用MD5等HASH算法对需要传输的文本计算摘要值,然后利用私钥对摘要值进行加密,得到的密文即被称为该次传输过程的签名。数据接收端,拿到签名后利用自己持有的公钥对签名进行解密(密钥对中的一种密钥加密的数据必定能使用另一种密钥解密),得到文本的摘要,然后使用与发送方同样的HASH算法对文本计算摘要值,再与解密得到的摘要做对比,发现二者完全一致,则说明文本没有被篡改过。

加签:目的是确认该文本是否是发送端发出的内容,中途是否曾经被篡改。

公钥加密---私钥解密

私钥加签---公钥验签

二、Base64不是加密解密算法,只是个编码解码的算法。

Base64和RSA相伴相生,主要是为了防止乱码的产生,加密的数据只是改变其形式不出现乱码,但是发出和接收时数据未发生改变。

Base64流程:

1.原有的公钥Key文件中存放的Base64格式的公钥,那么我们读取回来进行使用,就需要先用Base64解码,获取我们原有的公钥字节

2.加密数据

3.把加密的数据提交给服务器,但是加密过的数据是一堆乱码,直接提交会有问题,所以我们再将这些乱码用Base64进行编码

4.将来服务器收到我们的数据,需要先用Base64解码,获取到原始加密数据

5.用私钥解密

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。