public bool MatchesCertificate(X509Certificate2 certificate)
        {
            switch (Type)
            {
            case SubjectIdentifierType.IssuerAndSerialNumber:
            {
                X509IssuerSerial issuerSerial     = (X509IssuerSerial)Value !;
                byte[]           serialNumber     = issuerSerial.SerialNumber.ToSerialBytes();
                string           issuer           = issuerSerial.IssuerName;
                byte[]           certSerialNumber = certificate.GetSerialNumber();

                return(PkcsHelpers.AreByteArraysEqual(certSerialNumber, serialNumber) && certificate.Issuer == issuer);
            }

            case SubjectIdentifierType.SubjectKeyIdentifier:
            {
                string skiString    = (string)Value !;
                byte[] ski          = skiString.ToSkiBytes();
                byte[] candidateSki = PkcsPal.Instance.GetSubjectKeyIdentifier(certificate);

                return(PkcsHelpers.AreByteArraysEqual(ski, candidateSki));
            }

            default:
                // SubjectIdentifier can only be created by this package so if this an invalid type, it's the package's fault.
                Debug.Fail($"Invalid SubjectIdentifierType: {Type}");
                throw new CryptographicException();
            }
        }
Example #2
0
        /// <summary>
        /// .NET Framework compat: We do not complain about multiple matches. Just take the first one and ignore the rest.
        /// </summary>
        public static X509Certificate2?TryFindMatchingCertificate(this X509Certificate2Collection certs, SubjectIdentifier recipientIdentifier)
        {
            //
            // Note: SubjectIdentifier has no public constructor so the only one that can construct this type is this assembly.
            //       Therefore, we trust that the string-ized byte array (serial or ski) in it is correct and canonicalized.
            //

            SubjectIdentifierType recipientIdentifierType = recipientIdentifier.Type;

            switch (recipientIdentifierType)
            {
            case SubjectIdentifierType.IssuerAndSerialNumber:
            {
                X509IssuerSerial issuerSerial = (X509IssuerSerial)(recipientIdentifier.Value !);
                byte[]           serialNumber = issuerSerial.SerialNumber.ToSerialBytes();
                string           issuer       = issuerSerial.IssuerName;
                foreach (X509Certificate2 candidate in certs)
                {
                    byte[] candidateSerialNumber = candidate.GetSerialNumber();
                    if (AreByteArraysEqual(candidateSerialNumber, serialNumber) && candidate.Issuer == issuer)
                    {
                        return(candidate);
                    }
                }
            }
            break;

            case SubjectIdentifierType.SubjectKeyIdentifier:
            {
                string skiString = (string)(recipientIdentifier.Value !);
                byte[] ski       = skiString.ToSkiBytes();
                foreach (X509Certificate2 cert in certs)
                {
                    /*
                     * byte[] candidateSki = PkcsPal.Instance.GetSubjectKeyIdentifier(cert);
                     * if (AreByteArraysEqual(ski, candidateSki))
                     *  return cert;
                     */
                }
            }
            break;

            default:
                // RecipientInfo's can only be created by this package so if this an invalid type, it's the package's fault.
                Debug.Fail($"Invalid recipientIdentifier type: {recipientIdentifierType}");
                throw new CryptographicException();
            }
            return(null);
        }
        internal SubjectIdentifier(
            IssuerAndSerialNumberAsn?issuerAndSerialNumber,
            ReadOnlyMemory <byte>?subjectKeyIdentifier)
        {
            if (issuerAndSerialNumber.HasValue)
            {
                ReadOnlySpan <byte> issuerNameSpan = issuerAndSerialNumber.Value.Issuer.Span;
                ReadOnlySpan <byte> serial         = issuerAndSerialNumber.Value.SerialNumber.Span;

                bool nonZero = false;

                for (int i = 0; i < serial.Length; i++)
                {
                    if (serial[i] != 0)
                    {
                        nonZero = true;
                        break;
                    }
                }

                // If the serial number is zero and the subject is exactly "CN=Dummy Signer"
                // then this is the special "NoSignature" signer.
                if (!nonZero &&
                    DummySignerEncodedValue.AsSpan().SequenceEqual(issuerNameSpan))
                {
                    Type  = SubjectIdentifierType.NoSignature;
                    Value = null;
                }
                else
                {
                    Type = SubjectIdentifierType.IssuerAndSerialNumber;

                    var name = new X500DistinguishedName(issuerNameSpan.ToArray());
                    Value = new X509IssuerSerial(name.Name, serial.ToBigEndianHex());
                }
            }
            else if (subjectKeyIdentifier != null)
            {
                Type  = SubjectIdentifierType.SubjectKeyIdentifier;
                Value = subjectKeyIdentifier.Value.Span.ToBigEndianHex();
            }
            else
            {
                Debug.Fail("Do not know how to decode value");
                throw new CryptographicException();
            }
        }
        internal bool IsEquivalentTo(SubjectIdentifier other)
        {
            SubjectIdentifier currentId = other;

            if (currentId.Type != Type)
            {
                return(false);
            }

            X509IssuerSerial issuerSerial = default;

            if (Type == SubjectIdentifierType.IssuerAndSerialNumber)
            {
                issuerSerial = (X509IssuerSerial)Value !;
            }

            switch (Type)
            {
            case SubjectIdentifierType.IssuerAndSerialNumber:
            {
                X509IssuerSerial currentIssuerSerial = (X509IssuerSerial)currentId.Value !;

                return(currentIssuerSerial.IssuerName == issuerSerial.IssuerName &&
                       currentIssuerSerial.SerialNumber == issuerSerial.SerialNumber);
            }

            case SubjectIdentifierType.SubjectKeyIdentifier:
                return((string)Value ! == (string)currentId.Value !);

            case SubjectIdentifierType.NoSignature:
                return(true);

            default:
                Debug.Fail($"No match logic for SubjectIdentifierType {Type}");
                throw new CryptographicException();
            }
        }