Como: usar certificados X.509 separados para assinatura e criptografia

Este tópico mostra como configurar o WCF (Windows Communication Foundation) para usar certificados diferentes para assinatura e criptografia de mensagens no cliente e no serviço.

Para permitir que certificados diferentes sejam usados para assinatura e criptografia, um cliente personalizado ou credenciais de serviço (ou ambos) precisam ser criados, pois o WCF não fornece uma API para definir vários certificados de cliente ou serviço. Além disso, um gerenciador de token de segurança deve ser fornecido para aproveitar as informações dos vários certificados e criar um provedor de token de segurança apropriado para o uso de chave e a direção da mensagem especificados.

O diagrama a seguir mostra as classes principais usadas, as classes das quais elas herdam (indicadas por uma seta para cima) e os tipos de retorno de determinados métodos e propriedades.

Chart showing how client credentials are used

Para obter mais informações sobre credenciais personalizadas, consulte Passo a passo: criando credenciais personalizadas de cliente e serviço.

Além disso, você precisa criar um verificador de identidade personalizado e vinculá-lo a um elemento de associação de segurança em uma associação personalizada. Você também precisa usar as credenciais personalizadas em vez das credenciais padrão.

O diagrama a seguir mostra as classes envolvidas na associação personalizada e como o verificador de identidade personalizado é vinculado. Vários elementos de associação estão envolvidos, todos herdados de BindingElement. O AsymmetricSecurityBindingElement tem a propriedade LocalClientSecuritySettings, que retorna uma instância de IdentityVerifier, de onde MyIdentityVerifier é personalizado.

Chart showing a custom binding element

Para obter mais informações sobre como criar um verificador de identidade personalizado, consulte Como criar um verificador de identidade de cliente personalizado.

