基于Jakarta,TypeScript,Golong的国密SM2、3、4

文章目录

    • 前言
    • 一. Jakarta代码
    • 二. TypeScript
    • 三.golang


前言

最近还要深度研究hutools底层实现,一定要搞透澈,本章将会是持续更新 所有密钥由Jakarta统一生成,因为没测试其他语言生成是否可以
参考资料:
Java代码实现SM2算法以及注意点总结(踩坑记录)
国密算法工具Smutil

一. Jakarta代码

        <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.29</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.69</version></dependency>
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;import java.nio.charset.StandardCharsets;
import java.security.KeyPair;/*** @author YuanJie* @date 2024/8/6 上午8:44* 加密方式* 加密方式里边,有两种 一种是 C1C3C2另一种是C1C2C3,* 这两种加密方式不同,当时找的资料说是,旧版本的标准上,* 使用的是C1C2C3,但是后续应该是更新过,使用的是C1C3C2,* 其他语言,比如Python或者Golang或者C的实现大多直接就是C1C3C2的,* 但是如果java中使用的bouncycastle的包,默认使用的是C1C2C3,* 就会发生与其他语言的加密结果不能相互解密的情况,但是可能你跟其他人的Java系统加解密又没有问题。* <p>* 导出* Java生成的密钥,在导出的时候,最好使用 PrivateKey.getD().toByteArray() 和 PublicKey.getQ().getEncoded() 导出密钥,然后再转成Base64或者Hex给其他系统;* <p>* 导入* 导入的时候,请使用我上边的代码转换成对应的公钥或者私钥的对象,* 这里有另一个容易出错的地方,在私钥byte[]转私钥对象的时候,* 有些人会使用new BigInteger(byte[])这个方法将byte[]转为BigInteger,* 然后调用 keyFactory.generatePrivate(new ECPrivateKeySpec(BigInteger, ECParameterSpec)),* 但是实测这样在一些情况下会报错,这个时间长了记不清具体原因了,好像是因为第一位为负数的情况下会报错,* 我的方法是把byte[]转为Hex,然后再使用new BigInteger(hexStr, int)这种方式转为BigInteger,这个需要注意。* <p>* 公钥压缩* publicKey.getQ().getEncoded()这个方法,* 有一个boolean参数,控制输出的密钥是否为压缩后的密钥,* 输出内容转为Hex之后,02和03开头的为压缩后的密钥,04表示未经压缩的密钥。* Java里边压缩为压缩的调用同一个方法就能转为公钥对象,但是其他语言的目前不清楚,所以导出的时候,最好标注一下压缩或者未压缩。* <p>* Sm2签名时,有一个userId的概念,这个东西一般直接用CipherParameters对象是带不进去的,* 如果没有,默认是 Hex.decodeStrict(“31323334353637383132333435363738”) ,* 也就是1234567812345678的Ascii值,如果要使用自定义的userId,则需要使用ParametersWithID这个对象调用Signer的init,* 这个对象可以传入一个CipherParameters,然后再传入一个userId,可以把制定的userId带进去。* <p>* 签名验签RS* 我们平常接触的算法,一般我们调用加解密算法只返回一个值,* 但是Sm2算法,签名其实是有两个值,一个R,一个S,* 两个值构成一个签名结果,Java中bouncycastle的返回虽然也是一个值,* 但是大概看了一下算法的实现代码,其实得出的结果也是两个值,* 一个R,一个S,然后通过一个方法拼接成一个值(不确定这个方法的转换方式是不是有标准的)。* 在我们与C程序一块测试的时候,他们反馈了这个问题,* 然后我对着bouncycastle包内的org.bouncycastle.crypto.signers.SM2Signer类,* 摘出来了R、S和单一返回值的转换代码,已经提取到上边的代码里,可以直接使用。*/
@Configuration
@Slf4j
public class NationalSecretsUtils {public static String privateKey2;public static String publicKey2;public static String secretKey4;public NationalSecretsUtils(@Value("${sm2.privateKey}") String privateKey2,@Value("${sm2.publicKey}") String publicKey2,@Value("${sm4.secretKey}") String secretKey4) {NationalSecretsUtils.privateKey2 = privateKey2;NationalSecretsUtils.publicKey2 = publicKey2;NationalSecretsUtils.secretKey4 = secretKey4;}public static void main(String[] args) {KeyPair keyPair = SecureUtil.generateKeyPair("SM2");// 2. 获取公私钥//这里公钥不压缩  公钥的第一个字节用于表示是否压缩  可以不要 65字节变64字节byte[] publicKey = ((BCECPublicKey) keyPair.getPublic()).getQ().getEncoded(false);byte[] privateKey = ((BCECPrivateKey) keyPair.getPrivate()).getD().toByteArray();String sm2pub = HexUtil.encodeHexStr(publicKey);String sm2pri = HexUtil.encodeHexStr(privateKey);NationalSecretsUtils.publicKey2 = sm2pub;NationalSecretsUtils.privateKey2 = sm2pri;NationalSecretsUtils.secretKey4 = HexUtil.encodeHexStr(SecureUtil.generateKey("SM4").getEncoded());log.info("sm2公钥:{}", sm2pub);log.info("sm2私钥:{}", sm2pri);log.info("sm4密钥:{}", NationalSecretsUtils.secretKey4);// 测试sm2加解密log.info("sm2加密:{}", HexUtil.encodeHexStr(encryptSM2Sign("我是sm2数据")));log.info("sm2解密:{}", decryptSM2Sign(encryptSM2Sign("我是sm2解密数据")));// 测试sm2加签名验证log.info("sm2签名:{}", HexUtil.encodeHexStr(generateSM2Sign("我是sm2数据")));log.info("sm2验证:{}", verifySM2Sign("我是sm2数据", generateSM2Sign("我是sm2数据")));// 测试sm4加解密log.info("sm4加密:{}", HexUtil.encodeHexStr(generateSM4Sign("我是sm4数据")));log.info("sm4解密:{}", decryptSM4Sign(generateSM4Sign("我是sm4数据")));// 测试sm3哈希算法log.info("sm3哈希算法:{}", generateSM3Sign("我是sm3数据"));log.info("sm3验证:{}", verifySM3Sign("我是sm3数据", generateSM3Sign("我是sm3数据")));}/*** SM2 加密*/public static byte[] encryptSM2Sign(String text) {SM2 sm2 = new SM2(null, publicKey2);sm2.usePlainEncoding();return sm2.encrypt(text.getBytes(StandardCharsets.UTF_8));}/*** SM2 解密*/public static String decryptSM2Sign(byte[] text) {SM2 sm2 = new SM2(privateKey2, null);sm2.usePlainEncoding();return new String(sm2.decrypt(text), StandardCharsets.UTF_8);}/*** SM2签名 使用私钥D值签名* 默认C1C3C2**/public static byte[] generateSM2Sign(String text) {SM2 sm2 = new SM2(privateKey2, null, null);sm2.usePlainEncoding();return sm2.sign(text.getBytes(StandardCharsets.UTF_8), null);}/*** SM2验证 使用公钥Q值验证签名*/public static boolean verifySM2Sign(String text, byte[] sign) {SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKey2));sm2.usePlainEncoding();return sm2.verify(text.getBytes(StandardCharsets.UTF_8), sign);}/*** SM2*//*** SM3 哈希算法 3是能够计算出256比特的散列值的单向散列函数,主要用于数字签名和消息认证码。* base16*/public static String generateSM3Sign(String text) {return SmUtil.sm3(text);}/*** SM3验证**/public static boolean verifySM3Sign(String text, String sign) {return SmUtil.sm3(text).equals(sign);}/*** SM4 是一种对称加密算法,它使用128位密钥,使用分组密码模式,使用CBC模式加密。* SM4加密*/public static String generateSM4Sign(String text) {SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(secretKey4));return sm4.encryptHex(text);}/*** SM4解密*/public static String decryptSM4Sign(String text) {SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(secretKey4));return sm4.decryptStr(text, StandardCharsets.UTF_8);}
}

在这里插入图片描述

提取这里数据,供ts和go自检

二. TypeScript

npm install sm-crypto
/*** npm install sm-crypto* https://www.npmjs.com/package/sm-crypto*/
import {sm2, sm3, sm4} from 'sm-crypto';export class NationalSecretsUtils {static privateKey2: string;static publicKey2: string;static secretKey4: string;constructor(privateKey2: string, publicKey2: string, secretKey4: string) {NationalSecretsUtils.privateKey2 = privateKey2;NationalSecretsUtils.publicKey2 = publicKey2;NationalSecretsUtils.secretKey4 = secretKey4;}static main() {console.log('sm2公钥:', NationalSecretsUtils.publicKey2);console.log('sm2私钥:', NationalSecretsUtils.privateKey2);console.log('sm4密钥:', NationalSecretsUtils.secretKey4);const sm2Sign = NationalSecretsUtils.generateSM2Sign("我是sm2数据");console.log('sm2加密:', NationalSecretsUtils.generateSM2Encrypt("我是sm2数据"));console.log('sm2解密:', NationalSecretsUtils.generateSM2Decrypt(NationalSecretsUtils.generateSM2Encrypt("我是sm2数据")));console.log('sm2签名:', sm2Sign);console.log('sm2验证:', NationalSecretsUtils.verifySM2Sign("我是sm2数据", sm2Sign));const sm4Encrypt = NationalSecretsUtils.generateSM4Sign("我是sm4数据");console.log('sm4加密:', sm4Encrypt);console.log('sm4解密:', NationalSecretsUtils.decryptSM4Sign(sm4Encrypt));const sm3Hash = NationalSecretsUtils.generateSM3Sign("我是sm3数据");console.log('sm3哈希算法:', sm3Hash);console.log('sm3验证:', NationalSecretsUtils.verifySM3Sign("我是sm3数据", sm3Hash));}/*** 生成sm2加密*/static generateSM2Encrypt(text: string): string {return sm2.doEncrypt(text, NationalSecretsUtils.publicKey2);}/*** 生成sm2解密*/static generateSM2Decrypt(text: string): string {return sm2.doDecrypt(text, NationalSecretsUtils.privateKey2);}/*** 生成sm2签名* @param text*/static generateSM2Sign(text: string): string {return sm2.doSignature(text, NationalSecretsUtils.privateKey2);}/*** 验证sm2签名* @param text* @param sign*/static verifySM2Sign(text: string, sign: string): boolean {return sm2.doVerifySignature(text, sign, NationalSecretsUtils.publicKey2);}/*** 生成sm3哈希算法* @param text*/static generateSM3Sign(text: string): string {return sm3(text);}/*** 验证sm3哈希算法* @param text* @param sign*/static verifySM3Sign(text: string, sign: string): boolean {return sm3(text) === sign;}/*** 生成sm4加密* @param text*/static generateSM4Sign(text: string): string {const key = NationalSecretsUtils.secretKey4;return sm4.encrypt(text,key);}/*** 生成sm4解密* @param text*/static decryptSM4Sign(text: string): string {const key = NationalSecretsUtils.secretKey4;return sm4.decrypt(text,key);}
}// 示例调用
const nsu = new NationalSecretsUtils('00900b2ba339026a0ab4f5d7bfc03c640084c5e178ac88a3b9d7ab1184957897a1','040ff81a6e29ba81e7997740f5c1f010a98e9782ed3c659868e506acf4ab3ff8922737d8e8b10799ae1e2ffb3a7009e8a81f02a8ed7d95db2133cc82522b901bf3','60bfa3a9b5d6531b690c0ca2096f2e2e');
NationalSecretsUtils.main();

在这里插入图片描述

三.golang

package mainimport ("bytes""crypto/rand""encoding/hex""fmt""github.com/tjfoc/gmsm/sm2""github.com/tjfoc/gmsm/sm3""github.com/tjfoc/gmsm/sm4""log""math/big"
)/**
* go get  -u github.com/tjfoc/gmsm@v1.4.1*/
type NationalSecretsUtils struct {PrivateKey2 *sm2.PrivateKeyPublicKey2  *sm2.PublicKeySecretKey4  []byte
}func NewNationalSecretsUtils(privateKeyHex2, publicKeyHex2, secretKeyHex string) *NationalSecretsUtils {// Decode SM2 private keyprivateKeyBytes, err := hex.DecodeString(privateKeyHex2)if err != nil {log.Fatalf("Failed to decode SM2 private key: %v", err)}privateKey := new(sm2.PrivateKey)privateKey.D = new(big.Int).SetBytes(privateKeyBytes)// Initialize the rest of the private key fieldsprivateKey.Curve = sm2.P256Sm2()privateKey.PublicKey.Curve = privateKey.CurveprivateKey.PublicKey.X, privateKey.PublicKey.Y = privateKey.Curve.ScalarBaseMult(privateKey.D.Bytes())// Decode SM2 public keypublicKeyBytes, err := hex.DecodeString(publicKeyHex2)if err != nil {log.Fatalf("Failed to decode SM2 public key: %v", err)}publicKey := new(sm2.PublicKey)publicKey.Curve = sm2.P256Sm2()publicKey.X = new(big.Int).SetBytes(publicKeyBytes[1:33])publicKey.Y = new(big.Int).SetBytes(publicKeyBytes[33:65])// Decode SM4 secret keysecretKey, err := hex.DecodeString(secretKeyHex)if err != nil {log.Fatalf("Failed to decode SM4 secret key: %v", err)}if len(secretKey) != 16 {log.Fatalf("Invalid SM4 secret key length: expected 16 bytes, got %d bytes", len(secretKey))}return &NationalSecretsUtils{PrivateKey2: privateKey,PublicKey2:  publicKey,SecretKey4:  secretKey,}
}/**
* SM2加密*/
func (nsu *NationalSecretsUtils) EncryptSM2(text string) string {// 0 -> C1C3C2  1->C1C2C3cipher, err := sm2.Encrypt(nsu.PublicKey2, []byte(text), nil, 0)if err != nil {log.Fatalf("Failed to encrypt text: %v", err)}return hex.EncodeToString(cipher)
}/**
* SM2解密*/
func (nsu *NationalSecretsUtils) DecryptSM2(ciphertextHex string) string {ciphertext, err := hex.DecodeString(ciphertextHex)if err != nil {log.Fatalf("Failed to decode ciphertext: %v", err)}plaintext, err := sm2.Decrypt(nsu.PrivateKey2, ciphertext, 0)if err != nil {log.Fatalf("Failed to decrypt text: %v", err)}return string(plaintext)
}/**
* 生成SM2签名*/
func (nsu *NationalSecretsUtils) GenerateSM2Sign(text string) []byte {signature, err := nsu.PrivateKey2.Sign(rand.Reader, []byte(text), nil)if err != nil {log.Fatalf("Failed to generate SM2 signature: %v", err)}return signature
}/**
* 验证SM2签名*/
func (nsu *NationalSecretsUtils) VerifySM2Sign(text string, signature []byte) bool {ok := nsu.PublicKey2.Verify([]byte(text), signature)return ok
}/**
* 生成SM3签名*/
func (nsu *NationalSecretsUtils) GenerateSM3Sign(text string) string {hash := sm3.New()hash.Write([]byte(text))return hex.EncodeToString(hash.Sum(nil))
}/**
* 验证SM3签名*/
func (nsu *NationalSecretsUtils) VerifySM3Sign(text string, sign string) bool {return nsu.GenerateSM3Sign(text) == sign
}/**
* 生成SM4签名*/
func (nsu *NationalSecretsUtils) GenerateSM4Sign(text string) string {cipher, err := sm4.NewCipher(nsu.SecretKey4)if err != nil {log.Fatalf("Failed to create SM4 cipher: %v", err)}plaintext := []byte(text)padding := sm4.BlockSize - len(plaintext)%sm4.BlockSizepadText := bytes.Repeat([]byte{byte(padding)}, padding)plaintext = append(plaintext, padText...)ciphertext := make([]byte, len(plaintext))cipher.Encrypt(ciphertext, plaintext)return hex.EncodeToString(ciphertext)
}/**
* 解密SM4签名*/
func (nsu *NationalSecretsUtils) DecryptSM4Sign(ciphertextHex string) string {cipher, err := sm4.NewCipher(nsu.SecretKey4)if err != nil {log.Fatalf("Failed to create SM4 cipher: %v", err)}ciphertext, err := hex.DecodeString(ciphertextHex)if err != nil {log.Fatalf("Failed to decode hex string: %v", err)}plaintext := make([]byte, len(ciphertext))cipher.Decrypt(plaintext, ciphertext)padding := int(plaintext[len(plaintext)-1])return string(plaintext[:len(plaintext)-padding])
}func main() {// 自定义的密钥,可以替换成实际使用的密钥privateKeyHex2 := "00900b2ba339026a0ab4f5d7bfc03c640084c5e178ac88a3b9d7ab1184957897a1"publicKeyHex2 := "040ff81a6e29ba81e7997740f5c1f010a98e9782ed3c659868e506acf4ab3ff8922737d8e8b10799ae1e2ffb3a7009e8a81f02a8ed7d95db2133cc82522b901bf3"secretKeyHex := "60bfa3a9b5d6531b690c0ca2096f2e2e"nsu := NewNationalSecretsUtils(privateKeyHex2, publicKeyHex2, secretKeyHex)fmt.Printf("sm2公钥: %s\n", hex.EncodeToString(nsu.PublicKey2.X.Bytes())+hex.EncodeToString(nsu.PublicKey2.Y.Bytes()))fmt.Printf("sm2私钥: %s\n", hex.EncodeToString(nsu.PrivateKey2.D.Bytes()))fmt.Printf("sm4密钥: %s\n", hex.EncodeToString(nsu.SecretKey4))// 测试SM2加密和解密fmt.Printf("sm2加密: %s\n", nsu.EncryptSM2("我是sm2数据"))fmt.Printf("sm2解密: %s\n", nsu.DecryptSM2(nsu.EncryptSM2("我是sm2数据")))// 测试SM2签名和验证sm2Sign := nsu.GenerateSM2Sign("我是sm2数据")fmt.Printf("sm2签名: %s\n", hex.EncodeToString(sm2Sign))fmt.Printf("sm2验证: %v\n", nsu.VerifySM2Sign("我是sm2数据", sm2Sign))// 测试SM4加解密sm4Encrypt := nsu.GenerateSM4Sign("我是sm4数据")fmt.Printf("sm4加密: %s\n", sm4Encrypt)fmt.Printf("sm4解密: %s\n", nsu.DecryptSM4Sign(sm4Encrypt))// 测试SM3哈希算法sm3Hash := nsu.GenerateSM3Sign("我是sm3数据")fmt.Printf("sm3哈希算法: %s\n", sm3Hash)fmt.Printf("sm3验证: %v\n", nsu.VerifySM3Sign("我是sm3数据", sm3Hash))
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/396661.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

整理 钢琴 基础知识

大普表和钢琴键盘对照表 一 大普表和钢琴键盘对照表 二 五线谱、键位、左右手 八分音符 坐姿 手型

机器学习——支持向量机(SVM)(1)

目录 一、认识SVM 1. 基本介绍 2. 支持向量机分类器目标 二、线性SVM分类原理&#xff08;求解损失&#xff09; 三、重要参数 1. kernel&#xff08;核函数&#xff09; 2 .C&#xff08;硬间隔与软间隔&#xff09; 四、sklearn中的支持向量机&#xff08;自查&#…

使用Adobe Photoshop CS5给图片加水印

使用Adobe Photoshop CS5给图片加水印 前言1.我这里使用的是Adobe Photoshop CS52.新建空白画布3.写入水印内容4.按 Ctrl T 将其倾斜5.右键图层选择“混合选项”6.选择描边&#xff0c;颜色选择灰色7.效果如下8.填充选择0&#xff0c;不透明度选择75%9.打开编辑&#xff0c;选…

transformer中编码器之间是串行还是并行的;算力共享中,transformer实现编码器并行运行,怎么进行聚合的

目录 transformer中编码器之间是串行还是并行的 1. 编码器结构的独立性 2. 编码器内部的并行处理 3. 编码器之间的数据流 4. 训练阶段的并行性 算力共享中,transformer实现编码器并行运行,怎么进行聚合的 编码器并行运行的实现 编码器的输出聚合 举例说明 transform…

对 Go 语言中循环屏障 CyclicBarrier 的理解

同步屏障 (Barrier) 是并发编程中的一种同步方法。对于一组 goroutine ,程序中的一个同步屏障意味着任何 goroutine 执行到此后都必须等待,直到所有的 goroutine 都达到此点才可继续执行下文。 Barrier 无论是翻译成屏障、障碍还是栅栏,都很形象,就是一道拦截坝,拦截一组对…

国内大量家用路由器惨遭DNS劫持,你中招了吗?

近期&#xff0c;D妹收到不少用户反馈&#xff0c;在访问网站或APP时都遭遇了访问失败的问题。经深入排查&#xff0c;我们监测到大量家用路由器的DNS解析配置被篡改&#xff0c;从而影响到了正常的网站和APP访问。 该情况于2024年5月开始出现&#xff0c;于8月5日集中爆发达到…

图像变换算法

1.1 傅里叶变换 (Fourier Transform) 介绍 傅里叶变换是一种数学变换&#xff0c;用于将图像从空间域转换到频率域。它广泛应用于图像去噪和滤波。 原理 傅里叶变换将图像表示为频率成分的叠加&#xff0c;使得频率成分可以独立处理。通过对频率成分的分析和处理&#xff0…

【登录扫码】--集成企业微信

背景&#xff1a; 在系统的登录流程中&#xff0c;我们引入了一种创新的扫码登录方式&#xff0c;旨在提升用户体验与安全性。此流程的核心在于通过生成并扫描二维码来实现快速、便捷的登录认证 调用流程详细说明&#xff1a; 扫码登录选择&#xff1a;用户首先访问系统登录页面…

STM32的SDIO接口详解

目录 1. 定义与兼容性 2. SDIO时钟 3. SDIO命令与响应 4. SDIO块数据传输 5. SDIO控制器的硬件结构 6.代码实现 1.SD初始化 2.测试SD卡的读取 3.测试SD卡的写入 STM32的SDIO&#xff08;Secure Digital Input/Output&#xff0c;安全数字输入输出&#xff09;接口是一…

010集——按值传递、按引用传递等方法——C#学习笔记

按值传递参数 这是参数传递的默认方式。在这种方式下&#xff0c;当调用一个方法时&#xff0c;会为每个值参数创建一个新的存储位置。 实际参数的值会复制给形参&#xff0c;实参和形参使用的是两个不同内存中的值。所以&#xff0c;当形参的值发生改变时&#xff0c;不会影…

Flask+LayUI开发手记(一):LayUI表格的前端数据分页展现

用数据表格table展示系统数据&#xff0c;是LayUI的基本功能&#xff0c;编码十分简单&#xff0c;就是通过table.render()渲染&#xff0c;把属性配置好就OK了&#xff0c;十分方便&#xff0c;功能也十分强大。 不过&#xff0c;在实现时&#xff0c;把table的有个功能却理解…

ue4.27 C++ 解析内容为json的字符串

json字符串为 R"({"x": -1870.0, "y": -11400.0})"&#xff0c;里面内容是个json对象。 const FString& Message R"({"x": -1870.0, "y": -11400.0})"; TSharedRef<TJsonReader<>> Reader TJs…

Java Nacos与Gateway的使用

Java系列文章目录 IDEA使用指南 Java泛型总结&#xff08;快速上手详解&#xff09; Java Lambda表达式总结&#xff08;快速上手详解&#xff09; Java Optional容器总结&#xff08;快速上手图解&#xff09; Java 自定义注解笔记总结&#xff08;油管&#xff09; Jav…

Python:jupyter 模型可视化(VS)

step1:打开vs安装扩展 安装后重新启动vs 建立可视化模型 import pandas as pd from sklearn.tree import DecisionTreeClassifier from sklearn import treemusic_data pd.read_csv(music.csv)Xmusic_data.drop(columns[genre]) Ymusic_data[genre]modelDecisionTreeClassifie…

IDEA构建SpringBoot多模块项目

前言 最近一直在思考一个问题&#xff0c;springboot的多模块项目到底是怎么运行和运作的&#xff1f; 一般我们大部分的springboot项目都是单模块的项目&#xff0c;但是如果后续有要求开发多模块的项目应该怎么处理&#xff1f;于是基于这点进行了研究。 本次文章将会带大…

java语言特点

Java语言是一种广泛使用的编程语言&#xff0c;它具有以下几个显著的特点&#xff1a; 面向对象&#xff1a;Java是一种纯面向对象的语言&#xff0c;它支持类的封装、继承和多态等特性。面向对象的设计使得Java程序更加模块化&#xff0c;易于维护和扩展。 平台无关性&#xf…

Linux驱动开发基础(Hello驱动)

所学内容来自百问网 目录 1. 文件在内核中的表示 2. 打开字符设备节点时&#xff0c;内核中也有对应的struct file 3. 编写驱动程序步骤 4. 相关知识点 4.1 涉及函数解析 4.2 module_init/module_exit的实现 4.3 register_chrdev的内部实现 4.4 class_destroy/device_…

K8s知识内容总结

1. K8s是个什么东西&#xff1f;解决了什么核心问题&#xff1f;相比docker有什么核心优势&#xff1f; k8s源于google内部的一个集群管理系统&#xff0c;它是用来管理集群的。比例&#xff0c;一个大型的电商系统&#xff0c;在微服务架构模式下&#xff0c;一个集群中可能有…

冒泡,选择,插入,希尔,快速,归并

冒泡&#xff0c;选择&#xff0c;插入&#xff0c;希尔&#xff0c;快速&#xff0c;归并 选择类的排序&#xff1a;选择排序&#xff0c;堆排序 交换类的排序&#xff1a;冒泡&#xff0c;快排 #include <stdio.h> #include<stdbool.h> #include<stdlib.h&…

10个html+css+js 绚丽按钮合集(1)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享10个htmlcssjs 绚丽按钮合集(1) 创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文章目录 10个htmlcssjs 绚丽按钮第1个&#xff1a;效果&#xff…