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)》的发布,北京、湖北、重庆等多地出台北斗支持政策,北斗系统正稳步迈向“安全可控,泛在融合,开放兼容,服务全球”的发展目标。遨游通讯紧跟国家战略步…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
