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(); } }
/// <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(); } }