openssl.build

sudo apt update

sudo apt install -y build-essential

下载

wget https://www.openssl.org/source/openssl-3.3.0.tar.gz

解压

tar -zxvf openssl-3.3.0.tar.gz

cd openssl-3.3.0

OUT=/home/ubuntu22/ssl/openssl-3.3.0/output

./config --prefix=$OUT/openssl33 \

--openssldir=$OUT/openssl33/etc \

-Wl,-rpath=$OUT/openssl33/lib64

make -j$(nproc)

make install

////////////////////demo1

openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes

openssl s_server -accept 4433 -tls1_2 -cert server.crt -key server.key -www

curl -v --insecure https://localhost:4433

////////////////////demo2

curl -v --insecure https://localhost:4433

/////////////////// openssl1.2 demo

openssl s_client -connect www.baidu.com:443 -tls1_2 -servername www.baidu.com -quiet // 打印私钥

////////////

OUT=/home/ubuntu22/ssl/openssl-3.3.0/output

./config --prefix=$OUT/openssl33 \

--openssldir=$OUT/openssl33/etc \

-Wl,-rpath=$OUT/openssl33/lib64 \

-g -O0

make -j4

make install

//////////////////////////

gdb --args output/openssl33/bin/openssl s_client -connect www.baidu.com:443 -tls1_2 -servername www.baidu.com -quiet

b main

r

//////////////////////////

ssl/statem/statem_clnt.c

static int tls_construct_cke_ecdhe(SSL_CONNECTION *s, WPACKET *pkt)

{

unsigned char *encodedPoint = NULL;

size_t encoded_pt_len = 0;

EVP_PKEY *ckey = NULL, *skey = NULL;

int ret = 0;

skey = s->s3.peer_tmp;

if (skey == NULL) {

SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);

return 0;

}

ckey = ssl_generate_pkey(s, skey);

if (ckey == NULL) {

SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);

goto err;

}

//====================== 打印 P-256 私钥 ======================

{

BIGNUM *priv_bn = NULL;

unsigned char priv_bytes32 = {0};

EVP_PKEY_get_bn_param(ckey, OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn);

if (priv_bn != NULL) {

BN_bn2binpad(priv_bn, priv_bytes, 32);

printf("\n+ TLS 1.2 CLIENT P-256 PRIVATE KEY = ");

for (int i = 0; i < 32; i++)

printf("%02x", priv_bytesi);

printf("\n");

BN_free(priv_bn);

}

}

//===========================================================

// ====================== 打印 客户端 P-256 公钥(发送给server) ======================

encoded_pt_len = EVP_PKEY_get1_encoded_public_key(ckey, &encodedPoint);

if (encoded_pt_len > 0 && encodedPoint != NULL) {

printf("+ TLS 1.2 CLIENT P-256 PUBLIC KEY (send to server) = ");

for (int i = 0; i < encoded_pt_len; i++)

printf("%02x", encodedPointi);

printf("\n");

}

// ==================================================================================

ssl/statem/statem_clnt.c

//publick key

static int tls_process_ske_ecdhe(SSL_CONNECTION *s, PACKET *pkt, EVP_PKEY **pkey)

{

if (EVP_PKEY_set1_encoded_public_key(s->s3.peer_tmp,

PACKET_data(&encoded_pt),

PACKET_remaining(&encoded_pt)) <= 0) {

SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);

return 0;

}

// ====================== 打印 SERVER P-256 公钥 ======================

{

const unsigned char *pub_key_bytes = PACKET_data(&encoded_pt);

size_t pub_key_len = PACKET_remaining(&encoded_pt);

printf("\n+ TLS Server Public Key (P-256) = ");

for (size_t i = 0; i < pub_key_len; i++)

printf("%02x", pub_key_bytesi);

printf("\n");

}

///////////////共享密钥

providers/implementations/kdfs/tls1_prf.c

static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,

const unsigned char *sec, size_t slen,

const unsigned char *seed, size_t seed_len,

unsigned char *out, size_t olen)

