Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.4k views
in Technique[技术] by (71.8m points)

cryptography - Set CipherSuite at C# code level using Bouncy Castle, unable to get correct byte array[] for Http GET request

I want to download some files on Windows 7 & 8.1 using cipher suites which are not available by default on Win 7 & 8.1

I am using HttpClient class (with TLS 1.2 as default protocol) and .NET framework 4.6 to download and it is working fine on Windows 10. However the same code does not work on Windows 7 & 8.1 because of missing cipher suites on these OS.

I found we can programmatically select a particular cipher suite using Bouncy Castle as per links: MS Forum and Stack Overflow Forum

Using the example provided in the above links, I am able to create the connection using my preferred cipher suite (TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) and able to download files from source server on Win 7 & 8.1

However the problem I am facing now is few of the files have certain characters in them because of which even though the file is downloaded with correct length, because of some characters which do not transfer/download properly, the downloaded files are corrupted.

To resolve this, I tried to force the byte array[] to be returned in UTF-8 encoding by adding "Accept-Charset: utf-8" in the Http GET request, still the bytes are not downloaded in the correct way which is leading to corrupting.

Could anyone provide me with pointers on how I can make Bouncy Castle to send me the bytes in the encoding I want? Or I am I missing certain settings/properties which I could use to correct the issue.

Please see below code block which I am using as of now.

using Org.BouncyCastle.Crypto.Tls;
    using System;
    using System.IO;
    using System.Net.Sockets;
    using System.Text;
    public void GetFileStream(string fileUrl, out Stream stream)
{
    
    
    string contentType = string.Empty;
    long fileSize = 0;

    try
    {

        string url = "sourceserverhostname";
        TcpClient client = new TcpClient(url, 443);
        NetworkStream targetStream = client.GetStream();
        targetStream.ReadTimeout = 10000;
        targetStream.WriteTimeout = 10000;


        TlsClientProtocol protocol = new TlsClientProtocol(targetStream, new Org.BouncyCastle.Security.SecureRandom());
        protocol.Connect(new CustomTlsClient());

       

        string message = @"GET {0} HTTP/1.1 
                        " + Environment.NewLine + "Accept-Charset: utf-8" + "

";

        message = string.Format(message, fileUrl);

        //Send Http Get Request
        byte[] bytes = Encoding.UTF8.GetBytes(message);
        protocol.Stream.Write(bytes, 0, bytes.Length);

        var reader = new StreamReader(protocol.Stream, Encoding.UTF8);

        //check and extract http response parameters
        int index = 0;
        do
        {
            string lineData = reader.ReadLine();
            if (!string.IsNullOrEmpty(lineData))
            {
                if (lineData.ToLower().Contains("content-type"))
                {
                    string[] keyValueList = lineData.Split(new char[] { ':' });
                    if (keyValueList != null && keyValueList.Length > 1)
                    {
                        contentType = keyValueList[1];
                    }
                }
                if (lineData.ToLower().Contains("content-length"))
                {
                    string[] keyValueList = lineData.Split(new char[] { ':' });
                    if (keyValueList != null && keyValueList.Length > 1)
                    {
                        fileSize = long.Parse(keyValueList[1]);
                    }
                }
                index = index + lineData.Length + 2;
            }
            else
                break;
        } while (!reader.EndOfStream);

        //Send Http Get Request again to get hold of Stream object
        bytes = Encoding.UTF8.GetBytes(message);
        protocol.Stream.Write(bytes, 0, bytes.Length);

        //Read the Http Get Request response header content into dataToDiscard
        byte[] dataToDiscard = new byte[index + 2];
        protocol.Stream.Read(dataToDiscard, 0, index + 2);

        result.MimeType = contentType;            
        result.FileSize = fileSize;
        
        //Return stream object with current pointer set to location from wherer the data starts
        stream = protocol.Stream;

        

    }
    catch (Exception exp)
    {
        throw exp;
    }
    
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...