salida para paquetes manejo flujos flujo estandar entrada datos concepto bytes archivos c# ssl stream bouncycastle

c# - para - Lee un flujo especial sin saber la cantidad de bytes



paquetes para entrada y salida de datos (2)

Todo lo que obtengo es una cadena de la capa TCP

Este es seguramente el defecto fatal en sus intentos de hacer que esto funcione. Implícito en lo que intenta hacer es que los datos enviados a través de la conexión TCP están encriptados con TLS. Lo que produce valores de bytes altamente aleatorios, cualquier valor entre 0 y 255 es posible. El paquete de datos que recibiría de una llamada Read () de un socket es byte [], no una cadena.

La conversión de bytes [] a una cadena requiere el uso de la clase de codificación .NET. Existen muchas variedades, las de stock son ASCIIEncoding, UnicodeEncoding, UTF8Encoding. Y un montón de personalizaciones diseñadas para trabajar con una página de códigos específica, las obtiene utilizando el constructor Encoding (int codePage).

No sabemos qué codificación utiliza la "capa TCP" con la que necesita trabajar, es probable que sea UTF8, pero es un hecho que siempre producirá datos dañados cuando se le solicite convertir un byte [] con cifrado. contenido. Algunos valores de bytes no tienen un punto de código Unicode correspondiente. El objeto de codificación hace ese tipo de problema generando un ? o a como un personaje sustituto. Cualquiera que sea el valor de Encoding.EncoderFallback resulta ser. Algunas probabilidades de que pueda verlas en el depurador, aunque la frecuencia es impredecible.

En otras palabras, los datos cifrados se corrompen inevitablemente con estas sustituciones. No hay una solución para esto, nada que pueda hacer para recuperar el byte original [] ya que las sustituciones perdieron el contenido. Esto debe ser abordado por las capas inferiores, o bien deben codificar el contenido byte [] a una cadena que siempre se puede convertir (base64 es la solución estándar) o necesita dejar de convertir los datos a una cadena. Realmente necesitas el byte sin formato [] para que esto funcione.

Antes de ir y decir usar la respuesta de Jon Skeet , no puedo. Estoy usando esta secuencia que es genial al principio, pero ahora, me he encontrado con un pequeño problema. Ahora estoy en un punto en el que no sé la cantidad de datos que espero, así que pensé que usaría el método que Jon Skeet proporcionó, pero desafortunadamente espera en packet = mPackets.Take() cuando todos los paquetes han sido leídos .

No tengo ni idea de cómo solucionar esto, la transmisión hace lo que se supone que debe hacer (al principio) pero desafortunadamente esta es una ocasión en la que no quiero que haga lo que se hizo para ...

¿Debería intentar reescribir la waitingstream o existe un método readall diferente que funcionaría mejor en mi caso?

Intenté devolver 0 cuando no había más paquetes disponibles (cuando quise que todos lo leyeran y no esperar), pero luego arroja una IO end of stream exception .

Realmente estoy perdido aquí, entiendo que he cavado un agujero profundo para mí ...

Hasta ahora no he podido encontrar una solución mejor que restar el encabezado TLS y GCM IV y MAC de la longitud total (como se menciona a continuación) Esto funciona bien para la suite 1 que estoy usando ahora, pero no cuenta con una buena para futuras suites de cifrado.

Algún contexto de por qué estoy haciendo esto:
Estoy usando https://github.com/bcgit/bc-csharp para crear un cifrado basado en TLS. Sin embargo, debido a limitaciones, no puedo asignarle una transmisión TCP, todo lo que obtengo es una cadena de la capa TCP, no puedo proporcionar con una transmisión TCP adecuada.

Estoy usando el servidor y el cliente mockPskTls y lo he creado así:

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);

Esto funciona bien, también he agregado un evento a la secuencia de espera que se activa cuando hay salida para la transmisión. Esto para poder recibir los múltiples mensajes de saludo cuando se crearon.

Todo esto funciona bien, podría haberse hecho mejor (¿menos ... hackeado?) Pero hace lo que se supone que debe hacer.

Sí sé de cómo hacerlo funcionar, pero este es un HACK y estoy buscando una forma elegante de hacerlo. Aquí hay un ejemplo de código para uno de esos HACKS:

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; }

o anteponiendo la longitud del texto sin formato en x bytes reservados al paquete TLS y recuperando estos bytes antes de descifrarlos.

pero como se puede ver claramente en el ejemplo del código, el búfer en el método de lectura completa debe ser la longitud de los bytes que deseo extraer, puede ser menor que la secuencia pero no puede ser más porque esperará indefinidamente.

Cuando hablo de métodos como ReadAll y ReadFully me refiero a estos métodos


¿Has tratado de eliminar el flujo de entrada después de escribir en él?

Esto debería indicar al BlockingCollection<byte> interno BlockingCollection<byte> de mStdIn que no entrará nada más. tlsStream embargo, no estoy seguro si esto se propaga a tu tlsStream .