私は2年後に戻って答えを受け入れることはできませんが、私はあなたが尋ねていることをやっただけですが、これはかなり一般的な問題だと思いますので、私はこれを投稿して、この質問の向こう側に。
GregSの情報を実装に取り入れました。具体的な目的のために、Initializeメソッドをコンストラクタにし、net & diffie-hellmanコードを取り除き、(生成されたキーの代わりに)Aesオブジェクトに事前共有キーを割り当てます。
AES126と似ているのにもかかわらず、AES256を使用していることに注意してください(あなたのキーは私の知る限りの実装不良のため関連しています)。 NSAが仕様を乱しているかどうかを知るためにNISTを信頼しない場合は、AESを使用しないでください。
また、これが出発点です! NETでNetworkStreamを介して暗号化されたデータを送信する際によく遭遇する問題を解決しようとしています。前置き百12行以下で
:
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);
}
}
}
なぜ容認できない2つのストリームを作成していますか?このような状況では、私は通常、ここで起こっている2つの "セッション"に対して異なる暗号鍵を設定したいと思っています(キーとして 'HASH(パスフレーズ+ '||' +送信者名)を使用してください)。 –
@Damien私はこのストリームの上にさらにストリームを重ねるので、それらのすべてを複製したくないからです。 –
読み込みと書き込みをサポートする単一のストリームオブジェクトのセマンティクスが必要であるが(シークではないと思われますが)、その操作で渡された "ReadStream"または "WriteStream"書くために1ページ分のコードを取る。したがって、Cryptoクラスを使用してチャネルの両側に暗号化を追加し、この別のクラスを使用して上位クラスへの単一のストリームとして提示することができます。 –