Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不知道字节数的情况下读取特殊流_C#_Ssl_Stream_Bouncycastle - Fatal编程技术网

C# 在不知道字节数的情况下读取特殊流

C# 在不知道字节数的情况下读取特殊流,c#,ssl,stream,bouncycastle,C#,Ssl,Stream,Bouncycastle,在你说使用之前,我不能。 我一开始很好,但现在,我遇到了一个小问题。我现在不知道我期望的数据量,所以我认为我应该使用Jon Skeet提供的方法,但不幸的是,它在读取所有数据包后等待packet=mpackes.Take() 我不知道如何解决这个问题,流做了它应该做的事情(在开始),但不幸的是,这是一个场合,我不希望它做什么,它是为 我应该尝试重写waitingstream,还是有一种不同的readall方法在我的情况下更有效 我尝试在没有更多可用数据包时返回0(当我希望它读取所有数据包而不是等

在你说使用之前,我不能。 我一开始很好,但现在,我遇到了一个小问题。我现在不知道我期望的数据量,所以我认为我应该使用Jon Skeet提供的方法,但不幸的是,它在读取所有数据包后等待
packet=mpackes.Take()

我不知道如何解决这个问题,流做了它应该做的事情(在开始),但不幸的是,这是一个场合,我不希望它做什么,它是为

我应该尝试重写
waitingstream
,还是有一种不同的
readall
方法在我的情况下更有效

我尝试在没有更多可用数据包时返回0(当我希望它读取所有数据包而不是等待时),但随后它抛出了一个
IO流结束异常

我在这里真的不知所措,我知道我为自己挖了一个深坑

到目前为止,我还没有找到比从总长度中减去TLS报头和GCM IV和MAC更好的解决方案(如下所述),这对我现在使用的1套件很好,但对未来的密码套件来说并不好


关于我为什么这样做的一些背景:
我正在使用创建基于TLS的加密,但是由于限制,我无法为其分配TCP流,我只能从TCP层获得一个字符串,我无法为其提供propper TCP流

我使用的是,我创建的是:

WaitingStream mStdin = new WaitingStream();
WaitingStream mStdout = new WaitingStream();
CryptoPskTlsClient mServer = new CryptoPskTlsClient(null);
SecureRandom secureRandom = new SecureRandom();
TlsClientProtocol TlsProtocol = new TlsServerProtocol(Stdin, Stdout, secureRandom);
TlsProtocol.Connect(mServer);
这很好,我还向等待的流添加了一个事件,当流有输出时触发该事件。这样我就可以在创建多个握手消息时获得它们

这一切都很好,本来可以做得更好(少被黑客攻击?),但它做了它应该做的

我知道如何让它工作,但这是一个黑客,我正在寻找一个优雅的方式来做到这一点。下面是其中一个黑客的代码示例:

public override string DecryptData(string ciphertext)
{
    byte[] ciphertextBuff = ASCIIEncoding.Default.GetBytes(ciphertext);
    mStdin.Write(ciphertextBuff, 0, ciphertextBuff.Length);

    Stream tlsStream = mServerProtocol.Stream;
    byte[] plaintextBuffer = new byte[ciphertextBuff.Length - 29];//filthy HACK 29 bytes bij AES-GCM want TLS packet = 5, GCM IV = 8, GCM-MAC = 16 totaal = 29.
    Streams.ReadFully(tlsStream, plaintextBuffer);

    string plaintext = ASCIIEncoding.Default.GetString(plaintextBuffer);
    return plaintext;
}
或者,将明文长度(以x保留字节为单位)预先添加到TLS数据包中,并在解密之前检索这些字节

但是从代码示例中可以清楚地看到,read fully方法中的缓冲区必须是我想要提取的字节长度,它可以小于流的长度,但不能大于,因为这样它将无限期地等待

当我谈论像
ReadAll
ReadFully

我从TCP层得到的只是一个字符串

这无疑是你试图使这项工作成功的致命缺陷。您试图做的隐含操作是,通过TCP连接发送的数据是TLS加密的。它产生高度随机的字节值,0到255之间的任何值都是可能的。从套接字的Read()调用接收的数据包是byte[],而不是字符串

将字节[]转换为字符串需要使用.NET编码类。它有很多种类,库存的有ASCIONODING、UNICODEENCODE、UTF8编码。还有一堆定制的代码,设计用于特定的代码页,您可以通过使用编码(int-codePage)构造函数获得它们

我们不知道您需要使用的“TCP层”使用的是什么编码,UTF8可能会使用,但当要求它将字节[]转换为加密内容时,它总是会产生损坏的数据。某些字节值没有相应的Unicode代码点。编码对象通过生成
作为替换字符。不管Encoding.encoderCallback的值是什么。您可能会在调试器中看到它们,尽管频率不可预测


换句话说,加密数据将不可避免地被这些替换损坏。没有解决方法,因为内容因替换而丢失,所以无法恢复原始字节[]。这个必须由较低的层来解决,它们要么需要将字节[]内容编码为始终可以转换的字符串(base64是标准解决方案),要么需要停止将数据转换为字符串。您确实需要原始字节[]才能执行此操作。

您是否尝试在写入输入流后处理它


这应该告诉
mStdIn
的内部
BlockingCollection
,不会有更多的内容。但是,我不确定这是否会传播到您的
tlsStream

您是否可以使用带有超时的
TryTake
,而不是
Take
?我不确定是否理解您的问题(最初的问题还是这个问题)。为什么要替换初始TcpClient Networkstream?@SimonMourier,因为我没有访问TcpClient Networkstream的权限。我只有字符串。@DanielHilgarth但是当超时超过时我该怎么办,我仍然需要返回一些东西,我不能返回0,因为这样它会抛出一个异常。我知道这一点,它是ASCII编码的,解码工作正常,您确实得到了原始数据。这不是问题所在,请参见编辑。虽然我意识到这可能不是最整洁的方式,但这不是我面临的问题。这也不行,ASCII只支持0-127。拿起电话,和程序员交谈,明确地问他如何将byte[]转换为字符串。我知道他是怎么做的,我面前有源代码,它是ascienceod.default.getString(byte[])和解码:ascienceod.default.getBytes(string)。这确实有效,对于我检查过的127以上的值也是如此。这是糟糕的代码,它实际上使用操作系统的默认编码。通常代码页1252和你的名字一样。就像我描述的那样,1252没有0x81、0x8D、0x8F、0x90和0x9E的字符。你必须在程序员破坏数据之前得到原始字节[],这是一个非常严格的要求