Para usar certificados separados para assinatura e criptografia

  1. Defina uma nova classe de credenciais de cliente que herda da classe ClientCredentials. Implemente quatro novas propriedades para permitir a especificação de vários certificados: ClientSigningCertificate, ClientEncryptingCertificate, ServiceSigningCertificate e ServiceEncryptingCertificate. Substitua também o método CreateSecurityTokenManager para retornar uma instância da classe ClientCredentialsSecurityTokenManager personalizada definida na próxima etapa.

    public class MyClientCredentials : ClientCredentials
    {
        X509Certificate2 clientSigningCert;
        X509Certificate2 clientEncryptingCert;
        X509Certificate2 serviceSigningCert;
        X509Certificate2 serviceEncryptingCert;
    
        public MyClientCredentials()
        {
        }
    
        protected MyClientCredentials(MyClientCredentials other)
            : base(other)
        {
            this.clientEncryptingCert = other.clientEncryptingCert;
            this.clientSigningCert = other.clientSigningCert;
            this.serviceEncryptingCert = other.serviceEncryptingCert;
            this.serviceSigningCert = other.serviceSigningCert;
        }
    
        public X509Certificate2 ClientSigningCertificate
        {
            get
            {
                return this.clientSigningCert;
            }
            set
            {
                this.clientSigningCert = value;
            }
        }
    
        public X509Certificate2 ClientEncryptingCertificate
        {
            get
            {
                return this.clientEncryptingCert;
            }
            set
            {
                this.clientEncryptingCert = value;
            }
        }
    
        public X509Certificate2 ServiceSigningCertificate
        {
            get
            {
                return this.serviceSigningCert;
            }
            set
            {
                this.serviceSigningCert = value;
            }
        }
    
        public X509Certificate2 ServiceEncryptingCertificate
        {
            get
            {
                return this.serviceEncryptingCert;
            }
            set
            {
                this.serviceEncryptingCert = value;
            }
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new MyClientCredentialsSecurityTokenManager(this);
        }
    
        protected override ClientCredentials CloneCore()
        {
            return new MyClientCredentials(this);
        }
    }
    
    Public Class MyClientCredentials
        Inherits ClientCredentials
    
        Private clientSigningCert As X509Certificate2
        Private clientEncryptingCert As X509Certificate2
        Private serviceSigningCert As X509Certificate2
        Private serviceEncryptingCert As X509Certificate2
    
        Public Sub New()
        End Sub
    
        Protected Sub New(ByVal other As MyClientCredentials)
            MyBase.New(other)
            Me.clientEncryptingCert = other.clientEncryptingCert
            Me.clientSigningCert = other.clientSigningCert
            Me.serviceEncryptingCert = other.serviceEncryptingCert
            Me.serviceSigningCert = other.serviceSigningCert
        End Sub
    
        Public Property ClientSigningCertificate() As X509Certificate2
            Get
                Return Me.clientSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientSigningCert = value
            End Set
        End Property
    
        Public Property ClientEncryptingCertificate() As X509Certificate2
            Get
                Return Me.clientEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientEncryptingCert = value
            End Set
        End Property
    
        Public Property ServiceSigningCertificate() As X509Certificate2
            Get
                Return Me.serviceSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceSigningCert = value
            End Set
        End Property
    
        Public Property ServiceEncryptingCertificate() As X509Certificate2
            Get
                Return Me.serviceEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceEncryptingCert = value
            End Set
        End Property
    
        Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
            Return New MyClientCredentialsSecurityTokenManager(Me)
        End Function
    
        Protected Overrides Function CloneCore() As ClientCredentials
            Return New MyClientCredentials(Me)
        End Function
    
    End Class
    
  2. Defina um novo gerenciador de token de segurança do cliente que herda da classe ClientCredentialsSecurityTokenManager. Substitua o método CreateSecurityTokenProvider para criar um provedor de token de segurança apropriado. O parâmetro requirement (um SecurityTokenRequirement) fornece a direção da mensagem e o uso da chave.

    internal class MyClientCredentialsSecurityTokenManager :
        ClientCredentialsSecurityTokenManager
    {
        MyClientCredentials credentials;
    
        public MyClientCredentialsSecurityTokenManager(
            MyClientCredentials credentials): base(credentials)
        {
            this.credentials = credentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(
            SecurityTokenRequirement requirement)
        {
            SecurityTokenProvider result = null;
            if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
            {
                MessageDirection direction = requirement.GetProperty
                    <MessageDirection>(ServiceModelSecurityTokenRequirement.
                    MessageDirectionProperty);
                if (direction == MessageDirection.Output)
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Signature)
                    {
                        result = new X509SecurityTokenProvider(
                            this.credentials.ClientSigningCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(this.credentials.
                            ServiceEncryptingCertificate);
                    }
                }
                else
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Signature)
                    {
                        result = new X509SecurityTokenProvider(this.
                            credentials.ServiceSigningCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(credentials.
                            ClientEncryptingCertificate);
                    }
                }
            }
            else
            {
                result = base.CreateSecurityTokenProvider(requirement);
            }
    
            return result;
        }
    
        public override SecurityTokenAuthenticator
            CreateSecurityTokenAuthenticator(SecurityTokenRequirement
            tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
        {
            return base.CreateSecurityTokenAuthenticator(tokenRequirement,
                out outOfBandTokenResolver);
        }
    }
    
    Friend Class MyClientCredentialsSecurityTokenManager
        Inherits ClientCredentialsSecurityTokenManager
    
        Private credentials As MyClientCredentials
    
        Public Sub New(ByVal credentials As MyClientCredentials)
            MyBase.New(credentials)
            Me.credentials = credentials
        End Sub
    
        Public Overrides Function CreateSecurityTokenProvider(ByVal requirement As SecurityTokenRequirement) As SecurityTokenProvider
            Dim result As SecurityTokenProvider = Nothing
            If requirement.TokenType = SecurityTokenTypes.X509Certificate Then
                Dim direction = requirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
                If direction = MessageDirection.Output Then
                    If requirement.KeyUsage = SecurityKeyUsage.Signature Then
                        result = New X509SecurityTokenProvider(Me.credentials.ClientSigningCertificate)
                    Else
                        result = New X509SecurityTokenProvider(Me.credentials.ServiceEncryptingCertificate)
                    End If
                Else
                    If requirement.KeyUsage = SecurityKeyUsage.Signature Then
                        result = New X509SecurityTokenProvider(Me.credentials.ServiceSigningCertificate)
                    Else
                        result = New X509SecurityTokenProvider(credentials.ClientEncryptingCertificate)
                    End If
                End If
            Else
                result = MyBase.CreateSecurityTokenProvider(requirement)
            End If
    
            Return result
        End Function
    
        Public Overrides Function CreateSecurityTokenAuthenticator(ByVal tokenRequirement As SecurityTokenRequirement, _
                                                                   <System.Runtime.InteropServices.Out()> ByRef outOfBandTokenResolver As SecurityTokenResolver) As SecurityTokenAuthenticator
            Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, _
                                                           outOfBandTokenResolver)
        End Function
    
    End Class
    
  3. Defina uma nova classe de credenciais de serviço que herda da classe ServiceCredentials. Implemente quatro novas propriedades para permitir a especificação de vários certificados: ClientSigningCertificate, ClientEncryptingCertificate, ServiceSigningCertificate e ServiceEncryptingCertificate. Substitua também o método CreateSecurityTokenManager para retornar uma instância da classe ServiceCredentialsSecurityTokenManager personalizada definida na próxima etapa.

    public class MyServiceCredentials : ServiceCredentials
    {
        X509Certificate2 clientSigningCert;
        X509Certificate2 clientEncryptingCert;
        X509Certificate2 serviceSigningCert;
        X509Certificate2 serviceEncryptingCert;
    
        public MyServiceCredentials()
        {
        }
    
        protected MyServiceCredentials(MyServiceCredentials other)
            : base(other)
        {
            this.clientEncryptingCert = other.clientEncryptingCert;
            this.clientSigningCert = other.clientSigningCert;
            this.serviceEncryptingCert = other.serviceEncryptingCert;
            this.serviceSigningCert = other.serviceSigningCert;
        }
    
        public X509Certificate2 ClientSigningCertificate
        {
            get
            {
                return this.clientSigningCert;
            }
            set
            {
                this.clientSigningCert = value;
            }
        }
    
        public X509Certificate2 ClientEncryptingCertificate
        {
            get
            {
                return this.clientEncryptingCert;
            }
            set
            {
                this.clientEncryptingCert = value;
            }
        }
    
        public X509Certificate2 ServiceSigningCertificate
        {
            get
            {
                return this.serviceSigningCert;
            }
            set
            {
                this.serviceSigningCert = value;
            }
        }
    
        public X509Certificate2 ServiceEncryptingCertificate
        {
            get
            {
                return this.serviceEncryptingCert;
            }
            set
            {
                this.serviceEncryptingCert = value;
            }
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new MyServiceCredentialsSecurityTokenManager(this);
        }
    
        protected override ServiceCredentials CloneCore()
        {
            return new MyServiceCredentials(this);
        }
    }
    
    Public Class MyServiceCredentials
        Inherits ServiceCredentials
    
        Private clientSigningCert As X509Certificate2
        Private clientEncryptingCert As X509Certificate2
        Private serviceSigningCert As X509Certificate2
        Private serviceEncryptingCert As X509Certificate2
    
        Public Sub New()
        End Sub
    
        Protected Sub New(ByVal other As MyServiceCredentials)
            MyBase.New(other)
            Me.clientEncryptingCert = other.clientEncryptingCert
            Me.clientSigningCert = other.clientSigningCert
            Me.serviceEncryptingCert = other.serviceEncryptingCert
            Me.serviceSigningCert = other.serviceSigningCert
        End Sub
    
        Public Property ClientSigningCertificate() As X509Certificate2
            Get
                Return Me.clientSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientSigningCert = value
            End Set
        End Property
    
        Public Property ClientEncryptingCertificate() As X509Certificate2
            Get
                Return Me.clientEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientEncryptingCert = value
            End Set
        End Property
    
        Public Property ServiceSigningCertificate() As X509Certificate2
            Get
                Return Me.serviceSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceSigningCert = value
            End Set
        End Property
    
        Public Property ServiceEncryptingCertificate() As X509Certificate2
            Get
                Return Me.serviceEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceEncryptingCert = value
            End Set
        End Property
    
        Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
            Return New MyServiceCredentialsSecurityTokenManager(Me)
        End Function
    
        Protected Overrides Function CloneCore() As ServiceCredentials
            Return New MyServiceCredentials(Me)
        End Function
    
    End Class
    
  4. Defina um novo gerenciador de token de segurança do serviço que herda da classe ServiceCredentialsSecurityTokenManager. Substitua o método CreateSecurityTokenProvider para criar um provedor de token de segurança apropriado, considerando a direção da mensagem passada e o uso da chave.

    internal class MyServiceCredentialsSecurityTokenManager :
        ServiceCredentialsSecurityTokenManager
    {
        MyServiceCredentials credentials;
    
        public MyServiceCredentialsSecurityTokenManager(
            MyServiceCredentials credentials)
            : base(credentials)
        {
            this.credentials = credentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(
            SecurityTokenRequirement requirement)
        {
            SecurityTokenProvider result = null;
            if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
            {
                MessageDirection direction = requirement.
                    GetProperty<MessageDirection>(
                    ServiceModelSecurityTokenRequirement.
                    MessageDirectionProperty);
                if (direction == MessageDirection.Input)
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Exchange)
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ServiceEncryptingCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ClientSigningCertificate);
                    }
                }
                else
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Signature)
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ServiceSigningCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ClientEncryptingCertificate);
                    }
                }
            }
            else
            {
                result = base.CreateSecurityTokenProvider(requirement);
            }
            return result;
        }
    }
    
    Friend Class MyServiceCredentialsSecurityTokenManager
        Inherits ServiceCredentialsSecurityTokenManager
    
        Private credentials As MyServiceCredentials
    
        Public Sub New(ByVal credentials As MyServiceCredentials)
            MyBase.New(credentials)
            Me.credentials = credentials
        End Sub
    
        Public Overrides Function CreateSecurityTokenProvider(ByVal requirement As SecurityTokenRequirement) As SecurityTokenProvider
            Dim result As SecurityTokenProvider = Nothing
            If requirement.TokenType = SecurityTokenTypes.X509Certificate Then
                Dim direction = requirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
                If direction = MessageDirection.Input Then
                    If requirement.KeyUsage = SecurityKeyUsage.Exchange Then
                        result = New X509SecurityTokenProvider(credentials.ServiceEncryptingCertificate)
                    Else
                        result = New X509SecurityTokenProvider(credentials.ClientSigningCertificate)
                    End If
                Else
                    If requirement.KeyUsage = SecurityKeyUsage.Signature Then
                        result = New X509SecurityTokenProvider(credentials.ServiceSigningCertificate)
                    Else
                        result = New X509SecurityTokenProvider(credentials.ClientEncryptingCertificate)
                    End If
                End If
            Else
                result = MyBase.CreateSecurityTokenProvider(requirement)
            End If
            Return result
        End Function
    
    End Class
    

