murat sekerci
murat sekerci

Reputation: 11

C# WCF Soap Sign Sha256 "keyset does not exist"

I call a web service which requires a WSS. TimeStamp and Body blocks should be signed by Digital Signature (I use USB token)

I do the job by using AsymmetricSecurityBindingElement.

If a use DefaultAlgorithmSuite, signing request message works perfectly. But when changed DefaultAsymmetricSignatureAlgorithm to RsaSha256Signature by CustomDefaultAlgorithmSuite class, it throws

"CryptographicException: keyset does not exist" (at line : durum response = proxy.getBatchStatus("1");

X509Certificate2 certificate = null;

            X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

            X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;

            foreach (X509Certificate2 cert in collection)
            {
                if (cert.Subject.Contains("SERIALNUMBER=26635982214"))
                {
                    if (cert.NotAfter > DateTime.Today)
                    {
                        certificate = cert;
                    }
                }
            }

            CustomBinding binding = new CustomBinding();
            AsymmetricSecurityBindingElement securityElement = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);

            securityElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
            securityElement.IncludeTimestamp = true;
            securityElement.EnableUnsecuredResponse = true;
            securityElement.AllowInsecureTransport = true;
            securityElement.SetKeyDerivation(false);
            securityElement.KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy;
            securityElement.DefaultAlgorithmSuite = new CustomDefaultAlgorithmSuite();
            securityElement.SecurityHeaderLayout = System.ServiceModel.Channels.SecurityHeaderLayout.Strict;
            securityElement.RequireSignatureConfirmation = false;

            X509SecurityTokenParameters x509ProtectionParameters = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.IssuerSerial);
            x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
            x509ProtectionParameters.X509ReferenceStyle = X509KeyIdentifierClauseType.RawDataKeyIdentifier;
            x509ProtectionParameters.RequireDerivedKeys = false;
            securityElement.InitiatorTokenParameters = x509ProtectionParameters;

            binding.Elements.Add(securityElement);
            binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8));
            binding.Elements.Add(new HttpsTransportBindingElement());

            AddressHeader[] addressHeaders = null;
            EndpointAddress endpoint = new EndpointAddress(new Uri("https://uygtest.edefter.gov.tr/edefter/services/EDefterWSPort"), EndpointIdentity.CreateDnsIdentity("*.edefter.gov.tr"), addressHeaders);

            EDefterWSClient proxy = new gibService.EDefterWSClient(binding, endpoint);
            proxy.ClientCredentials.ClientCertificate.Certificate = certificate;
            string serverCertFilePath = Path.Combine(Application.StartupPath, "edefter.gov.tr.crt");
            proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(serverCertFilePath);
            proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;

            durum response = proxy.getBatchStatus("1"); 

stack trace: konum: System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) konum: System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) konum: System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() konum: System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) konum: System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm) konum: System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey) konum: System.ServiceModel.Security.WSSecurityOneDotZeroSendSecurityHeader.CompletePrimarySignatureCore(SendSecurityHeaderElement[] signatureConfirmations, SecurityToken[] signedEndorsingTokens, SecurityToken[] signedTokens, SendSecurityHeaderElement[] basicTokens, Boolean isPrimarySignature) konum: System.ServiceModel.Security.SendSecurityHeader.CompleteSignature() konum: System.ServiceModel.Security.SendSecurityHeader.CompleteSecurityApplication() konum: System.ServiceModel.Security.SecurityAppliedMessage.OnWriteMessage(XmlDictionaryWriter writer) konum: System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota) konum: System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset) konum: System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message, Boolean shouldRecycleBuffer) konum: System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) konum: System.ServiceModel.Channels.HttpChannelFactory1.HttpRequestChannel.HttpChannelRequest.SendRequest(Message message, TimeSpan timeout) konum: System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) konum: System.ServiceModel.Channels.SecurityChannelFactory1.SecurityRequestChannel.Request(Message message, TimeSpan timeout) konum: System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) konum: System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) konum: System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)

konum: System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

public class CustomDefaultAlgorithmSuite : SecurityAlgorithmSuite
{
    public override string DefaultAsymmetricKeyWrapAlgorithm
    {
        get { return SecurityAlgorithms.RsaOaepKeyWrap; }
    }

    public override string DefaultAsymmetricSignatureAlgorithm
    {
        get { return SecurityAlgorithms.RsaSha256Signature; }
    }

    public override string DefaultCanonicalizationAlgorithm
    {
        get { return SecurityAlgorithms.ExclusiveC14n; ; }
    }

    public override string DefaultDigestAlgorithm
    {
        get { return SecurityAlgorithms.Sha1Digest; }
    }

    public override string DefaultEncryptionAlgorithm
    {
        get { return SecurityAlgorithms.Aes128Encryption; }
    }

    public override int DefaultEncryptionKeyDerivationLength
    {
        get { return 128; }
    }

    public override int DefaultSignatureKeyDerivationLength
    {
        get { return 128; }
    }

    public override int DefaultSymmetricKeyLength
    {
        get { return 128; }
    }

    public override string DefaultSymmetricKeyWrapAlgorithm
    {
        get { return SecurityAlgorithms.Aes128Encryption; }
    }

    public override string DefaultSymmetricSignatureAlgorithm
    {
        get { return SecurityAlgorithms.HmacSha1Signature; }
    }

    public override bool IsAsymmetricKeyLengthSupported(int length)
    {
        return length >= 1024 && length <= 4096;
    }

    public override bool IsSymmetricKeyLengthSupported(int length)
    {
        return length >= 128 && length <= 256;
    }
}  

Upvotes: 1

Views: 1171

Answers (2)

jQP
jQP

Reputation: 99

I think your problem is about that your private key is stored on USB Token/ Smart Card and this private key is not exportable/extractable or its protected with PIN. So WCF client can't use this private key to sign soap message.

If your certificate and private key is stored on pfx then you can call this WS as you mention above, but in your case i think it is not possible to sign soap message by using wcf client.

Upvotes: 0

pepo
pepo

Reputation: 8877

Are you sure that certificate with SERIALNUMBER=26635982214 has been found in current user store? You don't have any check on it.

Also, what user does the WCF client run under? Check if the certificate you are looking for is in the correct store.

Upvotes: 0

Related Questions