当前位置: 首页 > news >正文

ubuntu18.04 + openssl + engine + pkcs11+ softhsm2 双向认证测试

安装环境

openssl 1.1.1
pkcs11-tool (由sudo apt-get install opensc 安装)
libpksc11 (需源码安装apt install 只有libp11, 源码安装才有 libpksc11.so -> pkcs11.so)
softhsm2 (由sudo apt-get install softhsm2 libsofthsm2-dev pkcs11-dump 安装)

配置引擎

vim /etc/ssl/openssl.cnfline 1 openssl_conf = openssl_initline n[openssl_init]engines=engine_section[engine_section]pkcs11 = pkcs11_section[pkcs11_section]engine_id = pkcs11dynamic_path = /usr/lib/x86_64-linux-gnu/engines-1.1/libpkcs11.soMODULE_PATH = /usr/lib/softhsm/libsofthsm2.soinit = 0
line end

验证配置

$ openssl engine -t
(rdrand) Intel RDRAND engine[ available ]
(dynamic) Dynamic engine loading support[ unavailable ]
(pkcs11) pkcs11 engine[ available ]

 一次完整RSA加解密

# 需要Slot Token Pin So-Pin
softhsm2-util --init-token --slot 0 --label "mytoken" --pin 1234 --so-pin 12345
# 生成密钥
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --login --keypairgen --key-type rsa:2048 --id 1 --label "mytoken" --pin 1234
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l      -k           --key-type rsa:2048 --id 2 --label "mytoken" --pin 1234# get the public key first
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --read-object --type pubkey --id 1 --output-file public.der# 公钥加密
echo 'NetHSM rulez!NetHSM rulez!' | openssl pkeyutl -encrypt -pubin -inkey public.der -keyform DER -out data.crypt# 私钥解密
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --decrypt --id 1 --mechanism RSA-PKCS --input-file data.crypt

双向认证

# 生成根证书私钥(pem文件)
openssl genrsa -out root.key 2048
# 生成根证书签发申请文件(csr文件)
openssl req -new -key root.key -out root.csr -subj "/CN=localhost/C=CN/ST=rootprovince/L=rootcity/O=rootorganization/OU=rootgroup"
# 自签发根证书(cer文件)
openssl x509 -req -days 365 -extensions v3_ca -signkey root.key -in root.csr -out root.crt# 生成服务端私钥   
openssl genrsa -out server.key 2048
# 生成证书请求文件 
openssl req -new -key server.key -out server.csr -subj "/CN=localhost/C=CN/ST=serverprovince/L=servercity/O=serverorganization/OU=servergroup"
# 使用根证书签发服务端证书
openssl x509 -req -days 365 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.srl -CAcreateserial -in server.csr -out server.crt
# 使用CA证书验证服务端证书
openssl verify -CAfile root.crt server.crt# 须先执行softhsm的步骤
# 生成client密钥对 //module 为pkcs11格式的硬件驱动 id、label和pin要记住
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so --login --keypairgen --key-type rsa:2048 --id 2 --label "mytoken" --pin 1234
# 生成请求文件
openssl req -new -subj "/CN=localhost/C=CN/ST=clientprovince/L=clientcity/O=clientorganization/OU=clientgroup" -engine pkcs11 -keyform engine -key "pkcs11:token=mytoken;object=mytoken;type=private;pin-value=12345" -out client.csr
# 使用根证书签发客户端证书
openssl x509 -req -days 365 -extensions v3_req -CA root.crt -CAkey root.key -CAserial root.srl -CAcreateserial -in client.csr -out client.crt
# 使用CA证书验证客户端证书
openssl verify -CAfile root.crt client.crt
# 将cert写入softhsm中
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l --id 1 --label mytoken -y cert -w client.crt --pin 1234

