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; }
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 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> /// 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); } } } }
/// <summary> /// Updates the session after receiving the remote SDP. /// At this point check that the codecs match. We currently only support: /// - Audio: PCMU, /// - Video: VP8. /// If they are not available there's no point carrying on. /// </summary> /// <param name="sessionDescription">The answer/offer SDP from the remote party.</param> public SetDescriptionResultEnum setRemoteDescription(RTCSessionDescriptionInit init) { RTCSessionDescription description = new RTCSessionDescription { type = init.type, sdp = SDP.ParseSDPDescription(init.sdp) }; remoteDescription = description; SDP remoteSdp = SDP.ParseSDPDescription(init.sdp); SdpType sdpType = (init.type == RTCSdpType.offer) ? SdpType.offer : SdpType.answer; var setResult = base.SetRemoteDescription(sdpType, remoteSdp); if (setResult == SetDescriptionResultEnum.OK) { string remoteIceUser = remoteSdp.IceUfrag; string remoteIcePassword = remoteSdp.IcePwd; string dtlsFingerprint = remoteSdp.DtlsFingerprint; var audioAnnounce = remoteSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.audio).FirstOrDefault(); if (audioAnnounce != null) { remoteIceUser = remoteIceUser ?? audioAnnounce.IceUfrag; remoteIcePassword = remoteIcePassword ?? audioAnnounce.IcePwd; dtlsFingerprint = dtlsFingerprint ?? audioAnnounce.DtlsFingerprint; } var videoAnnounce = remoteSdp.Media.Where(x => x.Media == SDPMediaTypesEnum.video).FirstOrDefault(); if (videoAnnounce != null) { if (remoteIceUser == null || remoteIcePassword == null || dtlsFingerprint == null) { remoteIceUser = remoteIceUser ?? videoAnnounce.IceUfrag; remoteIcePassword = remoteIcePassword ?? videoAnnounce.IcePwd; dtlsFingerprint = dtlsFingerprint ?? videoAnnounce.DtlsFingerprint; } } SdpSessionID = remoteSdp.SessionId; if (init.type == RTCSdpType.answer) { _rtpIceChannel.IsController = true; // Set DTLS role to be server. IceRole = IceRolesEnum.passive; } else { // Set DTLS role as client. IceRole = IceRolesEnum.active; } if (remoteIceUser != null && remoteIcePassword != null) { _rtpIceChannel.SetRemoteCredentials(remoteIceUser, remoteIcePassword); } if (!string.IsNullOrWhiteSpace(dtlsFingerprint)) { dtlsFingerprint = dtlsFingerprint.Trim().ToLower(); if (RTCDtlsFingerprint.TryParse(dtlsFingerprint, out var remoteFingerprint)) { RemotePeerDtlsFingerprint = remoteFingerprint; } else { logger.LogWarning($"The DTLS fingerprint was invalid or not supported."); return(SetDescriptionResultEnum.DtlsFingerprintDigestNotSupported); } } else { logger.LogWarning("The DTLS fingerprint was missing from the remote party's session description."); return(SetDescriptionResultEnum.DtlsFingerprintMissing); } // All browsers seem to have gone to trickling ICE candidates now but just // in case one or more are given we can start the STUN dance immediately. if (remoteSdp.IceCandidates != null) { foreach (var iceCandidate in remoteSdp.IceCandidates) { addIceCandidate(new RTCIceCandidateInit { candidate = iceCandidate }); } } foreach (var media in remoteSdp.Media) { if (media.IceCandidates != null) { foreach (var iceCandidate in media.IceCandidates) { addIceCandidate(new RTCIceCandidateInit { candidate = iceCandidate }); } } } signalingState = RTCSignalingState.have_remote_offer; onsignalingstatechange?.Invoke(); } return(setResult); }