예제 #1
0
        public override Symmetric.SymmetricKeyPair Exchange(System.IO.Stream stream)
        {
            BinaryReader binaryReader = new BinaryReader(stream);
            BinaryWriter binaryWriter = new BinaryWriter(stream);

            //Write our local RSA public key.
            WritePublicParameters(binaryWriter, localRsa.ExportParameters(false));
            binaryWriter.Flush();

            //Read the RSA public key of the remote party.
            RSAParameters remoteParameters = ReadPublicParameters(binaryReader);

            //Verify the remote party's public key.
            if (identityVerifier.VerifyIdentity(new RSAIdentity(remoteParameters)))
            {
                binaryWriter.Write(true);
                binaryWriter.Flush();
            }
            else
            {
                binaryWriter.Write(false);
                binaryWriter.Flush();

                throw new SecurityException("The remote party's RSA public key was denied by the local identifier.");
            }

            //Read the status code from the remote party, and ensure our local public key wasn't denied.
            if (!binaryReader.ReadBoolean())
            {
                throw new SecurityException("The local RSA public key was denied by the remote party's identifier.");
            }

            //Construct an RSA instance and import the remote public key.
            RSACryptoServiceProvider remoteRsa = new RSACryptoServiceProvider();

            remoteRsa.ImportParameters(remoteParameters);

            //Generate an AES key for ourselves. This will be sent to the remote party.
            RandomNumberGenerator rng = RandomNumberGenerator.Create();

            byte[] localCipherKey = new byte[factory.BlockSize / 8];
            rng.GetBytes(localCipherKey);

            //Encrypt and send the generated AES key using remote party's public key using PKCS#1 v1.5 padding.
            Packet.WriteBytes(binaryWriter, remoteRsa.Encrypt(localCipherKey, false));

            //Read the remote party's generated AES key, recovering the original byte size using the padding.
            byte[] remoteCipherKey = localRsa.Decrypt(Packet.ReadBytes(binaryReader), false);

            //Construct the symmetric key pair and return the value to the upper-level.
            return(new SymmetricKeyPair(
                       factory.CreateKey(factory.CreateIV(localCipherKey), localCipherKey),
                       factory.CreateKey(factory.CreateIV(remoteCipherKey), remoteCipherKey)
                       ));
        }
        public override SymmetricKeyPair Exchange(System.IO.Stream stream)
        {
            //Construct a binary stream around the underlying stream.
            BinaryWriter binaryWriter = new BinaryWriter(stream);
            BinaryReader binaryReader = new BinaryReader(stream);

            //Generate an elliptic-curve Diffie-Hellman key for private use.
            ECDiffieHellmanCng local = new ECDiffieHellmanCng(keySize);

            local.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
            local.HashAlgorithm         = symmetricKeyHashAlgorithm;

            //Send our ECDH public key to the other party.
            Packet.WriteBytes(binaryWriter, local.PublicKey.ToByteArray());
            binaryWriter.Flush();

            //Recieve the ECDH public key from the other party.
            ECDiffieHellmanCng remote = new ECDiffieHellmanCng(
                CngKey.Import(
                    Packet.ReadBytes(binaryReader),
                    CngKeyBlobFormat.EccPublicBlob
                    )
                );

            //Compute the shared secret using the ECDH keys transmitted.
            byte[]       sharedSecret = local.DeriveKeyMaterial(remote.PublicKey);
            SymmetricKey sharedKey    = factory.CreateKey(factory.CreateIV(sharedSecret), sharedSecret);

            //Return a keypair to the upper level, using the shared key for both directions.
            return(new SymmetricKeyPair(sharedKey, sharedKey));
        }