代码加载引擎使用hsm计算

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/engine.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>#define PKCS11_ENGINE_PATH "/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so"
// #define PKCS11_MODULE_PATH "/usr/lib/softhsm/libsofthsm2.so"
#define PKCS11_MODULE_PATH "/home/ubuntu/Documents/openssl_engine/p11_engine_module/build/lib/libmypkcs11.so"#define TOKEN_LABEL "mytoken"
#define PIN "12345"
#define KEY_ID "mytoken"int main() {ENGINE *e = NULL;EVP_PKEY *pkey = NULL;EVP_PKEY_CTX *ctx = NULL;unsigned char *plaintext = (unsigned char *)"Hello, PKCS#11!!!!!";unsigned char ciphertext[256];unsigned char decryptedtext[256];size_t ciphertext_len, decryptedtext_len;// 初始化 OpenSSL 引擎ENGINE_load_dynamic();e = ENGINE_by_id("dynamic");if (!e) {fprintf(stderr, "Failed to load dynamic engine\n");return 1;}if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", PKCS11_ENGINE_PATH, 0) ||!ENGINE_ctrl_cmd_string(e, "ID", "pkcs11", 0) ||!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0) ||!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {fprintf(stderr, "Failed to configure PKCS#11 engine\n");ENGINE_free(e);return 1;}// 设置 PKCS#11 模块if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", PKCS11_MODULE_PATH, 0)) {fprintf(stderr, "Failed to set PKCS#11 module path\n");ENGINE_free(e);return 1;}// 初始化引擎if (!ENGINE_init(e)) {fprintf(stderr, "Failed to initialize PKCS#11 engine\n");ENGINE_free(e);return 1;}// 设置 PINif (!ENGINE_ctrl_cmd_string(e, "PIN", PIN, 0)) {fprintf(stderr, "Failed to set PIN\n");ENGINE_free(e);return 1;}// 显示使用的引擎printf("Using engine: %s\n", ENGINE_get_name(e));// 加载私钥char key_id[256];snprintf(key_id, sizeof(key_id), "pkcs11:token=%s;object=%s", TOKEN_LABEL, KEY_ID);pkey = ENGINE_load_private_key(e, key_id, NULL, NULL);if (!pkey) {fprintf(stderr, "Failed to load private key\n");ENGINE_free(e);return 1;}// 创建 EVP_PKEY_CTX 用于加密ctx = EVP_PKEY_CTX_new(pkey, e);if (!ctx) {fprintf(stderr, "Failed to create EVP_PKEY_CTX for encryption\n");EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 初始化加密操作if (EVP_PKEY_encrypt_init(ctx) <= 0) {fprintf(stderr, "Failed to initialize encryption\n");EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 计算密文长度if (EVP_PKEY_encrypt(ctx, NULL, &ciphertext_len, plaintext, strlen((char *)plaintext)) <= 0) {fprintf(stderr, "Failed to calculate ciphertext length\n");EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 执行加密操作if (EVP_PKEY_encrypt(ctx, ciphertext, &ciphertext_len, plaintext, strlen((char *)plaintext)) <= 0) {fprintf(stderr, "Failed to encrypt data\n");EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 输出加密后的数据printf("Ciphertext (%zu bytes):\n", ciphertext_len);for (size_t i = 0; i < ciphertext_len; i++) {printf("%02x", ciphertext[i]);}printf("\n");// 解密操作// 创建 EVP_PKEY_CTX 用于解密EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_new(pkey, e);if (!dctx) {fprintf(stderr, "Failed to create EVP_PKEY_CTX for decryption\n");EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 初始化解密操作if (EVP_PKEY_decrypt_init(dctx) <= 0) {fprintf(stderr, "Failed to initialize decryption\n");EVP_PKEY_CTX_free(dctx);EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 计算解密后的长度if (EVP_PKEY_decrypt(dctx, NULL, &decryptedtext_len, ciphertext, ciphertext_len) <= 0) {fprintf(stderr, "Failed to calculate decrypted text length\n");EVP_PKEY_CTX_free(dctx);EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 执行解密操作if (EVP_PKEY_decrypt(dctx, decryptedtext, &decryptedtext_len, ciphertext, ciphertext_len) <= 0) {fprintf(stderr, "Failed to decrypt data\n");EVP_PKEY_CTX_free(dctx);EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 1;}// 输出解密后的数据printf("Decrypted text (%zu bytes):\n", decryptedtext_len);printf("%.*s\n", (int)decryptedtext_len, decryptedtext);const EVP_MD *md;ENGINE *used_engine = NULL;// Load the SHA-256 digest methodmd = EVP_get_digestbyname("SHA256");if (!md) {fprintf(stderr, "Error loading SHA256 digest method\n");}// Check which engine is used for SHA-256used_engine = ENGINE_get_digest_engine(EVP_MD_type(md));if (used_engine) {printf("SHA-256 is provided by engine: %s\n", ENGINE_get_id(used_engine));} else {printf("SHA-256 is provided by the default OpenSSL implementation\n");}// 释放资源EVP_PKEY_CTX_free(dctx);EVP_PKEY_CTX_free(ctx);EVP_PKEY_free(pkey);ENGINE_free(e);return 0;
}

pkcs11模块

