0

为什么我得到这个异常。x509 证书中不存在私钥 这是为了生成一个带有 nonce+ 2 个二进制安全令牌的用户名(一个用于用户证书,一个用于服务器)。我的用户证书有一个私钥,但服务器证书没有。这是用于非对称绑定。

    using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.Text;

namespace MYEmedny
{


    public class CustomCredentials : ClientCredentials
    {
        private X509Certificate2 clientAuthCert;
        private X509Certificate2 clientSigningCert;

        public CustomCredentials() : base() { }

        public CustomCredentials(CustomCredentials other)
            : base(other)
        {
            // other.clientSigningCert = SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "LMWARD");
            clientSigningCert = other.clientSigningCert;
            clientAuthCert = other.clientAuthCert;
        }

        protected override ClientCredentials CloneCore()
        {
            CustomCredentials scc = new CustomCredentials(this);
            return scc;
        }

        public CustomCredentials(X509Certificate2 ClientAuthCert, X509Certificate2 ClientSigningCert)
            : base()
        {
            clientAuthCert = ClientAuthCert;
            clientSigningCert = ClientSigningCert;
        }

        public X509Certificate2 ClientAuthCert
        {
            get { return clientAuthCert; }
            set { clientAuthCert = value; }
        }

        public X509Certificate2 ClientSigningCert
        {
            get { return clientSigningCert; }
            set { clientSigningCert = value; }
        }

        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new CustomTokenManager(this);
        }
    }

    public class CustomTokenManager : ClientCredentialsSecurityTokenManager
    {
        private CustomCredentials custCreds;

        public CustomTokenManager(CustomCredentials CustCreds)
            : base(CustCreds)
        {
            custCreds = CustCreds;
        }

        public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
        {
            try
            {
                if (tokenRequirement.TokenType == SecurityTokenTypes.X509Certificate)
                {
                    x509CustomSecurityTokenProvider prov;
                    object temp = null;
                    //TransportSecurityBindingElement secBE = null;
                    AsymmetricSecurityBindingElement secBE = null;

                    if (tokenRequirement.Properties.TryGetValue("http://schemas.microsoft.com/ws/2006/05/servicemodel/securitytokenrequirement/SecurityBindingElement", out temp))
                    {
                        //secBE = (TransportSecurityBindingElement)temp;
                        secBE = (AsymmetricSecurityBindingElement)temp;

                    }

                    if (secBE == null)
                        prov = new x509CustomSecurityTokenProvider(custCreds.ClientAuthCert);
                    else
                        prov = new x509CustomSecurityTokenProvider(custCreds.ClientSigningCert);
                    return prov;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return base.CreateSecurityTokenProvider(tokenRequirement);
        }

        public override System.IdentityModel.Selectors.SecurityTokenSerializer CreateSecurityTokenSerializer(System.IdentityModel.Selectors.SecurityTokenVersion version)
        {
            return new CustomTokenSerializer(System.ServiceModel.Security.SecurityVersion.WSSecurity10);
        }
    }

    class x509CustomSecurityTokenProvider : SecurityTokenProvider
    {
        private X509Certificate2 clientCert;

        public x509CustomSecurityTokenProvider(X509Certificate2 cert)
            : base()
        {
            clientCert = cert;
        }

        protected override SecurityToken GetTokenCore(TimeSpan timeout)
        {
            return new X509SecurityToken(clientCert);
        }
    }

    public class CustomTokenSerializer : WSSecurityTokenSerializer
    {
        public CustomTokenSerializer(SecurityVersion sv) : base(sv) { }

        protected override void WriteTokenCore(System.Xml.XmlWriter writer, System.IdentityModel.Tokens.SecurityToken token)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            if (token.GetType() == new UserNameSecurityToken("x", "y").GetType())
            {
                UserNameSecurityToken userToken = token as UserNameSecurityToken;

                if (userToken == null)
                {
                    throw new ArgumentNullException("userToken: " + token.ToString());
                }

                string tokennamespace = "wsse";

                DateTime created = DateTime.Now;
                string createdStr = created.ToString("yyyy-MM-ddThh:mm:ss.fffZ");
                string phrase = Guid.NewGuid().ToString();
                string nonce = GetSHA1String(phrase);
                string password = userToken.Password;
                //string password = userToken.Password;

                writer.WriteStartElement(tokennamespace, "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                writer.WriteAttributeString("wsu", "Id", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", token.Id);
                writer.WriteElementString(tokennamespace, "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", userToken.UserName);
                writer.WriteStartElement(tokennamespace, "Password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
                writer.WriteValue(password);
                writer.WriteEndElement();
                writer.WriteStartElement(tokennamespace, "Nonce", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
                writer.WriteValue(nonce);
                writer.WriteEndElement();
                writer.WriteElementString(tokennamespace, "Created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", createdStr);
                writer.WriteEndElement();
                writer.Flush();
            }
            else
            {
                base.WriteTokenCore(writer, token);
            }
        }

        protected string GetSHA1String(string phrase)
        {
            SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
            byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
            return Convert.ToBase64String(hashedDataBytes);
        }
    }//CustomTokenSerializer
}

这就是我使用它的方式

private CustomBinding GetCustomBinding()
{


    AsymmetricSecurityBindingElement secBE = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement
        (
        MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10
        );
    secBE.ProtectTokens = false;
    X509SecurityTokenParameters x509ProtectionParameters = new X509SecurityTokenParameters();
    x509ProtectionParameters.RequireDerivedKeys = false;
    x509ProtectionParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.SubjectKeyIdentifier;
    x509ProtectionParameters.ReferenceStyle = SecurityTokenReferenceStyle.Internal;

    //x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
    secBE.MessageSecurityVersion = System.ServiceModel.MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
    secBE.InitiatorTokenParameters = x509ProtectionParameters;
    secBE.RecipientTokenParameters = x509ProtectionParameters;
    secBE.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;

    secBE.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
    secBE.EnableUnsecuredResponse = true;
    secBE.SetKeyDerivation(false);
    secBE.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.TripleDesRsa15;
    secBE.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters());
    secBE.ProtectTokens = true;
    //  secBE.in = SecurityTokenInclusionMode.Never, RequireDerivedKeys = false );
    secBE.EnableUnsecuredResponse = true;
    secBE.IncludeTimestamp = false;

    TextMessageEncodingBindingElement textEncBE = new TextMessageEncodingBindingElement(MessageVersion.Soap11WSAddressing10, System.Text.Encoding.UTF8);
    HttpsTransportBindingElement httpsBE = new HttpsTransportBindingElement();
   httpsBE.RequireClientCertificate = true;

    CustomBinding myBinding = new CustomBinding();
    myBinding.Elements.Add(secBE);
    myBinding.Elements.Add(textEncBE);
    myBinding.Elements.Add(httpsBE);

    return myBinding;
}

    ProxyGeneration.MHSClient proxy = new ProxyGeneration.MHSClient(GetCustomBinding(), new EndpointAddress(new Uri("https://service100.emedny.org:9047/MHService"), EndpointIdentity.CreateDnsIdentity("DPMedsHistory"), new AddressHeaderCollection()));
    var vs = proxy.Endpoint.Behaviors.Where((i) => i.GetType().Namespace.Contains("VisualStudio"));
    proxy.Endpoint.Behaviors.Remove((System.ServiceModel.Description.IEndpointBehavior)vs.Single());
    proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName,"User");
    proxy.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "Server");
  proxy.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
  proxy.Endpoint.Behaviors.Add(new CustomCredentials(GetCertificateFromStore("User"), GetCertificateFromStore("Server")));
    proxy.ClientCredentials.UserName.UserName = "User1";
    proxy.ClientCredentials.UserName.Password = "PWD";
4

0 回答 0