Esempio n. 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)
                       ));
        }
Esempio n. 2
0
        protected override void HandleIdentityResponse(Packet3IdentityResponse response)
        {
            //Ensure the identity has not already been received, and this is not duplicate.
            if (receivedIdentity)
            {
                Disconnect(Packet255Disconnect.DisconnectReason.UnexpectedPacket);
                return;
            }

            //Set the identity received flag to true to prevent future identities from being read.
            receivedIdentity = true;

            //Ensure the signed data matches our salt, and we've sent a request.
            if (!requestedIdentity || salt == null || !response.Signature.Data.SequenceEqual(salt))
            {
                Disconnect(Packet255Disconnect.DisconnectReason.AuthenticationFailed);
                return;
            }

            //Ensure the identity is not ours, which would mean we're connecting to ourselves.
            if (response.SignatureAlgorithm.Identity.Equals(signatureAlgorithm.Identity))
            {
                Disconnect(Packet255Disconnect.DisconnectReason.AuthenticationFailed);
                return;
            }

            //Ensure the identity matches the expected identity.
            if (!identityVerifier.VerifyIdentity(response.SignatureAlgorithm.Identity))
            {
                Disconnect(Packet255Disconnect.DisconnectReason.AuthenticationFailed);
                return;
            }

            //Ensure the signature created by the remote party is valid.
            if (!response.SignatureAlgorithm.Verify(response.Signature))
            {
                Disconnect(Packet255Disconnect.DisconnectReason.AuthenticationFailed);
                return;
            }

            /*
             * ================== WARNING ==================
             *
             * Beyond this point, the peer is trusted to be
             * a valid recipient of data destined to his
             * identity (see: Identity class). The actual
             * authentication process occurs in the
             * implementation of the signature algorithm the
             * endpoint has chosen, which may be faulty or
             * have a vulnerability. It is up to the peer who
             * requests the identity to ensure the algorithm
             * chosen by the endpoint is safe to use for
             * identity authentication.
             *
             * Should an issue be discovered in a signature
             * algorithm, when used it should always throw a
             * SecurityException, detailing the vulnerability
             * present by using its standard for
             * authentication. This exception will be caught
             * by the PacketHandler processing the handshake
             * and by specification should disconnect.
             *
             * =============================================
             */

            //Initialize the new authorized handler.
            Stream.PacketHandler = new RimPacketHandlerAuthorized(Stream, new Contact.Contact(response.SignatureAlgorithm, null), signatureAlgorithm);
        }