#ifndef MYPKCS11_H
#define MYPKCS11_H#include <pkcs11.h>/* Define your own structures and global variables here */
typedef struct {CK_SESSION_HANDLE handle;CK_BBOOL active;
} SESSION;/* Function prototypes */
CK_RV C_Initialize(CK_VOID_PTR pInitArgs);
CK_RV C_Finalize(CK_VOID_PTR pReserved);
CK_RV C_GetInfo(CK_INFO_PTR pInfo);
CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession);
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession);
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo);#endif /* MYPKCS11_H */
#include "mypkcs11.h"
#include <stdio.h>
#include <string.h>/* Global variables */
static CK_BBOOL initialized = CK_FALSE;
static SESSION sessions[16] = {0};  /* Example session storage */// Define our PKCS#11 function list
CK_FUNCTION_LIST functionList;/* C_Initialize initializes the Cryptoki library */
CK_RV C_Initialize(CK_VOID_PTR pInitArgs) {printf("[bgk][module] C_Initialize\n");if (initialized) {return CKR_CRYPTOKI_ALREADY_INITIALIZED;}/* Perform initialization */memset(sessions, 0, sizeof(sessions));initialized = CK_TRUE;return CKR_OK;
}/* C_Finalize finalizes the Cryptoki library */
CK_RV C_Finalize(CK_VOID_PTR pReserved) {printf("[bgk][module] C_Finalize\n");if (!initialized) {return CKR_CRYPTOKI_NOT_INITIALIZED;}/* Perform cleanup */initialized = CK_FALSE;return CKR_OK;
}/* C_GetInfo returns general information about the Cryptoki library */
CK_RV C_GetInfo(CK_INFO_PTR pInfo) {printf("[bgk][module] C_GetInfo\n");if (!initialized) {return CKR_CRYPTOKI_NOT_INITIALIZED;}if (pInfo == NULL) {return CKR_ARGUMENTS_BAD;}pInfo->cryptokiVersion.major = 2;pInfo->cryptokiVersion.minor = 40;strcpy((char*)pInfo->manufacturerID, "MyCompany");pInfo->flags = 0;strcpy((char*)pInfo->libraryDescription, "My PKCS#11 Library");pInfo->libraryVersion.major = 1;pInfo->libraryVersion.minor = 0;return CKR_OK;
}/* C_OpenSession opens a session between an application and a token */
CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) {printf("[bgk][module] C_OpenSession\n");if (!initialized) {return CKR_CRYPTOKI_NOT_INITIALIZED;}for (int i = 0; i < 16; i++) {if (!sessions[i].active) {sessions[i].handle = i + 1;sessions[i].active = CK_TRUE;*phSession = sessions[i].handle;return CKR_OK;}}return CKR_SESSION_COUNT;
}/* C_CloseSession closes a session between an application and a token */
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) {printf("[bgk][module] C_CloseSession\n");if (!initialized) {return CKR_CRYPTOKI_NOT_INITIALIZED;}for (int i = 0; i < 16; i++) {if (sessions[i].handle == hSession && sessions[i].active) {sessions[i].active = CK_FALSE;return CKR_OK;}}return CKR_SESSION_HANDLE_INVALID;
}/* C_GetSessionInfo returns information about the session */
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) {printf("[bgk][module] C_GetSessionInfo\n");if (!initialized) {return CKR_CRYPTOKI_NOT_INITIALIZED;}if (pInfo == NULL) {return CKR_ARGUMENTS_BAD;}for (int i = 0; i < 16; i++) {if (sessions[i].handle == hSession && sessions[i].active) {pInfo->slotID = 1;  /* Example slot ID */pInfo->state = CKS_RO_USER_FUNCTIONS;  /* Example state */pInfo->flags = 0;  /* Example flags */pInfo->ulDeviceError = 0;return CKR_OK;}}return CKR_SESSION_HANDLE_INVALID;
}CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) {// Initialize digest operationif (pMechanism->mechanism != CKM_SHA256) {return CKR_MECHANISM_INVALID;}return CKR_OK;
}CK_RV C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) {// Perform SHA-256 digest calculationif (pDigest == NULL) {*pulDigestLen = 32; // SHA-256 produces 32-byte digestsreturn CKR_OK;}if (*pulDigestLen < 32) {return CKR_BUFFER_TOO_SMALL;}// Mock SHA-256 computation (replace with actual SHA-256 implementation)memset(pDigest, 0xAA, 32); // Dummy hash value*pulDigestLen = 32;return CKR_OK;
}/* Module entry point */
CK_FUNCTION_LIST function_list = {{ 2, 40 },  /* version */C_Initialize,C_Finalize,C_GetInfo,NULL, /* C_GetFunctionList */NULL, /* C_GetSlotList */NULL, /* C_GetSlotInfo */NULL, /* C_GetTokenInfo */NULL, /* C_GetMechanismList */NULL, /* C_GetMechanismInfo */NULL, /* C_InitToken */NULL, /* C_InitPIN */NULL, /* C_SetPIN */C_OpenSession,C_CloseSession,NULL, /* C_CloseAllSessions */C_GetSessionInfo,NULL, /* C_GetOperationState */NULL, /* C_SetOperationState */NULL, /* C_Login */NULL, /* C_Logout */NULL, /* C_CreateObject */NULL, /* C_CopyObject */NULL, /* C_DestroyObject */NULL, /* C_GetObjectSize */NULL, /* C_GetAttributeValue */NULL, /* C_SetAttributeValue */NULL, /* C_FindObjectsInit */NULL, /* C_FindObjects */NULL, /* C_FindObjectsFinal */NULL, /* C_EncryptInit */NULL, /* C_Encrypt */NULL, /* C_EncryptUpdate */NULL, /* C_EncryptFinal */NULL, /* C_DecryptInit */NULL, /* C_Decrypt */NULL, /* C_DecryptUpdate */NULL, /* C_DecryptFinal */C_DigestInit, /* C_DigestInit */C_Digest, /* C_Digest */NULL, /* C_DigestUpdate */NULL, /* C_DigestKey */NULL, /* C_DigestFinal */NULL, /* C_SignInit */NULL, /* C_Sign */NULL, /* C_SignUpdate */NULL, /* C_SignFinal */NULL, /* C_SignRecoverInit */NULL, /* C_SignRecover */NULL, /* C_VerifyInit */NULL, /* C_Verify */NULL, /* C_VerifyUpdate */NULL, /* C_VerifyFinal */NULL, /* C_VerifyRecoverInit */NULL, /* C_VerifyRecover */NULL, /* C_DigestEncryptUpdate */NULL, /* C_DecryptDigestUpdate */NULL, /* C_SignEncryptUpdate */NULL, /* C_DecryptVerifyUpdate */NULL, /* C_GenerateKey */NULL, /* C_GenerateKeyPair */NULL, /* C_WrapKey */NULL, /* C_UnwrapKey */NULL, /* C_DeriveKey */NULL, /* C_SeedRandom */NULL, /* C_GenerateRandom */NULL, /* C_GetFunctionStatus */NULL, /* C_CancelFunction */NULL, /* C_WaitForSlotEvent */
};/* Define other PKCS#11 functions here... */
/* Module entry point */
__attribute__((visibility("default")))
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {printf("[bgk][module] C_GetFunctionList\n");if (ppFunctionList == NULL) {return CKR_ARGUMENTS_BAD;}*ppFunctionList = &function_list;return CKR_OK;
}

