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

非对称密钥PKCS#1和PKCS#8格式互相转换(Java)

目录

  • 一、序言
  • 二、代码示例
    • 1、Maven依赖
    • 2、工具类封装
  • 三、测试用例
    • 1、密钥文件
    • 2、公私钥PKCS1和PKCS8格式互相转换

一、序言

之前在 《前后端RSA互相加解密、加签验签、密钥对生成》 中提到过PKCS#1格式和PKCS#8格式密钥的区别以及如何生成密钥。实际有些场景中有可能也会涉及到前后端密钥格式不一致,这篇文章我们会讨论关于PKCS#1PKCS#8格式密钥的互相转换。

这里我们会用到Bouncy Castle,它提供了各种加密算法的Java实现,其中Java相关的资料可以参考Bouncy Castle Github。



二、代码示例

1、Maven依赖

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk18on</artifactId><version>1.72</version>
</dependency>

2、工具类封装

package com.universe.crypto;import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;/*** @author Nick Liu* @date 2023/2/2*/
public class AsymmetricKeyUtils {private static final String ALGORITHM_NAME = "RSA";private static final Encoder BASE64_ENCODER = Base64.getEncoder();private static final Decoder BASE64_DECODER = Base64.getDecoder();static {// 必须创建Bouncy Castle提供者Security.addProvider(new BouncyCastleProvider());}/*** 格式化密钥为标准Pem格式* @param keyFormat 密钥格式,参考{@link KeyFormat}* @param asymmetricKey 非对称密钥* @return .pem格式密钥字符串* @throws IOException*/public static String formatKeyAsPemString(KeyFormat keyFormat, String asymmetricKey) throws IOException {byte[] keyInBytes = BASE64_DECODER.decode(asymmetricKey);PemObject pemObject = new PemObject(keyFormat.getName(), keyInBytes);try (StringWriter stringWriter = new StringWriter()) {PemWriter pemWriter = new PemWriter(stringWriter);pemWriter.writeObject(pemObject);pemWriter.flush();return stringWriter.toString();}}/*** 从标准Pem格式中提取密钥* @param asymmetricKeyAsPem* @return 无---BEGIN---和---END---前后缀的密钥字符串* @throws IOException*/public static String extractKeyFromPemString(String asymmetricKeyAsPem) throws IOException {try (PemReader pemReader = new PemReader(new StringReader(asymmetricKeyAsPem))) {PemObject pemObject = pemReader.readPemObject();return BASE64_ENCODER.encodeToString(pemObject.getContent());}}/*** 从文件中提取密钥* @param pemFilePath* @return 无---BEGIN---和---END---前后缀的密钥字符串* @throws Exception*/public static String readKeyFromPath(String pemFilePath) throws Exception {try (PemReader pemReader = new PemReader(new InputStreamReader(Files.newInputStream(Paths.get(pemFilePath))))) {PemObject pemObject = pemReader.readPemObject();return BASE64_ENCODER.encodeToString(pemObject.getContent());}}/*** 将PKCS1公钥转换为PKCS8公钥* @param pubKeyInPKCS1 PKCS1形式公钥* @return PKCS8形式公钥* @throws Exception*/public static String transformPubKeyFromPkcs1ToPkcs8(String pubKeyInPKCS1) throws Exception {RSAPublicKey rsaPublicKey = RSAPublicKey.getInstance(BASE64_DECODER.decode(pubKeyInPKCS1));KeySpec keySpec = new RSAPublicKeySpec(rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);PublicKey publicKey = keyFactory.generatePublic(keySpec);return BASE64_ENCODER.encodeToString(publicKey.getEncoded());}/*** 将PKCS8公钥转换为PKCS1公钥* @param pubKeyInPKCS8 PKCS8公钥* @return PKCS1公钥*/public static String transformPubKeyFromPkcs8ToPkcs1(String pubKeyInPKCS8) {ASN1Sequence publicKeyASN1Object = ASN1Sequence.getInstance(BASE64_DECODER.decode(pubKeyInPKCS8));DERBitString derBitString = (DERBitString) publicKeyASN1Object.getObjectAt(1);return BASE64_ENCODER.encodeToString(derBitString.getBytes());}/*** 将PKCS1私钥转换为PKCS8公钥* @param privateKeyInPKCS1 PKCS1公钥* @return PKCS8公钥* @throws Exception*/public static String transformPrivateKeyFromPkcs1ToPkcs8(String privateKeyInPKCS1) throws Exception {KeySpec keySpec = new PKCS8EncodedKeySpec(BASE64_DECODER.decode(privateKeyInPKCS1));KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM_NAME);PrivateKey privateKey = keyFactory.generatePrivate(keySpec);return BASE64_ENCODER.encodeToString(privateKey.getEncoded());}/*** 将PKCS1私钥转换为PKCS8私钥* @param privateKeyInPKCS8 PKCS8私钥* @return PKCS1私钥* @throws Exception*/public static String transformPrivateKeyFromPkcs8ToPkcs1(String privateKeyInPKCS8) throws Exception {PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance(BASE64_DECODER.decode(privateKeyInPKCS8));RSAPrivateKey rsaPrivateKey = RSAPrivateKey.getInstance(privateKeyInfo.parsePrivateKey());return BASE64_ENCODER.encodeToString(rsaPrivateKey.getEncoded());}public enum KeyFormat {/*** PKCS1格式RSA私钥*/RSA_PRIVATE_KEY_PKCS1("RSA PRIVATE KEY"),/*** PKCS8格式RSA私钥*/RSA_PRIVATE_KEY_PKCS8("PRIVATE KEY"),/*** PKCS1格式RSA公钥*/RSA_PUBLIC_KEY_PKCS1("RSA PUBLIC KEY"),/*** PKCS8格式RSA公钥*/RSA_PUBLIC_KEY_PKCS8("PUBLIC KEY");private String name;KeyFormat(String name) {this.name = name;}public String getName() {return name;}}}

备注:必须要添加Bouncy Castle提供者,代码中Security.addProvider(new BouncyCastleProvider())展示的是动态添加,也可以静态添加,更多请参考 Bouncy Castle提供者安装。
在这里插入图片描述



三、测试用例

1、密钥文件

准备.pem两个文件,里面分别是PKCS#1格式公钥和PKCS#1格式私钥,内容如下:

  • publicKeyInPkcs1.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCt3uiwkIsY29Vl88fiV9FkZqF65VW8emfkBFJfEVq92LZq6vw4
o/3Ldda5AQB0WZZIGILQoRwy7raiKbXqmyfZ3sJu+9CwKy5Sfrh5RXiTgy0ZAfg0
Lw2T+Ml2l70KZKkcSiAyaRTM1YPcYXIsQoRyp88tSnYvHn9ghoaljUGl2QIDAQAB
AoGBAIiEKg1gIGbvTHmVVE8qhpUfZBC7enrXXTUSE57jYG0JeAkw4cKTOFWE+4gc
+j9gi/eljyjCJwLynWFsAJLpKfrCdzbzd748XXuFxfFOqd8w6lsO28Pbhqy4YvXj
OegGJG9+RyfZWhTP9JmU/eumntLFkELr5m80SqiiYIo2uY0BAkEA07eket2UAy2d
zv3jMD3wbcEgPx97p/kTcTq4ntWUA5XuCPC3Tb0Ge9/iZmu1etZcDtPptQKvd3+H
fLmmFQyEYQJBANI8xy1PnfvqW8lRbb9TCQm5BmvmHXCONHdNAC3UW2jJ9cUD9/o8
AiPNv8ZXmTgsSbBvAW9dlUe35joWaBAvlHkCQQC5nWpdsb+fXbHaFKrG07bjcosD
7GUsKenKvpG350XiMuNDAU+jnxJ9Lha+drXf4OlKsq1V3enaGXu+dMDP+W5hAkAn
i0UPkcUuiCNhl45kCVNO392EWBE7hZP6yKH6/NGAwVQYDaoMCFOCtoWW4g0w0qu9
ovOLJfgZOE72qBZEzR5JAkBmwuH48K6Q3KJxUvQDpw6Bgh2zGayoy12BdDQM0ZW+
AblMqqb3iwqP+LWoES3SqAKRmA6clh/9DUqtOn6610gk
-----END RSA PRIVATE KEY-----
  • privateKeyInPkcs1.pem
-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAK3e6LCQixjb1WXzx+JX0WRmoXrlVbx6Z+QEUl8RWr3Ytmrq/Dij/ct1
1rkBAHRZlkgYgtChHDLutqIpteqbJ9newm770LArLlJ+uHlFeJODLRkB+DQvDZP4
yXaXvQpkqRxKIDJpFMzVg9xhcixChHKnzy1Kdi8ef2CGhqWNQaXZAgMBAAE=
-----END RSA PUBLIC KEY-----

2、公私钥PKCS1和PKCS8格式互相转换

public class Test {/*** 密钥保存在用户目录下keys文件夹*/private static final String BASE_PATH = Paths.get(System.getProperty("user.home"), "keys").toString();private static final String PRIVATE_KEY_PKCS1 = Paths.get(BASE_PATH, "privateKeyInPkcs1.pem").toString();private static final String PUBLIC_KEY_PKCS1 = Paths.get(BASE_PATH, "publicKeyInPkcs1.pem").toString();public static void main(String[] args) throws Exception {String pubicKeyInPkcs1 = AsymmetricKeyUtils.readKeyFromPath(PUBLIC_KEY_PKCS1);System.out.println("读取到的PKCS1格式公钥为:\n" + pubicKeyInPkcs1);String publicKeyInPkcs8 = AsymmetricKeyUtils.transformPubKeyFromPkcs1ToPkcs8(pubicKeyInPkcs1);System.out.println("转换后的PKCS8格式公钥为:\n" + publicKeyInPkcs8);pubicKeyInPkcs1 = AsymmetricKeyUtils.transformPubKeyFromPkcs8ToPkcs1(publicKeyInPkcs8);System.out.println("转换后的PKCS1格式公钥为:\n" + pubicKeyInPkcs1);System.out.println();String privateKeyInPkcs1 = AsymmetricKeyUtils.readKeyFromPath(PRIVATE_KEY_PKCS1);System.out.println("读取到的PKCS1格式私钥为:\n" + privateKeyInPkcs1);String privateKeyInPkcs8 = AsymmetricKeyUtils.transformPrivateKeyFromPkcs1ToPkcs8(privateKeyInPkcs1);System.out.println("转换后的PKCS8格式私钥为:\n" + privateKeyInPkcs8);privateKeyInPkcs1 = AsymmetricKeyUtils.transformPrivateKeyFromPkcs8ToPkcs1(privateKeyInPkcs8);System.out.println("转换后的PKCS1格式私钥为:\n" + privateKeyInPkcs1);}
}

控制台输出如下:

读取到的PKCS1格式公钥为:
MIGJAoGBAK3e6LCQixjb1WXzx+JX0WRmoXrlVbx6Z+QEUl8RWr3Ytmrq/Dij/ct11rkBAHRZlkgYgtChHDLutqIpteqbJ9newm770LArLlJ+uHlFeJODLRkB+DQvDZP4yXaXvQpkqRxKIDJpFMzVg9xhcixChHKnzy1Kdi8ef2CGhqWNQaXZAgMBAAE=
转换后的PKCS8格式公钥为:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt3uiwkIsY29Vl88fiV9FkZqF65VW8emfkBFJfEVq92LZq6vw4o/3Ldda5AQB0WZZIGILQoRwy7raiKbXqmyfZ3sJu+9CwKy5Sfrh5RXiTgy0ZAfg0Lw2T+Ml2l70KZKkcSiAyaRTM1YPcYXIsQoRyp88tSnYvHn9ghoaljUGl2QIDAQAB
转换后的PKCS1格式公钥为:
MIGJAoGBAK3e6LCQixjb1WXzx+JX0WRmoXrlVbx6Z+QEUl8RWr3Ytmrq/Dij/ct11rkBAHRZlkgYgtChHDLutqIpteqbJ9newm770LArLlJ+uHlFeJODLRkB+DQvDZP4yXaXvQpkqRxKIDJpFMzVg9xhcixChHKnzy1Kdi8ef2CGhqWNQaXZAgMBAAE=读取到的PKCS1格式私钥为:
MIICXQIBAAKBgQCt3uiwkIsY29Vl88fiV9FkZqF65VW8emfkBFJfEVq92LZq6vw4o/3Ldda5AQB0WZZIGILQoRwy7raiKbXqmyfZ3sJu+9CwKy5Sfrh5RXiTgy0ZAfg0Lw2T+Ml2l70KZKkcSiAyaRTM1YPcYXIsQoRyp88tSnYvHn9ghoaljUGl2QIDAQABAoGBAIiEKg1gIGbvTHmVVE8qhpUfZBC7enrXXTUSE57jYG0JeAkw4cKTOFWE+4gc+j9gi/eljyjCJwLynWFsAJLpKfrCdzbzd748XXuFxfFOqd8w6lsO28Pbhqy4YvXjOegGJG9+RyfZWhTP9JmU/eumntLFkELr5m80SqiiYIo2uY0BAkEA07eket2UAy2dzv3jMD3wbcEgPx97p/kTcTq4ntWUA5XuCPC3Tb0Ge9/iZmu1etZcDtPptQKvd3+HfLmmFQyEYQJBANI8xy1PnfvqW8lRbb9TCQm5BmvmHXCONHdNAC3UW2jJ9cUD9/o8AiPNv8ZXmTgsSbBvAW9dlUe35joWaBAvlHkCQQC5nWpdsb+fXbHaFKrG07bjcosD7GUsKenKvpG350XiMuNDAU+jnxJ9Lha+drXf4OlKsq1V3enaGXu+dMDP+W5hAkAni0UPkcUuiCNhl45kCVNO392EWBE7hZP6yKH6/NGAwVQYDaoMCFOCtoWW4g0w0qu9ovOLJfgZOE72qBZEzR5JAkBmwuH48K6Q3KJxUvQDpw6Bgh2zGayoy12BdDQM0ZW+AblMqqb3iwqP+LWoES3SqAKRmA6clh/9DUqtOn6610gk
转换后的PKCS8格式私钥为:
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK3e6LCQixjb1WXzx+JX0WRmoXrlVbx6Z+QEUl8RWr3Ytmrq/Dij/ct11rkBAHRZlkgYgtChHDLutqIpteqbJ9newm770LArLlJ+uHlFeJODLRkB+DQvDZP4yXaXvQpkqRxKIDJpFMzVg9xhcixChHKnzy1Kdi8ef2CGhqWNQaXZAgMBAAECgYEAiIQqDWAgZu9MeZVUTyqGlR9kELt6etddNRITnuNgbQl4CTDhwpM4VYT7iBz6P2CL96WPKMInAvKdYWwAkukp+sJ3NvN3vjxde4XF8U6p3zDqWw7bw9uGrLhi9eM56AYkb35HJ9laFM/0mZT966ae0sWQQuvmbzRKqKJgija5jQECQQDTt6R63ZQDLZ3O/eMwPfBtwSA/H3un+RNxOrie1ZQDle4I8LdNvQZ73+Jma7V61lwO0+m1Aq93f4d8uaYVDIRhAkEA0jzHLU+d++pbyVFtv1MJCbkGa+YdcI40d00ALdRbaMn1xQP3+jwCI82/xleZOCxJsG8Bb12VR7fmOhZoEC+UeQJBALmdal2xv59dsdoUqsbTtuNyiwPsZSwp6cq+kbfnReIy40MBT6OfEn0uFr52td/g6UqyrVXd6doZe750wM/5bmECQCeLRQ+RxS6II2GXjmQJU07f3YRYETuFk/rIofr80YDBVBgNqgwIU4K2hZbiDTDSq72i84sl+Bk4TvaoFkTNHkkCQGbC4fjwrpDconFS9AOnDoGCHbMZrKjLXYF0NAzRlb4BuUyqpveLCo/4tagRLdKoApGYDpyWH/0NSq06frrXSCQ=
转换后的PKCS1格式私钥为:
MIICXQIBAAKBgQCt3uiwkIsY29Vl88fiV9FkZqF65VW8emfkBFJfEVq92LZq6vw4o/3Ldda5AQB0WZZIGILQoRwy7raiKbXqmyfZ3sJu+9CwKy5Sfrh5RXiTgy0ZAfg0Lw2T+Ml2l70KZKkcSiAyaRTM1YPcYXIsQoRyp88tSnYvHn9ghoaljUGl2QIDAQABAoGBAIiEKg1gIGbvTHmVVE8qhpUfZBC7enrXXTUSE57jYG0JeAkw4cKTOFWE+4gc+j9gi/eljyjCJwLynWFsAJLpKfrCdzbzd748XXuFxfFOqd8w6lsO28Pbhqy4YvXjOegGJG9+RyfZWhTP9JmU/eumntLFkELr5m80SqiiYIo2uY0BAkEA07eket2UAy2dzv3jMD3wbcEgPx97p/kTcTq4ntWUA5XuCPC3Tb0Ge9/iZmu1etZcDtPptQKvd3+HfLmmFQyEYQJBANI8xy1PnfvqW8lRbb9TCQm5BmvmHXCONHdNAC3UW2jJ9cUD9/o8AiPNv8ZXmTgsSbBvAW9dlUe35joWaBAvlHkCQQC5nWpdsb+fXbHaFKrG07bjcosD7GUsKenKvpG350XiMuNDAU+jnxJ9Lha+drXf4OlKsq1V3enaGXu+dMDP+W5hAkAni0UPkcUuiCNhl45kCVNO392EWBE7hZP6yKH6/NGAwVQYDaoMCFOCtoWW4g0w0qu9ovOLJfgZOE72qBZEzR5JAkBmwuH48K6Q3KJxUvQDpw6Bgh2zGayoy12BdDQM0ZW+AblMqqb3iwqP+LWoES3SqAKRmA6clh/9DUqtOn6610gk

备注:可以将转换后的公私钥在RSA加/解密平台测试一下,博主亲测是okay的。

在这里插入图片描述

相关文章:

非对称密钥PKCS#1和PKCS#8格式互相转换(Java)

目录一、序言二、代码示例1、Maven依赖2、工具类封装三、测试用例1、密钥文件2、公私钥PKCS1和PKCS8格式互相转换一、序言 之前在 《前后端RSA互相加解密、加签验签、密钥对生成》 中提到过PKCS#1格式和PKCS#8格式密钥的区别以及如何生成密钥。实际有些场景中有可能也会涉及到…...

java获取当前时间的方法:LocalDateTime、Date、Calendar,以及三者的比较

文章目录前言一、LocalDateTime1.1 获取当前时间LocalDate.now()1.2 获取当前时间的年、月、日、时分秒localDateTime.getYear()……1.3 给LocalDateTime赋值LocalDateTime.of()1.4 时间与字符串相互转换LocalDateTime.parse()1.5 时间运算——加上对应时间LocalDateTime.now()…...

npm link

正文npm link的用法假如我们想自己开发一个依赖包&#xff0c;以便在多个项目中使用。一种可行的方法&#xff0c;也是npm给我们提供的标准做法&#xff0c;那就是我们独立开发好这个 "依赖包"&#xff0c;然后将它直接发布到 npm镜像站 上去&#xff0c;等以后想在其…...

Docker 如何配置镜像加速

Docker 镜像加速 国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务&#xff0c;例如&#xff1a; 科大镜像&#xff1a;https://docker.mirrors.ustc.edu.cn/网易&#xff1a;https://hub-…...

阅读笔记7——Focal Loss

一、提出背景 当前一阶的物体检测算法&#xff0c;如SSD和YOLO等虽然实现了实时的速度&#xff0c;但精度始终无法与两阶的Faster RCNN相比。是什么阻碍了一阶算法的高精度呢&#xff1f;何凯明等人将其归咎于正、负样本的不平衡&#xff0c;并基于此提出了新的损失函数Focal L…...

ZCMU--5009: 龙虎斗

轩轩和开开正在玩一款叫《龙虎斗》的游戏&#xff0c;游戏的棋盘是一条线段&#xff0c;线段上有n个兵营(自左至右编号1~n)&#xff0c;相邻编号的兵营之间相隔1厘米&#xff0c;即棋盘为长度为n-1厘米的线段。i号兵营里有ci位工兵。 下面图1为n 6的示例: 轩轩在左侧&#xf…...

创建项目(React+umi+typeScript)

项目框架搭建的方式react脚手架Ant-design官网一、安装方式npm二、安装方式yarn三、安装方式umi devreact脚手架 命令行&#xff1a; npx create-react-app myReactName项目目录结构&#xff1a; 浏览器运行&#xff0c;端口号3000&#xff1a; Ant-design官网 一、安装方…...

FISCO BCOS(二十七)———java操作WeBase

一、搭建fiscobcos环境 1.1、安装jdk1.8 https://blog.csdn.net/weixin_46457946/article/details/1232435131.2、安装mysql https://blog.csdn.net/weixin_46457946/article/details/1232447361.3、安装python https://blog.csdn.net/weixin_46457946/article/details/123…...

失眠时还在吃它?有风险,你了解过吗

失眠&#xff0c;是当代人的通病。所以解决失眠也成了刚需&#xff0c;市面上开始出现各种助眠产品。有商业机构调查发现&#xff0c;62%的90后消费者曾买过助眠产品&#xff0c;其中人气选手就是褪黑素。褪黑素本身就是人体天然存在的&#xff0c;与睡眠有关的物质&#xff0c…...

星戈瑞收藏Sulfo-CY7 amine/NHS ester/maleimide小鼠活体成像染料标记反应

关于小鼠活体成像&#xff0c;就一定要提到CY活性染料标记反应&#xff1a; 用不同的活性基团的Cyanine菁染料和相应的活性基团的生物分子或小分子药物发生反应&#xff0c;链接到一起。 根据需要标记的抗原、抗体、酶、多肽等分子所带的可标记基团的种类&#xff08;氨基、醛…...

守护最后一道防线:Coremail邮件安全网关推出邮件召回功能

根据Coremail邮件安全大数据中心2022年Q4季报显示&#xff0c;2021年CAC识别钓鱼邮件1.81亿&#xff0c;2022年上升至2.25亿&#xff0c;增幅高达24.1%。 这表明2022年平均每天有61万7088封钓鱼邮件被接收及发出&#xff0c;企业用户面临潜在经济损失不可估量。 尤其是活跃至今…...

Python实战之小说下载神器(二)整本小说下载:看小说不用这个程序,我实在替你感到可惜*(小说爱好者必备)

前言 这次的是一个系列内容给大家讲解一下何一步一步实现一个完整的实战项目案例系列之小说下载神器&#xff08;二&#xff09;&#xff08;GUI界面化程序&#xff09; 单章小说下载保存数据——整本小说下载 你有看小说“中毒”的经历嘛&#xff1f;小编多多少少还是爱看小说…...

ChatGPT三个关键技术

情景学习&#xff08;In-context learning&#xff09; 对于一些LLM没有见过的新任务&#xff0c;只需要设计一些任务的语言描述&#xff0c;并给出几个任务实例&#xff0c;作为模型的输入&#xff0c;即可让模型从给定的情景中学习新任务并给出满意的回答结果。这种训练方式能…...

考试系统 (springboot+vue前后端分离)

系统图片 下载链接 地址&#xff1a; http://www.gxcode.top/code 介绍 一款多角色在线培训考试系统&#xff0c;系统集成了用户管理、角色管理、部门管理、题库管理、试题管理、试题导入导出、考试管理、在线考试、错题训练等功能&#xff0c;考试流程完善。 技术栈 Spr…...

ChatGPT告诉你:项目管理能干到60岁吗?

早上好&#xff0c;我是老原。这段时间最火的莫过于ChatGPT&#xff0c;从文章创作到论文写作&#xff0c;甚至编程序&#xff0c;简直厉害的不要不要的。本以为过几天热度就自然消退了&#xff0c;结果是愈演愈烈&#xff0c;热度未减……大家也从一开始得玩乐心态&#xff0c…...

Python自动化测试框架【Allure-pytest功能特性介绍】

Python自动化测试框架【Allure-pytest功能特性介绍】 目录&#xff1a;导读 前言 生成报告 测试代码 目录结构 Allure特性 Environment Categories Fixtures and Finalizers allure.attach 总结 写在最后 前言 Allure框架是一个灵活的轻量级多语言测试报告工具&am…...

ToB 产品拆解—Temu 商家管理后台

Temu 是拼多多旗下的跨境电商平台&#xff0c;平台产品于9月1日上线&#xff0c;9月1日到9月15日为测试期&#xff0c;之后全量全品类放开售卖。短短几个月的时间&#xff0c;Temu 在 App Store 冲上了购物类榜首&#xff0c;引起了国内的广泛关注。本文将以 B 端产品经理的角度…...

Android Studio的笔记--socket通信

Android socket通信Socket协议android socket 代码清单文件开启服务服务端&#xff1a;TCPServerService客户端&#xff1a;TCPClientServicelogSocket Socket 作为一种通用的技术规范&#xff0c;首次是由 Berkeley 大学在 1983 为 4.2BSD Unix 提供的&#xff0c;后来逐渐演化…...

@Async 注解

异步执行 异步调用就是不用等待结果的返回就执行后面的逻辑&#xff1b;同步调用则需要等待结果再执行后面的逻辑。 通常我们使用异步操作时都会创建一个线程执行一段逻辑&#xff0c;然后把这个线程丢到线程池中去执行&#xff0c;代码如下所示。 ExecutorService executor…...

Redis:缓存穿透、缓存雪崩和缓存击穿(未完待续)

Redis的缓存穿透、缓存雪崩和缓存击穿一. 缓存穿透1.1 概念1.2 造成的问题1.3 解决方案1.4 案例&#xff1a;查询商铺信息&#xff08;缓存穿透的实现&#xff09;二. 缓存雪崩2.1 概念2.2 解决方案三. 缓存击穿&#xff08;热点key&#xff09;3.1 概念3.2 解决方案3.3 案例&a…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...