using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using RawHttpListener.TLS;
namespace RawHttpListener
{
#region HTTPParser
public interface IHTTPClientHandler
{
Task HTTPClientConnected(HttpContext ctx);
}
public class HttpContext
{
public HttpRequest Request { get; set; }
public HttpResponse Response { get; set; }
public HttpContext(HttpRequest request, HttpResponse response)
{
Request = request;
Response = response;
}
}
public class HttpRequest
{
public string HttpMethod { get; set; }
public string Url { get; set; }
public string UserHostName { get; set; }
public string UserAgent { get; set; }
public string Body { get; set; }
public HttpRequest(string httpMethod, string url, string userHostName, string userAgent)
{
HttpMethod = httpMethod;
Url = url;
UserHostName = userHostName;
UserAgent = userAgent;
}
}
public class HttpResponse
{
public string ContentType { get; set; }
public Encoding ContentEncoding { get; set; }
public long ContentLength64 { get; set; }
public Stream OutputStream { get; set; }
public HttpResponse(Stream outputStream)
{
OutputStream = outputStream;
}
}
public class HTTPParser : Stream
{
private readonly IHTTPClientHandler _clientHandler;
private readonly Stream _baseStream;
private readonly MemoryStream _memoryStream = new MemoryStream();
private const int BufferSize = 4096;
private readonly byte[] _buffer = new byte[BufferSize];
public HTTPParser(Stream baseStream, IHTTPClientHandler clientHandler)
{
_baseStream = baseStream;
_clientHandler = clientHandler;
}
public async Task HandleClientConnected()
{
int bytesRead;
// Read the incoming data until the connection is closed
while ((bytesRead = await _baseStream.ReadAsync(_buffer, 0, _buffer.Length)) > 0)
{
await _memoryStream.WriteAsync(_buffer, 0, bytesRead);
// Check for the end of the request (empty line means headers end)
if (bytesRead < BufferSize) break;
}
// Convert the raw request to a string
string rawRequest = Encoding.UTF8.GetString(_memoryStream.ToArray());
Console.WriteLine("Raw HTTP Request:");
Console.WriteLine(rawRequest);
// Handle the HTTP request
await HandleHttpRequest(rawRequest);
}
private async Task HandleHttpRequest(string rawRequest)
{
// Fill the MyOwnHttpListenerContext object and call the HTTPClientConnected method
var lines = rawRequest.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
if (lines.Length == 0) return;
// Parse the request line (first line)
var requestLine = lines[0].Split(' ');
if (requestLine.Length < 3) return; // Invalid request
string method = requestLine[0]; // e.g., GET, POST
string url = requestLine[1]; // e.g., /path
string httpVersion = requestLine[2]; // e.g., HTTP/1.1
// Extract headers
string userHostName = string.Empty;
string userAgent = string.Empty;
for (int i = 1; i < lines.Length; i++) // Skip the request line
{
if (lines[i].StartsWith("Host:"))
{
userHostName = lines[i].Substring(6).Trim(); // Skip "Host: "
}
else if (lines[i].StartsWith("User-Agent:"))
{
userAgent = lines[i].Substring(12).Trim(); // Skip "User-Agent: "
}
}
// Create the request and response objects
var request = new HttpRequest(method, url, userHostName, userAgent);
var response = new HttpResponse(_baseStream);
var ctx = new HttpContext(request, response);
await _clientHandler.HTTPClientConnected(ctx);
}
// Implementing abstract members of Stream class
public override bool CanRead => _baseStream.CanRead;
public override bool CanSeek => _baseStream.CanSeek;
public override bool CanWrite => _baseStream.CanWrite;
public override long Length => _baseStream.Length;
public override long Position { get => _baseStream.Position; set => _baseStream.Position = value; }
public override void Flush() => _baseStream.Flush();
public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);
public override void SetLength(long value) => _baseStream.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count);
}
#endregion
#region RawHttpServer
public class RawHttpServer : IHTTPClientHandler
{
public string ipAddress = string.Empty; // Change to your desired IP address
public int port; // Use a non-privileged port for testing
bool isHTTPS;
public RawHttpServer()
{
this.ipAddress = "172.0.0.1";
this.port = 80;
this.isHTTPS = false;
}
public RawHttpServer(IPAddress ip, int port, bool isHTTPS)
{
this.ipAddress = ip.ToString();
this.port = port;
this.isHTTPS = isHTTPS;
}
public void Start()
{
TcpListener tcpListener = new TcpListener(IPAddress.Parse(ipAddress), port);
tcpListener.Start();
Console.WriteLine($"Listening for connections on {ipAddress}:{port}");
while (true)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
Task.Run(() => HandleClient(tcpClient));
}
}
private async Task HandleClient(TcpClient tcpClient)
{
using (NetworkStream stream = tcpClient.GetStream())
{
HTTPParser httpParser;
if (!this.isHTTPS)
{
//Reading RAW request, for debugging purposes
//byte[] buffer = new byte[4096]; // Adjust the buffer size as necessary
//int bytesRead;
//while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
//{
// // Handle the data
// string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
// Console.WriteLine("Data: " + data);
//}
httpParser = new HTTPParser(stream, this);
await httpParser.HandleClientConnected(); // Handle the client connection
}
else
{
// Wrap the inner stream with TlsStream
//using (var tlsStream = new TlsStream(stream, "cert.pem", "key.pem", new[] { "http/1.1" }))
using (var tlsStream = new TlsStream(stream, "cert.pem", "key.pem", new[] { "http/1.1" }))
{
// Perform the TLS handshake
await tlsStream.DoHandshakeAsync();
// Read decrypted data
byte[] buffer = new byte[4096]; // Adjust the buffer size as necessary
int bytesRead;
while ((bytesRead = await tlsStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
// Handle the decrypted data
string decryptedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine("Decrypted Data: " + decryptedData);
}
// Create a new HTTP parser using the TlsStream for the connection
httpParser = new HTTPParser(tlsStream, this);
await httpParser.HandleClientConnected(); // Handle the client connection
}
}
}
tcpClient.Close();
}
public async Task HTTPClientConnected(HttpContext ctx)
{
// Print out some info about the request
Console.WriteLine($"URL: {ctx.Request.Url}");
Console.WriteLine($"Method: {ctx.Request.HttpMethod}");
Console.WriteLine($"User Host Name: {ctx.Request.UserHostName}");
Console.WriteLine($"User Agent: {ctx.Request.UserAgent}");
Console.WriteLine();
if (ctx.Request.HttpMethod == "POST")
{
Console.WriteLine("POST BODY:");
// Here you can handle the POST body if needed
}
// Write the response info
byte[] data = Encoding.UTF8.GetBytes("Hello World");
ctx.Response.ContentType = "text/html";
ctx.Response.ContentEncoding = Encoding.UTF8;
ctx.Response.ContentLength64 = data.Length;
// Write out to the response stream (asynchronously), then close it
await ctx.Response.OutputStream.WriteAsync(data, 0, data.Length);
ctx.Response.OutputStream.Close(); // Close the output stream
}
}
#endregion
//Our main class here
class Program
{
static void Main(string[] args)
{
bool isHTTPS = true;
RawHttpServer server = new RawHttpServer(IPAddress.Parse("192.168.88.12"), 443, isHTTPS);
server.Start();
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace RawHttpListener.TLS
{
public class TlsStream : Stream
{
private static unsafe OpenSsl.alpn_select_cb_t _alpnSelectCallback = AlpnSelectCallback;
private readonly Stream _innerStream;
private readonly byte[] _protocols;
private readonly GCHandle _protocolsHandle;
private IntPtr _ctx;
private IntPtr _ssl;
private IntPtr _inputBio;
private IntPtr _outputBio;
private readonly byte[] _inputBuffer = new byte[1024 * 1024];
private readonly byte[] _outputBuffer = new byte[1024 * 1024];
static TlsStream()
{
OpenSsl.SSL_library_init();
OpenSsl.SSL_load_error_strings();
OpenSsl.ERR_load_BIO_strings();
OpenSsl.OpenSSL_add_all_algorithms();
}
public TlsStream(Stream innerStream, string certificatePath, string privateKeyPath, IEnumerable protocols)
{
_innerStream = innerStream;
_protocols = ToWireFormat(protocols);
_protocolsHandle = GCHandle.Alloc(_protocols);
_ctx = OpenSsl.SSL_CTX_new(OpenSsl.TLSv1_2_method());
if (_ctx == IntPtr.Zero)
{
throw new Exception("Unable to create SSL context.");
}
OpenSsl.SSL_CTX_set_ecdh_auto(_ctx, 1);
if (OpenSsl.SSL_CTX_use_certificate_file(_ctx, certificatePath, 1) != 1)
{
throw new Exception("Unable to load certificate file.");
}
if (OpenSsl.SSL_CTX_use_PrivateKey_file(_ctx, privateKeyPath, 1) != 1)
{
throw new Exception("Unable to load private key file.");
}
OpenSsl.SSL_CTX_set_alpn_select_cb(_ctx, _alpnSelectCallback, GCHandle.ToIntPtr(_protocolsHandle));
_ssl = OpenSsl.SSL_new(_ctx);
_inputBio = OpenSsl.BIO_new(OpenSsl.BIO_s_mem());
OpenSsl.BIO_set_mem_eof_return(_inputBio, -1);
_outputBio = OpenSsl.BIO_new(OpenSsl.BIO_s_mem());
OpenSsl.BIO_set_mem_eof_return(_outputBio, -1);
OpenSsl.SSL_set_bio(_ssl, _inputBio, _outputBio);
}
~TlsStream()
{
if (_ssl != IntPtr.Zero)
{
OpenSsl.SSL_free(_ssl);
}
if (_ctx != IntPtr.Zero)
{
// This frees the BIOs.
OpenSsl.SSL_CTX_free(_ctx);
}
if (_protocolsHandle.IsAllocated)
{
_protocolsHandle.Free();
}
}
public override bool CanRead => true;
public override bool CanWrite => true;
public override bool CanSeek => false;
public override long Length => throw new NotSupportedException();
public override long Position
{
get => throw new NotSupportedException();
set => throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Flush()
{
FlushAsync(default(CancellationToken)).GetAwaiter().GetResult();
}
public override int Read(byte[] buffer, int offset, int count)
{
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
}
public override void Write(byte[] buffer, int offset, int count)
{
WriteAsync(buffer, offset, count).GetAwaiter().GetResult();
}
public override async Task FlushAsync(CancellationToken cancellationToken)
{
var pending = OpenSsl.BIO_ctrl_pending(_outputBio);
while (pending > 0)
{
var count = OpenSsl.BIO_read(_outputBio, _outputBuffer, 0, _outputBuffer.Length);
await _innerStream.WriteAsync(_outputBuffer, 0, count, cancellationToken);
pending = OpenSsl.BIO_ctrl_pending(_outputBio);
}
}
public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (OpenSsl.BIO_ctrl_pending(_inputBio) == 0)
{
var bytesRead = await _innerStream.ReadAsync(_inputBuffer, 0, _inputBuffer.Length, cancellationToken);
if (bytesRead == 0)
{
return 0;
}
OpenSsl.BIO_write(_inputBio, _inputBuffer, 0, bytesRead);
}
return OpenSsl.SSL_read(_ssl, buffer, offset, count);
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
OpenSsl.SSL_write(_ssl, buffer, offset, count);
return FlushAsync(cancellationToken);
}
public void DoHandshake()
{
OpenSsl.SSL_set_accept_state(_ssl);
var count = 0;
try
{
while ((count = _innerStream.Read(_inputBuffer, 0, _inputBuffer.Length)) > 0)
{
if (count == 0)
{
throw new IOException("TLS handshake failed: the inner stream was closed.");
}
OpenSsl.BIO_write(_inputBio, _inputBuffer, 0, count);
var ret = OpenSsl.SSL_do_handshake(_ssl);
if (ret != 1)
{
var error = OpenSsl.SSL_get_error(_ssl, ret);
if (error != 2) // Typically SSL_ERROR_WANT_READ, handled non-blocking in async
{
throw new IOException($"TLS handshake failed: {nameof(OpenSsl.SSL_do_handshake)} error {error}.");
}
}
Flush(); // Replace FlushAsync with its synchronous counterpart
if (ret == 1)
{
return; // Handshake successful, return from the method.
}
}
}
finally
{
_protocolsHandle.Free();
}
}
public async Task DoHandshakeAsync(CancellationToken cancellationToken = default(CancellationToken))
{
OpenSsl.SSL_set_accept_state(_ssl);
var count = 0;
try
{
while ((count = await _innerStream.ReadAsync(_inputBuffer, 0, _inputBuffer.Length, cancellationToken)) > 0)
{
if (count == 0)
{
throw new IOException("TLS handshake failed: the inner stream was closed.");
}
OpenSsl.BIO_write(_inputBio, _inputBuffer, 0, count);
var ret = OpenSsl.SSL_do_handshake(_ssl);
if (ret != 1)
{
var error = OpenSsl.SSL_get_error(_ssl, ret);
if (error != 2)
{
throw new IOException($"TLS handshake failed: {nameof(OpenSsl.SSL_do_handshake)} error {error}.");
}
}
await FlushAsync(cancellationToken);
if (ret == 1)
{
return;
}
}
}
finally
{
_protocolsHandle.Free();
}
}
public string GetNegotiatedApplicationProtocol()
{
OpenSsl.SSL_get0_alpn_selected(_ssl, out var protocol);
return protocol;
}
private static unsafe int AlpnSelectCallback(IntPtr ssl, out byte* @out, out byte outlen, byte* @in, uint inlen, IntPtr arg)
{
var protocols = GCHandle.FromIntPtr(arg);
var server = (byte[])protocols.Target;
fixed (byte* serverPtr = server)
{
return OpenSsl.SSL_select_next_proto(out @out, out outlen, serverPtr, (uint)server.Length, @in, (uint)inlen) == OpenSsl.OPENSSL_NPN_NEGOTIATED
? OpenSsl.SSL_TLSEXT_ERR_OK
: OpenSsl.SSL_TLSEXT_ERR_NOACK;
}
}
private static byte[] ToWireFormat(IEnumerable protocols)
{
var buffer = new byte[protocols.Count() + protocols.Sum(protocol => protocol.Length)];
var offset = 0;
foreach (var protocol in protocols)
{
buffer[offset++] = (byte)protocol.Length;
offset += Encoding.ASCII.GetBytes(protocol, 0, protocol.Length, buffer, offset);
}
return buffer;
}
}
}
Вот мои оболочки OpenSSL для OpenSSL 1.1 (мне пришлось разместить их в другом месте, потому что текст моего вопроса был бы слишком большим, если бы они были здесь: https://hastebin.com/share/ weruzapebe.csharp
Моя библиотека OpenSSL загружается правильно
cert.pem
key.pem
работают правильно, я пытался использовать их на веб-сервере Apache, и они там работают нормально.
Я ожидал, что Firefox покажет мою расшифрованную страницу, но единственное, что я получаю в ответ, это р>
Connecting to 192.168.88.12
CONNECTED(00000128)
BC370000:error:0A000126:SSL routines::unexpected eof while reading:../openssl-3.
3.2/ssl/record/rec_layer_s3.c:687:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 334 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
что я делаю неправильно, я думал, что добавить https на мой сервер будет тривиально (просто передайте свой поток openSSL, который выполнит всю работу и будет работать с расшифрованным потоком)
p>
но что-то не работает
Я пытаюсь расширить свой HTTP-сервер с помощью поддержки TLS Мой HTTP-сервер здесь [code] using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using RawHttpListener.TLS;
public class HttpRequest { public string HttpMethod { get; set; } public string Url { get; set; } public string UserHostName { get; set; } public string UserAgent { get; set; } public string Body { get; set; }
public class HttpResponse { public string ContentType { get; set; } public Encoding ContentEncoding { get; set; } public long ContentLength64 { get; set; } public Stream OutputStream { get; set; }
public HttpResponse(Stream outputStream) { OutputStream = outputStream; } }
public class HTTPParser : Stream { private readonly IHTTPClientHandler _clientHandler; private readonly Stream _baseStream; private readonly MemoryStream _memoryStream = new MemoryStream(); private const int BufferSize = 4096; private readonly byte[] _buffer = new byte[BufferSize];
public async Task HandleClientConnected() { int bytesRead; // Read the incoming data until the connection is closed while ((bytesRead = await _baseStream.ReadAsync(_buffer, 0, _buffer.Length)) > 0) { await _memoryStream.WriteAsync(_buffer, 0, bytesRead);
// Check for the end of the request (empty line means headers end) if (bytesRead < BufferSize) break; }
// Convert the raw request to a string string rawRequest = Encoding.UTF8.GetString(_memoryStream.ToArray()); Console.WriteLine("Raw HTTP Request:"); Console.WriteLine(rawRequest);
// Handle the HTTP request await HandleHttpRequest(rawRequest); }
private async Task HandleHttpRequest(string rawRequest) { // Fill the MyOwnHttpListenerContext object and call the HTTPClientConnected method var lines = rawRequest.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); if (lines.Length == 0) return;
// Parse the request line (first line) var requestLine = lines[0].Split(' '); if (requestLine.Length < 3) return; // Invalid request
for (int i = 1; i < lines.Length; i++) // Skip the request line { if (lines[i].StartsWith("Host:")) { userHostName = lines[i].Substring(6).Trim(); // Skip "Host: " } else if (lines[i].StartsWith("User-Agent:")) { userAgent = lines[i].Substring(12).Trim(); // Skip "User-Agent: " } }
// Create the request and response objects var request = new HttpRequest(method, url, userHostName, userAgent); var response = new HttpResponse(_baseStream);
var ctx = new HttpContext(request, response); await _clientHandler.HTTPClientConnected(ctx); }
// Implementing abstract members of Stream class public override bool CanRead => _baseStream.CanRead; public override bool CanSeek => _baseStream.CanSeek; public override bool CanWrite => _baseStream.CanWrite; public override long Length => _baseStream.Length; public override long Position { get => _baseStream.Position; set => _baseStream.Position = value; }
public override void Flush() => _baseStream.Flush();
public override int Read(byte[] buffer, int offset, int count) => _baseStream.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);
public override void SetLength(long value) => _baseStream.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count); }
#endregion #region RawHttpServer public class RawHttpServer : IHTTPClientHandler { public string ipAddress = string.Empty; // Change to your desired IP address public int port; // Use a non-privileged port for testing bool isHTTPS;
public void Start() { TcpListener tcpListener = new TcpListener(IPAddress.Parse(ipAddress), port); tcpListener.Start(); Console.WriteLine($"Listening for connections on {ipAddress}:{port}");
private async Task HandleClient(TcpClient tcpClient) { using (NetworkStream stream = tcpClient.GetStream()) { HTTPParser httpParser; if (!this.isHTTPS) { //Reading RAW request, for debugging purposes //byte[] buffer = new byte[4096]; // Adjust the buffer size as necessary //int bytesRead;
//while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0) //{ // // Handle the data // string data = Encoding.UTF8.GetString(buffer, 0, bytesRead); // Console.WriteLine("Data: " + data); //}
httpParser = new HTTPParser(stream, this); await httpParser.HandleClientConnected(); // Handle the client connection } else { // Wrap the inner stream with TlsStream //using (var tlsStream = new TlsStream(stream, "cert.pem", "key.pem", new[] { "http/1.1" })) using (var tlsStream = new TlsStream(stream, "cert.pem", "key.pem", new[] { "http/1.1" })) { // Perform the TLS handshake await tlsStream.DoHandshakeAsync();
// Read decrypted data byte[] buffer = new byte[4096]; // Adjust the buffer size as necessary int bytesRead;
while ((bytesRead = await tlsStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { // Handle the decrypted data string decryptedData = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine("Decrypted Data: " + decryptedData);
}
// Create a new HTTP parser using the TlsStream for the connection httpParser = new HTTPParser(tlsStream, this); await httpParser.HandleClientConnected(); // Handle the client connection
} } } tcpClient.Close(); }
public async Task HTTPClientConnected(HttpContext ctx) { // Print out some info about the request Console.WriteLine($"URL: {ctx.Request.Url}"); Console.WriteLine($"Method: {ctx.Request.HttpMethod}"); Console.WriteLine($"User Host Name: {ctx.Request.UserHostName}"); Console.WriteLine($"User Agent: {ctx.Request.UserAgent}"); Console.WriteLine();
if (ctx.Request.HttpMethod == "POST") { Console.WriteLine("POST BODY:"); // Here you can handle the POST body if needed }
// Write the response info byte[] data = Encoding.UTF8.GetBytes("Hello World"); ctx.Response.ContentType = "text/html"; ctx.Response.ContentEncoding = Encoding.UTF8; ctx.Response.ContentLength64 = data.Length;
// Write out to the response stream (asynchronously), then close it await ctx.Response.OutputStream.WriteAsync(data, 0, data.Length); ctx.Response.OutputStream.Close(); // Close the output stream } } #endregion
//Our main class here class Program { static void Main(string[] args) { bool isHTTPS = true; RawHttpServer server = new RawHttpServer(IPAddress.Parse("192.168.88.12"), 443, isHTTPS); server.Start(); } } } [/code] Вот мой файл TLSStream.cs [code]using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks;
namespace RawHttpListener.TLS { public class TlsStream : Stream { private static unsafe OpenSsl.alpn_select_cb_t _alpnSelectCallback = AlpnSelectCallback;
~TlsStream() { if (_ssl != IntPtr.Zero) { OpenSsl.SSL_free(_ssl); }
if (_ctx != IntPtr.Zero) { // This frees the BIOs. OpenSsl.SSL_CTX_free(_ctx); }
if (_protocolsHandle.IsAllocated) { _protocolsHandle.Free(); } }
public override bool CanRead => true; public override bool CanWrite => true;
public override bool CanSeek => false; public override long Length => throw new NotSupportedException(); public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); public override void SetLength(long value) => throw new NotSupportedException();
public override void Flush() { FlushAsync(default(CancellationToken)).GetAwaiter().GetResult(); }
public override int Read(byte[] buffer, int offset, int count) { return ReadAsync(buffer, offset, count).GetAwaiter().GetResult(); }
public override void Write(byte[] buffer, int offset, int count) { WriteAsync(buffer, offset, count).GetAwaiter().GetResult(); }
public override async Task FlushAsync(CancellationToken cancellationToken) { var pending = OpenSsl.BIO_ctrl_pending(_outputBio);
while (pending > 0) { var count = OpenSsl.BIO_read(_outputBio, _outputBuffer, 0, _outputBuffer.Length); await _innerStream.WriteAsync(_outputBuffer, 0, count, cancellationToken);
public string GetNegotiatedApplicationProtocol() { OpenSsl.SSL_get0_alpn_selected(_ssl, out var protocol); return protocol; }
private static unsafe int AlpnSelectCallback(IntPtr ssl, out byte* @out, out byte outlen, byte* @in, uint inlen, IntPtr arg) { var protocols = GCHandle.FromIntPtr(arg); var server = (byte[])protocols.Target;
return buffer; } } } [/code] Вот мои оболочки OpenSSL для OpenSSL 1.1 (мне пришлось разместить их в другом месте, потому что текст моего вопроса был бы слишком большим, если бы они были здесь: https://hastebin.com/share/ weruzapebe.csharp Моя библиотека OpenSSL загружается правильно cert.pem key.pem работают правильно, я пытался использовать их на веб-сервере Apache, и они там работают нормально. Я ожидал, что Firefox покажет мою расшифрованную страницу, но единственное, что я получаю в ответ, это р> [code]PR_END_OF_FILE_ERROR [/code] Если я не выполню TLSHandshake, я получу [code]PR_CONNECT_RESET_ERROR [/code] Я даже пытался подключиться к OpenSSL вот так: [code]openssl s_client -connect domain.local:443 [/code] Но единственное, что я получаю, это обратно [code]Connecting to 192.168.88.12 CONNECTED(00000128) BC370000:error:0A000126:SSL routines::unexpected eof while reading:../openssl-3. 3.2/ssl/record/rec_layer_s3.c:687: --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 0 bytes and written 334 bytes Verification: OK --- New, (NONE), Cipher is (NONE) This TLS version forbids renegotiation. Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok) --- [/code] что я делаю неправильно, я думал, что добавить https на мой сервер будет тривиально (просто передайте свой поток openSSL, который выполнит всю работу и будет работать с расшифрованным потоком) p> но что-то не работает