执行代码

$ sudo ./bin/p11_engine_app 
[sudo] password for ubuntu: 
[bgk][libp11] engine_ctrl
[bgk][libp11][ctrl] ctx_engine_ctrl, cmd = 201
[bgk][libp11][ctrl] ctx_ctrl_set_module 0, ctx->module = (null)
[bgk][libp11][ctrl] ctx_ctrl_set_module 1, ctx->module = (null), modulename = /home/ubuntu/Documents/openssl_engine/p11_engine_module/build/lib/libmypkcs11.so
[bgk][libp11][ctrl] ctx_ctrl_set_module 1, ctx->module = /home/ubuntu/Documents/openssl_engine/p11_engine_module/build/lib/libmypkcs11.so
[bgk][libp11] engine_init
[bgk][libp11] engine_ctrl
[bgk][libp11][ctrl] ctx_engine_ctrl, cmd = 202
Using engine: pkcs11 engine
[bgk][module] C_GetFunctionList
[bgk][module] C_Initialize
[bgk][module] C_GetInfo
Segmentation fault

执行libsofthsm.so模块

$ sudo ./bin/p11_engine_app 
[bgk][libp11] engine_ctrl
[bgk][libp11][ctrl] ctx_engine_ctrl, cmd = 201
[bgk][libp11][ctrl] ctx_ctrl_set_module 0, ctx->module = (null)
[bgk][libp11][ctrl] ctx_ctrl_set_module 1, ctx->module = (null), modulename = /usr/lib/softhsm/libsofthsm2.so
[bgk][libp11][ctrl] ctx_ctrl_set_module 1, ctx->module = /usr/lib/softhsm/libsofthsm2.so
[bgk][libp11] engine_init
[bgk][libp11] engine_ctrl
[bgk][libp11][ctrl] ctx_engine_ctrl, cmd = 202
Using engine: pkcs11 engine
Ciphertext (256 bytes):
b0847d8e84c56d368afaeb83c08f285274daaaac08a4347c0ce282ff9b09a8f4cc57143281d05470477ed25f65fb67ddea840c902a24ebb3d7c9b97eaf5e737b638e0224077664e048482922930bd283f125395b474b09cfc933b21cd287bdeaaf3316625e4cf271fdbec9d686d6354eee6f45aef66a6909a61da34519cda034a739018a6b614b45d0e32d9ad871952c98c8c83358884d110d7eec7444430cf3bb9c57fc69b2a666a306da4860ed39ea3982d9bae7f3c7022d29a50c8d6fb3a3c89fdf56a21ed1d48bc06f063ac8ead56be4b0bb80e8d8a8505c7d15ea199f35ebd8cbcfb9330882238c938de861dba99dffece4bcfab5fd86fe4f2bd421c9d3
Decrypted text (19 bytes):
Hello, PKCS#11!!!!!

Reference:

openssl + engine + pkcs11 双向认证测试_pkcs11-tool-CSDN博客

pkcs11 工具 - Nitrokey Documentation

