当前位置: 首页 > news >正文

Java实现非对称加密【详解】

Java实现非对称加密

  • 1. 简介
  • 2. 非对称加密算法--DH(密钥交换)
  • 3. 非对称加密算法--RSA
  • 非对称加密算法--EIGamal
  • 5. 总结
  • 6 案例
    • 6.1 案例1
    • 6.2 案例2

1. 简介

公开密钥密码学(英语:Public-key cryptography)也称非对称式密码学(英语:Asymmetric cryptography)是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密。使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文,最初用来加密的公钥不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密;不同于加密和解密都使用同一个密钥的对称加密。公钥可以公开,可任意向外发布;私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。
基于公开密钥加密的特性,它还能提供数字签名的功能,使电子文件可以得到如同在纸本文件上亲笔签署的效果。公开密钥基础建设透过信任数字证书认证机构的根证书、及其使用公开密钥加密作数字签名核发的公开密钥认证,形成信任链架构,已在TLS实现并在万维网的HTTP以HTTPS、在电子邮件的SMTP以SMTPS或STARTTLS引入。
在现实世界上可作比拟的例子是,一个传统保管箱,开门和关门都是使用同一条钥匙,这是对称加密;而一个公开的邮箱,投递口是任何人都可以寄信进去的,这可视为公钥;而只有信箱主人拥有钥匙可以打开信箱,这就视为私钥。
非对称加密过程:

在这里插入图片描述
此流程图显示非对称加密过程是单向的,其中一条密钥加密后只能用相对应的另一条密钥解密。

2. 非对称加密算法–DH(密钥交换)

密钥长度默认工作模式填充方式实现方
512~1024(64倍数)1024JDK

DH加解密应用:

package com.bity.dh;import org.apache.commons.codec.binary.Base64;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;import static java.lang.System.*;/*** <p>Title: JdkDh</p >* <p>Description: DH非对称算法实现 </p >* <p>Company: http://www.agree.com</p >* <p>Project: security</p >** @author <a href="mailto:weiqi@agree.com.cn">WEIQI</a>* @version 1.0* @date 2022-04-27 19:51*/
public class JdkDh {private static final String SRC = "I'm DH encryption algorithm";public static void main(String[] args) {// 解决 Unsupported secret key algorithm: DES 异常System.getProperties().setProperty("jdk.crypto.KeyAgreement.legacyKDF", "true");jdkDh();}private static void jdkDh() {try {// 初始化发送方密钥KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");senderKeyPairGenerator.initialize(512);KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();// 发送方密钥,发送给接收方(可以通过文件、优盘、网络等...)byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();// 初始化接收方密钥,注意在实际环境中接收方和发送方肯定不会在一个函数中KeyFactory keyFactory = KeyFactory.getInstance("DH");X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);PublicKey receiverPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);DHParameterSpec dhParameterSpec = ((DHPublicKey)receiverPublicKey).getParams();KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");receiverKeyPairGenerator.initialize(dhParameterSpec);KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();// 构建密钥KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");receiverKeyAgreement.init(receiverPrivateKey);receiverKeyAgreement.doPhase(receiverPublicKey, true);SecretKey receiverSecretKey = receiverKeyAgreement.generateSecret("DES");KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");senderKeyAgreement.init(senderKeyPair.getPrivate());senderKeyAgreement.doPhase(senderPublicKey, true);SecretKey senderSecretKey = senderKeyAgreement.generateSecret("DES");if (Objects.equals(receiverSecretKey, senderSecretKey)) {out.println("双方密钥相同");}// 加密Cipher cipher = Cipher.getInstance("DES");cipher.init(Cipher.ENCRYPT_MODE, senderSecretKey);byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8));out.println("jdk dh encryption is : " + Base64.encodeBase64String(result));// 解密cipher.init(Cipher.DECRYPT_MODE, receiverSecretKey);result = cipher.doFinal(result);out.println("jdk dh decrypt is : " + new String(result));} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {e.printStackTrace();}}
}

运行结果:

双方密钥相同
jdk dh encryption is : Be3LeXqV/q1PDEbpH62LL129gaV5Og0Eo3GY9e00B4o=
jdk dh decrypt is : I'm DH encryption algorithm

注意:由于JDK8 update 161之后,DH的密钥长度至少为512位,但DES算法密钥不能达到这样的长度,所以运行会抛出Unsupported secret key algorithm: DES异常。解决办法有两种如下:

