JAVA使用SM2算法生成密钥对加密解密加签验签
简介
SM2是非对称加密算法,一提非对称加密算法,第一想到的是RSA,没错,这个就是替代RSA的。它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号发布。SM2采用的是ECC 256位的一种,其安全强度比RSA 2048位高,且运算速度快于RSA。随着密码技术和计算技术的发展,目前常用的1024位RSA算法面临严重的安全威胁,我们国家密码管理部门经过研究,决定采用SM2椭圆曲线算法替换RSA算法。SM2算法在安全性、性能上都具有优势。
用途
可以用于前后端传输数据加密解密。可以用于对数据加签验签,确保报文的安全性和完整性。比如,生成一套前端公私钥密钥对,生成一套后端服务器公私钥密钥对。前端把参数json字符串通过服务器公钥用sm2算法加密,服务器后端接收到请求后用服务器私钥解密,拿到原始参数,处理数据并生成响应数据,把响应数据用前端公钥加密,前端接收到响应加密后数据,用前端私钥解密,拿到响应json。这个过程是快速且安全的。(一般这个过程在网关上公共实现)
代码实现
引入依赖(maven引入bcprov-jdk15on jar包,截止发文,最新版本是1.70)
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.70</version>
</dependency>
新建StandardSM2Engine实体类
package com.zhaohy.app.utils;import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine.Mode;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.math.ec.ECFieldElement;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.Memoable;
import org.bouncycastle.util.Pack;/*** 自定义SM2Engine类,对加密解密数据进行了ASN.1编码*/
public class StandardSM2Engine {private final Digest digest;private final Mode mode;private boolean forEncryption;private ECKeyParameters ecKey;private ECDomainParameters ecParams;private int curveLength;private SecureRandom random;public StandardSM2Engine() {this(new SM3Digest());}public StandardSM2Engine(Mode mode) {this(new SM3Digest(), mode);}public StandardSM2Engine(Digest digest) {this(digest, Mode.C1C2C3);}public StandardSM2Engine(Digest digest, Mode mode) {if (mode == null) {throw new IllegalArgumentException("mode cannot be NULL");}this.digest = digest;this.mode = mode;}public void init(boolean forEncryption, CipherParameters param) {this.forEncryption = forEncryption;if (forEncryption) {ParametersWithRandom rParam = (ParametersWithRandom) param;ecKey = (ECKeyParameters) rParam.getParameters();ecParams = ecKey.getParameters();ECPoint s = ((ECPublicKeyParameters) ecKey).getQ().multiply(ecParams.getH());if (s.isInfinity()) {throw new IllegalArgumentException("invalid key: [h]Q at infinity");}random = rParam.getRandom();} else {ecKey = (ECKeyParameters) param;ecParams = ecKey.getParameters();}curveLength = (ecParams.getCurve().getFieldSize() + 7) / 8;}public byte[] processBlock(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {if (forEncryption) {return encrypt(in, inOff, inLen);} else {return decrypt(in, inOff, inLen);}}public int getOutputSize(int inputLen) {return (1 + 2 * curveLength) + inputLen + digest.getDigestSize();}protected ECMultiplier createBasePointMultiplier() {return new FixedPointCombMultiplier();}/*** 加密* * @param in* @param inOff* @param inLen* @return* @throws InvalidCipherTextException*/private byte[] encrypt(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {byte[] c2 = new byte[inLen];System.arraycopy(in, inOff, c2, 0, c2.length);ECMultiplier multiplier = createBasePointMultiplier();ECPoint c1P;ECPoint kPB;do {BigInteger k = nextK();c1P = multiplier.multiply(ecParams.getG(), k).normalize();kPB = ((ECPublicKeyParameters) ecKey).getQ().multiply(k).normalize();kdf(digest, kPB, c2);} while (notEncrypted(c2, in, inOff));byte[] c3 = new byte[digest.getDigestSize()];addFieldElement(digest, kPB.getAffineXCoord());digest.update(in, inOff, inLen);addFieldElement(digest, kPB.getAffineYCoord());digest.doFinal(c3, 0);return convertToASN1(c1P, c2, c3);}/*** 解密* * @param in* @param inOff* @param inLen* @return* @throws InvalidCipherTextException*/private byte[] decrypt(byte[] in, int inOff, int inLen) throws InvalidCipherTextException {byte[] decryptData = new byte[inLen];System.arraycopy(in, inOff, decryptData, 0, decryptData.length);BigInteger x;BigInteger y;byte[] originC3;byte[] c2;ECPoint c1P;byte[] c1;try (ASN1InputStream aIn = new ASN1InputStream(decryptData)) {ASN1Sequence seq;try {seq = (ASN1Sequence) aIn.readObject();} catch (IOException e) {throw new InvalidCipherTextException();}x = ASN1Integer.getInstance(seq.getObjectAt(0)).getValue();y = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue();c1P = ecParams.getCurve().validatePoint(x, y);c1 = c1P.getEncoded(false);if (mode == Mode.C1C3C2) {originC3 = ASN1OctetString.getInstance(seq.getObjectAt(2)).getOctets();c2 = ASN1OctetString.getInstance(seq.getObjectAt(3)).getOctets();} else {c2 = ASN1OctetString.getInstance(seq.getObjectAt(2)).getOctets();originC3 = ASN1OctetString.getInstance(seq.getObjectAt(3)).getOctets();}} catch (IOException e) {throw new InvalidCipherTextException();}ECPoint s = c1P.multiply(ecParams.getH());if (s.isInfinity()) {throw new InvalidCipherTextException("[h]C1 at infinity");}c1P = c1P.multiply(((ECPrivateKeyParameters) ecKey).getD()).normalize();kdf(digest, c1P, c2);byte[] c3 = new byte[digest.getDigestSize()];addFieldElement(digest, c1P.getAffineXCoord());digest.update(c2, 0, c2.length);addFieldElement(digest, c1P.getAffineYCoord());digest.doFinal(c3, 0);int check = 0;for (int i = 0; i != c3.length; i++) {check |= c3[i] ^ originC3[i];}Arrays.fill(c1, (byte) 0);Arrays.fill(c3, (byte) 0);if (check != 0) {Arrays.fill(c2, (byte) 0);throw new InvalidCipherTextException("invalid cipher text");}return c2;}private boolean notEncrypted(byte[] encData, byte[] in, int inOff) {for (int i = 0; i != encData.length; i++) {if (encData[i] != in[inOff + i]) {return false;}}return true;}private void kdf(Digest digest, ECPoint c1, byte[] encData) {int digestSize = digest.getDigestSize();byte[] buf = new byte[Math.max(4, digestSize)];int off = 0;Memoable memo = null;Memoable copy = null;if (digest instanceof Memoable) {addFieldElement(digest, c1.getAffineXCoord());addFieldElement(digest, c1.getAffineYCoord());memo = (Memoable) digest;copy = memo.copy();}int ct = 0;while (off < encData.length) {if (memo != null) {memo.reset(copy);} else {addFieldElement(digest, c1.getAffineXCoord());addFieldElement(digest, c1.getAffineYCoord());}Pack.intToBigEndian(++ct, buf, 0);digest.update(buf, 0, 4);digest.doFinal(buf, 0);int xorLen = Math.min(digestSize, encData.length - off);xor(encData, buf, off, xorLen);off += xorLen;}}private void xor(byte[] data, byte[] kdfOut, int dOff, int dRemaining) {for (int i = 0; i != dRemaining; i++) {data[dOff + i] ^= kdfOut[i];}}private BigInteger nextK() {int qBitLength = ecParams.getN().bitLength();BigInteger k;do {k = BigIntegers.createRandomBigInteger(qBitLength, random);} while (k.equals(BigIntegers.ZERO) || k.compareTo(ecParams.getN()) >= 0);return k;}private void addFieldElement(Digest digest, ECFieldElement v) {byte[] p = BigIntegers.asUnsignedByteArray(curveLength, v.toBigInteger());digest.update(p, 0, p.length);}private byte[] convertToASN1(ECPoint c1P, byte[] c2, byte[] c3) {ASN1Integer x = new ASN1Integer(c1P.getXCoord().toBigInteger());ASN1Integer y = new ASN1Integer(c1P.getYCoord().toBigInteger());DEROctetString derDig = new DEROctetString(c3);DEROctetString derEnc = new DEROctetString(c2);ASN1EncodableVector v = new ASN1EncodableVector();switch (mode) {case C1C3C2:v.add(x);v.add(y);v.add(derDig);v.add(derEnc);break;default:v.add(x);v.add(y);v.add(derEnc);v.add(derDig);}DERSequence seq = new DERSequence(v);try {return seq.getEncoded();} catch (IOException e) {throw new RuntimeException(e);}}}
新建Sm2Utils工具类
package com.zhaohy.app.utils;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.Signature;
import java.security.SignatureException;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;/*** SM2工具类*/
public class Sm2Utils {/*** 加签* @param plainText* @return*/public static String sign(String plainText, String privateKeyStr) {BouncyCastleProvider provider = new BouncyCastleProvider();try { // 获取椭圆曲线KEY生成器KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);byte[] privateKeyData = Base64.getDecoder().decode(privateKeyStr);PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyData);Signature rsaSignature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), provider);rsaSignature.initSign(keyFactory.generatePrivate(privateKeySpec));rsaSignature.update(plainText.getBytes());byte[] signed = rsaSignature.sign();return Base64.getEncoder().encodeToString(signed);} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException e) {throw new RuntimeException(e);}}/*** 验签* @param plainText* @param signatureValue* @return*/public static boolean verify(String plainText, String signatureValue, String publicKeyStr) {BouncyCastleProvider provider = new BouncyCastleProvider();try {// 获取椭圆曲线KEY生成器KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);byte[] publicKeyData = Base64.getDecoder().decode(publicKeyStr);X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyData);// 初始化为验签状态Signature signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(), provider);signature.initVerify(keyFactory.generatePublic(publicKeySpec));signature.update(Hex.decodeHex(plainText.toCharArray()));return signature.verify(Hex.decodeHex(signatureValue.toCharArray()));} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException e) {throw new RuntimeException(e);} catch (IllegalArgumentException e) {LogUtils.error("验签失败", e);return false;} catch (DecoderException e) {LogUtils.error("验签失败", e);return false;}}/*** 加密* @param plainText* @return*/public static byte[] encrypt(String plainText, String publicKeyStr) throws Exception {Security.addProvider(new BouncyCastleProvider());try { // 获取椭圆曲线KEY生成器KeyFactory keyFactory = KeyFactory.getInstance("EC");byte[] publicKeyData = Base64.getDecoder().decode(publicKeyStr);X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyData);PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);CipherParameters publicKeyParamerters = ECUtil.generatePublicKeyParameter(publicKey);//数据加密StandardSM2Engine engine = new StandardSM2Engine(new SM3Digest(), SM2Engine.Mode.C1C3C2);engine.init(true, new ParametersWithRandom(publicKeyParamerters));byte[] encryptData = engine.processBlock(plainText.getBytes(), 0, plainText.getBytes().length);return encryptData;} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | InvalidCipherTextException e) {throw new RuntimeException(e);}}/*** 解密* @param encryptedText* @return*/public static String decrypt(byte[] encryptedData, String privateKeyStr) {Security.addProvider(new BouncyCastleProvider());try { // 获取椭圆曲线KEY生成器KeyFactory keyFactory = KeyFactory.getInstance("EC");byte[] privateKeyData = Base64.getDecoder().decode(privateKeyStr);PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyData);PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);CipherParameters privateKeyParamerters = ECUtil.generatePrivateKeyParameter(privateKey);//数据解密StandardSM2Engine engine = new StandardSM2Engine(new SM3Digest(), SM2Engine.Mode.C1C3C2);engine.init(false, privateKeyParamerters);byte[] plainText = engine.processBlock(encryptedData, 0, encryptedData.length);return new String(plainText);} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | InvalidCipherTextException e) {throw new RuntimeException(e);}}/*** SM2算法生成密钥对* @return 密钥对信息*/public static KeyPair generateSm2KeyPair() {try {final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");// 获取一个椭圆曲线类型的密钥对生成器final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());SecureRandom random = new SecureRandom();// 使用SM2的算法区域初始化密钥生成器kpg.initialize(sm2Spec, random);// 获取密钥对KeyPair keyPair = kpg.generateKeyPair();return keyPair;} catch (Exception e) {LogUtils.error("generate sm2 key pair failed:{}", e.getMessage(), e);return null;}}public static void main(String[] args) throws Exception {KeyPair keyPair = generateSm2KeyPair();String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());String data = "{\"daId\":\"123456\"}";String encryptedJsonStr = Hex.encodeHexString(encrypt(data, publicKey)) + "";//16进制字符串String decryptedJsonStr = decrypt(Hex.decodeHex(encryptedJsonStr), privateKey);String sign = Hex.encodeHexString(Base64.getDecoder().decode(sign(data, privateKey)));boolean flag = verify(Hex.encodeHexString(data.getBytes()), sign, publicKey);System.out.println("base64后privateKey:" + privateKey);System.out.println("base64后publicKey:" + publicKey);System.out.println("加密前数据:" + data);System.out.println("公钥加密后16进制字符串:" + encryptedJsonStr);System.out.println("私钥解密后数据:" + decryptedJsonStr);System.out.println("私钥加签后数据(16进制):" + sign);System.out.println("公钥验签结果:" + flag);}}
工具类里已经写好了调用测试main方法,运行结果如下:
base64后privateKey:MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgmze2hmNoi3XpeMPmLNIQBOC7+P1iMbwGMMAdQXko0VWgCgYIKoEcz1UBgi2hRANCAATyF9jHsCvFaLkR4DS+viX9CShZEXc7Nc1OueDaIpzZx/DRTRejSpTOcFmb0B9TsyYutnRWAx46nfkQ289NVXjg base64后publicKey:MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE8hfYx7ArxWi5EeA0vr4l/QkoWRF3OzXNTrng2iKc2cfw0U0Xo0qUznBZm9AfU7MmLrZ0VgMeOp35ENvPTVV44A== 加密前数据:{"daId":"123456"} 公钥加密后16进制字符串:307b022100f1ab8b4fc8755d2ab84bf530f15ab14f5250d060d52679fd38e822a85eeceb860221009eef85a579ef9e2f27f44461a89046b95f8c630773be7ced1f3f3f48057f4777042064d9b5fb396591e022791858e334fc40b1ee9c93412442d403385266a00dd78704117b30ed38afcb361f8176acbbfbabad71e9 私钥解密后数据:{"daId":"123456"} 私钥加签后数据(16进制):304402201505caa731d9b70987a6c19f40618593e9acd8cad880dc001e52ef4b48638e2302204bdb5c5dc881789e716de7360aa387e5e4caa9f9f2fd6d1fbce35f1227b34440 公钥验签结果:true
可以看到加密解密加签验签都是成功的。上面加密后生成的是byte[],转换成16进制字符串处理的,也可以用base64实现byte[]和字符串的转换处理,但是要保证对应加解密都是用base64实现byte[]和字符串的转换,对应的上就行。
相关文章:
JAVA使用SM2算法生成密钥对加密解密加签验签
简介 SM2是非对称加密算法,一提非对称加密算法,第一想到的是RSA,没错,这个就是替代RSA的。它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替…...
uniapp(vue)打包web项目页面刷新后报404解决方案
一、问题概述 uniapp是一款优秀的跨平台开发框架,它可以帮助开发者快速构建出适用于多端的应用程序。然而,在项目打包后,有可能发现页面在刷新时会出现404错误。这无疑给用户体验带来了极大的困扰,下面我们就来分析一下这个问题。…...
ansible学习之ansible-vault
相关文档参考:http://www.ansible.com.cn/docs/playbooks_vault.html#what-can-be-encrypted-with-vault ansible-vault 功能介绍 Ansible-Vault是一个用于加密和管理Ansible playbook中敏感数据的工具。通过创建、编辑、加密、解密、查看和重置密码,可以安全地存储…...

封装el-upload组件,用于上传图片和视频的组件
使用环境 vue3element plus 需要根据后端返回结构修改的函数:onPreview onRemove onSuccess 组件使用 基本使用 源代码: <script setup> import AutoUploadFile from /components/auto-upload-file/index.vue function change(urls){console.log…...
6.将扩散模型与其他生成模型的关联(2)
1.归一化流与扩散模型 自一化流(Normalizing Flow)是生成模型,通过将易于处理的分布进行变换以队对高维数据进行建模。归一化流可以将简单的概率分布转化为极其复杂的分布,并用于强化学习、变分推理等领域。 现有的归一化流是基于变量替换公式构…...

【C++】基于红黑树封装set和map
🚀个人主页:小羊 🚀所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言一、更高维度的泛型二、模版参数三、比较逻辑的重写四、迭代器4.1 const迭代器4.2 重载4.3 - -重载 五、完整代…...

24最新新手入门指南:Stable Diffusion!
前言 Stable Diffusion,一款新兴的开源AI绘画软件,正逐渐成为数字艺术家和爱好者的新宠。它的强大功能让用户能够轻松创造出令人印象深刻的数字艺术作品。 无论你是专业艺术家还是艺术新手,Stable Diffusion都为你提供了一个探索创造力的新…...

Java-基础
1. 导入模块不能纯粹的复制粘贴,要从new里导入,因为前者建立不了关联 2. 数组 String[] name{"张三","李四","王五"};int[] numsnew int[]{1,2,3};//二维String[][] names{{"张三","李四"},{"…...

二、后台管理系统布局菜单可拖动
前两天产品提出了一个需求,说后台管理系统的左边菜单的名称字数过多,遮挡了。希望能让客户能够看到全部的名称,给左侧菜单增加一个可拖动的功能,经过我的研究,这个功能最终也做出来了,先看效果,双击查看。 下面咱们进入实现步骤 第一步,找到文件。一般的项目中都存在l…...
socket和http区别
socket和http区别:1、主体不同;2、所处层次不同;3、连接状态不同;4、传输数据量不同;5、数据安全性不同;6、连接方式不同。其中,主体不同指的是socke是一个调用接口(API)…...

算法:974.和可以被K整除的子数组
题目 链接:leetcode链接 思路分析(前缀和 同余定理) 首先,我们要了解一下什么是同余定理 同余定理: 如果(a - b)/ p k …… 0 则 a % p b % p 证明我写在草稿纸上,如下图: 初…...

QD1-P8 HTML 格式化标签(font、pre、b、strong、i、u、del、s、sub、sup)
本节学习:HTML 格式化标签。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p8 一、font 标签 用途:定义文本的字体大小、颜色和 face(字体类型)。 示例 <!DOCTYPE html> <html><head><meta cha…...

红米Turbo 3工程固件预览 修复底层 体验原生态系统 默认开启diag端口
红米Turbo 3机型代码:peridot 国外版本:POCO F6 用于以下型号的小米机型:24069RA21C, 24069PC21G, 24069PC21I。搭载1.5K OLED屏、骁龙8s处理器、5000mAh电池+90W快充、5000万像素主摄。 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2💝💝�…...
sql的调优指南及高级sql技巧
SQL调优是优化数据库性能的重要手段,涉及编写高效的SQL查询、合理设计索引、优化数据库结构等。以下是一些SQL调优指南和高级技巧: SQL调优指南 选择合适的查询方式: **避免使用SELECT ***:仅选择所需的列,减少数据传…...

生成式专题的第一节课---GAN图像生成
一、GAN的起源与发展 1.GAN的起源 GAN (生成式对抗网络)诞生于 2014 年,由 Ian Goodfellow 提出,是用于生成数据的深度学习模型,创新点是对抗性训练,即生成器与判别器的竞争关系,为图像生成、…...

中科星图GVE(案例)——AI实现建筑用地变化前后对比情况
目录 简介 函数 gve.Services.AI.ConstructionLandChangeExtraction(image1,image2) 代码 结果 知识星球 机器学习 简介 AI可以通过分析卫星图像、航拍影像或其他地理信息数据,实现建筑用地变化前后对比。以下是一种可能的实现方法: 数据获取&am…...
Spring Boot中获取application.yml中属性的几种方式
在Spring Boot应用程序中,可以通过多种方式从application.yml文件中获取配置属性。以下是几种常见的方法: 1. 使用Value注解 你可以使用Value注解将application.yml中的属性注入到Spring管理的bean中。 application.yml app:name: MySpringBootAppve…...

YOLO11改进 | 注意力机制 | 结合静态和动态上下文信息的注意力机制
秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 上下文Transformer(CoT&…...
Python中函数的使用方法
1 问题 在python的学习中,一个相同的程序可能会有多种不同的代码输入方式,那么函数这种方式是否方便快捷呢?今天我们来简单介绍函数的部分使用方法。 2 方法 定义函数:代码清单1Def function name (arguments):return result在上面…...

遨游智能终端赋能“危急特”场景,力推北斗技术规模化应用!
随着《北斗规模应用三年行动计划(2023-2025)》的发布,北京、湖北、重庆等多地出台北斗支持政策,北斗系统正稳步迈向“安全可控,泛在融合,开放兼容,服务全球”的发展目标。遨游通讯紧跟国家战略步…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...