public DtlsSrtpClient(Certificate certificateChain, AsymmetricKeyParameter privateKey, UseSrtpData clientSrtpData) { if (certificateChain == null && privateKey == null) { (certificateChain, privateKey) = DtlsUtils.CreateSelfSignedTlsCert(); } if (clientSrtpData == null) { SecureRandom random = new SecureRandom(); int[] protectionProfiles = { SrtpProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80 }; byte[] mki = new byte[(SrtpParameters.SRTP_AES128_CM_HMAC_SHA1_80.GetCipherKeyLength() + SrtpParameters.SRTP_AES128_CM_HMAC_SHA1_80.GetCipherSaltLength()) / 8]; random.NextBytes(mki); // Reusing our secure random for generating the key. this.clientSrtpData = new UseSrtpData(protectionProfiles, mki); } else { this.clientSrtpData = clientSrtpData; } this.mPrivateKey = privateKey; mCertificateChain = certificateChain; //Generate FingerPrint var certificate = mCertificateChain.GetCertificateAt(0); Fingerprint = certificate != null?DtlsUtils.Fingerprint(certificate) : null; }
protected override TlsSignerCredentials GetRsaSignerCredentials() { /* * TODO Note that this code fails to provide default value for the client supported * algorithms if it wasn't sent. */ SignatureAndHashAlgorithm signatureAndHashAlgorithm = null; IList sigAlgs = mSupportedSignatureAlgorithms; if (sigAlgs != null) { foreach (var sigAlgUncasted in sigAlgs) { SignatureAndHashAlgorithm sigAlg = sigAlgUncasted as SignatureAndHashAlgorithm; if (sigAlg != null && sigAlg.Signature == SignatureAlgorithm.rsa) { signatureAndHashAlgorithm = sigAlg; break; } } if (signatureAndHashAlgorithm == null) { return(null); } } return(DtlsUtils.LoadSignerCredentials(mContext, mCertificateChain, mPrivateKey, signatureAndHashAlgorithm)); }
public DtlsSrtpServer(Certificate certificateChain, AsymmetricKeyParameter privateKey) { this.cipherSuites = base.GetCipherSuites(); this.mPrivateKey = privateKey; mCertificateChain = certificateChain; //Generate FingerPrint var certificate = mCertificateChain.GetCertificateAt(0); this.mFingerPrint = certificate != null?DtlsUtils.Fingerprint(certificate) : null; }
public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest) { byte[] certificateTypes = certificateRequest.CertificateTypes; if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign)) { return(null); } return(DtlsUtils.LoadSignerCredentials(mContext, certificateRequest.SupportedSignatureAlgorithms, SignatureAlgorithm.rsa, mClient.mCertificateChain, mClient.mPrivateKey)); }
public DtlsSrtpServer(Certificate certificateChain, AsymmetricKeyParameter privateKey) { if (certificateChain == null && privateKey == null) { (certificateChain, privateKey) = DtlsUtils.CreateSelfSignedTlsCert(); } this.cipherSuites = base.GetCipherSuites(); this.mPrivateKey = privateKey; mCertificateChain = certificateChain; //Generate FingerPrint var certificate = mCertificateChain.GetCertificateAt(0); this.mFingerPrint = certificate != null?DtlsUtils.Fingerprint(certificate) : null; }
/// <summary> /// DtlsHandshake requires DtlsSrtpTransport to work. /// DtlsSrtpTransport is similar to C++ DTLS class combined with Srtp class and can perform /// Handshake as Server or Client in same call. The constructor of transport require a DtlsStrpClient /// or DtlsSrtpServer to work. /// </summary> /// <param name="dtlsHandle">The DTLS transport handle to perform the handshake with.</param> /// <returns></returns> private bool DoDtlsHandshake(DtlsSrtpTransport dtlsHandle) { logger.LogDebug("RTCPeerConnection DoDtlsHandshake started."); var rtpChannel = GetRtpChannel(SDPMediaTypesEnum.audio); dtlsHandle.OnDataReady += (buf) => { //logger.LogDebug($"DTLS transport sending {buf.Length} bytes to {AudioDestinationEndPoint}."); rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, AudioDestinationEndPoint, buf); }; var handshakeResult = dtlsHandle.DoHandshake(); if (!handshakeResult) { logger.LogWarning($"RTCPeerConnection DTLS handshake failed."); return(false); } else { logger.LogDebug($"RTCPeerConnection DTLS handshake result {handshakeResult}, is handshake complete {dtlsHandle.IsHandshakeComplete()}."); var expectedFp = RemotePeerDtlsFingerprint; var remoteFingerprint = DtlsUtils.Fingerprint(expectedFp.algorithm, dtlsHandle.GetRemoteCertificate().GetCertificateAt(0)); if (remoteFingerprint.value != expectedFp.value) { logger.LogWarning($"RTCPeerConnection remote certificate fingerprint mismatch, expected {expectedFp}, actual {remoteFingerprint}."); return(false); } else { logger.LogDebug($"RTCPeerConnection remote certificate fingerprint matched expected value of {remoteFingerprint.value} for {remoteFingerprint.algorithm}."); base.SetSecurityContext( dtlsHandle.ProtectRTP, dtlsHandle.UnprotectRTP, dtlsHandle.ProtectRTCP, dtlsHandle.UnprotectRTCP); return(true); } } }
/// <summary> /// Attempts to parse the fingerprint fields from a string. /// </summary> /// <param name="str">The string to parse from.</param> /// <param name="fingerprint">If successful a fingerprint object.</param> /// <returns>True if a fingerprint was successfully parsed. False if not.</returns> public static bool TryParse(string str, out RTCDtlsFingerprint fingerprint) { fingerprint = null; if (string.IsNullOrEmpty(str)) { return(false); } else { int spaceIndex = str.IndexOf(' '); if (spaceIndex == -1) { return(false); } else { string algStr = str.Substring(0, spaceIndex); string val = str.Substring(spaceIndex + 1); if (!DtlsUtils.IsHashSupported(algStr)) { return(false); } else { fingerprint = new RTCDtlsFingerprint { algorithm = algStr, value = val }; return(true); } } } }
public DtlsSrtpClient(string[] certificatesPath, string keyPath) : this(DtlsUtils.LoadCertificateChain(certificatesPath), DtlsUtils.LoadPrivateKeyResource(keyPath)) { }
public DtlsSrtpClient(X509Certificate2 certificate) : this(DtlsUtils.LoadCertificateChain(certificate), DtlsUtils.LoadPrivateKeyResource(certificate)) { }
protected override TlsEncryptionCredentials GetRsaEncryptionCredentials() { return(DtlsUtils.LoadEncryptionCredentials(mContext, mCertificateChain, mPrivateKey)); }
protected override TlsSignerCredentials GetECDsaSignerCredentials() { return(DtlsUtils.LoadSignerCredentials(mContext, mCertificateChain, mPrivateKey, new SignatureAndHashAlgorithm(HashAlgorithm.sha256, SignatureAlgorithm.ecdsa))); }
public List <RTCDtlsFingerprint> getFingerprints() { return(new List <RTCDtlsFingerprint> { DtlsUtils.Fingerprint(Certificate) }); }
public DtlsSrtpClient(UseSrtpData clientSrtpData) : this(DtlsUtils.CreateSelfSignedCert()) { this.clientSrtpData = clientSrtpData; }
public DtlsSrtpClient() : this(DtlsUtils.CreateSelfSignedCert()) { }
public DtlsSrtpServer() : this(DtlsUtils.CreateSelfSignedCert()) { }
public DtlsSrtpServer(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) : this(DtlsUtils.LoadCertificateChain(certificate), DtlsUtils.LoadPrivateKeyResource(certificate)) { }
/// <summary> /// Constructor to create a new RTC peer connection instance. /// </summary> /// <param name="configuration">Optional.</param> public RTCPeerConnection(RTCConfiguration configuration) : base(true, true, true, configuration?.X_BindAddress) { if (_configuration != null && _configuration.iceTransportPolicy == RTCIceTransportPolicy.relay && _configuration.iceServers?.Count == 0) { throw new ApplicationException("RTCPeerConnection must have at least one ICE server specified for a relay only transport policy."); } if (configuration != null) { _configuration = configuration; if (_configuration.certificates?.Count > 0) { // Find the first certificate that has a usable private key. RTCCertificate usableCert = null; foreach (var cert in _configuration.certificates) { // Attempting to check that a certificate has an exportable private key. // TODO: Does not seem to be a particularly reliable way of checking private key exportability. if (cert.Certificate.HasPrivateKey) { //if (cert.Certificate.PrivateKey is RSACryptoServiceProvider) //{ // var rsa = cert.Certificate.PrivateKey as RSACryptoServiceProvider; // if (!rsa.CspKeyContainerInfo.Exportable) // { // logger.LogWarning($"RTCPeerConnection was passed a certificate for {cert.Certificate.FriendlyName} with a non-exportable RSA private key."); // } // else // { // usableCert = cert; // break; // } //} //else //{ usableCert = cert; break; //} } } if (usableCert == null) { throw new ApplicationException("RTCPeerConnection was not able to find a certificate from the input configuration list with a usable private key."); } else { _currentCertificate = usableCert; } } if (_configuration.X_UseRtpFeedbackProfile) { RTP_MEDIA_PROFILE = RTP_MEDIA_FEEDBACK_PROFILE; } } else { _configuration = new RTCConfiguration(); } // No certificate was provided so create a new self signed one. if (_configuration.certificates == null || _configuration.certificates.Count == 0) { _currentCertificate = new RTCCertificate { Certificate = DtlsUtils.CreateSelfSignedCert() }; _configuration.certificates = new List <RTCCertificate> { _currentCertificate }; } SessionID = Guid.NewGuid().ToString(); LocalSdpSessionID = Crypto.GetRandomInt(5).ToString(); // Request the underlying RTP session to create a single RTP channel that will // be used to multiplex all required media streams. addSingleTrack(); _rtpIceChannel = GetRtpChannel(); _rtpIceChannel.OnIceCandidate += (candidate) => onicecandidate?.Invoke(candidate); _rtpIceChannel.OnIceConnectionStateChange += (state) => { if (state == RTCIceConnectionState.connected && _rtpIceChannel.NominatedEntry != null) { var connectedEP = _rtpIceChannel.NominatedEntry.RemoteCandidate.DestinationEndPoint; base.SetDestination(SDPMediaTypesEnum.audio, connectedEP, connectedEP); logger.LogInformation($"ICE connected to remote end point {AudioDestinationEndPoint}."); DtlsSrtpTransport dtlsHandle = new DtlsSrtpTransport( IceRole == IceRolesEnum.active ? (IDtlsSrtpPeer) new DtlsSrtpClient(_currentCertificate.Certificate) : (IDtlsSrtpPeer) new DtlsSrtpServer(_currentCertificate.Certificate)); OnDtlsPacket += (buf) => { logger.LogDebug($"DTLS transport received {buf.Length} bytes from {AudioDestinationEndPoint}."); dtlsHandle.WriteToRecvStream(buf); }; logger.LogDebug($"Starting DLS handshake with role {IceRole}."); Task.Run <bool>(() => DoDtlsHandshake(dtlsHandle)) .ContinueWith(t => { if (t.IsFaulted) { logger.LogWarning($"RTCPeerConnection DTLS handshake task completed in a faulted state. {t.Exception?.Flatten().Message}"); connectionState = RTCPeerConnectionState.failed; onconnectionstatechange?.Invoke(connectionState); } else { connectionState = (t.Result) ? RTCPeerConnectionState.connected : connectionState = RTCPeerConnectionState.failed; onconnectionstatechange?.Invoke(connectionState); } }); } iceConnectionState = state; oniceconnectionstatechange?.Invoke(iceConnectionState); }; _rtpIceChannel.OnIceGatheringStateChange += (state) => onicegatheringstatechange?.Invoke(state); _rtpIceChannel.OnIceCandidateError += (candidate, error) => onicecandidateerror?.Invoke(candidate, error); OnRtpClosed += Close; OnRtcpBye += Close; onnegotiationneeded?.Invoke(); _rtpIceChannel.StartGathering(); }