Liunx Softhsm2的安装和使用-CSDN博客

https://zhuanlan.zhihu.com/p/476163845

OpenSC team · GitHub

相关文章:

ubuntu18.04 + openssl + engine + pkcs11+ softhsm2 双向认证测试

安装环境 openssl 1.1.1 pkcs11-tool &#xff08;由sudo apt-get install opensc 安装&#xff09; libpksc11 &#xff08;需源码安装apt install 只有libp11, 源码安装才有 libpksc11.so -> pkcs11.so&#xff09; softhsm2 &#xff08;由sudo apt-get install softhsm…...

【C++】类和对象2.0

俺来写笔记了&#xff0c;哈哈哈&#xff0c;浅浅介绍类和对象的知识点&#xff01; 1.类的6个默认成员函数 俺们定义一个空类&#xff1a; class N {}; 似乎这个类N里面什么都没有&#xff0c;其实不是这样子的。这个空类有6个默认的成员函数 。 默认成员函数&#xff1a…...

【LLM之KG】KoPA论文阅读笔记

研究背景 知识图谱补全&#xff08;KGC&#xff09;是通过预测知识图谱中缺失的三元组来完善知识图谱的信息。传统方法主要基于嵌入和预训练语言模型&#xff0c;但这些方法往往忽视了知识图谱的结构信息&#xff0c;导致预测效果不佳。 研究目标 本文的研究目标是探索如何将…...

UI设计速成课:理解模态窗口与非模态窗口的区别

我们日常所说的弹性框架是非常笼统的概念。我们习惯性地称之为对话框架、浮动层和提示条。弹性框架可以分为两种:模态弹性框架和非模态弹性框架。产品需要弹性框架来传递信息&#xff0c;用户需要弹性框架来接受反馈&#xff0c;但是没有经过推敲的弹出窗口设计很容易让用户感到…...

【Linux】基础IO_4

文章目录 六、基础I/O4. 动静态库 未完待续 六、基础I/O 4. 动静态库 既然我们能够成功创建静态库了&#xff0c;接下来我们将这个代码打包成动态库&#xff1a; shared: 表示生成共享库格式 fPIC&#xff1a;产生位置无关码(position independent code) 动态库库名规则&…...

C++模板类原理讲解

C模板类原理讲解 C模板是一种强大的编译期工具&#xff0c;它允许我们创建通用的、类型无关的类和函数。模板的主要目的是实现代码的重用和泛型编程。模板类的原理涉及以下几个方面&#xff1a; 模板的定义和实例化模板的类型参数模板特化模板的编译过程模板的优点和缺点 1.…...

scratch编程03-反弹球

这篇文章和上一篇文章《scratch3编程02-使用克隆来编写小游戏》类似&#xff08;已经完全掌握了克隆的可以忽略这篇文章&#xff09;&#xff0c;两篇文章都使用到了克隆来编写一个小游戏&#xff0c;这篇文章与上篇文章不同的是&#xff0c;本体在进行克隆操作时&#xff0c;不…...

postgresql数据库进阶知识

postgresql数据库进阶知识 # 如果表存在就先删除 drop table if exists student; # 创建学生表 # id serial not null 表示id自增 # id integer not null 表示id不自增 create table student (id serial not nullconstraint student_pkprimary…...

关于HTTP劫持,该如何理解、防范和应对

一、引言 HTTP劫持&#xff08;HTTP Hijacking&#xff09;是一种网络安全威胁&#xff0c;它发生在HTTP通信过程中&#xff0c;攻击者试图通过拦截、篡改或监控用户与服务器之间的数据流量&#xff0c;以达到窃取敏感信息或执行恶意操作的目的。今天我们就来详细了解HTTP劫持…...

System.Data.OracleClient.OracleException:“ORA-12571: TNS: 包写入程序失败

System.Data.OracleClient.OracleException:“ORA-12571: TNS: 包写入程序失败 解决方法&#xff1a; 首先%oracle_home%/network/admin下的sqlnet.ora文件&#xff0c;把SQLNET.AUTHENTICATION_SERVICES (NTS)加个 # 注释掉就好了...

saas产品运营案例 | 联盟营销计划如何帮助企业提高销售额?

在当今数字化时代&#xff0c;SaaS&#xff08;软件即服务&#xff09;产品已成为企业提高效率、降低成本的重要工具。然而&#xff0c;面对激烈的市场竞争&#xff0c;如何有效地推广SaaS产品、提高销售额&#xff0c;成为许多企业面临的挑战。林叔将以ClickFunnels为例&#…...

模式分解算法-满足3NF的无损且保持函数依赖的分解算法、满足BCNF的无损连接分解算法

一、引言 1、对指定的关系模式&#xff0c;若范式级别较低&#xff0c;为第一范式或第二范式&#xff0c;由于存在数据冗余或更新异常问题&#xff0c;在实际中一般是不可用的&#xff0c;关系模式的规范化就是将满足低一级的关系模式分解为若干满足高一级范式的关系模式的集合…...