  1. 在代码中加如下代码:
System.getProperties().setProperty("jdk.crypto.KeyAgreement.legacyKDF", "true");
  1. 在启动的时候添加JVM变量:-Djdk.crypto.KeyAgreement.legacyKDF=true
    在这里插入图片描述
    在这里插入图片描述

3. 非对称加密算法–RSA

RSA加密算法是一种非对称加密算法,在公开密钥加密和电子商业中被广泛使用。RSA是由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)在1977年一起提出的。当时他们三人都在麻省理工学院工作。RSA 就是他们三人姓氏开头字母拼在一起组成的。

对极大整数做因数分解的难度决定了 RSA 算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA 算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用 RSA 加密的信息的可靠性就会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的 RSA 钥匙才可能被强力方式破解。到2020年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被破解的。

RSA算法加密实现:

package com.bity.rsa;import org.apache.commons.codec.binary.Base64;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;import static java.lang.System.*;/*** <p>Title: JdkRsa</p >* <p>Description: RSA非对称加密算法实现 </p >* <p>Company: http://www.agree.com</p >* <p>Project: security</p >** @author <a href="mailto:weiqi@agree.com.cn">WEIQI</a>* @version 1.0* @date 2022-04-27 21:38*/
public class JdkRsa {private static final String SRC = "I'm RSA encryption algorithm";public static void main(String[] args) {jdkRsa();}/*** JDK-RSA算法实现* * @author: <a href="mailto:weiqi@agree.com.cn">WEIQI</a>* @date: 2022-04-28 0:15*/private static void jdkRsa() {try {// 初始化密钥KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(512);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();out.println("public key is : " + Base64.encodeBase64String(rsaPublicKey.getEncoded()));out.println("private key is : " + Base64.encodeBase64String(rsaPrivateKey.getEncoded()));// 私钥加密,公钥解密 -- 加密PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, privateKey);byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8));out.println("私钥加密,公钥解密 -- 加密 : " + Base64.encodeBase64String(result));// 私钥加密,公钥解密 -- 解密X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);cipher.init(Cipher.DECRYPT_MODE, publicKey);result = cipher.doFinal(result);out.println("私钥加密,公钥解密 -- 解密 : " + new String(result));// 公钥加密,私钥解密 -- 加密cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] res = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8));out.println("公钥加密,私钥解密 -- 加密 : " + Base64.encodeBase64String(res));// 公钥加密,私钥解密 -- 解密cipher.init(Cipher.DECRYPT_MODE, privateKey);res = cipher.doFinal(res);out.println("公钥加密,私钥解密 -- 解密 : " + new String(res));} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {e.printStackTrace();}}
}

运行结果:

public key is : MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIfDTXqCrjGHP9tCmLujavsngP8nqSHIl/JkFN8ZmQEcn48xzSXdijEG8Ssgm3SkDWICT0cW9wf3mZ+UkVxLx90CAwEAAQ==
private key is : MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAh8NNeoKuMYc/20KYu6Nq+yeA/yepIciX8mQU3xmZARyfjzHNJd2KMQbxKyCbdKQNYgJPRxb3B/eZn5SRXEvH3QIDAQABAkASyfa5E8jj1eICiE72+QDfTXJO3cBMiqRsyWkSD0rbmlL/Qv1xDDQonWM58sIR6DOBWQZ+uXbkL1VtOuZ9sgfBAiEA9IxhRwkTYA1GVUKmgZPX+7CsfUmIZi8P/r9/C29XQZUCIQCOHtBkIOupaTLPv3A4yznEidygfbL8nrLV2Xhf6wVrKQIhAJ+RdewPDPhw0QLTIaiNWrIdXv/FWl4quUolk/VXKl1dAiASpbpkGOmy7cmr9otr+EZZIlmfeT695LjEVGd19mlcmQIhAJfua+j3/PT0+z0nPIaGDvczviyl5SxmDo79rfMNpi10
私钥加密,公钥解密 -- 加密 : AiYjJSlGlz5x86mwVW/wjieG/uJsoLEqF+xRcPLzq2HL7yIrSrE3oT4wibrvUDR6kp37eHvFaAT+/wVYCreVvg==
私钥加密,公钥解密 -- 解密 : I'm RSA encryption algorithm
公钥加密,私钥解密 -- 加密 : Io2diORtKbeTz5eOOziHrqZKzS1K19U4t3YPydhM4w2LrzW7bJK/d4DQrWTBAhg8rt28OjbGcJfqd1w8MMy4iw==
公钥加密,私钥解密 -- 解密 : I'm RSA encryption algorithm

从上面例子可以看出RSA算法是支持私钥加密、公钥解密和公钥加密、私钥解密的算法。RSA也是唯一被广泛接受并实现的非对称加密算法,从某种程度来说,RSA已经成为非对称加密算法的一个标准了。

RSA数据加密传输图示:
在这里插入图片描述

非对称加密算法–EIGamal

在密码学中,ElGamal加密算法是一个基于迪菲-赫尔曼密钥交换的非对称加密算法。它在1985年由塔希尔·盖莫尔提出。GnuPG和PGP等很多密码学系统中都应用到了ElGamal算法。
ElGamal加密算法由三部分组成:密钥生成、加密和解密。

ElGamal算法加解密应用:

package com.bity.eigamal;import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.DHParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;import static java.lang.System.out;/*** <p>Title: BouncyCastleEiGamal</p >* <p>Description: ElGamal加密算法实现 </p >* <p>Company: http://www.agree.com</p >* <p>Project: security</p >** @author <a href="mailto:weiqi@agree.com.cn">WEIQI</a>* @version 1.0* @date 2022-04-28 0:38*/
public class BouncyCastleElGamal {private static final String SRC = "I'm ElGamal encryption algorithm";public static void main(String[] args) {bcElGamal();}private static void bcElGamal() {try {Security.addProvider(new BouncyCastleProvider());AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator.getInstance("ElGamal");algorithmParameterGenerator.init(256);AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();DHParameterSpec dhParameterSpec = algorithmParameters.getParameterSpec(DHParameterSpec.class);// 初始化密钥KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ElGamal");keyPairGenerator.initialize(dhParameterSpec, new SecureRandom());KeyPair keyPair = keyPairGenerator.generateKeyPair();PublicKey elGamalPublicKey = keyPair.getPublic();PrivateKey elGamalPrivateKey = keyPair.getPrivate();out.println("public key is : " + Base64.encodeBase64String(elGamalPublicKey.getEncoded()));out.println("private key is : " + Base64.encodeBase64String(elGamalPrivateKey.getEncoded()));// 公钥加密,私钥解密 -- 加密X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(elGamalPublicKey.getEncoded());KeyFactory keyFactory = KeyFactory.getInstance("ElGamal");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Cipher cipher = Cipher.getInstance("ElGamal");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8));out.println("私钥加密,公钥解密 -- 解密 : " + Base64.encodeBase64String(result));// 公钥加密,私钥解密 -- 解密PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded());keyFactory = KeyFactory.getInstance("ElGamal");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);cipher.init(Cipher.DECRYPT_MODE, privateKey);result = cipher.doFinal(result);out.println("私钥加密,公钥解密 -- 加密 : " + new String(result));} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidParameterSpecException | InvalidAlgorithmParameterException e) {e.printStackTrace();}}
}

运行结果:

 
public key is : MHYwTwYGKw4HAgEBMEUCIQCxvT1SNSrVl1/8KpvPhaE1MKiaXOHWk5SACDd39SfnHwIgQ5O8oKi9mIKhEDOCKwvYB+mozFgvmuoipw/ZDl6xCicDIwACIBh0K6bn2mtdvmiSMJj/HDlotAGOmTRFMZs+PFoIobQG
private key is : MHgCAQAwTwYGKw4HAgEBMEUCIQCxvT1SNSrVl1/8KpvPhaE1MKiaXOHWk5SACDd39SfnHwIgQ5O8oKi9mIKhEDOCKwvYB+mozFgvmuoipw/ZDl6xCicEIgIge9eM9ELM12n6bQKkj8iBtIXjvPeN5mwX9clNriqfSsA=
私钥加密,公钥解密 -- 解密 : e39h4LkKXQn1EIXdDkIxmWiB2pwgO5dZJcNfSmlXqS07SrW1VSLrx0L3RhdWm8hPLaqBZieR5quU/7oTzH/uuA==
私钥加密,公钥解密 -- 加密 : I'm ElGamal encryption algorithm

ElGamal数据加密传输图示:
在这里插入图片描述

5. 总结

对称密码是指在加密和解密时使用同一个密钥的方式,公钥密码则是指在加密和解密时使用不同密钥的方式。
对称密钥加密牵涉到密钥管理的问题,尤其是密钥交换,它需要通信双方在通信之前先透过另一个安全的渠道交换共享的密钥,才可以安全地把密文透过不安全的渠道发送;对称密钥一旦被窃,其所作的加密将即时失效;而在互联网,如果通信双方分隔异地而素未谋面,则对称加密事先所需要的“安全渠道”变得不可行;非对称加密则容许加密公钥随便散布,解密的私钥不发往任何用户,只在单方保管;如此,即使公钥在网上被截获,如果没有与其匹配的私钥,也无法解密,极为适合在互联网上使用。
另一方面,公钥解密的特性可以形成数字签名,使数据和文件受到保护并可信赖;如果公钥透过数字证书认证机构签授成为电子证书,更可作为数字身份的认证,这都是对称密钥加密无法实现的。不过,公钥加密在在计算上相当复杂,性能欠佳、远远不比对称加密;因此,在一般实际情况下,往往通过公钥加密来随机创建临时的对称秘钥,亦即对话键,然后才通过对称加密来传输大量、主体的数据。

6 案例

6.1 案例1

package com.test;import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;public class MyTest02 {public static void main(String[] args) throws Exception {MyTest02 myTest02 = new MyTest02();myTest02.test1(); //生成密钥String jm = myTest02.test2(); //通过公钥加密myTest02.test3(jm); //通过私钥解密}public void test1() throws NoSuchAlgorithmException {// 初始化密钥KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(512);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();System.out.println("public key is : " + Base64.getEncoder().encodeToString(rsaPublicKey.getEncoded()));System.out.println("private key is : " + Base64.getEncoder().encodeToString(rsaPrivateKey.getEncoded()));}public String test2() throws Exception {String SRC = "I'm RSA encryption algorithm";String pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIOz/OOCWjqI/6gssHGA/cHiJnR3hNdp230g1x7Y/aWzFc8WrQnjlX4v0PdEOphfkt8CtdzgDAlz4gMTLkLdU30CAwEAAQ==";byte[] pubKeyDecode = Base64.getDecoder().decode(pubKey);X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKeyDecode);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] res = cipher.doFinal(SRC.getBytes(StandardCharsets.UTF_8));System.out.println("公钥加密,私钥解密 -- 加密 : " + Base64.getEncoder().encodeToString(res));return Base64.getEncoder().encodeToString(res);}public void test3 (String data) throws Exception {String pvtKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAg7P844JaOoj/qCywcYD9weImdHeE12nbfSDXHtj9pbMVzxatCeOVfi/Q90Q6mF+S3wK13OAMCXPiAxMuQt1TfQIDAQABAkAbcnUvjMj1DfwJtlaHMRSxRUoyV34tznfZmfB7E0m5MEwfCMECzVKVtnmPpl3abbSt7UFwarvhnhhqfMM3Z9BBAiEA7ny1zoW04a/KM7VJRprOtkC3IQzjiyPl8aeoaseuvIkCIQCNX9t9K6GmSpwPLdBDtfk+Krk0qfiZaB9tEOhtG4hqVQIhAIriiaZJ63r7OtA+JPw/L16n9X4D2YewUjsXHleBDluxAiB9bkjs22NGiPfBN+KJ0NBcacd8hDl+0jTfrZqqAz2bKQIgUokJPDnwtnWVvWEwAK2wkDHkpIuvVRiG0HxNhS/ZDQA=";byte[] pvtDecoder = Base64.getDecoder().decode(pvtKey);PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(pvtDecoder);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decode = Base64.getDecoder().decode(data);byte[] res = cipher.doFinal(decode);System.out.printf("公钥加密,私钥解密 -- 解密: " + new String(res));}

6.2 案例2

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import javax.crypto.Cipher;
public class RSAEncryptionExample {public static void main(String[] args) throws Exception {String data = "Hello, world!";KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();PublicKey publicKey = keyPair.getPublic();PrivateKey privateKey = keyPair.getPrivate();Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] encryptedData = cipher.doFinal(data.getBytes());System.out.println(Base64.getEncoder().encodeToString(encryptedData));cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedData = cipher.doFinal(encryptedData);System.out.println(new String(decryptedData));}
}

相关文章:

Java实现非对称加密【详解】

Java实现非对称加密 1. 简介2. 非对称加密算法--DH&#xff08;密钥交换&#xff09;3. 非对称加密算法--RSA非对称加密算法--EIGamal5. 总结6 案例6.1 案例16.2 案例2 1. 简介 公开密钥密码学&#xff08;英语&#xff1a;Public-key cryptography&#xff09;也称非对称式密…...

simulinkveristandlabview联合仿真——模型导入搭建人机界面

目录 1.软件版本 2.搭建simulink仿真模型 编译错误 3.导入veristand并建立工程 4.veristand导入labview labview显示veristand工程数据 labview设置veristand工程数据 运行labview工程 1.软件版本 matlab2020a&#xff0c;veristand2020 R4&#xff0c;labview2020 SP…...

k8s中Helm工具实践

k8s中Helm工具实践 1&#xff09;安装redis-cluster 先搭建一个NFS的SC&#xff08;只需要SC&#xff0c;不需要pvc&#xff09;&#xff0c;具体步骤此文档不再提供&#xff0c;请参考前面相关章节。 下载redis-cluster的chart包 helm pull bitnami/redis-cluster --untar…...

推荐算法架构7:特征工程(吊打面试官,史上最全!)

系列文章&#xff0c;请多关注 推荐算法架构1&#xff1a;召回 推荐算法架构2&#xff1a;粗排 推荐算法架构3&#xff1a;精排 推荐算法架构4&#xff1a;重排 推荐算法架构5&#xff1a;全链路专项优化 推荐算法架构6&#xff1a;数据样本 推荐算法架构7&#xff1a;特…...

Web前端 ---- 【Vue】vue路由守卫(全局前置路由守卫、全局后置路由守卫、局部路由path守卫、局部路由component守卫)

目录 前言 全局前置路由守卫 全局后置路由守卫 局部路由守卫之path守卫 局部路由守卫之component守卫 前言 本文介绍Vue2最后的知识点&#xff0c;关于vue的路由守卫。也就是鉴权&#xff0c;不是所有的组件任何人都可以访问到的&#xff0c;需要权限&#xff0c;而根据权限…...

uniapp点击tabbar之前做判断

在UniApp中&#xff0c;可以通过监听 tabBar 的 click 事件来在点击 tabBar 前做判断。具体步骤如下&#xff1a; 在 pages.json 文件中配置 tabBar&#xff0c;例如&#xff1a; {"pages":[{"path":"pages/home/home","name":"h…...

DLLNotFoundException:xxx tolua... 错误打印

DLLNotFoundException:xxx tolua... 错误打印 一、DLLNotFoundException介绍二、Plugins文件夹文件目录结构如下&#xff1a; 三、Plugins中的Android文件夹四、Plugins中的IOS文件夹这里不说了没测试过不过原理应该也是选择对应的平台即可五、Plugins中的x86和X86_64文件夹 一…...

Python量化投资——金融数据最佳实践: 使用qteasy+tushare搭建本地金融数据仓库并定期批量更新【附源码】

用qteasytushare实现金融数据本地化存储及访问 目的什么是qteasy什么是tushare为什么要本地化使用qteasy创建本地数据仓库qteasy支持的几种本地化仓库类型配置本地数据仓库配置tushare 的API token 配置本地数据源 —— 用MySQL数据库作为本地数据源下载金融历史数据 数据的定期…...

【投稿】北海 - Rust与面向对象(二)

模板方法 Rust提供了trait&#xff0c;类似于面向对象的接口&#xff0c;不同的是&#xff0c;将传统面向对象的虚函数表从对象中分离出来&#xff0c;trait仍然是一个函数表&#xff0c;只不过是独立的&#xff0c;它的参数self指针可以指向任何实现了该trait的结构。 从对象中…...

HarmonyOS构建第一个ArkTS应用(FA模型)

构建第一个ArkTS应用&#xff08;FA模型&#xff09; 创建ArkTS工程 若首次打开DevEco Studio&#xff0c;请点击Create Project创建工程。如果已经打开了一个工程&#xff0c;请在菜单栏选择File > New > Create Project来创建一个新工程。 选择Application应用开发&a…...

阿里云 ARMS 应用监控重磅支持 Java 21

作者&#xff1a;牧思 & 山猎 前言 今年的 9 月 19 日&#xff0c;作为最新的 LTS (Long Term Support) Java 版本&#xff0c;Java 21 正式 GA&#xff0c;带来了不少重量级的更新&#xff0c;详情请参考 The Arrival of Java 21 [ 1] 。虽然目前 Java 11 和 Java 17 都…...

C++ 类的析构函数和构造函数

构造函数 类的构造函数是类的一种特殊的成员函数&#xff0c;它会在每次创建类的新对象时执行。主要用来在创建对象时初始化对象即为对象成员变量赋初始值。 构造函数的名称与类的名称是完全相同的&#xff0c;并且不会返回任何类型&#xff0c;也不会返回 void。构造函数可用…...

STM32——CAN协议

文章目录 一.CAN协议的基本特点1.1 特点1.2 电平标准1.3 基本的五个帧1.4 数据帧 二.数据帧解析2.1 帧起始和仲裁段2.2 控制段2.3 数据段和CRC段2.4 ACK段和帧结束 三.总线仲裁四.位时序五.STM32CAN控制器原理与配置5.1 STM32CAN控制器介绍5.2 CAN的模式5.3 CAN框图 六 手册寄存…...

数据结构-如何巧妙实现一个栈?逐步解析与代码示例

文章目录 引言1.栈的基本概念2.选择数组还是链表&#xff1f;3. 定义栈结构4.初始化栈5.压栈操作6.弹栈操作7.查看栈顶和判断栈空9.销毁栈操作10.测试并且打印栈内容栈的实际应用结论 引言 栈是一种基本但强大的数据结构&#xff0c;它在许多算法和系统功能中扮演着关键角色。…...

web前端之拖拽API、vue3实现图片上传拖拽排序、拖放、投掷、复制、若依、vuedraggable

MENU vue2html5原生dom原生JavaScript实现跨区域拖放vue2实现跨区域拖放vue2mousedown实现全屏拖动&#xff0c;全屏投掷vue3element-plusvuedraggable实现图片上传拖拽排序vue2transition-group实现拖动排序原生拖拽排序 vue2html5原生dom原生JavaScript实现跨区域拖放 关键代…...

第11章 GUI Page403~405 步骤三 设置滚动范围

运行效果&#xff1a; 源代码&#xff1a; /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…...

【Spring Security】打造安全无忧的Web应用--使用篇

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Spring Security的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Spring Security中的授权是…...

体验一下 CodeGPT 插件

体验一下 CodeGPT 插件 0. 背景1. CodeGPT 插件安装2. CodeGPT 插件基本配置3. (可选)CodeGPT 插件预制提示词原始配置(英文)4. CodeGPT 插件预制提示词配置(中文)5. 简单验证一下 0. 背景 看到B站Up主 “wwwzhouhui” 一个关于 CodeGPT 的视频&#xff0c;感觉挺有意思&#…...

深度学习 | 基础卷积神经网络

卷积神经网络是人脸识别、自动驾驶汽车等大多数计算机视觉应用的支柱。可以认为是一种特殊的神经网络架构&#xff0c;其中基本的矩阵乘法运算被卷积运算取代&#xff0c;专门处理具有网格状拓扑结构的数据。 1、全连接层的问题 1.1、全连接层的问题 “全连接层”的特点是每个…...

[字符编码]windwos下使用libiconv转换编码格式(二)

在http://t.csdnimg.cn/PLUuz笔记中实现了常用编码格式转换的功能,但这还是一个demo。因为代码中向libiconv库函数传递的字符串是存放在堆空间中的(我也是从网上找例子测试,是否一定要开辟堆空间存放还有待考证),如果一次性转换的字节数很巨大的话,就会导致内存空间不足,进而引…...

textile 语法

1、文字修饰 修饰行内文字 字体样式textile 语法对应的 XHTML 语法实际显示效果加强*strong*<strong>strong</strong>strong强调_emphasis_<em>emphasis</em>emphasis加粗**bold**<b>bold</b>bold斜体__italics__<i>italics</i…...

【快速开发】使用SvelteKit

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…...

【docker笔记】docker常用命令

1、帮助启动类命令 1.1 启动、重启、查询当前状态、停止 systemctl start docker systemctl stop docker systemctl restart docker systemctl status docker1.2 设置开机启动 systemctl enable docker1.3 查看docker概要信息 docker info1.4 查看docker帮助文档 docker -…...

API 接口怎样设计才安全?

设计安全的API接口是确保应用程序和数据安全的重要方面之一。下面是一些设计安全的API接口的常见实践&#xff1a; 1. 身份验证和授权&#xff1a; 使用适当的身份验证机制&#xff0c;如OAuth、JWT或基本身份验证&#xff0c;以确保只有经过身份验证的用户可以访问API。实施…...

网站被CC攻击了怎么办?CC攻击有什么危害

网络爆炸性地发展&#xff0c;网络环境也日益复杂和开放&#xff0c;同时各种各样的恶意威胁和攻击日益增多&#xff0c;其中网站被CC也是常见的情况。 CC攻击有什么危害呢&#xff1f; 被CC会导致&#xff1a; 1.访问速度变慢&#xff1a;网站遭受CC攻击后&#xff0c;由于…...

Docker - 镜像 | 容器 日常开发常用指令 + 演示(一文通关)

目录 Docker 开发常用指令汇总 辅助命令 docker version docker info docker --help 镜像命令 查看镜像信息 下载镜像 搜索镜像 删除镜像 容器命令 查看运行中的容器 运行容器 停止、启动、重启、暂停、恢复容器 杀死容器 删除容器 查看容器日志 进入容器内部…...

要参加微软官方 Copilot 智能编程训练营了

GitHub Copilot 是由 GitHub、OpenAI 和 Microsoft 联合开发的生成式 AI 模型驱动的。 GitHub Copilot 分析用户正在编辑的文件及相关文件的上下文&#xff0c;并在编写代码时提供自动补全式的建议。 刚好下周要参加微软官方组织的 GitHub Copilot 工作坊-智能编程训练营&…...

Python入门学习篇(五)——列表字典

1 列表 1.1 定义 ①有序可重复的元素集合 ②可以存放不同类型的数据 ③个人理解:类似于java中的数组1.2 相关方法 1.2.1 获取列表长度 a 语法 len(列表名)b 示例代码 list2 [1, 2, "hello", 4] print(len(list2))c 运行结果 1.2.2 获取列表值 a 语法 列表名…...

React尝鲜

组件 React的组件就是一个js函数&#xff0c;函数内部return一个由jsx语法创建的html代码片段。 //MyComp.js export default function MyComp(){return (<h1>我是新组件MyComp</h1>) } 在需要引入组件的地方import导入组件&#xff0c;并放在相应位置 //App.js…...

锯齿云服务器租赁使用教程

首先登陆锯齿云账号 网盘上传数据集与代码 随后我们需要做的是将所需要的数据集与代码上传到网盘&#xff08;也可以直接在租用服务器后将数据集与代码传到服务器的硬盘上&#xff0c;但这样做会消耗大量时间&#xff0c;造成资源浪费&#xff09; 点击工作空间&#xff1a;…...

HarmonyOS和OpenHarmony的区别

1.概要 众所周知&#xff0c;鸿蒙是华为开发的一款分布式操作系统。因为开发系统&#xff0c;最重要的是集思广益&#xff0c;大家共同维护。为了在IOS和Android之间生存&#xff0c;鸿蒙的茁壮成长一定是需要开源&#xff0c;各方助力才能实现。   在这种思想上&#xff0c;…...

Redis Stream消息队列之基本语法与使用方式

前言 本文的主角是Redis Stream&#xff0c;它是Redis5.0版本新增加的数据结构&#xff0c;主要用于消息队列&#xff0c;提供了消息的持久化和主备复制功能&#xff0c;可以让任何客户端访问任何时刻的数据&#xff0c;并且能记住每一个客户端的访问位置&#xff0c;还能保证…...

制造行业定制软件解决方案——工业信息采集平台

摘要&#xff1a;针对目前企业在线检测数据信号种类繁多&#xff0c;缺乏统一监控人员和及时处置措施等问题。蓝鹏测控开发针对企业工业生产的在线数据的集中采集分析平台&#xff0c;通过该工业信息采集平台可将企业日常各种仪表设备能够得到数据进行集中分析处理存储&#xf…...

[python]用python实现对arxml文件的操作

目录 关键词平台说明一、背景二、方法2.1 库2.2 code 关键词 python、excel、DBC、openpyxl 平台说明 项目Valuepython版本3.6 一、背景 有时候需要批量处理arxml文件(ARXML 文件符合 AUTOSAR 4.0 标准)&#xff0c;但是工作量太大&#xff0c;阔以考虑用python。 二、方…...

pdf 在线编辑

https://smallpdf.com/edit-pdf#rapp 参考 https://zh.wikihow.com/%E5%B0%86%E5%9B%BE%E5%83%8F%E6%8F%92%E5%85%A5PDF...

自然语言处理(NLP):理解语言,赋能未来

目录 前言1 什么是NLP2 NLP的用途3 发展历史4 NLP的基本任务4.1 词性标注&#xff08;Part-of-Speech Tagging&#xff09;4.2 命名实体识别&#xff08;Named Entity Recognition&#xff09;4.3 共指消解&#xff08;Co-reference Resolution&#xff09;4.4 依存关系分析&am…...

FastAPI使用loguru时,出现重复日志打印的解决方案

首先看图&#xff0c;发现每个日志都被打印了3条。其实这个和uvicorn日志打印的设计有关&#xff0c;在uvicorn中有多个logger&#xff0c;分别是uvicorn、uvicorn.error、uvicorn.access 而LOGGING默认有一个属性propagate&#xff0c;这个属性为True时&#xff0c;子日志记录…...

构建每个聚类的profile和deletion_mean特征

通过summarize_clusters函数构建每个聚类的protein[cluster_profile]和protein[cluster_deletion_mean]特征。目的是把extra_msa信息反映到msa中。 集成函数数据处理流程&#xff1a; sample_msa ->make_masked_msa -> nearest_neighbor_clusters -> summarize_clu…...

Milvus数据一致性介绍及选择方法

1、Milvus 时钟机制 Milvus 通过时间戳水印来保障读链路的一致性&#xff0c;如下图所示&#xff0c;在往消息队列插入数据时&#xff0c; Milvus 不光会为这些插入记录打上时间戳&#xff0c;还会不间断地插入同步时间戳&#xff0c;以图中同步时间戳 syncTs1 为例&#xff0…...

异常处理和单元测试python

一、实验题目 异常处理和单元测试 二、实验目的 了解异常的基本概念和常用异常类。掌握异常处理的格式、处理方法。掌握断言语句的作用和使用方法。了解单元测试的基本概念和作用。掌握在Python中使用测试模块进行单元测试的方法和步骤。 三、实验内容 编程实现如下功能&a…...

蓝牙物联网在汽车领域的应用

I、蓝牙的技术特点 ​ 1998 年 5 月&#xff0c;瑞典爱立信、芬兰诺基亚、日本东芝、美国IBM 和英特尔公司五家著名厂商&#xff0c;在联合拓展短离线通信技术的标准化活动时提出了蓝牙技术的概念。蓝牙工作在无需许可的 2.4GHz 工业频段 (SIM)之上(我国的频段范围为2400.0~248…...

用23种设计模式打造一个cocos creator的游戏框架----(二十二)原型模式

1、模式标准 模式名称&#xff1a;原型模式 模式分类&#xff1a;创建型 模式意图&#xff1a;用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象 结构图&#xff1a; 适用于&#xff1a; 1、当一个系统应该独立于它的产品创建、构成和表示时 2、…...

paddle 55 使用Paddle Inference部署嵌入nms的PPYoloe模型(端到端fps达到52.63)

Paddle Inference 是飞桨的原生推理库,提供服务器端的高性能推理能力。由于 Paddle Inference 能力直接基于飞桨的训练算子,因此它支持飞桨训练出的所有模型的推理。paddle平台训练出的模型转换为静态图时可以选用Paddle Inference的框架进行推理,博主以前都是将静态图转换为…...

自动化测试工具-Selenium:WebDriver的API/方法使用全解

我们上一篇文章介绍了Selenium的三大组件&#xff0c;其中介绍了WebDriver是最重要的组件。在这里&#xff0c;我们将看到WebDriver常用的API/方法&#xff08;注&#xff1a;这里使用Python语言来进行演示&#xff09;。 1. WebDriver创建 打开VSCode&#xff0c;我们首先引…...

如何通过蓝牙串口启动智能物联网?

1、低功耗蓝牙(BLE)介绍 BLE 技术是一种低成本、短距离、可互操作的鲁棒性无线技术&#xff0c;工作在免许可的 2,4 GHZ 工业、科学、医学(Industrial Scientific Medical&#xff0c;ISM)频段。BLE在设计之初便被定位为一种超低功耗(Ultra Low Power&#xff0c;ULP)无线技术&…...

Linux---基础操作命令

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…...

uniapp怎么动态渲染导航栏的title?

直接在接口请求里面写入以下&#xff1a; 自己要什么参数就写什么参数 本人仅供参考&#xff1a; this.name res.data.data[i].name; console.log(名字, res.data.data[i].name); uni.setNavigationBarTitle({title: this.name}) 效果&#xff1a;...

【机器学习】决策树

参考课程视频&#xff1a;https://www.icourse163.org/course/NEU-1462101162?tid1471214452 1 概述 样子&#xff1a; 2 分裂 2.1 分裂原则 信息增益 信息增益比 基尼指数 3 终止 & 剪枝 3.1 终止条件 无需分裂 当前节点内样本同属一类 无法分裂 当前节点内…...

[node] Node.js的全局对象Global

[node] Node.js的全局对象Global 什么是全局对象 & 全局变量全局对象与全局变量全局变量-- __filename全局变量-- __dirname全局函数-- setTimeout(cb, ms)全局函数-- clearTimeout(t)全局函数-- setInterval(cb, ms)全局变量-- consoleconsole 方法概览 全局变量-- proces…...

完整的 Meteor NPM 集成

在Meteor中&#xff0c;你只能使用包内的模块。你不能直接将模块与流星应用一起使用。此软件包解决了该问题 文章目录 源码下载地址安装定义软件包使用软件包在 Meteor 方法中使用 npm 模块的示例应用程序接口异步实用程序Async.runSync&#xff08;函数&#xff09;Meteor.sy…...