选择Java加密算法第3部分–公钥/私钥非对称加密
抽象
这是涵盖Java加密算法的三部分博客系列的第3部分。 本系列介绍如何实现以下目标:
- 使用SHA–512散列
- 使用AES–256的单密钥对称加密
- RSA–4096
这第三篇文章详细介绍了如何实现非对称的RSA-4096公/私钥加密。 让我们开始吧。
免责声明
这篇文章仅供参考。 在使用所提供的任何信息之前,请认真思考。 从中学到东西,但最终自己做出决定,风险自负。
要求
我使用以下主要技术完成了本文的所有工作。 您可能可以使用不同的技术或版本来做相同的事情,但不能保证。
- Java 1.8.0_152_x64
- NetBeans 8.2(内部版本201609300101)
- Maven 3.0.5(与NetBeans捆绑在一起)
下载
访问我的GitHub页面以查看我所有的开源项目。 这篇文章的代码位于项目中: thoth-cryptography
非对称加密
关于
非对称算法基于两个密钥:公钥和私钥。 公钥负责加密,私钥负责解密。 公用密钥可以自由分发。 使用公共密钥,任何客户端都可以加密一条消息,只有您(使用私有密钥)可以解密该消息(非对称算法,第3段)。
非对称算法是Internet的主力军。 像SSH,OpenPGP,SSL和TLS之类的协议依赖于非对称算法(Rouse,2016,第2段)。 使用网络浏览器进行在线银行之类的工作的人都固有地知道非对称算法的重要性。
截至目前,已完成的研究似乎表明,以下是最佳和最安全的公钥/私钥,非对称加密算法(Sheth,2017年,“选择正确的算法”,第2段):
- 算法: RSA
- 模式: ECB //确实没有,但是需要ECB才能使Java工作。
- 填充: OAEPWithSHA–512AndMGF1Padding
- 密钥大小: 4096位
RSA不是分组密码,因此ECB模式没有多大意义,但是,即使未在内部使用该模式,也需要ECB
来使Java工作(Brightwell,2015年)。 OAEP提供了高度的随机性和填充性。 让我们看一个例子。
例
清单1是RsaTest.java单元测试。 这是以下内容的完整演示:
- 生成并存储RSA 4096位密钥
- RSA加密
- RSA解密
清单2显示了RsaKeyPairProducer.java 。 这是一个帮助程序类,负责产生一个新的KeyPair
。 KeyPair
对同时包含PublicKey
和PrivateKey
。
清单3显示了RsaPrivateKeyProducer.java 。 这是一个帮助程序类,负责从byte[]
再现PrivateKey
。
清单4显示了RsaPublicKeyProducer.java 。 这是一个帮助程序类,负责从byte[]
复制PublicKey
。
清单5显示了ByteArrayWriter.java ,清单6显示了ByteArrayReader.java 。 这些是帮助程序类,负责将byte[]
读写到文件中。 由您决定如何存储密钥的byte[]
,但需要将其安全地存储在某个地方(文件,数据库,git存储库等)。
清单7显示了RsaEncrypter.java 。 这是一个负责加密的助手类。
最后,清单8显示了RsaDecrypter.java 。 这是一个负责解密的助手类。
清单1 – RsaTest.java类
package org.thoth.crypto.asymmetric;import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.thoth.crypto.io.ByteArrayReader;
import org.thoth.crypto.io.ByteArrayWriter;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class RsaTest {static Path privateKeyFile;static Path publicKeyFile;@BeforeClasspublic static void beforeClass() throws Exception {// Store the PrivateKey and PublicKey bytes in the ./target// diretory. Do this so it will be ignore by source control.// We don't want this file committed.privateKeyFile= Paths.get("./target/RsaPrivate.key").toAbsolutePath();publicKeyFile= Paths.get("./target/RsaPublic.key").toAbsolutePath();// Create KeyPair for RSAKeyPair keyPair= new RsaKeyPairProducer().produce();// Store the PrivateKey bytes. This is what// you want to keep absolutely safe{ByteArrayWriter writer = new ByteArrayWriter(privateKeyFile);writer.write(keyPair.getPrivate().getEncoded());}// Store the PublicKey bytes. This you// can freely distribute so others can// encrypt messages which you can then// decrypt with the PrivateKey you keep safe.{ByteArrayWriter writer = new ByteArrayWriter(publicKeyFile);writer.write(keyPair.getPublic().getEncoded());}}@Testpublic void encrypt_and_decrypt() throws Exception {// setupPrivateKey privateKey= new RsaPrivateKeyProducer().produce(new ByteArrayReader(privateKeyFile).read());PublicKey publicKey= new RsaPublicKeyProducer().produce(new ByteArrayReader(publicKeyFile).read());RsaDecrypter decrypter= new RsaDecrypter(privateKey);RsaEncrypter encrypter= new RsaEncrypter(publicKey);String toEncrypt= "encrypt me";// runbyte[] encryptedBytes= encrypter.encrypt(toEncrypt);System.out.printf("Encrypted %s%n", new String(encryptedBytes,"UTF-8"));String decrypted= decrypter.decrypt(encryptedBytes);// assertAssert.assertEquals(toEncrypt, decrypted);}}
清单2 – RsaKeyPairProducer.java类
package org.thoth.crypto.asymmetric;import java.security.KeyPair;
import java.security.KeyPairGenerator;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class RsaKeyPairProducer {/*** Generates a new RSA-4096 bit {@code KeyPair}.** @return {@code KeyPair}, never null* @throws RuntimeException All exceptions are caught* and re-thrown as {@code RuntimeException}*/public KeyPair produce() {KeyPairGenerator keyGen;try {keyGen = KeyPairGenerator.getInstance("RSA");//keyGen.initialize(3072);keyGen.initialize(4096);return keyGen.generateKeyPair();} catch (Exception ex) {throw new RuntimeException(ex);}}
}
清单3 – RsaPrivateKeyProducer.java类
package org.thoth.crypto.asymmetric;import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class RsaPrivateKeyProducer {/*** Regenerates a previous RSA {@code PrivateKey}.** @param encodedByteArrayForPrivateKey The bytes this method* will use to regenerate a previously created {@code PrivateKey}** @return {@code PrivateKey}, never null* @throws RuntimeException All exceptions are caught* and re-thrown as {@code RuntimeException}*/public PrivateKey produce(byte[] encodedByteArrayForPrivateKey) {try {PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(encodedByteArrayForPrivateKey));return privateKey;} catch (Exception ex) {throw new RuntimeException(ex);}}
}
清单4 – RsaPublicKeyProducer.java类
package org.thoth.crypto.asymmetric;import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class RsaPublicKeyProducer {/*** Regenerates a previous RSA {@code PublicKey}.** @param encodedByteArrayForPublicKey The bytes this method* will use to regenerate a previously created {@code PublicKey}** @return {@code PublicKey}, never null* @throws RuntimeException All exceptions are caught* and re-thrown as {@code RuntimeException}*/public PublicKey produce(byte[] encodedByteArrayForPublicKey) {try {PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(encodedByteArrayForPublicKey));return publicKey;} catch (Exception ex) {throw new RuntimeException(ex);}}
}
清单5 – ByteArrayWriter.java类
package org.thoth.crypto.io;import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class ByteArrayWriter {protected Path outputFile;private void initOutputFile(Path outputFile) {this.outputFile = outputFile;}private void initOutputDirectory() {Path outputDirectory = outputFile.getParent();if (!Files.exists(outputDirectory)) {try {Files.createDirectories(outputDirectory);} catch (IOException e) {throw new RuntimeException(e);}}}public ByteArrayWriter(Path outputFile) {initOutputFile(outputFile);initOutputDirectory();}public void write(byte[] bytesArrayToWrite) {try (OutputStream os= Files.newOutputStream(outputFile);PrintWriter writer= new PrintWriter(os);){for (int i=0; i<bytesArrayToWrite.length; i++) {if (i>0) {writer.println();}writer.print(bytesArrayToWrite[i]);}} catch (IOException ex) {throw new RuntimeException(ex);}}
}
清单6 – ByteArrayReader.java类
package org.thoth.crypto.io;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Scanner;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class ByteArrayReader {protected Path inputFile;public ByteArrayReader(Path inputFile) {this.inputFile = inputFile;}public byte[] read() {try (Scanner scanner= new Scanner(inputFile);ByteArrayOutputStream baos= new ByteArrayOutputStream();){while (scanner.hasNext()) {baos.write(Byte.parseByte(scanner.nextLine()));}baos.flush();return baos.toByteArray();} catch (IOException ex) {throw new RuntimeException(ex);}}
}
清单7 – RsaEncrypter.java类
package org.thoth.crypto.asymmetric;import java.security.PublicKey;
import javax.crypto.Cipher;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class RsaEncrypter {protected RsaCipher cipher;public RsaEncrypter(PublicKey key) {this.cipher = new RsaCipher(Cipher.ENCRYPT_MODE, key);}public byte[] encrypt(String message) {try {return cipher.update(message.getBytes("UTF-8")).doFinal();} catch (Exception e) {throw new RuntimeException(e);}}
}
清单8 – RsaDecrypter.java类
package org.thoth.crypto.asymmetric;import java.security.PrivateKey;
import javax.crypto.Cipher;/**** @author Michael Remijan mjremijan@yahoo.com @mjremijan*/
public class RsaDecrypter {protected RsaCipher cipher;public RsaDecrypter(PrivateKey key) {this.cipher = new RsaCipher(Cipher.DECRYPT_MODE, key);}public String decrypt(byte[] message) {try {return new String(cipher.update(message).doFinal(), "UTF-8");} catch (Exception e) {throw new RuntimeException(e);}}}
摘要
加密并不容易。 简单的示例将为您的应用程序带来带有安全漏洞的实现。 如果需要公用/专用密钥,非对称加密算法,请使用具有4096位密钥的RSA / ECB / OAEPWithSHA–512AndMGF1Padding。
参考文献
Sheth,M.(2017年4月18日)。 Java密码学中的加密和解密。 从https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography检索。
- 最佳算法,模式和填充
- 使用4096位密钥
华盛顿州布莱特韦尔,雨披。 (2015年5月4日)。 ECB模式与RSA加密一起使用是否安全? 从https://crypto.stackexchange.com/questions/25420/is-ecb-mode-safe-to-use-with-rsa-encryption检索。
- 欧洲央行不适用; Java不会在幕后使用它。
- RSA使用随机性和填充来避免相同明文的ECB问题生成相同的密文
玛丽莲娜 (2016年11月29日)。 Java –非对称密码术示例。 从https://www.mkyong.com/java/java-asymmetric-cryptography-example/检索。
- 将公用/专用密钥写入文件
- 从文件中读取公钥/私钥
- 加密与解密
密钥大小。 (2017年10月12日)。 维基百科。 取自https://en.wikipedia.org/wiki/Key_size 。
- 到2030年,2048位密钥就足够了
- 如果2030年以后仍需要安全性,则应使用3072位的RSA密钥长度
用户4982。 (2013年11月4日)。 IV如何与RSA加密关联使用? 取自https://crypto.stackexchange.com/questions/11403/how-are-ivs-used-in-association-with-rsa-encryption 。
- IV值不适用于RSA
翻译自: https://www.javacodegeeks.com/2017/12/choosing-java-cryptographic-algorithms-part-3-public-private-key-asymmetric-encryption.html
选择Java加密算法第3部分–公钥/私钥非对称加密相关推荐
- 非对称加密 公钥私钥_选择Java加密算法第3部分–公钥/私钥非对称加密
非对称加密 公钥私钥 抽象 这是涵盖Java加密算法的三部分博客系列的第3部分. 该系列涵盖如何实现以下功能: 使用SHA–512散列 使用AES–256的单密钥对称加密 RSA–4096 这第三篇文 ...
- 对称密钥加密算法 对称轮数_选择Java加密算法第2部分–单密钥对称加密
对称密钥加密算法 对称轮数 抽象 这是涵盖Java加密算法的三部分博客系列的第2部分. 该系列涵盖如何实现以下功能: 使用SHA–512散列 AES–256 RSA–4096 这第二篇文章详细介绍了如 ...
- 选择Java加密算法第2部分–单密钥对称加密
抽象 这是涵盖Java加密算法的三部分博客系列的第2部分. 本系列介绍如何实现以下目标: 使用SHA–512散列 AES–256 RSA–4096 这第二篇文章详细介绍了如何实现单密钥对称AES-25 ...
- PHP RSA 生成公钥私钥 PSA2 加密解密
阅读目录 一.[PHP]生成 RSA 公钥私钥 二.[PHP]RSA2 签名与验签的使用类 1.php RSA2 签名 2.php RSA2 验签 三.[PHP]RSA2 加密算法的方法 1 使用公钥 ...
- python实现非对称加密算法_Python使用rsa模块实现非对称加密与解密
Python使用rsa模块实现非对称加密与解密 1.简单介绍: RSA加密算法是一种非对称加密算法 是由已知加密密钥推导出解密密钥在计算上是不可行的"密码体制.加密密钥(即公开密钥)PK是公 ...
- java rsautil_JAVA 通过RSA获取公钥私钥工具类
public class RSAUtil { //生成秘钥对 public static KeyPair getKeyPair() throws Exception { KeyPairGenerato ...
- java 哈希算法_选择Java密码算法第1部分-哈希
java 哈希算法 抽象 这是涵盖Java加密算法的三部分博客系列文章的第1部分. 该系列涵盖如何实现以下功能: 使用SHA–512散列 使用AES–256的单密钥对称加密 使用RSA–4096的公钥 ...
- 选择Java密码算法第1部分-散列
抽象 这是涵盖Java加密算法的三部分博客系列的第1部分. 本系列介绍如何实现以下目标: 使用SHA–512散列 使用AES–256的单密钥对称加密 使用RSA–4096的公钥/私钥非对称加密 这第一 ...
- 公钥私钥证书与https
公钥私钥 非对称加密: 在一个过程中使用两个密钥,公共密钥用于加密信息,私用密钥用于解译加密的信息.这种加密方法称为非对称加密,也称为公钥加密,因为其中一个密钥是公开的(另一个私钥则需要自己保密). ...
最新文章
- 【青少年编程】【四级】数字之和
- Android Activity的生命周期
- 关于 Kubernetes 规划的灵魂 n 问
- 命令行开启windows下的iis信息服务,开启及配置http端口,开启及配置ftp端口
- NodeManager启动流程与服务
- halcon clear_ocr_class_svm 清除基于SVM的OCR分类器
- idea for mac 控制台 mvn command not found
- 【C++深度剖析教程40】使用数值型模板技术计算1+2+3+...+N的值
- CentOS6.8_64位手动安装MySQL5.6
- Swiper学习之二---swiper的配置选项 ①
- mongodb更新操作符$rename
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp
- 响应式编程优点 有效_美团 EasyReact 源码剖析:图论与响应式编程
- 即时通讯源码/im源码uniapp基于在线聊天系统附完整搭建部署教程
- Android Gradle manifestPlaceholders 的妙用
- FAST-LIO,FAST-LIO2与FASTER-LIO
- 融资租赁公司信息科技规划研究
- 双alpha可以结合吗_推文简评《和我的Alpha一起待产》:这本双A甜文有点意思
- 关闭删库跑路的后门,打造高可用的MySQL
- js,javascript中判断一个数是否是素数
热门文章
- 介绍Java中的内存泄漏
- 用eclipse创建动态web项目手动生成web.xml方法
- python爬虫进阶(初始)
- VS2012找不到EF框架实体模型的解决方法
- mybatis简单案例源码详细【注释全面】——实体层(Role.java)
- Servlet使用适配器模式进行增删改查案例(DeptDaoImpl.java)
- React中构造函数、reader和函数的调用次数和时机测试
- 整合Druid---SpringBoot
- SparkSQL性能优化
- java path 注解_@PathVariable注解的使用和@Requestparam