/// <summary> /// Processes the shared key response. /// </summary> /// <param name="responseHeaders">Response transport headers.</param> private SymmetricAlgorithm ProcessSharedKeyResponse(ITransportHeaders responseHeaders) { // Get the encrypted key and initialization vector from the transport headers sent by the server string encryptedKey = (string)responseHeaders[CommonHeaderNames.SHARED_KEY]; string encryptedIV = (string)responseHeaders[CommonHeaderNames.SHARED_IV]; if (encryptedKey == null || encryptedKey == string.Empty) { throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_KeyChanged); } if (encryptedIV == null || encryptedIV == string.Empty) { throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_IVMissing); } // Create symmetric algorithm and set shared key and initialization vector SymmetricAlgorithm sharedProvider = CryptoTools.CreateSymmetricCryptoProvider(_algorithm); sharedProvider.Key = _rsaProvider.Decrypt(Convert.FromBase64String(encryptedKey), _oaep); sharedProvider.IV = _rsaProvider.Decrypt(Convert.FromBase64String(encryptedIV), _oaep); // Return the encryption provider return(sharedProvider); }
/// <summary>Verarbeitet die Antwort der Servers einer Anfrage nach einen Gemeinsamen Schlüssel</summary> /// <param name="responseHeaders">Transport-Header-Auflistung</param> /// <returns>Verschlüsselungsanbieter</returns> private SymmetricAlgorithm ProcessSharedKeyResponse(ITransportHeaders responseHeaders) { // Gemeinsamen Schlüssel und Inizialisierungsvektor asu den Antwort-Headern lesen string encryptedKey = (string)responseHeaders[CommonHeaderNames.SHARED_KEY]; string encryptedIV = (string)responseHeaders[CommonHeaderNames.SHARED_IV]; // Wenn kein gemeinsamer Schlüssel übermittelt wurde ... if (encryptedKey == null || encryptedKey == string.Empty) { // Ausnahme werfen throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_KeyChanged); } // Wenn kein Inizialisierungsvektor übermittelt wurde ... if (encryptedIV == null || encryptedIV == string.Empty) { // Ausnahme werfen throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_IVMissing); } // Gemeinsamen Schlüssel und Inizialisierungsvektor entschlüsseln SymmetricAlgorithm sharedProvider = CryptoTools.CreateSymmetricCryptoProvider(_algorithm); sharedProvider.Key = _rsaProvider.Decrypt(Convert.FromBase64String(encryptedKey), _oaep); sharedProvider.IV = _rsaProvider.Decrypt(Convert.FromBase64String(encryptedIV), _oaep); // Verschlüsselungsanbieter zurückgeben return(sharedProvider); }
/// <summary>Verschlüsselt eine bestimmte Remoting-Nachricht</summary> /// <param name="requestHeaders">Anfrage-Transport-Header-Auflistung</param> /// <param name="requestStream">Anfrage-Datenstrom</param> /// <returns>Verschlüsselter Datenstrom</returns> private Stream EncryptMessage(ITransportHeaders requestHeaders, Stream requestStream) { // Nachricht verschlüsseln requestStream = CryptoTools.GetEncryptedStream(requestStream, _provider); // Statusinformationen über die Sicherheitstransaktion in die Header-Auflistung schreiben requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)SecureTransactionStage.SendingEncryptedMessage).ToString(); requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_ID] = _secureTransactionID.ToString(); // Verschlüsselten Datenstrom zurückgeben return(requestStream); }
/// <summary> /// Encrypts the message. /// </summary> /// <param name="requestHeaders">Request transport headers.</param> /// <param name="requestStream">Request stream.</param> private Stream EncryptMessage(ITransportHeaders requestHeaders, Stream requestStream) { // Encrypt message using the symmetric encryption algorithm requestStream = CryptoTools.GetEncryptedStream(requestStream, _provider); // Send the current secure transaction stage and identifier in the transport headers requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)SecureTransactionStage.SendingEncryptedMessage).ToString(); requestHeaders[CommonHeaderNames.SECURE_TRANSACTION_ID] = _secureTransactionID.ToString(); // Return the encrypted data stream return(requestStream); }
/// <summary> /// Processes the encrypted message. /// </summary> /// <param name="transactID">Secure transaction identifier.</param> /// <param name="sinkStack">The sink stack.</param> /// <param name="requestMsg">Request message.</param> /// <param name="requestHeaders">Request transport headers.</param> /// <param name="requestStream">Request stream.</param> /// <param name="responseMsg">Response message.</param> /// <param name="responseHeaders">Response transport headers.</param> /// <param name="responseStream">Response stream.</param> public ServerProcessing ProcessEncryptedMessage(Guid transactID, IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { // Get the client connection data ClientConnectionData connectionData; lock (_connections.SyncRoot) { connectionData = (ClientConnectionData)_connections[transactID.ToString()]; } if (connectionData == null) { throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_ClientConnectionInfoMissing); } // Update the timestamp and indicate that method call is in progress connectionData.UpdateTimestamp(); connectionData.BeginMethodCall(); try { // Decrypt the data stream Stream decryptedStream = CryptoTools.GetDecryptedStream(requestStream, connectionData.CryptoProvider); requestStream.Close(); // Pass decrypted message for further processing to the next channel sink ServerProcessing processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, decryptedStream, out responseMsg, out responseHeaders, out responseStream); // Update secure transaction state responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)SecureTransactionStage.SendingEncryptedResult).ToString(); // Encrypt the response stream and close the original response stream now that we're done with it Stream encryptedStream = CryptoTools.GetEncryptedStream(responseStream, connectionData.CryptoProvider); responseStream.Close(); // // Use encrypted data stream as a response stream responseStream = encryptedStream; return(processingResult); } finally { // Method call is finished, so the connection data can be swept connectionData.EndMethodCall(); connectionData.UpdateTimestamp(); } }
/// <summary> /// Decrypts the incoming response stream. /// </summary> /// <param name="responseStream">The response stream.</param> /// <param name="responseHeaders">The response headers.</param> private Stream DecryptResponse(Stream responseStream, ITransportHeaders responseHeaders) { try { if (responseHeaders != null && (SecureTransactionStage)Convert.ToInt32((string)responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE]) == SecureTransactionStage.SendingEncryptedResult) { // Decrypt the response stream and close it as we won't be using it anymore Stream decryptedStream = CryptoTools.GetDecryptedStream(responseStream, _provider); responseStream.Close(); return(decryptedStream); } } catch { } // Failed to decrypt server's response return(null); }
/// <summary> /// Erzeugt den gemeinsamen Schlüssel und bereitet dessen Übertragung zum Client vor. /// </summary> /// <param name="transactID">Sicherheitstransaktionskennung</param> /// <param name="requestHeaders">Anfrage-Header vom Client</param> /// <param name="responseMsg">Antwortnachricht</param> /// <param name="responseHeaders">Antwort-Header</param> /// <param name="responseStream">Antwort-Datenstrom</param> /// <returns>Status</returns> private ServerProcessing MakeSharedKey(Guid transactID, ITransportHeaders requestHeaders, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { // Gemeinsamer Schlüssel und Inizialisierungsvektor SymmetricAlgorithm symmetricProvider = CryptoTools.CreateSymmetricCryptoProvider(_algorithm); // Clientverbindungsdaten erzeugen ClientConnectionData connectionData = new ClientConnectionData(transactID, symmetricProvider); lock (_connections.SyncRoot) { // Clientverbindungsdaten unter der angegebenen Sicherheitstransaktionskennung speichern _connections[transactID.ToString()] = connectionData; } // RSA Kryptografieanbieter erzeugen RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(); // Öffentlichen Schlüssel (vom Client) aus den Anfrage-Headern lesen string publicKey = (string)requestHeaders[CommonHeaderNames.PUBLIC_KEY]; // Wenn kein öffentlicher Schlüssel gefunden wurde ... if (string.IsNullOrEmpty(publicKey)) { throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_PublicKeyNotFound); } // Öffentlichen Schlüssel in den Kryptografieanbieter laden rsaProvider.FromXmlString(publicKey); // Gemeinsamen Schlüssel und dessen Inizialisierungsfaktor verschlüsseln byte[] encryptedKey = rsaProvider.Encrypt(symmetricProvider.Key, _oaep); byte[] encryptedIV = rsaProvider.Encrypt(symmetricProvider.IV, _oaep); // Antwort-Header zusammenstellen responseHeaders = new TransportHeaders(); responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)SecureTransactionStage.SendingSharedKey).ToString(); responseHeaders[CommonHeaderNames.SHARED_KEY] = Convert.ToBase64String(encryptedKey); responseHeaders[CommonHeaderNames.SHARED_IV] = Convert.ToBase64String(encryptedIV); // Es wird keine Antwortnachricht benötigt responseMsg = null; responseStream = new MemoryStream(); // Vollständige Verarbeitung zurückmelden return(ServerProcessing.Complete); }
/// <summary> /// Entschlüsselt die eingehende Nachricht vom Client. /// </summary> /// <param name="transactID">Sicherheitstransaktionskennung</param> /// <param name="sinkStack">Senkenstapel</param> /// <param name="requestMsg">Anfrage-Nachricht vom Client</param> /// <param name="requestHeaders">Anfrage-Header vom Cient</param> /// <param name="requestStream">Anfrage-Datenstrom</param> /// <param name="responseMsg">Antwort-Nachricht</param> /// <param name="responseHeaders">Antwort-Header</param> /// <param name="responseStream">Antwort-Datenstrom</param> /// <returns>Verarbeitungsstatus</returns> public ServerProcessing ProcessEncryptedMessage(Guid transactID, IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { // Variable für Client-Verbindungsinformationen ClientConnectionData connectionData; lock (_connections.SyncRoot) { // Client-Verbindungsdaten über die angegebene Sicherheitstransaktionskennung abrufen connectionData = (ClientConnectionData)_connections[transactID.ToString()]; } // Wenn keine Verbindungsdaten zu dieser Sicherheitstransaktionskennung gefunden wurden ... if (connectionData == null) { // Ausnahme werfen throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_ClientConnectionInfoMissing); } // Zeitstempel aktualisieren connectionData.UpdateTimestamp(); // Datenstrom entschlüsseln Stream decryptedStream = CryptoTools.GetDecryptedStream(requestStream, connectionData.CryptoProvider); // Verschlüsselten-Quelldatenstrom schließen requestStream.Close(); // Entschlüsselte Nachricht zur Weiterverarbeitung an die nächste Kanalsenke weitergeben ServerProcessing processingResult = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, decryptedStream, out responseMsg, out responseHeaders, out responseStream); // Status der Sicherheitstransaktion auf "verschlüsselte Atwortnachricht senden" einstellen responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)SecureTransactionStage.SendingEncryptedResult).ToString(); // Antwortnachricht verschlüsseln Stream encryptedStream = CryptoTools.GetEncryptedStream(responseStream, connectionData.CryptoProvider); // Unverschlüsselten Quell-Datenstrom schließen responseStream.Close(); // close the plaintext stream now that we're done with it // Verschlüsselten Datenstrom als Antwort-Datenstrom verwenden responseStream = encryptedStream; // Verarbeitungsstatus zurückgeben return(processingResult); }
/// <summary>Entschlüsselt den eingehenden Antwort-Datenstrom</summary> /// <param name="responseStream">Antwort-Datenstrom</param> /// <param name="responseHeaders">Antwort-Transportheader</param> /// <returns>Entschlüsselter Datenstrom (oder null, wenn die Verschlüsselung fehlgeschlagen ist)</returns> private Stream DecryptResponse(Stream responseStream, ITransportHeaders responseHeaders) { try { // Wenn laut Header verschlüsselte Daten vom Server zurückgesendet wurden ... if (responseHeaders != null && (SecureTransactionStage)Convert.ToInt32((string)responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE]) == SecureTransactionStage.SendingEncryptedResult) { // Antwort-Datenstrom entschlüsseln Stream decryptedStream = CryptoTools.GetDecryptedStream(responseStream, _provider); responseStream.Close(); // close the old stream as we won't be using it anymore // Entschlüsselten Datenstrom zurückgeben return(decryptedStream); } } catch {} // Nichts zurückgeben return(null); }
/// <summary> /// Creates the shared key. /// </summary> /// <param name="transactID">Secure transaction identifier.</param> /// <param name="requestHeaders">Request transport headers.</param> /// <param name="responseMsg">The response message.</param> /// <param name="responseHeaders">The response headers.</param> /// <param name="responseStream">The response stream.</param> private ServerProcessing MakeSharedKey(Guid transactID, ITransportHeaders requestHeaders, out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream) { // save shared symmetric encryption key and initialization vector for the current client connection SymmetricAlgorithm symmetricProvider = CryptoTools.CreateSymmetricCryptoProvider(_algorithm); ClientConnectionData connectionData = new ClientConnectionData(transactID, symmetricProvider); // Store client data connection under the specified security transaction identifier lock (_connections.SyncRoot) { _connections[transactID.ToString()] = connectionData; } // Get client's RSA public key string publicKey = (string)requestHeaders[CommonHeaderNames.PUBLIC_KEY]; if (string.IsNullOrEmpty(publicKey)) { throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_PublicKeyNotFound); } // Initialize RSA cryptographic provider using the client's public key RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(); rsaProvider.FromXmlString(publicKey); // Encrypt shared key for the symmetric algorithm using the client's public key byte[] encryptedKey = rsaProvider.Encrypt(symmetricProvider.Key, _oaep); byte[] encryptedIV = rsaProvider.Encrypt(symmetricProvider.IV, _oaep); // Put the data to the response headers responseHeaders = new TransportHeaders(); responseHeaders[CommonHeaderNames.SECURE_TRANSACTION_STATE] = ((int)SecureTransactionStage.SendingSharedKey).ToString(); responseHeaders[CommonHeaderNames.SHARED_KEY] = Convert.ToBase64String(encryptedKey); responseHeaders[CommonHeaderNames.SHARED_IV] = Convert.ToBase64String(encryptedIV); // There is no response message responseMsg = null; responseStream = new MemoryStream(); return(ServerProcessing.Complete); }