{

/* ====================== 打印 1:输入共享密钥 ====================== */

printf("\nTLS PRF Input Secret (共享密钥) - Length: %zu bytes\n", slen);

for (size_t i = 0; i < slen; i++) {

printf("%02x ", seci);

if ((i + 1) % 16 == 0) printf("\n");

}

printf("\n");

output/openssl33/bin/openssl s_client -connect www.baidu.com:443 -tls1_2 -servername www.baidu.com -quiet

+ TLS Server Public Key (P-256) = 04acd64c5f95631566d0f45abb0dfee729336d33b68903189652533bb1eeb2d58378c16fe04daccf0870e89c4beee97d94520da3ebfb579e2992433fe741484700

+ TLS 1.2 CLIENT P-256 PRIVATE KEY = 33c6dac5f402f14921eb7a559172efacb61e8c80cdddc305f8879c16ec68c904

+ TLS 1.2 CLIENT P-256 PUBLIC KEY (send to server) = 04c037222c28c78d19a2780a6102105d073a7fa3dc413d3f2b2675a67bc0f4aa5510b705524438841f86a160833fa336b8944e34e962e72ed4ff9ffb00e3d5abc7

TLS PRF Input Secret (共享密钥) - Length: 32 bytes

43 ef 63 0d e7 3e 2f eb 7f 5b cc d3 c7 7a 00 8c

3b 1b fa ce 93 c7 6a 3b b0 2a ad 1e 3e 07 7c f7

///////////////////////////////////////////

验证共享密钥的计算

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <openssl/evp.h>

#include <openssl/ec.h>

#include <openssl/err.h>

// 工具函数:十六进制字符串 → 二进制数组

static int hex2bin(const char *hex, unsigned char *bin, size_t *bin_len) {

size_t hex_len = strlen(hex);

if (hex_len % 2 != 0) return 0;

*bin_len = hex_len / 2;

for (size_t i = 0; i < *bin_len; i++) {

sscanf(hex + i*2, "%02hhx", &bini);

}

return 1;

}

int main() {

// ========== 你提供的真实密钥 ==========

const char *server_pub_hex =

"04acd64c5f95631566d0f45abb0dfee729336d33b68903189652533bb1eeb2d58378c16fe04daccf0870e89c4beee97d94520da3ebfb579e2992433fe741484700";

const char *client_pri_hex =

"33c6dac5f402f14921eb7a559172efacb61e8c80cdddc305f8879c16ec68c904";

// 转换为二进制

unsigned char server_pub128;

unsigned char client_pri64;

size_t server_pub_len, client_pri_len;

hex2bin(server_pub_hex, server_pub, &server_pub_len);

hex2bin(client_pri_hex, client_pri, &client_pri_len);

// ========== 1. 加载服务端原始 EC 公钥 (P-256) ==========

EC_KEY *server_ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

const unsigned char *p = server_pub;

o2i_ECPublicKey(&server_ec, &p, server_pub_len);

EVP_PKEY *server_pkey = EVP_PKEY_new();

EVP_PKEY_set1_EC_KEY(server_pkey, server_ec);

// ========== 2. 加载客户端私钥 ==========

EC_KEY *client_ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

BIGNUM *priv_bn = BN_bin2bn(client_pri, client_pri_len, NULL);

EC_KEY_set_private_key(client_ec, priv_bn);

EVP_PKEY *client_pkey = EVP_PKEY_new();

EVP_PKEY_set1_EC_KEY(client_pkey, client_ec);

// ========== 3. ECDH 计算共享密钥 ==========

EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(client_pkey, NULL);

EVP_PKEY_derive_init(ctx);

EVP_PKEY_derive_set_peer(ctx, server_pkey);

size_t secret_len = 0;

EVP_PKEY_derive(ctx, NULL, &secret_len);

unsigned char *secret = malloc(secret_len);

EVP_PKEY_derive(ctx, secret, &secret_len);

// ========== 输出结果 ==========

printf("+ ECDH 共享密钥 (TLS 1.2 Premaster Secret):\n");

for (size_t i = 0; i < secret_len; i++)

printf("%02x", secreti);

printf("\n");

// 清理

free(secret);

BN_free(priv_bn);

EVP_PKEY_free(client_pkey);

EVP_PKEY_free(server_pkey);

EC_KEY_free(client_ec);

EC_KEY_free(server_ec);

EVP_PKEY_CTX_free(ctx);

return 0;

}

////////

ubuntu22@NYX:~/ssl/openssl-3.3.0/demo1$ ./a.out

+ ECDH 共享密钥 (TLS 1.2 Premaster Secret):

43ef630de73e2feb7f5bccd3c77a008c3b1bface93c76a3bb02aad1e3e077cf7

TLSv1.2的这一步交换各自的public key之后就可以生成共享密钥.

相关推荐
徐小黑ACG1 小时前
nginx配置文件
linux·服务器·nginx
新时代牛马2 小时前
Linux VFS 完整篇:从path_openat、dentry/inode 到page cache 与挂载排障
linux·运维·服务器
java_logo2 小时前
Docker 部署 Rocky Linux:轻松搭建 RHEL 兼容企业级基础镜像平台
linux·docker·容器·rocky linux·基础镜像·轩辕镜像·rhel 兼容
拂拉氏2 小时前
【知识讲解】 Linux虚拟地址空间认识
linux·虚拟地址空间
新时代牛马4 小时前
Linux 驱动中断与定时完整篇:从 request_threaded_irq 到hrtimer 选型与排障
linux·运维·服务器
分支预测失败6 小时前
RISC-V 核间中断 IPI 实战:从 MSIP 寄存器到 IMSIC 消息投递
linux·后端
GeW7 小时前
RHCE考试避坑指南"90%考生容易忽略的细节
linux
键盘会跳舞8 小时前
【C++多线程】死锁诊断工具实战:从 Windows 到 Linux 的全链路排查
linux·c++·windows·死锁
拂拉氏9 小时前
【知识讲解】 Linux环境变量的认识与使用
linux·环境变量
zhangrelay9 小时前
答疑-是否软件源问题都必须更换为国内呢-
linux·笔记·学习·ubuntu·ros2