public BitChatService(BitChatProfile profile, Certificate[] trustedRootCertificates, SecureChannelCryptoOptionFlags supportedCryptoOptions, InvalidCertificateEvent invalidCertEventHandler) { //verify root certs foreach (Certificate trustedCert in trustedRootCertificates) trustedCert.Verify(trustedRootCertificates); //verify profile cert profile.LocalCertificateStore.Certificate.Verify(trustedRootCertificates); _invalidCertEventHandler = invalidCertEventHandler; _manager = new InternalBitChatService(this, profile, trustedRootCertificates, supportedCryptoOptions); foreach (BitChatProfile.BitChatInfo bitChatInfo in profile.BitChatInfoList) { if (bitChatInfo.Type == BitChatNetworkType.PrivateChat) _bitChats.Add(_manager.CreateBitChat(new MailAddress(bitChatInfo.NetworkNameOrPeerEmailAddress), bitChatInfo.SharedSecret, bitChatInfo.NetworkID, bitChatInfo.PeerCertificateList, bitChatInfo.SharedFileList, bitChatInfo.TrackerURIs)); else _bitChats.Add(_manager.CreateBitChat(bitChatInfo.NetworkNameOrPeerEmailAddress, bitChatInfo.SharedSecret, bitChatInfo.NetworkID, bitChatInfo.PeerCertificateList, bitChatInfo.SharedFileList, bitChatInfo.TrackerURIs)); } //check profile cert revocation ThreadPool.QueueUserWorkItem(CheckCertificateRevocationAsync, new Certificate[] { profile.LocalCertificateStore.Certificate }); //check trusted root cert revocation ThreadPool.QueueUserWorkItem(CheckCertificateRevocationAsync, trustedRootCertificates); }
public BitChatClient(BitChatProfile profile, Certificate[] trustedRootCertificates, SecureChannelCryptoOptionFlags supportedCryptoOptions) { _profile = profile; _trustedRootCertificates = trustedRootCertificates; _supportedCryptoOptions = supportedCryptoOptions; _maskedEmailAddress = BitChatNetwork.GetMaskedEmailAddress(_profile.LocalCertificateStore.Certificate.IssuedTo.EmailAddress); _profile.ProxyUpdated += profile_ProxyUpdated; _profile.ProfileImageChanged += profile_ProfileImageChanged; }
int _reNegotiateAfterSeconds = 3600; //1hr #endregion #region constructor public InternalBitChatService(BitChatService service, BitChatProfile profile, Certificate[] trustedRootCertificates, SecureChannelCryptoOptionFlags supportedCryptoOptions) { _service = service; _profile = profile; _trustedRootCertificates = trustedRootCertificates; _supportedCryptoOptions = supportedCryptoOptions; _connectionManager = new ConnectionManager(_profile.LocalEP, ChannelRequest); LocalPeerDiscovery.StartListener(41733); _localDiscovery = new LocalPeerDiscovery(_connectionManager.LocalEP.Port); _localDiscovery.PeerDiscovered += _localDiscovery_PeerDiscovered; _profile.LocalEP = _connectionManager.LocalEP; }
public SecureChannelClientStream(Stream stream, IPEndPoint remotePeerEP, CertificateStore clientCredentials, Certificate[] trustedRootCertificates, ISecureChannelSecurityManager manager, SecureChannelCryptoOptionFlags supportedOptions, int reNegotiateOnBytesSent, int reNegotiateAfterSeconds, string preSharedKey = null) : base(remotePeerEP, reNegotiateOnBytesSent, reNegotiateAfterSeconds) { _clientCredentials = clientCredentials; _trustedRootCertificates = trustedRootCertificates; _manager = manager; _supportedOptions = supportedOptions; _preSharedKey = preSharedKey; try { //read server protocol version _version = stream.ReadByte(); switch (_version) { case 4: //send supported client version stream.WriteByte(4); ProtocolV4(stream, clientCredentials, trustedRootCertificates, manager, preSharedKey, supportedOptions); break; default: throw new SecureChannelException(SecureChannelCode.ProtocolVersionNotSupported, _remotePeerEP, _remotePeerCert, "SecureChannel protocol version '" + _version + "' not supported."); } } catch (SecureChannelException ex) { try { if (_baseStream == null) { SecureChannelPacket.WritePacket(stream, ex.Code); } else { SecureChannelPacket.WritePacket(this, ex.Code); } } catch { } throw new SecureChannelException(ex.Code, _remotePeerEP, _remotePeerCert, ex.Message, ex.InnerException); } }
public SecureChannelClientStream(Stream stream, IPEndPoint remotePeerEP, CertificateStore clientCredentials, Certificate[] trustedRootCertificates, ISecureChannelSecurityManager manager, SecureChannelCryptoOptionFlags supportedOptions, int reNegotiateOnBytesSent, int reNegotiateAfterSeconds, string preSharedKey = null) : base(remotePeerEP, reNegotiateOnBytesSent, reNegotiateAfterSeconds) { _clientCredentials = clientCredentials; _trustedRootCertificates = trustedRootCertificates; _manager = manager; _supportedOptions = supportedOptions; _preSharedKey = preSharedKey; try { //read server protocol version _version = stream.ReadByte(); switch (_version) { case 4: //send supported client version stream.WriteByte(4); ProtocolV4(stream, clientCredentials, trustedRootCertificates, manager, preSharedKey, supportedOptions); break; default: throw new SecureChannelException(SecureChannelCode.ProtocolVersionNotSupported, _remotePeerEP, _remotePeerCert, "SecureChannel protocol version '" + _version + "' not supported."); } } catch (SecureChannelException ex) { try { if (_baseStream == null) SecureChannelPacket.WritePacket(stream, ex.Code); else SecureChannelPacket.WritePacket(this, ex.Code); } catch { } throw new SecureChannelException(ex.Code, _remotePeerEP, _remotePeerCert, ex.Message, ex.InnerException); } }
public SecureChannelServerStream(Stream stream, IPEndPoint remotePeerEP, CertificateStore serverCredentials, Certificate[] trustedRootCertificates, ISecureChannelSecurityManager manager, SecureChannelCryptoOptionFlags supportedOptions, int reNegotiateOnBytesSent, int reNegotiateAfterSeconds, byte[] preSharedKey) : base(remotePeerEP, reNegotiateOnBytesSent, reNegotiateAfterSeconds) { _serverCredentials = serverCredentials; _trustedRootCertificates = trustedRootCertificates; _manager = manager; _supportedOptions = supportedOptions; _preSharedKey = preSharedKey; try { //send server protocol version stream.WriteByte(4); //read client protocol version _version = stream.ReadByte(); switch (_version) { case 4: ProtocolV4(stream); break; case -1: throw new EndOfStreamException(); default: throw new SecureChannelException(SecureChannelCode.ProtocolVersionNotSupported, _remotePeerEP, _remotePeerCert, "SecureChannel protocol version '" + _version + "' not supported."); } } catch (SecureChannelException ex) { if (ex.Code == SecureChannelCode.RemoteError) { throw new SecureChannelException(ex.Code, _remotePeerEP, _remotePeerCert, ex.Message, ex); } else { try { if (_baseStream == null) { SecureChannelPacket.WritePacket(stream, ex.Code); } else { SecureChannelPacket.WritePacket(this, ex.Code); } } catch { } throw; } } catch (IOException) { throw; } catch { try { if (_baseStream == null) { SecureChannelPacket.WritePacket(stream, SecureChannelCode.UnknownException); } else { SecureChannelPacket.WritePacket(this, SecureChannelCode.UnknownException); } } catch { } throw; } }
public InternalBitChatService(BitChatService service, BitChatProfile profile, Certificate[] trustedRootCertificates, SecureChannelCryptoOptionFlags supportedCryptoOptions) { _service = service; _profile = profile; _trustedRootCertificates = trustedRootCertificates; _supportedCryptoOptions = supportedCryptoOptions; _connectionManager = new ConnectionManager(_profile.LocalEP, ChannelRequest); LocalPeerDiscovery.StartListener(41733); _localDiscovery = new LocalPeerDiscovery(_connectionManager.LocalEP.Port); _localDiscovery.PeerDiscovered += _localDiscovery_PeerDiscovered; _profile.LocalEP = _connectionManager.LocalEP; }
private void ProtocolV4(Stream stream, CertificateStore clientCredentials, Certificate[] trustedRootCertificates, ISecureChannelSecurityManager manager, string preSharedKey, SecureChannelCryptoOptionFlags supportedOptions) { #region 1. hello handshake //send client hello SecureChannelPacket.Hello clientHello = new SecureChannelPacket.Hello(BinaryID.GenerateRandomID256(), supportedOptions); SecureChannelPacket.WritePacket(stream, clientHello); //read server hello SecureChannelPacket.Hello serverHello = (new SecureChannelPacket(stream)).GetHello(); //read selected crypto option _selectedCryptoOption = supportedOptions & serverHello.CryptoOptions; if (_selectedCryptoOption == SecureChannelCryptoOptionFlags.None) { throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } #endregion #region 2. key exchange //read server key exchange data SecureChannelPacket.KeyExchange serverKeyExchange = (new SecureChannelPacket(stream)).GetKeyExchange(); SymmetricEncryptionAlgorithm encAlgo; string hashAlgo; KeyAgreement keyAgreement; switch (_selectedCryptoOption) { case SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256: encAlgo = SymmetricEncryptionAlgorithm.Rijndael; hashAlgo = "SHA256"; keyAgreement = new DiffieHellman(DiffieHellmanGroupType.RFC3526, 2048, KeyAgreementKeyDerivationFunction.Hmac, KeyAgreementKeyDerivationHashAlgorithm.SHA256); break; case SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256: encAlgo = SymmetricEncryptionAlgorithm.Rijndael; hashAlgo = "SHA256"; keyAgreement = new TechnitiumLibrary.Security.Cryptography.ECDiffieHellman(256, KeyAgreementKeyDerivationFunction.Hmac, KeyAgreementKeyDerivationHashAlgorithm.SHA256); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //send client key exchange data SecureChannelPacket.KeyExchange clientKeyExchange = new SecureChannelPacket.KeyExchange(keyAgreement.GetPublicKeyXML(), clientCredentials.PrivateKey, hashAlgo); SecureChannelPacket.WritePacket(stream, clientKeyExchange); //generate master key byte[] masterKey = GenerateMasterKey(clientHello, serverHello, _preSharedKey, keyAgreement, serverKeyExchange.PublicKeyXML); //verify master key using HMAC authentication { SecureChannelPacket.Authentication clientAuthentication = new SecureChannelPacket.Authentication(serverHello, masterKey); SecureChannelPacket.WritePacket(stream, clientAuthentication); SecureChannelPacket.Authentication serverAuthentication = (new SecureChannelPacket(stream)).GetAuthentication(); if (!serverAuthentication.IsValid(clientHello, masterKey)) { throw new SecureChannelException(SecureChannelCode.ProtocolAuthenticationFailed, _remotePeerEP, _remotePeerCert); } } //enable channel encryption switch (encAlgo) { case SymmetricEncryptionAlgorithm.Rijndael: //using MD5 for generating AES IV of 128bit block size HashAlgorithm md5Hash = HashAlgorithm.Create("MD5"); byte[] eIV = md5Hash.ComputeHash(clientHello.Nonce.ID); byte[] dIV = md5Hash.ComputeHash(serverHello.Nonce.ID); //create encryption and decryption objects SymmetricCryptoKey encryptionKey = new SymmetricCryptoKey(SymmetricEncryptionAlgorithm.Rijndael, masterKey, eIV, PaddingMode.None); SymmetricCryptoKey decryptionKey = new SymmetricCryptoKey(SymmetricEncryptionAlgorithm.Rijndael, masterKey, dIV, PaddingMode.None); //enable encryption EnableEncryption(stream, encryptionKey, decryptionKey, new HMACSHA256(masterKey), new HMACSHA256(masterKey)); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //channel encryption is ON! #endregion #region 3. exchange & verify certificates & signatures if (!_reNegotiating) { //send client certificate SecureChannelPacket.WritePacket(this, clientCredentials.Certificate); //read server certificate _remotePeerCert = (new SecureChannelPacket(this)).GetCertificate(); //verify server certificate try { _remotePeerCert.Verify(trustedRootCertificates); } catch (Exception ex) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteCertificate, _remotePeerEP, _remotePeerCert, "Invalid remote certificate.", ex); } } //verify key exchange signature switch (_selectedCryptoOption) { case SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256: case SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256: if (_remotePeerCert.PublicKeyEncryptionAlgorithm != AsymmetricEncryptionAlgorithm.RSA) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteCertificateAlgorithm, _remotePeerEP, _remotePeerCert); } if (!serverKeyExchange.IsSignatureValid(_remotePeerCert, "SHA256")) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteKeyExchangeSignature, _remotePeerEP, _remotePeerCert); } break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } if ((manager != null) && !manager.ProceedConnection(_remotePeerCert)) { throw new SecureChannelException(SecureChannelCode.SecurityManagerDeclinedAccess, _remotePeerEP, _remotePeerCert, "Security manager declined access."); } #endregion }
private void ProtocolV4(Stream stream, CertificateStore clientCredentials, Certificate[] trustedRootCertificates, ISecureChannelSecurityManager manager, string preSharedKey, SecureChannelCryptoOptionFlags supportedOptions) { #region 1. hello handshake //send client hello SecureChannelPacket.Hello clientHello = new SecureChannelPacket.Hello(BinaryID.GenerateRandomID256(), supportedOptions); SecureChannelPacket.WritePacket(stream, clientHello); //read server hello SecureChannelPacket.Hello serverHello = (new SecureChannelPacket(stream)).GetHello(); //read selected crypto option _selectedCryptoOption = supportedOptions & serverHello.CryptoOptions; if (_selectedCryptoOption == SecureChannelCryptoOptionFlags.None) throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); #endregion #region 2. key exchange //read server key exchange data SecureChannelPacket.KeyExchange serverKeyExchange = (new SecureChannelPacket(stream)).GetKeyExchange(); SymmetricEncryptionAlgorithm encAlgo; string hashAlgo; KeyAgreement keyAgreement; switch (_selectedCryptoOption) { case SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256: encAlgo = SymmetricEncryptionAlgorithm.Rijndael; hashAlgo = "SHA256"; keyAgreement = new DiffieHellman(DiffieHellmanGroupType.RFC3526, 2048, KeyAgreementKeyDerivationFunction.Hmac, KeyAgreementKeyDerivationHashAlgorithm.SHA256); break; case SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256: encAlgo = SymmetricEncryptionAlgorithm.Rijndael; hashAlgo = "SHA256"; keyAgreement = new TechnitiumLibrary.Security.Cryptography.ECDiffieHellman(256, KeyAgreementKeyDerivationFunction.Hmac, KeyAgreementKeyDerivationHashAlgorithm.SHA256); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //send client key exchange data SecureChannelPacket.KeyExchange clientKeyExchange = new SecureChannelPacket.KeyExchange(keyAgreement.GetPublicKeyXML(), clientCredentials.PrivateKey, hashAlgo); SecureChannelPacket.WritePacket(stream, clientKeyExchange); //generate master key byte[] masterKey = GenerateMasterKey(clientHello, serverHello, _preSharedKey, keyAgreement, serverKeyExchange.PublicKeyXML); //verify master key using HMAC authentication { SecureChannelPacket.Authentication clientAuthentication = new SecureChannelPacket.Authentication(serverHello, masterKey); SecureChannelPacket.WritePacket(stream, clientAuthentication); SecureChannelPacket.Authentication serverAuthentication = (new SecureChannelPacket(stream)).GetAuthentication(); if (!serverAuthentication.IsValid(clientHello, masterKey)) throw new SecureChannelException(SecureChannelCode.ProtocolAuthenticationFailed, _remotePeerEP, _remotePeerCert); } //enable channel encryption switch (encAlgo) { case SymmetricEncryptionAlgorithm.Rijndael: //using MD5 for generating AES IV of 128bit block size HashAlgorithm md5Hash = HashAlgorithm.Create("MD5"); byte[] eIV = md5Hash.ComputeHash(clientHello.Nonce.ID); byte[] dIV = md5Hash.ComputeHash(serverHello.Nonce.ID); //create encryption and decryption objects SymmetricCryptoKey encryptionKey = new SymmetricCryptoKey(SymmetricEncryptionAlgorithm.Rijndael, masterKey, eIV, PaddingMode.None); SymmetricCryptoKey decryptionKey = new SymmetricCryptoKey(SymmetricEncryptionAlgorithm.Rijndael, masterKey, dIV, PaddingMode.None); //enable encryption EnableEncryption(stream, encryptionKey, decryptionKey, new HMACSHA256(masterKey), new HMACSHA256(masterKey)); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } //channel encryption is ON! #endregion #region 3. exchange & verify certificates & signatures if (!_reNegotiating) { //send client certificate SecureChannelPacket.WritePacket(this, clientCredentials.Certificate); //read server certificate _remotePeerCert = (new SecureChannelPacket(this)).GetCertificate(); //verify server certificate try { _remotePeerCert.Verify(trustedRootCertificates); } catch (Exception ex) { throw new SecureChannelException(SecureChannelCode.InvalidRemoteCertificate, _remotePeerEP, _remotePeerCert, "Invalid remote certificate.", ex); } } //verify key exchange signature switch (_selectedCryptoOption) { case SecureChannelCryptoOptionFlags.DHE2048_RSA_WITH_AES256_CBC_HMAC_SHA256: case SecureChannelCryptoOptionFlags.ECDHE256_RSA_WITH_AES256_CBC_HMAC_SHA256: if (_remotePeerCert.PublicKeyEncryptionAlgorithm != AsymmetricEncryptionAlgorithm.RSA) throw new SecureChannelException(SecureChannelCode.InvalidRemoteCertificateAlgorithm, _remotePeerEP, _remotePeerCert); if (!serverKeyExchange.IsSignatureValid(_remotePeerCert, "SHA256")) throw new SecureChannelException(SecureChannelCode.InvalidRemoteKeyExchangeSignature, _remotePeerEP, _remotePeerCert); break; default: throw new SecureChannelException(SecureChannelCode.NoMatchingCryptoAvailable, _remotePeerEP, _remotePeerCert); } if ((manager != null) && !manager.ProceedConnection(_remotePeerCert)) throw new SecureChannelException(SecureChannelCode.SecurityManagerDeclinedAccess, _remotePeerEP, _remotePeerCert, "Security manager declined access."); #endregion }
public Hello(Stream s) { _nonce = new BinaryID(s); _cryptoOptions = (SecureChannelCryptoOptionFlags)s.ReadByte(); }
public Hello(BinaryID nonce, SecureChannelCryptoOptionFlags cryptoOptions) { _nonce = nonce; _cryptoOptions = cryptoOptions; }
public SecureChannelHandshakeHello(Stream s) : base(s) { _nonce = new BinaryNumber(s); _cryptoOptions = (SecureChannelCryptoOptionFlags)s.ReadByte(); }
public SecureChannelHandshakeHello(BinaryNumber nonce, SecureChannelCryptoOptionFlags cryptoOptions) : base(SecureChannelCode.None) { _nonce = nonce; _cryptoOptions = cryptoOptions; }
public BitChatService(BitChatProfile profile, Certificate[] trustedRootCertificates, SecureChannelCryptoOptionFlags supportedCryptoOptions, InvalidCertificateEvent invalidCertEventHandler) { //verify root certs foreach (Certificate trustedCert in trustedRootCertificates) { trustedCert.Verify(trustedRootCertificates); } //verify profile cert profile.LocalCertificateStore.Certificate.Verify(trustedRootCertificates); _invalidCertEventHandler = invalidCertEventHandler; _manager = new InternalBitChatService(this, profile, trustedRootCertificates, supportedCryptoOptions); foreach (BitChatProfile.BitChatInfo bitChatInfo in profile.BitChatInfoList) { if (bitChatInfo.Type == BitChatNetworkType.PrivateChat) { _bitChats.Add(_manager.CreateBitChat(new MailAddress(bitChatInfo.NetworkNameOrPeerEmailAddress), bitChatInfo.SharedSecret, bitChatInfo.NetworkID, bitChatInfo.PeerCertificateList, bitChatInfo.SharedFileList, bitChatInfo.TrackerURIs)); } else { _bitChats.Add(_manager.CreateBitChat(bitChatInfo.NetworkNameOrPeerEmailAddress, bitChatInfo.SharedSecret, bitChatInfo.NetworkID, bitChatInfo.PeerCertificateList, bitChatInfo.SharedFileList, bitChatInfo.TrackerURIs)); } } //check profile cert revocation ThreadPool.QueueUserWorkItem(CheckCertificateRevocationAsync, new Certificate[] { profile.LocalCertificateStore.Certificate }); //check trusted root cert revocation ThreadPool.QueueUserWorkItem(CheckCertificateRevocationAsync, trustedRootCertificates); }
public Hello(Stream s) { _nonce = new BinaryID(s); _cryptoOptions = (SecureChannelCryptoOptionFlags)s.ReadByte(); }
public Hello(BinaryID nonce, SecureChannelCryptoOptionFlags cryptoOptions) { _nonce = nonce; _cryptoOptions = cryptoOptions; }