gpt4 book ai didi

.net - 如何在底层 .NET 流之上创建双向加密流?

转载 作者:行者123 更新时间:2023-12-04 07:58:24 25 4
gpt4 key购买 nike

我有一个 Stream,它通过不安全的 channel 传输和接收数据。我有一个预先共享的 secret , channel 的两个端点都已经有了(比如密码)。

我想使用 secret 和原始不安全流构建一个新流。我遇到的两个问题是:

  • CryptoStream 是一种方式:只读或只写。我可以在原始 Stream 之上创建两个流(一个读取流和一个写入流),但这是 Not Acceptable 。我是否必须编写一个包装流才能得到我想要的? (即单个读/写流)
  • 据说 CryptoStream 在块中工作,并且在块完成之前可能不会向底层流写入任何内容。理想情况下,我想写入任意数量的数据并立即将其发送到底层流(加密)。

  • 有没有一种简单的方法来实现这一目标?我知道 SslStream,但它是为私钥/公钥和证书量身定制的,而不是预先共享的 secret 。

    最佳答案

    我怀疑你两年后会回来接受答案,但是我只是做了你所问的,我认为这是一个相当普遍的问题,所以我发布这个是为了其他可能遇到这个问题的人的利益。

    我将 GregS 的信息纳入了我的实现中。对于您的特定目的,您可以将 Initialize 方法作为您的构造函数,去除 net & diffie-hellman 代码,并将您的预共享 key 分配给 Aes 对象(而不是生成的 key )。

    请注意,我正在使用 AES256,尽管它已被妥协为与 AES128 具有相似的强度(如果您的 key 由于实现不当而相关,我不知道)。如果你不相信 NIST 知道 NSA 是否在搞乱他们的规范,那么不要使用 AES。

    此外,这是一个起点!我正在解决通过 .NET 中的 NetworkStream 发送加密数据的常见问题!

    在一百十二行或更少,不用多说:

    using System;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Security.Cryptography;

    namespace FullDuplexCrypto
    {
    class CryptoNetworkStream : Stream
    {
    public CryptoNetworkStream(IPAddress address, int port)
    {
    Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
    socket.Connect(address, port);
    //socket.NoDelay = true;
    Initialize(new NetworkStream(socket, true));
    }

    public CryptoNetworkStream(Socket socket)
    {
    Initialize(new NetworkStream(socket, true));
    }

    private void Initialize(Stream stream)
    {
    underlyer = stream;

    using(ECDiffieHellmanCng dh = new ECDiffieHellmanCng())
    {
    dh.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    dh.HashAlgorithm = CngAlgorithm.Sha256;
    byte[] buffer = dh.PublicKey.ToByteArray();
    underlyer.Write(buffer, 0, buffer.Length);
    underlyer.Read(buffer, 0, buffer.Length);

    using(Aes aes = Aes.Create())
    {
    aes.KeySize = 256;
    aes.Key = dh.DeriveKeyMaterial(CngKey.Import(buffer, CngKeyBlobFormat.EccPublicBlob));
    aes.FeedbackSize = 8;
    aes.Mode = CipherMode.CFB;

    underlyer.Write(aes.IV, 0, aes.IV.Length);
    encrypter = new CryptoStream(underlyer, aes.CreateEncryptor(), CryptoStreamMode.Write);

    underlyer.Read(aes.IV, 0, aes.IV.Length);
    decrypter = new CryptoStream(underlyer, aes.CreateDecryptor(), CryptoStreamMode.Read);
    }
    }
    }

    private Stream underlyer;
    private Stream encrypter;
    private Stream decrypter;

    public override bool CanRead { get { return decrypter.CanRead; } }
    public override bool CanWrite { get { return encrypter.CanWrite; } }
    public override bool CanSeek { get { return underlyer.CanSeek; } }
    public override long Length { get { return underlyer.Length; } }
    public override long Position { get { return underlyer.Position; } set { underlyer.Position = value; } }

    public override void Flush()
    {
    encrypter.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
    return decrypter.Read(buffer, offset, count);
    }

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

    public override long Seek(long offset, SeekOrigin origin)
    {
    return underlyer.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
    underlyer.SetLength(value);
    }

    private bool isDisposed = false;

    protected override void Dispose(bool isDisposing)
    {
    if(!isDisposed)
    {
    if(isDisposing)
    {
    // Release managed resources.
    encrypter.Dispose();
    decrypter.Dispose();
    underlyer.Dispose();

    }
    // Release unmanaged resources.

    isDisposed = true;
    }
    base.Dispose(isDisposing);
    }
    }
    }

    关于.net - 如何在底层 .NET 流之上创建双向加密流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6717356/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com