荷兰与法国战平,双方能携手出现?

就在昨天晚上&#xff0c;荷兰队经历了90分钟的鏖战&#xff0c;最终0-0与法国队握手言和。此役&#xff0c;哈维-西蒙斯为荷兰队打进一球&#xff0c;但进球被判无效。从目前的积分形势来看&#xff0c;双方基本上确定携手晋级16强赛。本场比赛&#xff0c;荷兰队后卫内森-阿克…...

数据可视化实验二:回归分析、判别分析与聚类分析

目录 一、使用回归分析方法分析某病毒是否与温度呈线性关系 1.1 代码实现 1.2 线性回归结果 1.3 相关系数验证 二、使用判别分析方法预测某病毒在一定的温度下是否可以存活&#xff0c;分别使用三种判别方法&#xff0c;包括Fish判别、贝叶斯判别、LDA 2.1 数据集展示&am…...

FL论文专栏|设备异构、异步联邦

论文&#xff1a;Asynchronous Federated Optimization&#xff08;12th Annual Workshop on Optimization for Machine Learning&#xff09; 链接 实现Server的异步更新。每次Server广播全局Model的时候附带一个时间戳&#xff0c;Client跑完之后上传将时间戳和Model同时带回…...

【Java毕业设计】基于JavaWeb的礼服租赁系统

文章目录 摘 要Abstract目录1 绪论1.1 课题背景和意义1.2 国内外研究现状1.2.1 国外研究现状 1.3 课题主要内容 2 开发相关技术介绍2.1 Spring Boot框架2.2 Vue框架2.3 MySQL数据库2.4 Redis数据库 3 系统分析3.1 需求分析3.1.1 用户需求分析3.1.2 功能需求分析 3.2 可行性分析…...

代码随想录训练营Day 66|卡码网101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

1.孤岛的总面积 101. 孤岛的总面积 | 代码随想录 代码&#xff1a;(bfs广搜) #include <iostream> #include <vector> #include <queue> using namespace std; int dir[4][2] {1,0,0,1,-1,0,0,-1}; int count; void bfs(vector<vector<int>>&a…...

根据状态转移写状态机-二段式

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 描述 题目描述&#xff1a; 如图所示为两种状态机中的一种&#xff0c;请根据状态转移图写出代码&#xff0c;状态转移线上的0/0等表示的意思是过程中data/flag的值。 要求&#xff1a; 1、 必须使用对应类型的状…...

PyTorch C++扩展用于AMD GPU

PyTorch C Extension on AMD GPU — ROCm Blogs 本文演示了如何使用PyTorch C扩展&#xff0c;并通过示例讨论了它相对于常规PyTorch模块的优势。实验在AMD GPU和ROCm 5.7.0软件上进行。有关支持的GPU和操作系统的更多信息&#xff0c;请参阅系统要求&#xff08;Linux&#xf…...

Hadoop archive

Index of /dist/hadoop/commonhttps://archive.apache.org/dist/hadoop/common/...

R语言——R语言基础

1、用repeat、for、while计算从1-10的所有整数的平方和 2、编写一个函数&#xff0c;给出两个正整数&#xff0c;计算他们的最小公倍数 3、编写一个函数&#xff0c;让用户输入姓名、年龄&#xff0c;得出他明年的年龄。用paste打印出来。例如&#xff1a;"Hi xiaoming …...

VFB电压反馈和CFB电流反馈运算放大器(运放)选择指南

VFB电压反馈和CFB电流反馈运算放大器(运放)选择指南 电流反馈和电压反馈具有不同的应用优势。在很多应用中&#xff0c;CFB和VFB的差异并不明显。当今的许多高速CFB和VFB放大器在性能上不相上下&#xff0c;但各有其优缺点。本指南将考察与这两种拓扑结构相关的重要考虑因素。…...

elasticsearch安装(centos7)

先给出网址 elasticsearch&#xff1a;Download Elasticsearch | Elastic elasticKibana&#xff1a;Download Kibana Free | Get Started Now | Elastic Logstash&#xff1a;Download Logstash Free | Get Started Now | Elastic ik分词&#xff1a;Releases infinilabs/…...

Java高手的30k之路|面试宝典|精通JVM(二)

JVM基本结构 类加载子系统&#xff1a;负责将.class文件加载到内存中&#xff0c;并进行验证、准备、解析和初始化。运行时数据区&#xff1a;包括堆&#xff08;Heap&#xff09;、方法区&#xff08;Method Area&#xff09;、Java栈&#xff08;Java Stack&#xff09;、本…...

JVM专题六:JVM的内存模型

