openssl加解密-干货分享
0.需要包含的头文件和预定义常量
#include <openssl/rand.h>#include <fstream>#include <openssl/aes.h>#include <openssl/rand.h>// 加密密钥和初始化向量(IV)长度#define AES_KEY_LENGTH 32#define AES_IV_LENGTH 16
1.密钥的生成与管理
unsigned char key[32];if (RAND_bytes(key, sizeof(key)) != 1) {// 处理错误}// 使用自己的加密密钥// 将 key 转换为十六进制字符串std::string key_str;for (size_t i = 0; i < sizeof(key); i++) {char hex[3];snprintf(hex, sizeof(hex), "%02x", key[i]);key_str += hex;}std::cout << "key_str=" << key_str << std::endl;
将加密密钥保存到文件:
// 将加密密钥保存到文件void saveKeyToFile(const char* filename, const AES_KEY* key) {std::ofstream file(filename, std::ios::binary);if (file.is_open()) {// 写入轮数file.write(reinterpret_cast<const char*>(&key->rounds), sizeof(key->rounds));// 写入密钥调度表file.write(reinterpret_cast<const char*>(key->rd_key), sizeof(key->rd_key));file.close();std::cout << "Encryption key saved to file: " << filename << std::endl;} else {std::cerr << "Error opening file for writing: " << filename << std::endl;}}
从文件中加载加密密钥:
// 从文件中加载加密密钥void loadKeyFromFile(const char* filename, AES_KEY* key) {std::ifstream file(filename, std::ios::binary);if (file.is_open()) {// 读取轮数file.read(reinterpret_cast<char*>(&key->rounds), sizeof(key->rounds));// 读取密钥调度表file.read(reinterpret_cast<char*>(key->rd_key), sizeof(key->rd_key));file.close();std::cout << "Encryption key loaded from file: " << filename << std::endl;} else {std::cerr << "Error opening file for reading: " << filename << std::endl;}}
2.加密
// 使用AES-256加密算法void encryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));//AES_set_encrypt_key(ckey, AES_KEY_LENGTH * 8, &aesKey);//(const unsigned char *)key.c_str()AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 将加密密钥保存到文件//saveKeyToFile("encryption_key.bin", &aesKey);std::cout << "key :\t" << key << std::endl;// 生成随机IVunsigned char iv[AES_IV_LENGTH];RAND_bytes(iv, AES_IV_LENGTH);iv[AES_IV_LENGTH-1]='\0';// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "ivBackup :\t" << ivBackup << std::endl;std::ifstream inputFile(inputFilename, std::ios::binary);std::ofstream outputFile(outputFilename, std::ios::binary);outputFile.write(reinterpret_cast<const char *>(iv), AES_IV_LENGTH);unsigned char inBuffer[16], outBuffer[16];int num = 0;static int testi=0;while (inputFile.good()) { // 检查文件是否有效inputFile.read(reinterpret_cast<char *>(inBuffer), 16);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (inputFile.gcount() > 0) { // 检查实际读取的字节数memcpy( iv , ivBackup, AES_BLOCK_SIZE);AES_cfb128_encrypt(inBuffer, outBuffer, 16, &aesKey, iv, &num, AES_ENCRYPT);// 重置 IV//memcpy(iv, ivBackup, AES_IV_LENGTH);/* //if(testi<=1)是为了检查,检查解密出来的第一段16字节内容是否跟加密前的一样if(testi<=1) {//std::cout << "inBuffer :\t" << inBuffer << std::endl;std::cout << "encryptFile, inBuffer:\n";for (int i = 0; i < 16; i++) {printf("%02x", inBuffer[i]); // 打印十六进制形式}std::cout << "\n";std::cout << "encrypted data:\t";for (int i = 0; i < 16; i++) {printf("%02x", outBuffer[i]); // 打印十六进制形式}std::cout << std::endl;memcpy( iv , ivBackup, AES_BLOCK_SIZE);unsigned char decrypt_outBuffer[16];AES_cfb128_encrypt(outBuffer, decrypt_outBuffer, 16, &aesKey, iv, &num, AES_DECRYPT);//std::cout << "decrypt_outBuffer :\t" << decrypt_outBuffer << std::endl;std::cout << "encryptFile, decrypt_outBuffer:\n";for (int i = 0; i < 16; i++) {printf("%02x", decrypt_outBuffer[i]); // 打印十六进制形式}std::cout << "\n";testi++;}*/outputFile.write(reinterpret_cast<const char *>(outBuffer), 16);}}}
这个写法有个很大的问题,把输入的文件内容认为是16字节的整数倍,这样是不合理的!修正后的写法:
void encryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 生成随机 IVunsigned char iv[AES_IV_LENGTH];RAND_bytes(iv, AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "key :\t" << key << std::endl;std::cout << "ivBackup :\t";for (int i = 0; i < AES_IV_LENGTH; i++) {printf("%02x", ivBackup[i]);}std::cout << std::endl;std::ifstream inputFile(inputFilename, std::ios::binary);std::ofstream outputFile(outputFilename, std::ios::binary);outputFile.write(reinterpret_cast<const char *>(iv), AES_IV_LENGTH);unsigned char inBuffer[AES_BLOCK_SIZE], outBuffer[AES_BLOCK_SIZE];int num = 0;//static int testi=0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), AES_BLOCK_SIZE);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (bytesRead > 0) {// 拷贝 IV//memcpy(iv, ivBackup, AES_BLOCK_SIZE);// 加密AES_cfb128_encrypt(inBuffer, outBuffer, bytesRead, &aesKey, iv, &num, AES_ENCRYPT);// 输出加密数据outputFile.write(reinterpret_cast<const char *>(outBuffer), bytesRead);// if(testi<=1) {// // 重置 IV// memcpy(iv, ivBackup, AES_BLOCK_SIZE);// // 解密,为了测试// unsigned char decrypt_outBuffer[AES_BLOCK_SIZE];// AES_cfb128_encrypt(outBuffer, decrypt_outBuffer, bytesRead, &aesKey, iv, &num, AES_DECRYPT);// // 打印信息,为了测试// std::cout << "inBuffer:\n";// for (int i = 0; i < bytesRead; i++) {// printf("%02x", inBuffer[i]);// }// std::cout << "\n";// std::cout << "encrypted data:\t";// for (int i = 0; i < bytesRead; i++) {// printf("%02x", outBuffer[i]);// }// std::cout << std::endl;// std::cout << "decrypt_outBuffer:\n";// for (int i = 0; i < bytesRead; i++) {// printf("%02x", decrypt_outBuffer[i]);// }// std::cout << "\n";// testi++;// }}}}
3.解密
void decryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));//unsigned char ckey[] = "helloworldkey\0";AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);//AES_set_decrypt_key(ckey, AES_KEY_LENGTH * 8, &aesKey);//(const unsigned char *)key.c_str()/* set the encryption key *///AES_set_decrypt_key(ckey, 128, &aesKey);// 加载加密密钥//loadKeyFromFile("encryption_key.bin", &aesKey);std::cout << "key :\t" << key << std::endl;std::ifstream inputFile(inputFilename, std::ios::binary);std::ofstream outputFile(outputFilename, std::ios::binary);// 从文件中读取IVunsigned char iv[AES_IV_LENGTH];inputFile.read(reinterpret_cast<char *>(iv), AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "ivBackup :\t" << ivBackup << std::endl;unsigned char inBuffer[16], outBuffer[16];int num = 0;static int testi=0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), 16);if (inputFile.gcount() > 0) { // 检查实际读取的字节数memcpy( iv , ivBackup, AES_BLOCK_SIZE);AES_cfb128_encrypt(inBuffer, outBuffer, 16, &aesKey, iv, &num, AES_DECRYPT);//nullptr// 重置 IV//memcpy(iv, ivBackup, AES_IV_LENGTH);if(testi<=1) {//std::cout << "inBuffer :\t" << inBuffer << std::endl;std::cout << "encrypted data:\t";for (int i = 0; i < 16; i++) {printf("%02x", inBuffer[i]); // 打印十六进制形式}std::cout << std::endl;//std::cout << "outBuffer :\t" << outBuffer << std::endl;std::cout << "decryptFile, outBuffer:\n";for (int i = 0; i < 16; i++) {printf("%02x", outBuffer[i]); // 打印十六进制形式}std::cout << "\n";testi++;}outputFile.write(reinterpret_cast<char *>(outBuffer), 16);}}}
这个写法有个很大的问题,把输入的文件内容认为是16字节的整数倍,这样是不合理的!修正后的写法:
void decryptFile(const std::string &inputFilename, const std::string &outputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 打开输入文件std::ifstream inputFile(inputFilename, std::ios::binary);if (!inputFile) {std::cerr << "Error opening input file." << std::endl;return;}// 打开输出文件std::ofstream outputFile(outputFilename, std::ios::binary);if (!outputFile) {std::cerr << "Error opening output file." << std::endl;return;}// 从文件中读取 IVunsigned char iv[AES_IV_LENGTH];inputFile.read(reinterpret_cast<char *>(iv), AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);std::cout << "ivBackup :\t";for (int i = 0; i < AES_IV_LENGTH; i++) {printf("%02x", ivBackup[i]);}std::cout << std::endl;unsigned char inBuffer[AES_BLOCK_SIZE], outBuffer[AES_BLOCK_SIZE];int num = 0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), AES_BLOCK_SIZE);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (bytesRead > 0) {// 拷贝 IV//memcpy(iv, ivBackup, AES_BLOCK_SIZE);// 解密AES_cfb128_encrypt(inBuffer, outBuffer, bytesRead, &aesKey, iv, &num, AES_DECRYPT);// 输出解密数据outputFile.write(reinterpret_cast<char *>(outBuffer), bytesRead);}}}
4.加密和解密接口的调用
encryptFile("./models/test.jpg", "./models/encrypted_cornerModel.crypt", key_str);
decryptFile("./models/encrypted_cornerModel.crypt", "./models/decrypt_test.jpg", key_str);
encryptFile("./models/patternModel.onnx", "./models/encrypted_patternModel.crypt", key_str);
decryptFile("./models/encrypted_patternModel.crypt", "./models/decrypt_patternModel.onnx", key_str);
encryptFile("./models/cornerModel.onnx", "./models/encrypted_cornerModel.crypt", key_str);
decryptFile("./models/encrypted_cornerModel.crypt", "./models/decrypt_cornerModel.onnx", key_str);
5.解密出来的内容,不保存到文件,而是直接保存到内存缓冲区后,再将内存缓冲区的模型数据传递给 readNet 接口
void decryptAndLoadModel(const std::string &inputFilename, const std::string &key) {AES_KEY aesKey;memset(&aesKey, 0, sizeof(AES_KEY));AES_set_encrypt_key((const unsigned char *)key.c_str(), 128, &aesKey);// 打开输入文件std::ifstream inputFile(inputFilename, std::ios::binary);if (!inputFile) {std::cerr << "Error opening input file." << std::endl;return;}// 从文件中读取 IVunsigned char iv[AES_IV_LENGTH];inputFile.read(reinterpret_cast<char *>(iv), AES_IV_LENGTH);// 备份 IVunsigned char ivBackup[AES_IV_LENGTH];memcpy(ivBackup, iv, AES_IV_LENGTH);// 定义内存缓冲区用于存储解密的模型数据std::vector<unsigned char> decryptedModelBuffer;unsigned char inBuffer[AES_BLOCK_SIZE], outBuffer[AES_BLOCK_SIZE];int num = 0;while (inputFile.good()) {inputFile.read(reinterpret_cast<char *>(inBuffer), AES_BLOCK_SIZE);// 获取实际读取的字节数int bytesRead = inputFile.gcount();if (bytesRead > 0) {// 解密AES_cfb128_encrypt(inBuffer, outBuffer, bytesRead, &aesKey, iv, &num, AES_DECRYPT);// 存储解密数据到内存缓冲区decryptedModelBuffer.insert(decryptedModelBuffer.end(), outBuffer, outBuffer + bytesRead);}}// 使用 OpenCV 读取解密后的模型数据cv::Mat modelDataMat(1, decryptedModelBuffer.size(), CV_8U, decryptedModelBuffer.data());// 将解密后的模型数据传递给 readNet 接口cv::dnn::Net neuralNet = cv::dnn::readNetFromONNX(modelDataMat);// 使用 neuralNet 对象进行后续操作,如推理等// ...
}
在加密中,IV(Initialization Vector,初始化向量)和 Key(密钥)是两个重要的概念,它们通常用于对数据进行加密和解密。
-
Initialization Vector(IV,初始化向量): IV 是在对称加密中使用的固定长度的随机值。它的作用是增强加密算法的安全性,以防止在相同密钥下对相同的明文进行多次加密时产生相同的密文输出。
IV 与密钥不同,IV 不需要保密,通常会与密文一起传输。对于每个独立的消息,IV 都应该是唯一的,但不需要保密。在开始加密之前,IV 会与密钥一起输入到加密算法中,以确保对相同的明文使用相同的密钥和 IV 时,每次得到的密文都是不同的。
-
Key(密钥): 密钥是用于加密和解密数据的机密值。在对称加密中,加密和解密使用相同的密钥。保持密钥的机密性对于加密的安全性至关重要。只有知道密钥的人才能解密数据。
密钥应该是足够长且具有足够的随机性,以防止被暴力破解。安全的加密算法强调了密钥的安全性和保密性,因为知道密钥的人可以解密被加密的数据。
IV 和密钥的选择对于加密的安全性至关重要。合适的 IV 长度和随机性以及安全的密钥管理对于确保加密系统的安全性非常重要。IV 和密钥的选择取决于所使用的加密算法和具体的安全需求。
相关文章:
openssl加解密-干货分享
0.需要包含的头文件和预定义常量 #include <openssl/rand.h>#include <fstream>#include <openssl/aes.h>#include <openssl/rand.h>// 加密密钥和初始化向量(IV)长度#define AES_KEY_LENGTH 32#define AES_IV_LENGTH 16 1.密…...
【考研数据结构代码题7】求一元多项式之和
题目:编写一个算法,求一元多项式之和 考纲:一元多项式的表示与相加 题型:代码填空或算法设计 难度:★★★ 参考代码 typedef struct node{float coef;//系数int exp;//次数struct node *next; }polynode; polynode *…...
python避坑指南(更新中)
os.path.join 避免连续的/,看示例即清楚,最好的避免方法是字符串首末都不要加’/: join用法 用join前面的符号将参数数组里面的字符串连接起来,注意join只有一个参数...
可以远程控制电脑桌面的软件有哪些?
随着电脑办公的普及,人们对于远程控制电脑的需求也越来越大。远程控制电脑技术能够让用户在不同地点的电脑之间进行操作和访问,能够提高工作效率。可以远程控制电脑桌面的软件有哪些? 1. 远程监控电脑软件 需要安装在被控制端电脑ÿ…...
洛谷 P1250 种树
种树 题目背景 一条街的一边有几座房子,因为环保原因居民想要在路边种些树。 题目描述 路边的地区被分割成块,并被编号成 1 , 2 , … , n 1, 2, \ldots,n 1,2,…,n。每个部分为一个单位尺寸大小并最多可种一棵树。 每个居民都想在门前种些树&#…...
java大视频在线预览(支持断点下载)
1.说明 大视频的在线预览,如果不支持断点下载,将无法在苹果手机上播放,同时不支持进度条拖动. 之所以这样,是因为视频文件太大了,通过二进制流向浏览器传输时,整个文件尚未传输完成时,会被浏览器强制关闭流,不再接收,等缓存播放到一定程度时,浏览器会再次向后端请求视频文件,同…...
OpenCV入门10——特征点检测与匹配
文章目录 特征检测的基本概念Harris角点检测Shi-Tomasi角点检测SIFT关键点检测SIFT计算描述子SURF特征检测OBR特征检测暴力特征匹配FLANN特征匹配实战flann特征匹配图像查找图像拼接基础知识图像拼接实战 特征点检测与匹配是计算机视觉中非常重要的内容。不是所有图像操作都是对…...
教育机构拒绝“数据陷阱”,群硕将英孚新一代教学管理系统搬上桌
为什么小机构年年担心招生不够,英孚却令学生家长趋之若鹜? 区别就在教学管理方式。为了更好地管理分布全球的校区、学生和老师,英孚应用了一套教学管理系统,帮助学校管理学员,帮老师智慧排课,帮助家长记录…...
小辰的智慧树(差分+前缀和)
登录—专业IT笔试面试备考平台_牛客网 1.考虑总长度之和不能超过m,2考虑限制每棵树高度不能低于ci,如果用二分最短输能截到的高度,还要另外去判断,是否每棵树mid都能严格大于ci ,这样容易超时,换个角度&…...
Windows如何使用key登录Linux服务器
场景:因为需要回收root管理员权限,禁止root用户远程登录,办公环境只允许普通用户远程登录,且不允许使用密码登录。 一、生成与配置ssh-key 1.使用root管理员权限登录到目标系统。 2.创建一个新的普通用户,和设置密码用…...
k8s无法删除pv,pvc问题
问题: 在k8s里面创建了pv,pvc删除时报错:error: resource(s) were provided, but no name was specified 解决: 正确的删除顺序:1.先删除pod2.再删除pv 3.在删除pvc 删除pv,pvc命令: kubect…...
基于框架的线性回归
线性回归是机器学习中最简单和最常用的回归方法之一。它建立了自变量和因变量之间的线性关系,并通过拟合一条直线或超平面来预测和分析数据。 基于框架的线性回归是构建线性回归模型的一种常见方法,它利用现有的机器学习框架来实现线性回归模型的建立、…...
万宾科技智能井盖传感器使用方式,具有什么效果?
有问题的井盖可能导致人们在行走或驾驶时不经意地踩中或碰到,从而导致摔倒、扭伤或交通事故等安全事故。有问题的井盖可能会破坏井盖和下方污水管道之间的密封性,导致污水泄漏。这不仅会对环境造成污染,还可能对公共卫生和健康构成威胁。 将智…...
13.什么是Spring beans?
什么是Spring beans? Spring 官方文档对 bean 的解释是: In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assem…...
算法通关村第十二关|白银|字符串经典基础面试题
1.反转问题 1.1 反转字符串 原题:力扣344. 要求原地修改。 public void reverseString(char[] s) {if (s null || s.length() 0) {return;}int n s.length;for (int left 0, right n - 1; left < right; left, right--) {char temp s[left];s[left] s…...
Spring框架学习 -- 读取和存储Bean对象
目录 🚀🚀 回顾 getBean()方法的使用 根据name来获取对象 再谈getBean() (1) 配置扫描路径 (2) 添加注解 ① spring注解简介 ② 对类注解的使用 ③ 注解Bean对象的命名问题 ④ 方法加Bean注解 (3) Bean 注解的重命名 (4) 获取Bean对象 -- …...
APM工具skywalking部署
一 整体架构 整个架构,分成上、下、左、右四部分: 上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是&…...
MFC打开可执行文件exe
CString exeName, propathdir;//propath _T("D:\\vs2017\\Project\\work\\mySqlselect\\release64\\mySqlselect.exe");//propathdir _T("D:\\vs2017\\Project\\work\\mySqlselect\\elease64\\");//路径太深的时候要指明文件所在路径,奇葩//p…...
css实现原生form表单label必填选项红色*样式,以及js控制必填校验
文章目录 一、css实现原生form表单label必填选项红色*样式,以及js控制必填校验?二、实现方案参考原文 一、css实现原生form表单label必填选项红色*样式,以及js控制必填校验? 二、实现方案 1.css实现原生form表单label必填选项红色…...
10_6 input输入子系统,流程解析
简单分层 应用层 内核层 --------------------------- input handler 数据处理层 driver/input/evdev.c1.和用户空间交互,实现fops2.不知道数据怎么得到的,但是可以把数据上传给用户--------------------------- input core层1.维护上面和下面的两个链表2.为上下两层提供接口--…...
从C语言转Verilog踩过的坑:逻辑运算‘真值’判定,差点让我电路跑飞
从C语言转Verilog踩过的坑:逻辑运算‘真值’判定差点让我电路跑飞 第一次用Verilog写状态机时,我遭遇了职业生涯最诡异的bug——仿真波形显示状态跳转完全随机,而RTL代码看起来毫无问题。直到深夜盯着波形图突然发现,当计数器值为…...
微信聊天记录永久保存:三步导出完整指南
微信聊天记录永久保存:三步导出完整指南 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMsg 你是…...
从物理约束到AI加速:NVIDIA PhysicsNeMo如何重塑科学计算范式
从物理约束到AI加速:NVIDIA PhysicsNeMo如何重塑科学计算范式 【免费下载链接】modulus Open-source deep-learning framework for building, training, and fine-tuning deep learning models using state-of-the-art Physics-ML methods 项目地址: https://gitc…...
Android位置伪装完整指南:7个实用场景教会你安全使用虚拟定位
Android位置伪装完整指南:7个实用场景教会你安全使用虚拟定位 【免费下载链接】FakeLocation Xposed module to mock locations per app. 项目地址: https://gitcode.com/gh_mirrors/fak/FakeLocation 你是否曾经想过,为什么某些应用总是知道你在…...
信号量(二进制/计数)
二进制信号量定义: #include "semphr.h" // SemaphoreHandle_t // 二进制信号量(Binary Semaphore) SemaphoreHandle_t xBinarySemaphore; void vTaskA(void *pvParameters) {while(1) {// 获取信号量if(xSemaphoreTake(xBinarySem…...
容器化AI推理成本失控?从$28/h到$3.6/h的真实压测数据,及不可跳过的4个资源泄漏盲区
更多请点击: https://intelliparadigm.com 第一章:容器化AI推理成本失控的真相与警示 当团队将 LLaMA-3 或 Qwen2 模型封装进 Docker 镜像并部署到 Kubernetes 集群时,CPU 利用率常低于 15%,而 GPU 显存占用却长期维持在 98%——…...
网易云音乐NCM转MP3终极解决方案:高效音频解密与格式转换实战指南
网易云音乐NCM转MP3终极解决方案:高效音频解密与格式转换实战指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?NCM转MP3的音频格式转换其…...
告别低效业务开发,大模型赋能程序员高效办公
文章目录 前言一、醒醒!2026年了,你还在靠堆时间写CRUD内卷?1.1 扎心现实:传统业务开发,正在陷入“越忙越穷”的死循环1.2 90%的程序员,都用错了大模型1.3 真相:大模型不是来抢饭碗的࿰…...
如何在Mac上轻松运行Windows应用:Whisky完整指南与实战教程
如何在Mac上轻松运行Windows应用:Whisky完整指南与实战教程 【免费下载链接】Whisky A modern Wine wrapper for macOS built with SwiftUI 项目地址: https://gitcode.com/gh_mirrors/wh/Whisky 你是否曾经因为某些软件只有Windows版本而感到困扰࿱…...
终极指南:如何用NX代码所有权彻底解决团队协作中的责任难题
终极指南:如何用NX代码所有权彻底解决团队协作中的责任难题 【免费下载链接】nx The Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time. …...