Para usar vários certificados no cliente

  1. Crie uma associação personalizada. O elemento de associação de segurança deve operar em modo duplex para permitir que diferentes provedores de token de segurança estejam presentes para solicitações e respostas. Uma maneira de fazer isso é usar um transporte compatível com o modo duplex ou usar o CompositeDuplexBindingElement conforme mostrado no código a seguir. Vincule o IdentityVerifier personalizado, que é definido na próxima etapa, ao elemento de associação de segurança. Substitua as credenciais de cliente padrão pelas credenciais de cliente personalizadas criadas anteriormente.

                EndpointAddress serviceEndpoint =
                    new EndpointAddress(new Uri("http://localhost:6060/service"));
    
                CustomBinding binding = new CustomBinding();
    
                AsymmetricSecurityBindingElement securityBE =
                    SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(
                    MessageSecurityVersion.
    WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
                // Add a custom IdentityVerifier because the service uses two certificates
                // (one for signing and one for encryption) and an endpoint identity that
                // contains a single identity claim.
                securityBE.LocalClientSettings.IdentityVerifier = new MyIdentityVerifier();
                binding.Elements.Add(securityBE);
    
                CompositeDuplexBindingElement compositeDuplex =
                    new CompositeDuplexBindingElement();
                compositeDuplex.ClientBaseAddress = new Uri("http://localhost:6061/client");
                binding.Elements.Add(compositeDuplex);
    
                binding.Elements.Add(new OneWayBindingElement());
    
                binding.Elements.Add(new HttpTransportBindingElement());
    
                using (ChannelFactory<IMyServiceChannel> factory =
                    new ChannelFactory<IMyServiceChannel>(binding, serviceEndpoint))
                {
                    MyClientCredentials credentials = new MyClientCredentials();
                    SetupCertificates(credentials);
                    factory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
                    factory.Endpoint.Behaviors.Add(credentials);
    
                    IMyServiceChannel channel = factory.CreateChannel();
                    Console.WriteLine(channel.Hello("world"));
                    channel.Close();
                }
    
    Dim serviceEndpoint As New EndpointAddress(New Uri("http://localhost:6060/service"))
    
    Dim binding As New CustomBinding()
    
    Dim securityBE = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
    ' Add a custom IdentityVerifier because the service uses two certificates 
    ' (one for signing and one for encryption) and an endpoint identity that 
    ' contains a single identity claim.
    securityBE.LocalClientSettings.IdentityVerifier = New MyIdentityVerifier()
    binding.Elements.Add(securityBE)
    
    Dim compositeDuplex As New CompositeDuplexBindingElement()
    
    compositeDuplex.ClientBaseAddress = New Uri("http://localhost:6061/client")
    
    With binding.Elements
        .Add(compositeDuplex)
        .Add(New OneWayBindingElement())
        .Add(New HttpTransportBindingElement())
    End With
    
    Using factory As New ChannelFactory(Of IMyServiceChannel)(binding, serviceEndpoint)
        Dim credentials As New MyClientCredentials()
        SetupCertificates(credentials)
    
        With factory.Endpoint.Behaviors
            .Remove(GetType(ClientCredentials))
            .Add(credentials)
        End With
    
        Dim channel = factory.CreateChannel()
        Console.WriteLine(channel.Hello("world"))
        channel.Close()
    End Using
    
  2. Definir um IdentityVerifier personalizado. O serviço tem várias identidades porque certificados diferentes são usados para criptografar a solicitação e assinar a resposta.

    Observação

    No exemplo a seguir, o verificador de identidade personalizado fornecido não executa nenhuma verificação de identidade de ponto de extremidade para fins de demonstração. Essa não é uma prática recomendada para o código de produção.

    class MyIdentityVerifier : IdentityVerifier
    {
        IdentityVerifier defaultVerifier;
    
        public MyIdentityVerifier()
        {
            this.defaultVerifier = IdentityVerifier.CreateDefault();
        }
    
        public override bool CheckAccess(EndpointIdentity identity,
            AuthorizationContext authContext)
        {
            // The following implementation is for demonstration only, and
            // does not perform any checks regarding EndpointIdentity.
            // Do not use this for production code.
            return true;
        }
    
        public override bool TryGetIdentity(EndpointAddress reference,
            out EndpointIdentity identity)
        {
            return this.defaultVerifier.TryGetIdentity(reference, out identity);
        }
    }
    
    
    Friend Class MyIdentityVerifier
        Inherits IdentityVerifier
    
        Private defaultVerifier As IdentityVerifier
    
        Public Sub New()
            Me.defaultVerifier = IdentityVerifier.CreateDefault()
        End Sub
    
        Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, ByVal authContext As AuthorizationContext) As Boolean
            ' The following implementation is for demonstration only, and
            ' does not perform any checks regarding EndpointIdentity.
            ' Do not use this for production code.
            Return True
        End Function
    
        Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
            Return Me.defaultVerifier.TryGetIdentity(reference, identity)
        End Function
    
    End Class
    