前面我们通过Java是如何编译、JVM的类加载机制、JVM类加载器与双亲委派机制等内容了解到了如何从我们编写的一个.Java 文件最终加载到JVM里的&#xff0c;今天我们就来剖析一下这个Java的‘中介平台’JVM里面到底长成啥样。 JVM的内存区域划分 Java虚拟机&#xff08;JVM&…...

学习java第一百零七天

解释JDBC抽象和DAO模块 使用JDBC抽象和DAO模块&#xff0c;我们可以确保保持数据库代码的整洁和简单&#xff0c;并避免数据库资源关闭而导致的问题。它在多个数据库服务器给出的异常之上提供了一层统一的异常。它还利用Spring的AOP模块为Spring应用程序中的对象提供事务管理服…...

k8s上尝试滚动更新和回滚

滚动更新和回滚 实验目标&#xff1a; 学习如何进行应用的滚动更新和回滚操作。 实验步骤&#xff1a; 创建一个 Deployment。更新 Deployment 的镜像版本&#xff0c;观察滚动更新过程。回滚到之前的版本&#xff0c;验证回滚操作。 今天呢&#xff0c;我们继续来进行我们k…...

GitHub Copilot 登录账号激活,已经在IntellJ IDEA使用

GitHub Copilot 想必大家都是熟悉的&#xff0c;一款AI代码辅助神器&#xff0c;相信对编程界的诸位并不陌生。 今日特此分享一项便捷的工具&#xff0c;助您轻松激活GitHub Copilot&#xff0c;尽享智能编码之便利&#xff01; GitHub Copilot 是由 GitHub 和 OpenAI 共同开…...

进程知识点(二)

文章目录 一、进程关系&#xff1f;二、孤儿态进程(Orphan)定义危害处理 三、僵尸进程定义处理 四、守护进程(Daemon )定义作用 总结 一、进程关系&#xff1f; 亲缘关系&#xff1a;亲缘关系主要体现于父子进程&#xff0c;子进程父进程创建&#xff0c;代码继承于父进程&…...

【线性代数】【一】1.6 矩阵的可逆性与线性方程组的解

文章目录 前言一、求解逆矩阵二、线性方程组的解的存在性总结 前言 前文我们引入了逆矩阵的概念&#xff0c;紧接着我们就需要讨论一个矩阵逆的存在性以及如何求解这个逆矩阵。最后再回归上最初的线性方程组的解&#xff0c;分析其中的联系。 一、求解逆矩阵 我们先回想一下在…...

基于大型语言模型的全双工语音对话方案

摘要解读 我们提出了一种能够以全双工方式运行的生成性对话系统&#xff0c;实现了无缝互动。该系统基于一个精心调整的大型语言模型&#xff08;LLM&#xff09;&#xff0c;使其能够感知模块、运动功能模块以及一个具有两种状态&#xff08;称为神经有限状态机&#xff0c;n…...

Spring Boot集成Minio插件快速入门

1 Minio介绍 MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容亚马逊 S3 云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据&#xff0c;例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等&#xff0c;而一个对象文件可以是任意大小&…...

【C++新特性】右值引用

右值和右值的区别 C11 中右值可以分为两种&#xff1a;一个是将亡值&#xff08; xvalue, expiring value&#xff09;&#xff0c;另一个则是纯右值&#xff08; prvalue, PureRvalue&#xff09;&#xff1a; 纯右值&#xff1a;非引用返回的临时变量、运算表达式产生的临时变…...

信息安全基础知识(完整)

信息安全基础知识 安全策略表达模型是一种对安全需求与安全策略的抽象概念表达&#xff0c;一般分为自主访问控制模型&#xff08;HRU&#xff09;和强制访问控制模型&#xff08;BLP、Biba&#xff09;IDS基本原理是通过分析网络行为&#xff08;访问方式、访问量、与历史访问…...

QT

#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) ,Gcancle(new QPushButton("取消",this)) ,EmmEdit(new QLineEdit(this)) { ui->setupUi(this);…...

双例集合(三)——双例集合的实现类之TreeMap容器类

Map接口有两个实现类&#xff0c;一个是HashMap容器类&#xff0c;另一个是TreeMap容器类。TreeMap容器类的使用在API上于HashMap容器类没有太大的区别。它们的区别主要体现在两个方面&#xff0c;一个是底层实现方式上&#xff0c;HashMap是基于Hash算法来实现的吗&#xff0c…...

[SAP ABAP] 运算符

1.算数运算符 算术运算符描述加法-减法*乘法/除法MOD取余 示例1 输出结果: 输出结果: 2.比较运算符 比较运算符描述示例 等于 A B A EQ B <> 不等于 A <> B A NE B >大于 A > B A GT B <小于 A < B A LT B >大于或等于 A > B A GE B <小…...

MSPM0G3507 ——GPIO例程讲解2——simultaneous_interrupts

