C# 无法解码.NET SslStream握手中的完整密码列表

C# 无法解码.NET SslStream握手中的完整密码列表,c#,.net,ssl,C#,.net,Ssl,在尝试使用.NET SslStream从基于“C”的SSL实现转移到C#的过程中,我们遇到了与.NET SslStream和我们尝试连接的AS400机器(以前工作过)的密码兼容性问题 当我们调用SslStream.authenticatesClient时,它将发送以下信息: 16 03 00 37 01 00 33 03 00 4d 2c 00 ee 99 4e 0c 5d 83 14 77 78 5c 0f d3 8f 8b d5 e6 b8 cd 61 0f 29 08 ab 75 03 f

在尝试使用.NET SslStream从基于“C”的SSL实现转移到C#的过程中,我们遇到了与.NET SslStream和我们尝试连接的AS400机器(以前工作过)的密码兼容性问题

当我们调用SslStream.authenticatesClient时,它将发送以下信息:

16 03 00 37 01 00 33 03 00 4d 2c 00 ee 99 4e 0c 5d 83 14 77 78 5c 0f d3 8f 8b d5 e6 b8 cd 61 0f 29 08 ab 75 03 f7 fa 7d 70 00 00 0c 00 05 00 0a 00 13 00 04 00 02 00 ff 01 00

其解码为(基于)

as400服务器以以下方式响应:

15 03 00 00 02 02 28

[15] SSL3_RT_ALERT  
[03 00] SSL Version  
[00 02] Body Length (2 Bytes)  

[02 28] 2 = SSL3_RT_FATAL, 40 = SSL3_AD_HANDSHAKE_FAILURE
我特别想解码密码末尾的'00FF'。 我解码正确了吗?如果有的话,“00 FF”也会解码什么

我正在使用以下代码进行测试/复制:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;

namespace TestSslStreamApp
{
    class DebugStream :
        Stream
    {
        private Stream AggregatedStream { get; set; }

        public DebugStream(Stream stream) { AggregatedStream = stream; }

        public override bool CanRead { get { return AggregatedStream.CanRead; } }
        public override bool CanSeek { get { return AggregatedStream.CanSeek; } }
        public override bool CanWrite { get { return AggregatedStream.CanWrite; } }
        public override void Flush() { AggregatedStream.Flush(); }
        public override long Length { get { return AggregatedStream.Length; } }

        public override long Position
        { 
            get { return AggregatedStream.Position; }
            set { AggregatedStream.Position = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            int bytesRead = AggregatedStream.Read(buffer, offset, count);

            return bytesRead;
        }

        public override long Seek(long offset, SeekOrigin origin) { return AggregatedStream.Seek(offset, origin); }
        public override void SetLength(long value) { AggregatedStream.SetLength(value); }

        public override void Write(byte[] buffer, int offset, int count)
        {
            AggregatedStream.Write(buffer, offset, count);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            const string HostName = "as400";

            TcpClient tcpClient = new TcpClient(HostName, 992);

            SslStream sslStream = new SslStream(new DebugStream(tcpClient.GetStream()), false, null, null,
                                                    EncryptionPolicy.AllowNoEncryption);

            sslStream.AuthenticateAsClient(HostName, null, SslProtocols.Ssl3, false);
        }
    }
}
资料来源:

3.3. 重新协商保护请求信令密码套件值 SSLv3和TLS 1.0/TLS 1.1规范都要求 在ClientHello之后忽略数据的实现(即。, 扩展)如果他们不理解它。然而,一些SSLv3和 在这种情况下,TLS1.0实现错误地使握手失败 案例这意味着提供“重新协商信息”的客户 分机可能会遇到握手失败。为了增强 与此类服务器兼容,本文档定义了第二个 通过特殊信令密码套件值(SCSV)的信令机制 “TLS_EMPTY_RENEGOTIATION_INFO_SCSV”,代码点为{0x00,0xFF}。 此SCSV不是真正的密码套件(它不对应于任何 有效的算法集),无法协商。相反,它有 与空的“重新协商信息”扩展相同的语义,如 以下各节将对此进行描述。因为SSLv3和TLS 实现可靠地忽略未知密码套件,SCSV可能 可以安全地发送到任何服务器。SCSV也可以包含在 SSLv2向后兼容客户端-HELLO(见附录E.2
[RFC5246])。最简单的方法是检查您的C实现发送的是什么,查看它请求的是哪个SSL版本和密码套件,并且,毕竟,查看服务器响应的是什么-SSL版本和选择的密码套件。

现在我知道了这一点,我可以开始计算服务器将实际接受什么。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;

namespace TestSslStreamApp
{
    class DebugStream :
        Stream
    {
        private Stream AggregatedStream { get; set; }

        public DebugStream(Stream stream) { AggregatedStream = stream; }

        public override bool CanRead { get { return AggregatedStream.CanRead; } }
        public override bool CanSeek { get { return AggregatedStream.CanSeek; } }
        public override bool CanWrite { get { return AggregatedStream.CanWrite; } }
        public override void Flush() { AggregatedStream.Flush(); }
        public override long Length { get { return AggregatedStream.Length; } }

        public override long Position
        { 
            get { return AggregatedStream.Position; }
            set { AggregatedStream.Position = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            int bytesRead = AggregatedStream.Read(buffer, offset, count);

            return bytesRead;
        }

        public override long Seek(long offset, SeekOrigin origin) { return AggregatedStream.Seek(offset, origin); }
        public override void SetLength(long value) { AggregatedStream.SetLength(value); }

        public override void Write(byte[] buffer, int offset, int count)
        {
            AggregatedStream.Write(buffer, offset, count);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            const string HostName = "as400";

            TcpClient tcpClient = new TcpClient(HostName, 992);

            SslStream sslStream = new SslStream(new DebugStream(tcpClient.GetStream()), false, null, null,
                                                    EncryptionPolicy.AllowNoEncryption);

            sslStream.AuthenticateAsClient(HostName, null, SslProtocols.Ssl3, false);
        }
    }
}
3.3. Renegotiation Protection Request Signaling Cipher Suite Value Both the SSLv3 and TLS 1.0/TLS 1.1 specifications require implementations to ignore data following the ClientHello (i.e., extensions) if they do not understand it. However, some SSLv3 and TLS 1.0 implementations incorrectly fail the handshake in such a case. This means that clients that offer the "renegotiation_info" extension may encounter handshake failures. In order to enhance compatibility with such servers, this document defines a second signaling mechanism via a special Signaling Cipher Suite Value (SCSV) "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", with code point {0x00, 0xFF}. This SCSV is not a true cipher suite (it does not correspond to any valid set of algorithms) and cannot be negotiated. Instead, it has the same semantics as an empty "renegotiation_info" extension, as described in the following sections. Because SSLv3 and TLS implementations reliably ignore unknown cipher suites, the SCSV may be safely sent to any server. The SCSV can also be included in the SSLv2 backward compatible CLIENT-HELLO (see Appendix E.2 of [RFC5246]).