学做外挂的网站/网站搜索查询

学做外挂的网站,网站搜索查询,公司网站做门户备案,网页设计图片平移版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ 前言 AES(Advanced Encryption Standard,高级加密标准) 是一种 对称加密算法,用于加密和解密数据。AES 由 美国…

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

前言

AES(Advanced Encryption Standard,高级加密标准) 是一种 对称加密算法,用于加密和解密数据。AES 由 美国国家标准与技术研究院(NIST) 在 2001 年正式发布,取代了 DES 和 3DES,目前被广泛应用于 网络安全、金融、通信 等领域。

支持 128(16字节)、192(24字节)、256(32字节) 位密钥。

特性描述
加密方式对称加密(加密和解密使用相同的密钥)
分组长度128 位(16 字节)
密钥长度128 位、192 位、256 位(分别对应 10、12、14 轮加密)
安全性目前无已知有效攻击,比 3DES 更安全
运算模式支持 ECB、CBC、CFB、OFB、CTR 等模式

关于算法的详细介绍可以参考这篇文章:常用加解密算法介绍

LibTomCrypt

LibTomCrypt 是一个开源的轻量级加密库,提供了多种加密算法和密码学相关功能。它是用 C 语言编写的,专注于嵌入式系统和资源受限的设备,非常适合在 Android 等平台上使用。

特点:

  • 算法支持丰富:包括对称加密(AES、DES 等)、非对称加密(RSA、ECC 等)、哈希算法(SHA-256、MD5 等)

  • 轻量级,代码简单。

  • 支持多种加密模式:ECB、CBC、CFB、OFB 等。

适用场景: 如果你需要一个开源、可自定义的库。

集成 LibTomCrypt 到 Android 工程

在 Android Studio 中集成 LibTomCrypt 并调用 JNI,可以按以下步骤操作:

1. 下载 LibTomCrypt

从官方 GitHub 仓库下载最新的源码:

LibTomCrypt GitHub

解压后,将整个 libtomcrypt/src 文件夹复制到 Android 工程中的 app/src/main/cpp 目录下。

word/media/image1.png

2. 配置 CMakeLists.txt

在 app/src/main/cpp/CMakeLists.txt 中添加以下配置:

# 添加 libtomcrypt 头文件路径
include_directories(libtomcrypt/src/headers)# 查找 libtomcrypt 所有的 C 文件
file(GLOB LIBTOMCRYPT_SOURCESlibtomcrypt/src/*.clibtomcrypt/src/misc/*.clibtomcrypt/src/misc/crypt/*.clibtomcrypt/src/ciphers/aes/*.clibtomcrypt/src/modes/cbc/*.clibtomcrypt/src/modes/cfb/*.clibtomcrypt/src/modes/ctr/*.clibtomcrypt/src/modes/ecb/*.c
)# 编译 LibTomCrypt
add_library(libtomcrypt STATIC ${LIBTOMCRYPT_SOURCES})

使用 LibTomCrypt 的实现 AES CBC 加解密

注意:

  • 数据对齐:AES CBC 模式要求输入数据的长度是 16 的倍数,如果不是,需要使用 PKCS7 Padding 或其他填充方式。。

  • Key 和 IV 长度:AES 支持 128、192、256 位密钥,Key 长度需要符合实际配置。

LibTomCrypt 本身不提供直接的 PKCS5Padding 实现,但你可以自己实现它。

PKCS5Padding 的规则是:

  • 每个填充值的值等于填充字节的数量。

  • 如果数据刚好是 16 字节的倍数,则会再添加一整块填充。

  • 填充值范围:0x01 ~ 0x10。

填充函数实现(PKCS5Padding)

void pkcs5_pad(uint8_t *data, int dataLen, int blockSize, int *paddedLen) {int padding = blockSize - (dataLen % blockSize);for (int i = 0; i < padding; i++) {data[dataLen + i] = (uint8_t)padding;}*paddedLen = dataLen + padding;
}
  • data:原始数据缓冲区,确保其有足够的空间存储填充后的数据。

  • dataLen:原始数据长度。

  • blockSize:通常为 16(AES)。

  • paddedLen:返回填充后的总长度。

去除填充函数(PKCS5UnPadding)

int pkcs5_unpad(uint8_t *data, int dataLen) {if (dataLen <= 0) return 0;uint8_t padding = data[dataLen - 1];if (padding > dataLen || padding > 16) return -1; // 不合法的填充for (int i = 0; i < padding; i++) {if (data[dataLen - 1 - i] != padding) return -1; // 填充不一致}return dataLen - padding;
}
  • data:解密后的数据。

  • dataLen:解密后的数据长度。

  • 返回值:去除填充后的实际数据长度。

AES CBC 加密

方法解析

  • register_cipher:确保 AES 算法已注册(返回 index != -1)

  • cbc_start:初始化 CBC 模式

  • cbc_encrypt:加密数据

  • cbc_decrypt:解密数据

  • cbc_done:清理资源

// AES CBC 加密方法
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesCBCEncode(JNIEnv *env, jclass clazz, jbyteArray data) {uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// 转换密钥和 IV 为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);uint8_t *ivBytes = stringToIV(IV);// PKCS5Paddingint paddedLen = dataLen + 16 - (dataLen % 16);uint8_t *paddedData = (uint8_t *) malloc(paddedLen);memcpy(paddedData, dataBytes, dataLen);pkcs5_pad(paddedData, dataLen, 16, &paddedLen);// 加密int cipher_index = register_cipher(&aes_desc);symmetric_CBC cbc;if (cbc_start(cipher_index, ivBytes, keyBytes, AES_KEYLEN, 0, &cbc) != CRYPT_OK) {LOGD("cbc_start failed.");free(paddedData);return nullptr;}uint8_t *output = (uint8_t *) malloc(paddedLen);if (cbc_encrypt(paddedData, output, paddedLen, &cbc) != CRYPT_OK) {LOGD("cbc_encrypt failed.");free(paddedData);free(output);return nullptr;}cbc_done(&cbc);jbyteArray result = env->NewByteArray(paddedLen);env->SetByteArrayRegion(result, 0, paddedLen, reinterpret_cast<jbyte *>(output));// 释放资源env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);free(paddedData);free(output);// 释放资源delete[] keyBytes;delete[] ivBytes;return result;
}

效果如下:

word/media/image2.png

AES CBC 解密

// AES CBC 解密方法
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesCBCDecode(JNIEnv *env, jclass clazz, jbyteArray data) {// 获取数据uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// 注册 AES 算法if (register_cipher(&aes_desc) == -1) {env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);return nullptr;}// 转换密钥和 IV 为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);uint8_t *ivBytes = stringToIV(IV);// 解密int cipher_index = register_cipher(&aes_desc);symmetric_CBC cbc;if (cbc_start(cipher_index, ivBytes, keyBytes, AES_KEYLEN, 0, &cbc) != CRYPT_OK) {LOGD("cbc_start failed.");return nullptr;}uint8_t *output = (uint8_t *) malloc(dataLen);if (cbc_decrypt(dataBytes, output, dataLen, &cbc) != CRYPT_OK) {LOGD("cbc_decrypt failed.");free(output);return nullptr;}cbc_done(&cbc);// 去除 PKCS5Paddingint unpaddedLen = pkcs5_unpad(output, dataLen);if (unpaddedLen < 0) {LOGD("PKCS5 unpadding failed.");free(output);return nullptr;}// 返回结果jbyteArray result = env->NewByteArray(unpaddedLen);env->SetByteArrayRegion(result, 0, unpaddedLen, reinterpret_cast<jbyte *>(output));// 释放资源free(output);env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);delete[] keyBytes;delete[] ivBytes;return result;
}

效果如下:

word/media/image3.png

完整代码

#include <jni.h>
#include <android/log.h>
#include <tomcrypt.h>#define AES_BLOCKLEN 16 // Block length in bytes AES is 128 b block only
#define AES_KEYLEN 16   // Key length in bytes#define LOG_TAG "aes_jni.cpp"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)const char * KEY = "CYRUS STUDIO    ";
const char * IV = "CYRUS STUDIO    ";// 将 const char* 转换为字节数组 (IV)
uint8_t *stringToIV(const char *str) {auto iv = new uint8_t[AES_BLOCKLEN];for (int i = 0; i < AES_BLOCKLEN; ++i) {iv[i] = static_cast<uint8_t>(str[i]);}return iv;
}// 将 const char* 转换为字节数组 (Key)
uint8_t *stringToSecretKey(const char *str) {auto key = new uint8_t[AES_KEYLEN];for (int i = 0; i < AES_KEYLEN; ++i) {key[i] = static_cast<uint8_t>(str[i]);}return key;
}void pkcs5_pad(uint8_t *data, int dataLen, int blockSize, int *paddedLen) {int padding = blockSize - (dataLen % blockSize);for (int i = 0; i < padding; i++) {data[dataLen + i] = (uint8_t)padding;}*paddedLen = dataLen + padding;
}int pkcs5_unpad(uint8_t *data, int dataLen) {if (dataLen <= 0) return 0;uint8_t padding = data[dataLen - 1];if (padding > dataLen || padding > 16) return -1; // 不合法的填充for (int i = 0; i < padding; i++) {if (data[dataLen - 1 - i] != padding) return -1; // 填充不一致}return dataLen - padding;
}// AES CBC 加密方法
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesCBCEncode(JNIEnv *env, jclass clazz, jbyteArray data) {uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// 转换密钥和 IV 为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);uint8_t *ivBytes = stringToIV(IV);// PKCS5Paddingint paddedLen = dataLen + 16 - (dataLen % 16);uint8_t *paddedData = (uint8_t *) malloc(paddedLen);memcpy(paddedData, dataBytes, dataLen);pkcs5_pad(paddedData, dataLen, 16, &paddedLen);// 加密int cipher_index = register_cipher(&aes_desc);symmetric_CBC cbc;if (cbc_start(cipher_index, ivBytes, keyBytes, AES_KEYLEN, 0, &cbc) != CRYPT_OK) {LOGD("cbc_start failed.");free(paddedData);return nullptr;}uint8_t *output = (uint8_t *) malloc(paddedLen);if (cbc_encrypt(paddedData, output, paddedLen, &cbc) != CRYPT_OK) {LOGD("cbc_encrypt failed.");free(paddedData);free(output);return nullptr;}cbc_done(&cbc);jbyteArray result = env->NewByteArray(paddedLen);env->SetByteArrayRegion(result, 0, paddedLen, reinterpret_cast<jbyte *>(output));// 释放资源env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);free(paddedData);free(output);// 释放资源delete[] keyBytes;delete[] ivBytes;return result;
}// AES CBC 解密方法
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesCBCDecode(JNIEnv *env, jclass clazz, jbyteArray data) {// 获取数据uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// 注册 AES 算法if (register_cipher(&aes_desc) == -1) {env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);return nullptr;}// 转换密钥和 IV 为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);uint8_t *ivBytes = stringToIV(IV);// 解密int cipher_index = register_cipher(&aes_desc);symmetric_CBC cbc;if (cbc_start(cipher_index, ivBytes, keyBytes, AES_KEYLEN, 0, &cbc) != CRYPT_OK) {LOGD("cbc_start failed.");return nullptr;}uint8_t *output = (uint8_t *) malloc(dataLen);if (cbc_decrypt(dataBytes, output, dataLen, &cbc) != CRYPT_OK) {LOGD("cbc_decrypt failed.");free(output);return nullptr;}cbc_done(&cbc);// 去除 PKCS5Paddingint unpaddedLen = pkcs5_unpad(output, dataLen);if (unpaddedLen < 0) {LOGD("PKCS5 unpadding failed.");free(output);return nullptr;}// 返回结果jbyteArray result = env->NewByteArray(unpaddedLen);env->SetByteArrayRegion(result, 0, unpaddedLen, reinterpret_cast<jbyte *>(output));// 释放资源free(output);env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);delete[] keyBytes;delete[] ivBytes;return result;
}

AES ECB 模式

ECB 模式没有 IV,因此只需要密钥即可。

// AES ECB 加密
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesECBEncode(JNIEnv *env,jclass clazz,jbyteArray data
) {uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// PKCS5Paddingint paddedLen = dataLen + 16 - (dataLen % 16);uint8_t *paddedData = (uint8_t *) malloc(paddedLen);memcpy(paddedData, dataBytes, dataLen);pkcs5_pad(paddedData, dataLen, 16, &paddedLen);// 设置 AES ECBsymmetric_ECB ecb;int cipher_index = register_cipher(&aes_desc);// 转换密钥为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);if (ecb_start(cipher_index, keyBytes, AES_KEYLEN, 0, &ecb) != CRYPT_OK) {LOGD("ecb_start failed.");delete[] keyBytes;free(paddedData);return nullptr;}// 加密uint8_t *output = (uint8_t *) malloc(paddedLen);if (ecb_encrypt(paddedData, output, paddedLen, &ecb) != CRYPT_OK) {LOGD("ecb_encrypt failed.");delete[] keyBytes;free(paddedData);free(output);return nullptr;}ecb_done(&ecb);jbyteArray result = env->NewByteArray(paddedLen);env->SetByteArrayRegion(result, 0, paddedLen, reinterpret_cast<jbyte *>(output));// 释放资源delete[] keyBytes;free(paddedData);free(output);env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);return result;
}// AES ECB 解密
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesECBDecode(JNIEnv *env,jclass clazz,jbyteArray data
) {uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// 初始化 ECBsymmetric_ECB ecb;int cipher_index = register_cipher(&aes_desc);// 转换密钥为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);if (ecb_start(cipher_index, keyBytes, AES_KEYLEN, 0, &ecb) != CRYPT_OK) {LOGD("ecb_start failed.");delete[] keyBytes;return nullptr;}// 解密uint8_t *output = (uint8_t *) malloc(dataLen);if (ecb_decrypt(dataBytes, output, dataLen, &ecb) != CRYPT_OK) {LOGD("ecb_decrypt failed.");delete[] keyBytes;free(output);return nullptr;}ecb_done(&ecb);// 去除 PKCS5Paddingint unpaddedLen = pkcs5_unpad(output, dataLen);if (unpaddedLen < 0) {LOGD("PKCS5 unpadding failed.");free(output);return nullptr;}jbyteArray result = env->NewByteArray(unpaddedLen);env->SetByteArrayRegion(result, 0, unpaddedLen, reinterpret_cast<jbyte *>(output));// 释放资源delete[] keyBytes;free(output);env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);return result;
}

效果如下:

word/media/image4.png

AES CTR 模式

CTR 模式需要 IV 和 Key,并且加密和解密使用相同的逻辑。

// AES CTR 加密
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesCTREncode(JNIEnv *env,jclass clazz,jbyteArray data
) {uint8_t *dataBytes = (uint8_t *) env->GetByteArrayElements(data, nullptr);int dataLen = env->GetArrayLength(data);// 设置 AES CTRsymmetric_CTR ctr;int cipher_index = register_cipher(&aes_desc);// 转换密钥和 IV 为字节数组uint8_t *keyBytes = stringToSecretKey(KEY);uint8_t *ivBytes = stringToIV(IV);if (ctr_start(cipher_index, ivBytes, keyBytes, AES_KEYLEN, 0, CTR_COUNTER_LITTLE_ENDIAN, &ctr) != CRYPT_OK) {LOGD("ctr_start failed.");delete[] keyBytes;delete[] ivBytes;return nullptr;}// 加密 / 解密uint8_t *output = (uint8_t *) malloc(dataLen);if (ctr_encrypt(dataBytes, output, dataLen, &ctr) != CRYPT_OK) {LOGD("ctr_encrypt failed.");delete[] keyBytes;delete[] ivBytes;free(output);return nullptr;}ctr_done(&ctr);jbyteArray result = env->NewByteArray(dataLen);env->SetByteArrayRegion(result, 0, dataLen, reinterpret_cast<jbyte *>(output));// 释放资源delete[] keyBytes;delete[] ivBytes;free(output);env->ReleaseByteArrayElements(data, (jbyte *) dataBytes, 0);return result;}// AES CTR 解密
extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_cyrus_example_aes_NativeAESUtils_aesCTRDecode(JNIEnv *env,jclass clazz,jbyteArray data
) {return Java_com_cyrus_example_aes_NativeAESUtils_aesCTREncode(env, clazz, data);
}

效果如下:

word/media/image5.png

AES 工作原理

AES 的加密过程分为多个轮次,每轮包含以下4个主要步骤:

  1. 字节代替 (SubBytes):使用 S-Box(替代盒)对每个字节进行非线性替换。

  2. 行移位 (ShiftRows):将数据分为4行,每行按特定规则循环移位。

  3. 列混合 (MixColumns):使用矩阵运算对每列的数据进行混合。

  4. 轮密钥加 (AddRoundKey):使用密钥进行 XOR 运算。

加密轮次:

  • 128位密钥:10轮

  • 192位密钥:12轮

  • 256位密钥:14轮

解密过程与加密过程类似,只是顺序相反,并使用逆S-Box和逆变换。

实现 AES 算法变体

在 LibTomCrypt 中,AES 算法的 S-Box(替代盒)是通过查找表(lookup table)实现的,而 AES 的表(如 S-Box)主要是存在于 src/cipher/aes/aes_tab.c 文件中。

该 S-Box 是一个 256 字节的查找表,用于将每个输入字节替换成加密的字节。

word/media/image6.png

理论上,你可以通过修改 LibTomCrypt 中的 S-Box 或其他查找表,来实现你自己的 AES 变体。

比如,把 0xc66363a5UL 改成 0xaa6363a5UL。

word/media/image7.png

AES 算法变体加密结果:

word/media/image8.png

标准 AES 算法加密结果:

word/media/image9.png

可以看到加密结果已经和标准的 AES 不一样了,解密结果还是一样的。

word/media/image10.png

完整源码

完整源码地址:https://github.com/CYRUS-STUDIO/AndroidExample

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

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

相关文章

小河:团队金牌精准计划

【趋势识别与预测】 数据趋势分析在随机序列研究中首要价值在于识别潜在规律并提升预测能力。随机序列常表现为无规则波动&#xff0c;但通过滑动平均、指数平滑、小波变换等方法&#xff0c;可剥离噪声干扰&#xff0c;提取长期趋势或周期性成分。例如&#xff0c;在金融时间序…

S32K144外设实验(七):FTM输出多路互补带死区PWM

文章目录 1. 概述1.1 时钟系统1.2 实验目的2. 代码的配置2.1 时钟配置2.2 FTM模块配置2.3 输出引脚配置2.4 API函数调用1. 概述 互补对的PWM输出是很重要的外设功能,尤其应用再无刷电机的控制。 1.1 时钟系统 笔者再墨迹一遍时钟的设置,因为很重要。 FTM的CPU接口时钟为SY…

数据结构与算法:算法分析

遇到的问题&#xff0c;都有解决方案&#xff0c;希望我的博客能为您提供一点帮助。 本篇参考《Data Structures and Algorithm Analysis in C》 “在程序设计中&#xff0c;不仅要写出能工作的程序&#xff0c;更要关注程序在大数据集上的运行时间。” 本章讨论要点&#xf…

排序--归并排序

一&#xff0c;引言 归并排序作为七大排序中一种&#xff0c;本文将讲解其排序原理和代码实现。 二&#xff0c;逻辑讲解 来看一组动图&#xff1a; 首先先进行大逻辑的讲解&#xff0c;在一个乱序的数组中如图&#xff1a; 通过递归进行一次次分组如图&#xff1a; 分组逻…

React程序打包与部署

===================== 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 为生产环境准备React应用最小化和打包环境变量错误处理部署到托管服务部署到Netlify探索高级主题:Hooks、Su…

Spring Data审计利器:@LastModifiedDate详解(依赖关系补充篇)!!!

&#x1f552; Spring Data审计利器&#xff1a;LastModifiedDate详解&#x1f525;&#xff08;依赖关系补充篇&#xff09; &#x1f50c; 核心依赖解析 使用LastModifiedDate必须知道的依赖关系 #mermaid-svg-qm1OUa9Era9ktbeK {font-family:"trebuchet ms",verd…

接口测试中数据库验证,怎么解决?

在接口测试中&#xff0c;通常需要在接口调用前后查询数据库&#xff0c;以验证接口操作是否正确影响了数据库状态。​这可以通过数据库断言来实现&#xff0c;PyMySQL库常用于连接和操作MySQL数据库。​通过该库&#xff0c;可以在测试中执行SQL语句&#xff0c;查询或修改数据…

游戏引擎学习第189天

今天的回顾与计划 在昨天&#xff0c;我们花了一些时间来优化调试数据的收集方法&#xff0c;并且在调试界面中增加了一些界面代码&#xff0c;使得我们可以悬停在不同的元素上&#xff0c;查看相关信息。今天的任务是对这些数据进行更多的操作&#xff0c;进行一些有趣的实验…

智能粉尘监测解决方案|守护工业安全,杜绝爆炸隐患

在厂房轰鸣的生产线上&#xff0c;一粒微小粉尘的聚集可能成为一场灾难的导火索。如何实现粉尘浓度的精准监控与快速响应&#xff1f;我们为您打造了一套"感知-预警-处置"全闭环的智能安全方案&#xff01; 行业痛点&#xff1a;粉尘管理的生死线 在金属加工、化工…

Axure设计之中继器表格——拖动行排序教程(中继器)

一、原理介绍 在Axure中实现表格行的拖动排序&#xff0c;主要依赖于中继器的排序事件。然而要实现拖动效果&#xff0c;就必须结合动态面板&#xff0c;因为动态面板可以设置拖动事件&#xff0c;之所以使用动态面板或许是因为它可以更灵活地处理位置变化。用户拖动行时&…

分布式渲染与云渲染:技术与应用的黄金搭档

一、核心概念&#xff1a;先区分再关联 分布式渲染是通过多台设备并行计算拆分渲染任务的技术&#xff08;如将一帧拆分为 64 个小块&#xff0c;64 台电脑同时渲染&#xff09;&#xff1b; 云渲染是基于云计算的渲染服务&#xff0c;本质是分布式渲染的商业化落地—— 用户无…

鼠标在客户区内按下左键和双击右键

书籍&#xff1a;《Visual C 2017从入门到精通》的2.6鼠标 环境&#xff1a;visual studio 2022 内容&#xff1a;【例2.44】鼠标在客户区内按下左键和双击右键 1.创建一个单文档程序 一个简单的单文档程序-CSDN博客https://blog.csdn.net/qq_20725221/article/details/1463…

【Java SE】包装类 Byte、Short、Integer、Long、Character、Float、Double、Boolean

参考笔记&#xff1a;java 包装类 万字详解&#xff08;通俗易懂)_java包装类-CSDN博客 目录 1.简介 2.包装类的继承关系图 3.装箱和拆箱 3.1 介绍 3.2 手动拆装箱 3.3. 自动拆装箱 ​4.关于String类型的转化问题 4.1 String类型和基本类型的相互转化 4.1.1 String —…

Stable Diffusion vue本地api接口对接,模型切换, ai功能集成开源项目 ollama-chat-ui-vue

1.开启Stable Diffusion的api服务 编辑webui-user.bat 添加 –api 开启api服务&#xff0c;然后保存启动就可以了 2.api 文档地址 http://127.0.0.1:7860/docs3. 文生图 接口 地址 /sdapi/v1/txt2img //post 请求入参 {enable_hr: false, // 开启高清hrdenoising_stre…

CentOS 7 部署RuoYi 项目

换源 备份现有的 YUM 源配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 默认的 CentOS 官方镜像源替换为阿里云的镜像源&#xff0c;以提高下载速度和稳定性。 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.co…

C++ stack容器总结

stack 基本概念 概念&#xff1a; stack是一种后进先出(Last In First Out, LIFO)的数据结构&#xff0c;它只有一个出口 栈中只有顶端的元素才可以被外界使用&#xff0c;因此栈不允许有遍历行为 栈中进入的数据称为----入栈&#xff08;PUSH&#xff09; 栈中出去的数据成…

【SDMs分析1】基于ENMTools R包的生态位分化分析和图像绘制(identity.test())

基于ENMTools包的生态位分化 1. 写在前面2. 生态位分化检验案例13. 生态位分化检验案例21. 写在前面 最近学了一个新的内容,主要是关于两个物种之间生态位分化检验的 R 语言代码。生态位分化是物种分布模型(SDM )研究中的关键部分,许多 SCI 论文都会涉及这一分析。该方法主…

SpringBoot 7 种实现 HTTP 调用的方式

1. HttpClient HttpClient是Apache基金会提供的一个用于发送HTTP请求的Java客户端库。 尽管它功能强大&#xff0c;但由于其API设计较为复杂且包体积庞大&#xff0c;在一些轻量级的应用场景中可能显得过于臃肿。 不过&#xff0c;在需要高度定制化的HTTP请求时&#xff0c;H…

Ubuntu与Windows之间相互复制粘贴的方法

一、打开Ubuntu终端 二、卸载已有的工具 sudo apt-get autoremove open-vm-tools 三、安装工具 sudo apt-get install open-vm-tools-desktop 四、重启 直接输入reboot 注&#xff1a;有任何问题欢迎评论区交流讨论或者私信&#xff01;

ECharts实现数据可视化

ECharts实现数据可视化 一、Echarts的简介二、Echarts使用教程1.下载echarts.min.js文件2.编写echarts代码&#xff08;1&#xff09;创建渲染实列&#xff08;2&#xff09;修改option达到预期的效果&#xff08;3&#xff09;创建配置项到实例中 三、Echarts的基础配置四、前…