Para usar vários certificados no serviço

  1. Crie uma associação personalizada. O elemento de associação de segurança deve operar em modo duplex para permitir que diferentes provedores de token de segurança estejam presentes para solicitações e respostas. Assim como acontece com o cliente, use um transporte compatível com o modo duplex ou use CompositeDuplexBindingElement conforme mostrado no código a seguir. Substitua as credenciais de serviço padrão pelas credenciais de serviço personalizadas criadas anteriormente.

                Uri serviceEndpoint = new Uri("http://localhost:6060/service");
                using (ServiceHost host = new ServiceHost(typeof(Service), serviceEndpoint))
                {
                    CustomBinding binding = new CustomBinding();
                    binding.Elements.Add(SecurityBindingElement.
                        CreateMutualCertificateDuplexBindingElement(
    MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10));
                    binding.Elements.Add(new CompositeDuplexBindingElement());
                    binding.Elements.Add(new OneWayBindingElement());
                    binding.Elements.Add(new HttpTransportBindingElement());
    
                    MyServiceCredentials credentials = new MyServiceCredentials();
                    SetupCertificates(credentials);
                    host.Description.Behaviors.Remove(typeof(ServiceCredentials));
                    host.Description.Behaviors.Add(credentials);
    
                    ServiceEndpoint endpoint = host.AddServiceEndpoint(
                        typeof(IMyService), binding, "");
                    host.Open();
    
                    Console.WriteLine("Service started, press ENTER to stop...");
                    Console.ReadLine();
                }
    
    Dim serviceEndpoint As New Uri("http://localhost:6060/service")
    Using host As New ServiceHost(GetType(Service), serviceEndpoint)
        Dim binding As New CustomBinding()
    
        With binding.Elements
            .Add(SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10))
            .Add(New CompositeDuplexBindingElement())
            .Add(New OneWayBindingElement())
            .Add(New HttpTransportBindingElement())
        End With
    
        Dim credentials As New MyServiceCredentials()
        SetupCertificates(credentials)
        With host.Description.Behaviors
            .Remove(GetType(ServiceCredentials))
            .Add(credentials)
        End With
    
        Dim endpoint = host.AddServiceEndpoint(GetType(IMyService), binding, "")
        host.Open()
    
        Console.WriteLine("Service started, press ENTER to stop...")
        Console.ReadLine()
    End Using
    

Confira também