예제 #1
0
        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;
        }
예제 #2
0
        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;
        }
예제 #3
0
        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;
        }
예제 #4
0
        /// <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);
                    }
                }
            }
        }
예제 #5
0
        /// <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);
        }