主函数&#xff1a; #include "ti_msp_dl_config.h"int main(void) {SYSCFG_DL_init();/* Enable Interrupt for both GPIOA and GPIOB ports */NVIC_EnableIRQ(GPIO_SWITCHES_GPIOA_INT_IRQN); //启用SWITCHES——A的中断 NVIC_EnableIRQ(GPIO_S…...

某程序员:30岁了,老婆管钱,背着我买了50万股票,亏了20w,强制她清仓后又买了36万

“辛辛苦苦攒了几年钱&#xff0c;本想买房买车&#xff0c;结果全被老婆炒股亏掉了&#xff01;” 近日&#xff0c;一位30岁的程序员大哥在网上吐苦水&#xff0c;引发了网友们的热议。 这位程序员大哥和妻子结婚后&#xff0c;一直秉持着“男主外&#xff0c;女主内”的传统…...

Docker常见面试题整理

文章目录 1. Docker 是什么&#xff1f;它解决了什么问题&#xff1f;2. Docker 和虚拟机&#xff08;VM&#xff09;的区别是什么&#xff1f;3、Docker三个核心概念4、如何构建一个 Docker 镜像&#xff1f;5、如何将一个 Docker 容器连接到多个网络&#xff1f;6、Docker Co…...

35 - 最后一个能进入巴士的人(高频 SQL 50 题基础版)

35 - 最后一个能进入巴士的人 -- sum(weight) over(order by turn) as total,根据turn升序&#xff0c;再求前面数的和 selectperson_name from(selectperson_name,sum(weight) over(order by turn) as totalfromQueue) new_Queue wheretotal<1000 order by total desc lim…...

WPF将dll文件嵌入到exe文件中

WPF将dll文件嵌入到exe文件中 第一步&#xff1a;打开.csproj文件&#xff0c;在Import节点后添加如下代码&#xff1a; <Target Name"AfterResolveReferences"><ItemGroup><EmbeddedResource Include"(ReferenceCopyLocalPaths)" Condit…...

2024年AI+游戏赛道的公司和工具归类总结

随着人工智能技术的飞速发展,AI在游戏开发领域的应用越来越广泛。以下是对2024年AI+游戏赛道的公司和工具的归类总结,涵盖了从角色和场景设计到音频制作,再到动作捕捉和动画生成等多个方面。 2D与3D创作 2D创作工具:专注于角色和场景的平面设计,提供AI辅助的图案生成和风…...

svm和决策树基本知识以及模型评价以及模型保存

svm和决策树基本知识以及模型评价以及模型保存 文章目录 一、SVM1.1&#xff0c;常用属性函数 二、决策树2.1&#xff0c;常用属性函数2.2&#xff0c;决策树可视化2.3&#xff0c;决策树解释 3&#xff0c;模型评价3.1&#xff0c;方面一&#xff08;评价指标&#xff09;3.2&…...

C++ 79 之 自己写异常类

#include <iostream> #include <string> using namespace std;class MyOutOfRange : public exception{ // 选中exception右键 转到定义 复制一份 virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW 进行函数重写 public: string m_msg;M…...

如何搭建一个成功的短剧制作平台

要搭建一个成功的短剧制作平台&#xff0c;需要考虑多个方面&#xff0c;包括目标定位、技术选择、内容管理、用户体验等。 1、明确目标和定位&#xff1a; 确定你的目标受众是谁&#xff0c;他们的年龄、兴趣、消费习惯等。 明确短剧制作平台的主要定位&#xff0c;是提供原创…...

kotlin类

一、定义 1、kotlin中使用关键字class 声明类,如果一个类没有类体&#xff0c;也可以省略花括号&#xff0c; 默认为public 类型的&#xff1a; // 这段代码定义了一个公开的、不可被继承的Test类 class Test{} // 没有类体&#xff0c;可以省略花括号 class Test 底层代码&…...

android | studio的UI布局和代码调试 | UI调试 (用于找到项目源码)

网上找到一个项目&#xff0c;想快速的搞懂是怎么实现的&#xff0c;搞了半天发现原来android都升级到Jetpack Compose了&#xff0c;然后去找源码挺不容易的&#xff0c;摸索中发现了这个调试的方法&#xff0c;还可以。 https://developer.android.com/studio/debug/layout-i…...

LangChain实战技巧之六:一起玩转config(上篇)——ConfigurableField

简介 Config 包含两大类内容&#xff0c; ConfigurableField 可配置的字段 configurable_alternatives 可配置的替代方案 分别使用两篇文章来给大家介绍&#xff0c;本篇先介绍ConfigurableField 常规介绍 一些资料会这样介绍 model_spec model.configurable_fields(model…...

扫码称重上位机

目录 一 设计原型 二 后台代码 一 设计原型 模拟工具: 二 后台代码 主程序&#xff1a; using System.IO.Ports; using System.Net; using System.Net.Sockets; using System.Text;namespace 扫码称重上位机 {public partial class Form1 : Form{public Form1(){Initialize…...