< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.IdentityModel.Tokens.X509AsymmetricSecurityKey
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs
Line coverage
17%
Covered lines: 25
Uncovered lines: 119
Coverable lines: 144
Total lines: 420
Line coverage: 17.3%
Branch coverage
17%
Covered branches: 23
Total branches: 130
Branch coverage: 17.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)50%22100%
DecryptKey(...)100%110%
EncryptKey(...)100%110%
GetAsymmetricAlgorithm(...)19.44%363614.28%
GetHashAlgorithmForSignature(...)0%14140%
GetSignatureDeformatter(...)0%18180%
GetSignatureFormatter(...)0%22220%
HasPrivateKey()100%110%
IsSupportedAlgorithm(...)55.55%181852.94%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/IdentityModel/Tokens/X509AsymmetricSecurityKey.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Security.Cryptography;
 6using System.Security.Cryptography.X509Certificates;
 7using System.Security.Cryptography.Xml;
 8
 9namespace CoreWCF.IdentityModel.Tokens
 10{
 11    public class X509AsymmetricSecurityKey : AsymmetricSecurityKey
 12    {
 13        private readonly X509Certificate2 _certificate;
 14        private AsymmetricAlgorithm _privateKey;
 15        private bool _privateKeyAvailabilityDetermined;
 16        private AsymmetricAlgorithm _publicKey;
 17        private bool _publicKeyAvailabilityDetermined;
 18
 419        public X509AsymmetricSecurityKey(X509Certificate2 certificate)
 20        {
 421            _certificate = certificate ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(certif
 422        }
 23
 24        public override int KeySize
 25        {
 326            get { return PublicKey.KeySize; }
 27        }
 28
 29        private AsymmetricAlgorithm PrivateKey
 30        {
 31            get
 32            {
 033                if (!_privateKeyAvailabilityDetermined)
 34                {
 035                    lock (ThisLock)
 36                    {
 037                        _privateKey = _certificate.GetRSAPrivateKey();
 038                        if (_privateKey != null)
 39                        {
 40                            // ProviderType == 1 is PROV_RSA_FULL provider type that only supports SHA1.
 41                            // Change it to PROV_RSA_AES=24 that supports SHA2 also.
 042                            if (_privateKey is RSACryptoServiceProvider rsaCsp && rsaCsp.CspKeyContainerInfo.ProviderTyp
 43                            {
 044                                CspParameters csp = new CspParameters
 045                                {
 046                                    ProviderType = 24,
 047                                    KeyContainerName = rsaCsp.CspKeyContainerInfo.KeyContainerName,
 048                                    KeyNumber = (int)rsaCsp.CspKeyContainerInfo.KeyNumber
 049                                };
 050                                if (rsaCsp.CspKeyContainerInfo.MachineKeyStore)
 51                                {
 052                                    csp.Flags = CspProviderFlags.UseMachineKeyStore;
 53                                }
 54
 055                                csp.Flags |= CspProviderFlags.UseExistingKey;
 056                                _privateKey = new RSACryptoServiceProvider(csp);
 57                            }
 58                        }
 59                        else
 60                        {
 061                            _privateKey = _certificate.GetECDsaPrivateKey();
 62                            // We don't support DSA certificates as we need DSACertificateExtensions which is in netstan
 63                            // As we target netstandard2.0, we don't have access to DSACertificateExtensions. If there's
 64                            // dependencies forward to provide support.
 65                        }
 66
 067                        if (_certificate.HasPrivateKey && _privateKey == null)
 68                        {
 069                            DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.PrivateKeyN
 70                        }
 71
 072                        _privateKeyAvailabilityDetermined = true;
 073                    }
 74                }
 075                return _privateKey;
 76            }
 77        }
 78
 79        private AsymmetricAlgorithm PublicKey
 80        {
 81            get
 82            {
 1283                if (!_publicKeyAvailabilityDetermined)
 84                {
 385                    lock (ThisLock)
 86                    {
 387                        if (!_publicKeyAvailabilityDetermined)
 88                        {
 389                            _publicKey = _certificate.GetRSAPublicKey();
 390                            if (_publicKey == null)
 91                            {
 92                                // Need DSACertificateExtensions  to support DSA certificate which is in netstandard2.1 
 93                                // have access to DSACertificateExtensions
 094                                DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.PublicK
 95                            }
 96
 397                            _publicKeyAvailabilityDetermined = true;
 98                        }
 399                    }
 100                }
 12101                return _publicKey;
 102            }
 103        }
 104
 7105        private object ThisLock { get; } = new object();
 106
 107        public override byte[] DecryptKey(string algorithm, byte[] keyData)
 108        {
 0109            throw new PlatformNotSupportedException();
 110        }
 111
 112        public override byte[] EncryptKey(string algorithm, byte[] keyData)
 113        {
 0114            throw new PlatformNotSupportedException();
 115        }
 116
 117        public override AsymmetricAlgorithm GetAsymmetricAlgorithm(string algorithm, bool privateKey)
 118        {
 3119            if (privateKey)
 120            {
 0121                if (PrivateKey == null)
 122                {
 0123                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.NoPrivateKeyA
 124                }
 125
 0126                if (string.IsNullOrEmpty(algorithm))
 127                {
 0128                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.Format(SR.EmptyOrNullArgu
 129                }
 130
 131                switch (algorithm)
 132                {
 133                    case SignedXml.XmlDsigDSAUrl:
 0134                        if ((PrivateKey as DSA) != null)
 135                        {
 0136                            return (PrivateKey as DSA);
 137                        }
 0138                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Algorithm
 139
 140                    case SignedXml.XmlDsigRSASHA1Url:
 141                    case SecurityAlgorithms.RsaSha256Signature:
 142                    case EncryptedXml.XmlEncRSA15Url:
 143                    case EncryptedXml.XmlEncRSAOAEPUrl:
 0144                        if ((PrivateKey as RSA) != null)
 145                        {
 0146                            return (PrivateKey as RSA);
 147                        }
 0148                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Algorithm
 149                    default:
 0150                        if (IsSupportedAlgorithm(algorithm))
 151                        {
 0152                            return PrivateKey;
 153                        }
 154                        else
 155                        {
 0156                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Forma
 157                        }
 158                }
 159            }
 160            else
 161            {
 162                switch (algorithm)
 163                {
 164                    case SignedXml.XmlDsigDSAUrl:
 0165                        if (PublicKey is DSA dsaPrivateKey)
 166                        {
 0167                            return dsaPrivateKey;
 168                        }
 0169                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException("AlgorithmAn
 170                    case SignedXml.XmlDsigRSASHA1Url:
 171                    case SecurityAlgorithms.RsaSha256Signature:
 172                    case EncryptedXml.XmlEncRSA15Url:
 173                    case EncryptedXml.XmlEncRSAOAEPUrl:
 3174                        if ((PublicKey as RSA) != null)
 175                        {
 3176                            return (PublicKey as RSA);
 177                        }
 0178                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException("AlgorithmAn
 179                    default:
 180
 0181                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR
 182                }
 183            }
 184        }
 185
 186        public override HashAlgorithm GetHashAlgorithmForSignature(string algorithm)
 187        {
 0188            if (string.IsNullOrEmpty(algorithm))
 189            {
 0190                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.Format(SR.EmptyOrNullArgument
 191            }
 192
 0193            object algorithmObject = CryptoHelper.GetAlgorithmFromConfig(algorithm);
 194
 0195            if (algorithmObject != null)
 196            {
 0197                if (algorithmObject is SignatureDescription description)
 198                {
 0199                    return description.CreateDigest();
 200                }
 201
 0202                if (algorithmObject is HashAlgorithm hashAlgorithm)
 203                {
 0204                    return hashAlgorithm;
 205                }
 206
 0207                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.Format(SR.Unsupp
 0208                        algorithm, "CreateDigest")));
 209            }
 210
 211            switch (algorithm)
 212            {
 213                case SignedXml.XmlDsigDSAUrl:
 214                case SignedXml.XmlDsigRSASHA1Url:
 0215                    return CryptoHelper.NewSha1HashAlgorithm();
 216                case SecurityAlgorithms.RsaSha256Signature:
 0217                    return CryptoHelper.NewSha256HashAlgorithm();
 218                default:
 0219                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR.Uns
 220            }
 221        }
 222
 223        public override AsymmetricSignatureDeformatter GetSignatureDeformatter(string algorithm)
 224        {
 225            // We support one of the two algoritms, but not both.
 226            //     XmlDsigDSAUrl = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
 227            //     XmlDsigRSASHA1Url = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
 228
 0229            if (string.IsNullOrEmpty(algorithm))
 230            {
 0231                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.Format(SR.EmptyOrNullArgument
 232            }
 233
 0234            object algorithmObject = CryptoHelper.GetAlgorithmFromConfig(algorithm);
 0235            if (algorithmObject != null)
 236            {
 0237                if (algorithmObject is SignatureDescription description)
 238                {
 0239                    return description.CreateDeformatter(PublicKey);
 240                }
 241
 242                try
 243                {
 0244                    if (algorithmObject is AsymmetricSignatureDeformatter asymmetricSignatureDeformatter)
 245                    {
 0246                        asymmetricSignatureDeformatter.SetKey(PublicKey);
 0247                        return asymmetricSignatureDeformatter;
 248                    }
 0249                }
 0250                catch (InvalidCastException e)
 251                {
 0252                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.AlgorithmAndP
 253                }
 254
 0255                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.Format(SR.Unsupp
 0256                       algorithm, nameof(GetSignatureDeformatter))));
 257            }
 258
 259            switch (algorithm)
 260            {
 261                case SignedXml.XmlDsigDSAUrl:
 262
 263                    // Ensure that we have a DSA algorithm object.
 0264                    DSA dsa = (PublicKey as DSA);
 0265                    if (dsa == null)
 266                    {
 0267                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException("PublicKeyNo
 268                    }
 269
 0270                    return new DSASignatureDeformatter(dsa);
 271
 272                case SignedXml.XmlDsigRSASHA1Url:
 273                case SecurityAlgorithms.RsaSha256Signature:
 274                    // Ensure that we have an RSA algorithm object.
 0275                    RSA rsa = (PublicKey as RSA);
 0276                    if (rsa == null)
 277                    {
 0278                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.PublicKey
 279                    }
 280
 0281                    return new RSAPKCS1SignatureDeformatter(rsa);
 282
 283                default:
 0284                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR.Uns
 285            }
 0286        }
 287
 288        public override AsymmetricSignatureFormatter GetSignatureFormatter(string algorithm)
 289        {
 290            // One can sign only if the private key is present.
 0291            if (PrivateKey == null)
 292            {
 0293                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.NoPrivateKeyAvail
 294            }
 295
 0296            if (string.IsNullOrEmpty(algorithm))
 297            {
 0298                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.Format(SR.EmptyOrNullArgument
 299            }
 300
 301            // We support:
 302            //     XmlDsigDSAUrl = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
 303            //     XmlDsigRSASHA1Url = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
 304            //     RsaSha256Signature = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
 0305            AsymmetricAlgorithm privateKey = PrivateKey;
 306
 0307            object algorithmObject = CryptoHelper.GetAlgorithmFromConfig(algorithm);
 0308            if (algorithmObject != null)
 309            {
 0310                if (algorithmObject is SignatureDescription description)
 311                {
 0312                    return description.CreateFormatter(privateKey);
 313                }
 314
 315                try
 316                {
 0317                    if (algorithmObject is AsymmetricSignatureFormatter asymmetricSignatureFormatter)
 318                    {
 0319                        asymmetricSignatureFormatter.SetKey(privateKey);
 0320                        return asymmetricSignatureFormatter;
 321                    }
 0322                }
 0323                catch (InvalidCastException e)
 324                {
 0325                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.AlgorithmAndP
 326                }
 327
 0328                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.Format(SR.Unsupp
 0329                       algorithm, nameof(GetSignatureFormatter))));
 330            }
 331
 332            switch (algorithm)
 333            {
 334                case SignedXml.XmlDsigDSAUrl:
 335
 336                    // Ensure that we have a DSA algorithm object.
 0337                    DSA dsa = (PrivateKey as DSA);
 0338                    if (dsa == null)
 339                    {
 0340                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.PrivateKe
 341                    }
 0342                    return new DSASignatureFormatter(dsa);
 343                case SignedXml.XmlDsigRSASHA1Url:
 344                    // Ensure that we have an RSA algorithm object.
 0345                    RSA rsa = (PrivateKey as RSA);
 0346                    if (rsa == null)
 347                    {
 0348                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.PrivateKe
 349                    }
 350
 0351                    return new RSAPKCS1SignatureFormatter(rsa);
 352
 353                case SecurityAlgorithms.RsaSha256Signature:
 354                    // Ensure that we have an RSA algorithm object.
 0355                    RSA rsaSha256 = (privateKey as RSA);
 0356                    if (rsaSha256 == null)
 357                    {
 0358                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.PrivateKe
 359                    }
 360
 0361                    return new RSAPKCS1SignatureFormatter(rsaSha256);
 362
 363                default:
 0364                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR.Uns
 365            }
 0366        }
 367
 368        public override bool HasPrivateKey()
 369        {
 0370            return (PrivateKey != null);
 371        }
 372
 373        public override bool IsSupportedAlgorithm(string algorithm)
 374        {
 6375            if (string.IsNullOrEmpty(algorithm))
 376            {
 0377                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(algorithm, SR.Format(SR.EmptyOrNullArgument
 378            }
 379
 6380            object algorithmObject = null;
 381            try
 382            {
 6383                algorithmObject = CryptoHelper.GetAlgorithmFromConfig(algorithm);
 6384            }
 0385            catch (InvalidOperationException)
 386            {
 0387                algorithm = null;
 0388            }
 389
 6390            if (algorithmObject != null)
 391            {
 3392                if (algorithmObject is SignatureDescription signatureDescription)
 393                {
 0394                    return true;
 395                }
 396
 3397                if (algorithmObject is AsymmetricAlgorithm asymmetricAlgorithm)
 398                {
 0399                    return true;
 400                }
 401
 3402                return false;
 403            }
 404
 405            switch (algorithm)
 406            {
 407                case SignedXml.XmlDsigDSAUrl:
 0408                    return (PublicKey is DSA);
 409
 410                case SignedXml.XmlDsigRSASHA1Url:
 411                case SecurityAlgorithms.RsaSha256Signature:
 412                case EncryptedXml.XmlEncRSA15Url:
 413                case EncryptedXml.XmlEncRSAOAEPUrl:
 3414                    return (PublicKey is RSA);
 415                default:
 0416                    return false;
 417            }
 418        }
 419    }
 420}