- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想使用以下代码发送此消息“Hello world!\n Bye world!”。此代码以 2 条 SSL 记录发送消息,但我需要以 1 条 SSL 记录发送。
我读了一些关于 base64 的文章 here和 here但我不知道如何在我的代码中使用它们!谁能帮我解决我的问题。
问题:我想发送消息的一部分,而不是用“\n”分隔的两部分!
更多说明: 我使用 OpenSSL s_client 连接它,我强制它使用 TLSv1 并使用 wireshark 嗅探网络。实际上这段代码是简化了一个更大的项目作为数据库代理。在主项目中,我们需要向不受我们控制的服务器发送一条消息,它只能处理 1 条 SSL 记录。
我的 OpenSSL 命令:
s_client -connect 127.0.0.1:9999 -tls1
消息的 Wireshark 结果:
17 03 01 00 24 db f3 59 37 98 78 3b b6 06 b0 c1 66 0c 78 04 4d 50 60 54 19 37 fe
77 65 27 7f 4e e8 4e 9a d7 94 66 3f 0d 03 17 03 01 00 34 83 a8 39 b3 3e 9a 35 7b
a2 64 07 35 9b c5 d7 d0 c9 03 3c 43 ac d8 1c ad d5 0f 55 34 10 6c 99 3e 57 b1 51
d4 a5 36 6a 8e 23 08 e0 2d 33 c1 53 63 4e d2 bd bd
我的模拟代码:
#include <cstdlib>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <unistd.h>
using namespace std;
static void ssl_set_sys_error(int ssl_error)
{
int error = 0;
switch (ssl_error) {
case SSL_ERROR_ZERO_RETURN:
error = 0;
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
#ifdef SSL_ERROR_WANT_CONNECT
case SSL_ERROR_WANT_CONNECT:
#endif
#ifdef SSL_ERROR_WANT_ACCEPT
case SSL_ERROR_WANT_ACCEPT:
#endif
error = 1;
break;
case SSL_ERROR_SSL:
/* Protocol error. */
#ifdef EPROTO
error = EPROTO;
#else
error = SOCKET_ECONNRESET;
#endif
break;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_NONE:
default:
break;
};
}
int main()
{
/*
------------------ START Initialize Server ------------------
*/
int serverfd, clientfd;
struct sockaddr_in vir_serv_addr, cli_addr;
serverfd = socket(AF_INET, SOCK_STREAM, 0);
bzero((char *) &vir_serv_addr, sizeof (vir_serv_addr));
vir_serv_addr.sin_family = AF_INET;
vir_serv_addr.sin_addr.s_addr = INADDR_ANY;
vir_serv_addr.sin_port = htons(9999);
bind(serverfd, (struct sockaddr *) &vir_serv_addr, sizeof (vir_serv_addr));
listen(serverfd, 5);
socklen_t client = sizeof (cli_addr);
clientfd = accept(serverfd, (struct sockaddr*) &cli_addr, (socklen_t*) & client);
/*
------------------- END Initialize Server -------------------
*/
/*
------------------ START SSL ------------------
*/
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
SSL_CTX* context = SSL_CTX_new(TLS_server_method());
SSL_CTX_set_ecdh_auto(context, 1);
SSL_CTX_use_certificate_file(context, "server-cert.pem", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(context, "server-key.pem", SSL_FILETYPE_PEM);
SSL_CTX_load_verify_locations(context, "ca-cert.pem", NULL);
SSL_CTX_check_private_key(context);
SSL* ssl = SSL_new(context);
BIO *rbio = BIO_new(BIO_s_mem());
BIO *wbio = BIO_new(BIO_s_mem());
SSL_set_bio(ssl, rbio, wbio);
char* buffer[8192];
int n;
SSL_set_accept_state(ssl);
while (!SSL_is_init_finished(ssl)) {
n = recv(clientfd, buffer, 8192, 0);
n = BIO_write(rbio, buffer, n);
int r = SSL_do_handshake(ssl);
n = BIO_read(wbio, buffer, 8192);
n = send(clientfd, buffer, n, 0);
bzero(buffer, 8192);
BIO_flush(rbio);
BIO_flush(wbio);
if (r != 1) {
ERR_print_errors_fp(stderr);
int err_SSL_get_error = SSL_get_error(ssl, r);
switch (err_SSL_get_error) {
case SSL_ERROR_NONE:
case SSL_ERROR_SSL:
return 0;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
continue;
default:
return 0;
}
}
}
string message = "Hello world! \n Bye world!";
n = SSL_write(ssl, message.c_str(), message.size());
n = BIO_read(wbio, buffer, 8192);
n = send(clientfd, buffer, n, 0);
/*
------------------- END SSL -------------------
*/
}
最佳答案
确实是个很有趣的问题。这里发生的是单个 SSL_write
导致两个应用程序数据 SSL 帧(类型 0x17)。而且这仅发生在 TLS 1.0 中,即不会发生在 TLS 1.1 或 TLS 1.2 中。
虽然它可能看起来像一个错误,但实际上是为了对抗 BEAST 而设计的。以及使用 SSL 3.0 和 TLS 1.0 中与 CBC 密码相关的协议(protocol)漏洞的类似攻击。这种保护是通过插入空数据片段来实现的,这会导致第一个 SSL 帧实际上不包含实际数据。像这种 0/n 拆分这样的类似保护以 1/n-1 拆分的形式存在于其他 TLS 堆栈中。
由于此攻击不影响 TLS 1.1 和 TLS 1.2,因此未在此处启用保护。有关此保护如何工作的更多详细信息,请参阅 Why does Firefox split HTTPS request?和 Is BEAST really fixed in all modern browsers? .
但是由于您背负着一些无法处理这种行为的错误应用程序,您需要找到一种方法来禁用它。这可以通过选择一个不是 CBC 的密码(但 TLS 1.0 中没有好的密码)或简单地禁用保护来完成:
SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
除了 SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
,您还可以使用 SSL_OP_ALL
,其中包括针对有问题的 TLS 实现的所有解决方法,包括这个。
关于c++ - 仅 OpenSSL BIO : single SSL_write broken in two SSL records with TLS 1. 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39328143/
是否可以使用 OpenSSL 或其他工具通过 TLS 建立 TLS 连接? 如果可能,每个级别的证书是否需要不同? 最佳答案 这在理论上应该工作得很好,但我不能确定 OpenSSL 或其他东西是否会轻
在我的 java 代码中,我正在使用命令创建 SSL 上下文的一个实例 SSLContext ctx = SSLContext.getInstance("TLS"); 但是在我的 tomcat 服务器
在我的 java 代码中,我正在使用命令创建一个 SSL 上下文实例 SSLContext ctx = SSLContext.getInstance("TLS"); 但在我的 tomcat 服务器中,
范围:这是一个具有一个 channel 的网络,该 channel 由 3 个组织组成,每个组织 1 个 anchor 节点,每个组织 1 个 CA 和每个组织 1 个 MSP。 我在我的 Hyper
无法找到用于在 iis 上启用/禁用 tls 的特定设置。启用/禁用 ssl 是否与启用/禁用 tls 相同? 我浏览了一些博客,发现 SSL 是 TLS 的前身,旧版本的 SSL 已被弃用。但我无法
最近,我一直在为基于物联网的项目评估不同的 API 网关 (API GW) 选项。这样做的目的是找到一个足够好的解决方案来执行设备和 API GW 的相互 TLS (mTLS) 身份验证。 我尝试过的
几个月来,我的 Web 应用程序在不同版本的 IE/Firefox/Chrome 上运行良好。我的应用程序在 IIS 10.0 上运行。当我从 Windows 7 框 (IE 11.0.***) 中点
我有一个在 Java 7 上运行的 HTTPS 网络服务。我需要进行更改,以便此服务仅接受 TLS1.2 连接并拒绝 SSL3、TLS1.0 和 TLS1.1。 我添加了以下 Java 参数,使 TL
我在资源管理器不显示网站时遇到问题:“无法显示此页面。在高级设置中打开 TLS 1.0、TLS 1.1 和 TLS 1.2”。 我在 chrome 中调试了证书并说“连接是使用 aes_128_cbc
我正在与 5 个订购者、1 个组织和 2 个同行建立我的网络。还有 1 个 cli 和 1 个 ca。 我从 1 个排序者扩展到 5 个实现 Raft 的排序者。这就是为什么我想扩展我的网络并对多个对
当k8s集群开启了TLS认证后,每个节点的kubelet组件都要使用由kube-apiserver的CA签发的有效证书才能与kube-apiserver通信;当节点非常多的时候,为每个节点都单独签署证
我正在尝试使用 pjsip 安装中的 pjsua 程序在两个虚拟机之间进行安全调用。我通过以下方式在每个节点上启动程序: pjsua-x86_64-unknown-linux-gnu --use-tl
我开发的软件应用程序使用 gRPC 在客户端和服务器之间建立双向流。 我只在 java 中寻找类似于这张票的答案的东西:How to enable server side SSL for gRPC?
我正在尝试调试与 TLS 相关的问题。TLS 在两个应用程序客户端 A 和服务器 B 之间设置。A 和 B 都交换了证书,我已经验证证书具有正确的扩展名,并且还通过其根 CA 成功验证。叶证书的根 C
“Java 1.7 TLS 1.1 服务器”和“Java 1.8 客户端”之间的 SSL/TLS 握手在我的环境中失败,服务器端出现以下异常: java.security.NoSuchAlgorith
我正在尝试了解 Docker ,但我不断收到神秘的(对我而言)错误消息。 可能最简单的例子是尝试打印我安装的 Docker 版本: $ sudo docker version Client versi
这是我第一次使用 Amazon Lighsail、Wordpress Multisite、Bitnami甚至使用 Let's Encrypt;现在似乎一切正常,除了我的虚拟主机文件中的 SSL 指令。
我有一个 MariaDB "M"。在同一台机器上有一个应用程序“A”,它可以访问它。在不同的服务器上,另一个应用程序“B”也在访问它。 现在我想在 MariaDB 上启用 TLS 以保护连接 B ->
我正在寻找通过代理连接到一些 HTTPS/TLS 站点,其中到代理本身的连接也是通过 HTTPS/TLS 建立的,来自一个高度依赖请求的 python 应用程序。 urllib3(因此 request
现在我正在努力改变 EMQtt 和 Erlang MQTT 代理,以便我可以使用预共享 key 而不是非对称方法执行 TLS 握手。 到目前为止,我几乎遍历了源代码中的每个文件,但找不到任何加密函数。
我是一名优秀的程序员,十分优秀!