public static void ReadIntegers() { byte[] derEncoded = { /* SEQUENCE */ 0x30, 23, /* INTEGER(0) */ 0x02, 0x01, 0x00, /* INTEGER(256) */ 0x02, 0x02, 0x01, 0x00, /* INTEGER(-1) */ 0x02, 0x01, 0xFF, /* Big integer */ 0x02, 0x0B, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, }; DerSequenceReader reader = new DerSequenceReader(derEncoded); Assert.True(reader.HasData); Assert.Equal(23, reader.ContentLength); int first = reader.ReadInteger(); Assert.Equal(0, first); int second = reader.ReadInteger(); Assert.Equal(256, second); int third = reader.ReadInteger(); Assert.Equal(-1, third); // Reader reads Big-Endian, BigInteger reads Little-Endian byte[] fourthBytes = reader.ReadIntegerBytes(); Array.Reverse(fourthBytes); BigInteger fourth = new BigInteger(fourthBytes); Assert.Equal(BigInteger.Parse("3645759592820458633497613"), fourth); // And... done. Assert.False(reader.HasData); }
public static void ReadOids() { byte[] derEncoded = { // Noise 0x10, 0x20, 0x30, 0x04, 0x05, // Data 0x30, 27, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x07, // More noise. 0x85, 0x71, 0x23, 0x74, 0x01, }; DerSequenceReader reader = new DerSequenceReader(derEncoded, 5, derEncoded.Length - 10); Assert.True(reader.HasData); Assert.Equal(27, reader.ContentLength); Oid first = reader.ReadOid(); Assert.Equal("1.2.840.113549.1.1.11", first.Value); Oid second = reader.ReadOid(); Assert.Equal("2.5.4.3", second.Value); Oid third = reader.ReadOid(); Assert.Equal("1.3.6.1.4.1.311.21.7", third.Value); // And... done. Assert.False(reader.HasData); }
public static void ReadIntegers() { byte[] derEncoded = { /* SEQUENCE */ 0x30, 23, /* INTEGER(0) */ 0x02, 0x01, 0x00, /* INTEGER(256) */ 0x02, 0x02, 0x01, 0x00, /* INTEGER(-1) */ 0x02, 0x01, 0xFF, /* Big integer */ 0x02, 0x0B, 0x03, 0x04,0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, }; DerSequenceReader reader = new DerSequenceReader(derEncoded); Assert.True(reader.HasData); Assert.Equal(23, reader.ContentLength); int first = reader.ReadInteger(); Assert.Equal(0, first); int second = reader.ReadInteger(); Assert.Equal(256, second); int third = reader.ReadInteger(); Assert.Equal(-1, third); // Reader reads Big-Endian, BigInteger reads Little-Endian byte[] fourthBytes = reader.ReadIntegerBytes(); Array.Reverse(fourthBytes); BigInteger fourth = new BigInteger(fourthBytes); Assert.Equal(BigInteger.Parse("3645759592820458633497613"), fourth); // And... done. Assert.False(reader.HasData); }
public static byte[] ConvertDerToIeee1363(byte[] input, int inputOffset, int inputCount, int fieldSizeBits) { int bytes = BitsToBytes(fieldSizeBits); try { DerSequenceReader derSequenceReader = new DerSequenceReader(input, inputOffset, inputCount); byte[] signatureField1 = derSequenceReader.ReadIntegerBytes(); byte[] signatureField2 = derSequenceReader.ReadIntegerBytes(); byte[] response = new byte[2 * bytes]; CopySignatureField(signatureField1, response, 0, bytes); CopySignatureField(signatureField2, response, bytes, bytes); return(response); } catch (System.InvalidOperationException ex) { throw new System.Security.Cryptography.CryptographicException($"Cryptography Exception", ex); } }
internal static NuGetV3ServiceIndexUrl Read(DerSequenceReader reader) { var urlString = reader.ReadIA5String(); if (reader.HasData) { throw new SignatureException(Strings.NuGetV3ServiceIndexUrlInvalid); } Uri url; if (!Uri.TryCreate(urlString, UriKind.Absolute, out url)) { throw new SignatureException(Strings.NuGetV3ServiceIndexUrlInvalid); } if (!string.Equals(url.Scheme, "https", StringComparison.Ordinal)) { throw new SignatureException(Strings.NuGetV3ServiceIndexUrlInvalid); } return(new NuGetV3ServiceIndexUrl(url)); }
public static void InteriorLengthTooLong() { byte[] bytes = { // CONSTRUCTED SEQUENCE (8 bytes) 0x30, 0x08, // CONSTRUCTED SEQUENCE (2 bytes) 0x30, 0x02, // OCTET STRING (0 bytes) 0x04, 0x00, // OCTET STRING (after the inner sequence, 3 bytes, but that exceeds the sequence bounds) 0x04, 0x03, 0x01, 0x02, 0x03 }; DerSequenceReader reader = new DerSequenceReader(bytes); DerSequenceReader nested = reader.ReadSequence(); Assert.Equal(0, nested.ReadOctetString().Length); Assert.False(nested.HasData); Assert.Throws <CryptographicException>(() => reader.ReadOctetString()); }
internal static NuGetPackageOwners Read(DerSequenceReader reader) { var packageOwners = new List <string>(); var ownersReader = reader.ReadSequence(); while (ownersReader.HasData) { var packageOwner = ownersReader.ReadUtf8String(); if (string.IsNullOrWhiteSpace(packageOwner)) { throw new SignatureException(Strings.NuGetPackageOwnersInvalid); } packageOwners.Add(packageOwner); } if (packageOwners.Count == 0) { throw new SignatureException(Strings.NuGetPackageOwnersInvalid); } return(new NuGetPackageOwners(packageOwners)); }
/// <summary> /// Determines if a certificate is self-issued. /// </summary> /// <remarks>Warning: this method does not evaluate certificate trust, revocation status, or validity! /// This method attempts to build a chain for the provided certificate, and although revocation status /// checking is explicitly skipped, the underlying chain building engine may go online to fetch /// additional information (e.g.: the issuer's certificate). This method is not a guaranteed offline /// check.</remarks> /// <param name="certificate">The certificate to check.</param> /// <returns><c>true</c> if the certificate is self-issued; otherwise, <c>false</c>.</returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception> public static bool IsSelfIssued(X509Certificate2 certificate) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } using (var chainHolder = new X509ChainHolder()) { X509Chain chain = chainHolder.Chain; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority | X509VerificationFlags.IgnoreRootRevocationUnknown | X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown; CertificateChainUtility.BuildWithPolicy(chain, certificate); if (chain.ChainElements.Count != 1) { return(false); } if (chain.ChainStatus.Any( chainStatus => chainStatus.Status.HasFlag(X509ChainStatusFlags.Cyclic) || chainStatus.Status.HasFlag(X509ChainStatusFlags.PartialChain) || chainStatus.Status.HasFlag(X509ChainStatusFlags.NotSignatureValid))) { return(false); } if (!certificate.IssuerName.RawData.SequenceEqual(certificate.SubjectName.RawData)) { return(false); } var akiExtension = certificate.Extensions[Oids.AuthorityKeyIdentifier]; var skiExtension = certificate.Extensions[Oids.SubjectKeyIdentifier] as X509SubjectKeyIdentifierExtension; if (akiExtension != null && skiExtension != null) { var reader = new DerSequenceReader(akiExtension.RawData); var keyIdentifierTag = (DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificTagFlag; if (reader.HasTag(keyIdentifierTag)) { var keyIdentifier = reader.ReadValue(keyIdentifierTag); #if NETCOREAPP var akiKeyIdentifier = BitConverter.ToString(keyIdentifier).Replace("-", "", StringComparison.Ordinal); #else var akiKeyIdentifier = BitConverter.ToString(keyIdentifier).Replace("-", ""); #endif return(string.Equals(skiExtension.SubjectKeyIdentifier, akiKeyIdentifier, StringComparison.OrdinalIgnoreCase)); } } return(true); } }
private static X509Certificate2 DownloadCertificate( byte[] authorityInformationAccess, ref TimeSpan remainingDownloadTime) { // Don't do any work if we're over limit. if (remainingDownloadTime <= TimeSpan.Zero) { return null; } DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess); while (reader.HasData) { DerSequenceReader innerReader = reader.ReadSequence(); // If the sequence's first element is a sequence, unwrap it. if (innerReader.PeekTag() == ConstructedSequenceTagId) { innerReader = innerReader.ReadSequence(); } Oid oid = innerReader.ReadOid(); if (StringComparer.Ordinal.Equals(oid.Value, Oids.CertificateAuthorityIssuers)) { string uri = innerReader.ReadIA5String(); Uri parsedUri; if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri)) { continue; } if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return CertificateAssetDownloader.DownloadCertificate(uri, ref remainingDownloadTime); } } return null; }
internal static string FindHttpAiaRecord(byte[] authorityInformationAccess, string recordTypeOid) { DerSequenceReader reader = new DerSequenceReader(authorityInformationAccess); while (reader.HasData) { DerSequenceReader innerReader = reader.ReadSequence(); // If the sequence's first element is a sequence, unwrap it. if (innerReader.PeekTag() == ConstructedSequenceTagId) { innerReader = innerReader.ReadSequence(); } Oid oid = innerReader.ReadOid(); if (StringComparer.Ordinal.Equals(oid.Value, recordTypeOid)) { string uri = innerReader.ReadIA5String(); Uri parsedUri; if (!Uri.TryCreate(uri, UriKind.Absolute, out parsedUri)) { continue; } if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return uri; } } return null; }
public static SigningCertificateV2 Read(byte[] bytes) { var reader = new DerSequenceReader(bytes); return(Read(reader)); }
public static Extensions Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
internal static ISet<string> ReadCertPolicyExtension(X509Extension extension) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); HashSet<string> policies = new HashSet<string>(); while (reader.HasData) { DerSequenceReader policyInformation = reader.ReadSequence(); policies.Add(policyInformation.ReadOidAsString()); // There is an optional policy qualifier here, but it is for information // purposes, there is no logic that would be changed. // Since reader (the outer one) has already skipped past the rest of the // sequence we don't particularly need to drain out here. } return policies; }
internal static TstInfo Read(DerSequenceReader reader) { var tstInfoReader = reader.ReadSequence(); var version = tstInfoReader.ReadInteger(); var policy = tstInfoReader.ReadOid(); var messageImprint = MessageImprint.Read(tstInfoReader); var serialNumber = tstInfoReader.ReadIntegerBytes(); if (serialNumber == null || serialNumber.Length == 0) { throw new CryptographicException(Strings.InvalidAsn1); } var genTime = tstInfoReader.ReadGeneralizedTime(); Accuracy accuracy = null; if (tstInfoReader.HasTag(DerSequenceReader.ConstructedSequence)) { accuracy = Accuracy.Read(tstInfoReader); } var ordering = false; if (tstInfoReader.HasTag(DerSequenceReader.DerTag.Boolean)) { ordering = tstInfoReader.ReadBoolean(); } byte[] nonce = null; if (tstInfoReader.HasTag(DerSequenceReader.DerTag.Integer)) { nonce = tstInfoReader.ReadIntegerBytes(); } byte[] tsa = null; if (tstInfoReader.HasData && tstInfoReader.HasTag(DerSequenceReader.ContextSpecificConstructedTag0)) { tsa = tstInfoReader.ReadValue((DerSequenceReader.DerTag)DerSequenceReader.ContextSpecificConstructedTag0); } X509ExtensionCollection extensions = null; if (tstInfoReader.HasData && tstInfoReader.HasTag(DerSequenceReader.ContextSpecificConstructedTag1)) { extensions = new X509ExtensionCollection(); var rawExtensions = Signing.Extensions.Read(tstInfoReader); foreach (var rawExtension in rawExtensions.ExtensionsList) { extensions.Add( new X509Extension( rawExtension.Id, rawExtension.Value, rawExtension.Critical)); } if (extensions.Count == 0) { throw new CryptographicException(Strings.InvalidAsn1); } } if (tstInfoReader.HasData) { throw new CryptographicException(Strings.InvalidAsn1); } return(new TstInfo( version, policy, messageImprint, serialNumber, genTime.ToUniversalTime(), accuracy, ordering, nonce, tsa, extensions)); }
internal DerSequenceReader ReadSequence() { // DerSequenceReader wants to read its own tag, so don't EatTag here. CheckTag(DerTag.Sequence, _data, _position); int lengthLength; int contentLength = ScanContentLength(_data, _position + 1, out lengthLength); int totalLength = 1 + lengthLength + contentLength; DerSequenceReader reader = new DerSequenceReader(_data, _position, totalLength); _position += totalLength; return reader; }
public static NuGetV3ServiceIndexUrl Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static MessageImprint Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
// DER -> Hash private static KeyValuePair <Common.HashAlgorithmName, byte[]> GetESSCertIDv2Entry(DerSequenceReader reader) { var hashAlgorithm = CryptoHashUtility.OidToHashAlgorithmName(reader.ReadOidAsString()); var attributeHashValue = reader.ReadOctetString(); return(new KeyValuePair <Common.HashAlgorithmName, byte[]>(hashAlgorithm, attributeHashValue)); }
private static void ReadCertPolicyConstraintsExtension(X509Extension extension, CertificatePolicy policy) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); while (reader.HasData) { // Policy Constraints context specific tag values are defined in RFC 3280 4.2.1.12, // and restated (unchanged) in RFC 5280 4.2.1.11. switch (reader.PeekTag()) { case DerSequenceReader.ContextSpecificTagFlag | 0: policy.RequireExplicitPolicyDepth = reader.ReadInteger(); break; case DerSequenceReader.ContextSpecificTagFlag | 1: policy.InhibitMappingDepth = reader.ReadInteger(); break; default: if (extension.Critical) { // If an unknown value is read, but we're marked as critical, // then we don't know what we're doing and MUST fail validation // (RFC 3280). // If it isn't critical then it means we're allowed to be ignorant // of data defined more recently than we understand. throw new CryptographicException(); } break; } } }
private static DerSequenceReader ReadEncryptedPkcs8Blob(string passphrase, DerSequenceReader reader) { // EncryptedPrivateKeyInfo::= SEQUENCE { // encryptionAlgorithm EncryptionAlgorithmIdentifier, // encryptedData EncryptedData } // // EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier // // EncryptedData ::= OCTET STRING DerSequenceReader algorithmIdentifier = reader.ReadSequence(); string algorithmOid = algorithmIdentifier.ReadOidAsString(); // PBES2 (Password-Based Encryption Scheme 2) if (algorithmOid != OidPbes2) { Debug.Fail($"Expected PBES2 ({OidPbes2}), got {algorithmOid}"); throw new CryptographicException(); } // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier { { PBES2 - KDFs} }, // encryptionScheme AlgorithmIdentifier { { PBES2 - Encs} } // } DerSequenceReader pbes2Params = algorithmIdentifier.ReadSequence(); algorithmIdentifier = pbes2Params.ReadSequence(); string kdfOid = algorithmIdentifier.ReadOidAsString(); // PBKDF2 (Password-Based Key Derivation Function 2) if (kdfOid != OidPbkdf2) { Debug.Fail($"Expected PBKDF2 ({OidPbkdf2}), got {kdfOid}"); throw new CryptographicException(); } // PBKDF2-params ::= SEQUENCE { // salt CHOICE { // specified OCTET STRING, // otherSource AlgorithmIdentifier { { PBKDF2 - SaltSources} } // }, // iterationCount INTEGER (1..MAX), // keyLength INTEGER(1..MAX) OPTIONAL, // prf AlgorithmIdentifier { { PBKDF2 - PRFs} } DEFAULT algid - hmacWithSHA1 // } DerSequenceReader pbkdf2Params = algorithmIdentifier.ReadSequence(); byte[] salt = pbkdf2Params.ReadOctetString(); int iterCount = pbkdf2Params.ReadInteger(); int keySize = -1; if (pbkdf2Params.HasData && pbkdf2Params.PeekTag() == (byte)DerSequenceReader.DerTag.Integer) { keySize = pbkdf2Params.ReadInteger(); } if (pbkdf2Params.HasData) { string prfOid = pbkdf2Params.ReadOidAsString(); // SHA-1 is the only hash algorithm our PBKDF2 supports. if (prfOid != OidSha1) { Debug.Fail($"Expected SHA1 ({OidSha1}), got {prfOid}"); throw new CryptographicException(); } } DerSequenceReader encryptionScheme = pbes2Params.ReadSequence(); string cipherOid = encryptionScheme.ReadOidAsString(); // DES-EDE3-CBC (TripleDES in CBC mode) if (cipherOid != OidTripleDesCbc) { Debug.Fail($"Expected DES-EDE3-CBC ({OidTripleDesCbc}), got {cipherOid}"); throw new CryptographicException(); } byte[] decrypted; using (TripleDES des3 = TripleDES.Create()) { if (keySize == -1) { foreach (KeySizes keySizes in des3.LegalKeySizes) { keySize = Math.Max(keySize, keySizes.MaxSize); } } byte[] iv = encryptionScheme.ReadOctetString(); using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, iterCount)) using (ICryptoTransform decryptor = des3.CreateDecryptor(pbkdf2.GetBytes(keySize / 8), iv)) { byte[] encrypted = reader.ReadOctetString(); decrypted = decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length); } } DerSequenceReader pkcs8Reader = new DerSequenceReader(decrypted); return(pkcs8Reader); }
private static List<CertificatePolicyMapping> ReadCertPolicyMappingsExtension(X509Extension extension) { DerSequenceReader reader = new DerSequenceReader(extension.RawData); List<CertificatePolicyMapping> mappings = new List<CertificatePolicyMapping>(); while (reader.HasData) { DerSequenceReader mappingSequence = reader.ReadSequence(); mappings.Add( new CertificatePolicyMapping { IssuerDomainPolicy = mappingSequence.ReadOidAsString(), SubjectDomainPolicy = mappingSequence.ReadOidAsString(), }); } return mappings; }
internal static DerSequenceReader SecKeyExport( SafeSecKeyRefHandle key, bool exportPrivate) { // Apple requires all private keys to be exported encrypted, but since we're trying to export // as parsed structures we will need to decrypt it for the user. const string ExportPassword = "******"; SafeCreateHandle exportPassword = exportPrivate ? CoreFoundation.CFStringCreateWithCString(ExportPassword) : s_nullExportString; int ret; SafeCFDataHandle cfData; int osStatus; try { ret = AppleCryptoNative_SecKeyExport( key, exportPrivate ? 1 : 0, exportPassword, out cfData, out osStatus); } finally { if (exportPassword != s_nullExportString) { exportPassword.Dispose(); } } byte[] exportedData; using (cfData) { if (ret == 0) { throw CreateExceptionForOSStatus(osStatus); } if (ret != 1) { Debug.Fail($"AppleCryptoNative_SecKeyExport returned {ret}"); throw new CryptographicException(); } exportedData = CoreFoundation.CFGetData(cfData); } DerSequenceReader reader = new DerSequenceReader(exportedData); if (!exportPrivate) { return(reader); } byte tag = reader.PeekTag(); // PKCS#8 defines two structures, PrivateKeyInfo, which starts with an integer, // and EncryptedPrivateKey, which starts with an encryption algorithm (DER sequence). if (tag == (byte)DerSequenceReader.DerTag.Integer) { return(reader); } const byte ConstructedSequence = DerSequenceReader.ConstructedFlag | (byte)DerSequenceReader.DerTag.Sequence; if (tag == ConstructedSequence) { return(ReadEncryptedPkcs8Blob(ExportPassword, reader)); } Debug.Fail($"Data was neither PrivateKey or EncryptedPrivateKey: {tag:X2}"); throw new CryptographicException(); }
public static IssuerSerial Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static AlgorithmIdentifier Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static EssCertId Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static CommitmentTypeQualifier Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static PolicyQualifierInfo Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
private static string GetCdpUrl(X509Certificate2 cert) { byte[] crlDistributionPoints = null; foreach (X509Extension extension in cert.Extensions) { if (StringComparer.Ordinal.Equals(extension.Oid.Value, Oids.CrlDistributionPoints)) { // If there's an Authority Information Access extension, it might be used for // looking up additional certificates for the chain. crlDistributionPoints = extension.RawData; break; } } if (crlDistributionPoints == null) { return null; } // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint // // DistributionPoint ::= SEQUENCE { // distributionPoint [0] DistributionPointName OPTIONAL, // reasons [1] ReasonFlags OPTIONAL, // cRLIssuer [2] GeneralNames OPTIONAL } // // DistributionPointName ::= CHOICE { // fullName [0] GeneralNames, // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } // // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // // GeneralName ::= CHOICE { // otherName [0] OtherName, // rfc822Name [1] IA5String, // dNSName [2] IA5String, // x400Address [3] ORAddress, // directoryName [4] Name, // ediPartyName [5] EDIPartyName, // uniformResourceIdentifier [6] IA5String, // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } DerSequenceReader cdpSequence = new DerSequenceReader(crlDistributionPoints); while (cdpSequence.HasData) { const byte ContextSpecificFlag = 0x80; const byte ContextSpecific0 = ContextSpecificFlag; const byte ConstructedFlag = 0x20; const byte ContextSpecificConstructed0 = ContextSpecific0 | ConstructedFlag; const byte GeneralNameUri = ContextSpecificFlag | 0x06; DerSequenceReader distributionPointReader = cdpSequence.ReadSequence(); byte tag = distributionPointReader.PeekTag(); // Only distributionPoint is supported if (tag != ContextSpecificConstructed0) { continue; } // The DistributionPointName is a CHOICE, not a SEQUENCE, but the reader is the same. DerSequenceReader dpNameReader = distributionPointReader.ReadSequence(); tag = dpNameReader.PeekTag(); // Only fullName is supported, // nameRelativeToCRLIssuer is for LDAP-based lookup. if (tag != ContextSpecificConstructed0) { continue; } DerSequenceReader fullNameReader = dpNameReader.ReadSequence(); while (fullNameReader.HasData) { tag = fullNameReader.PeekTag(); if (tag != GeneralNameUri) { fullNameReader.SkipValue(); continue; } string uri = fullNameReader.ReadIA5String(); Uri parsedUri = new Uri(uri); if (!StringComparer.Ordinal.Equals(parsedUri.Scheme, "http")) { continue; } return uri; } } return null; }
public void FindByTemplateName(string templateName) { FindCore( cert => { X509Extension ext = FindExtension(cert, Oids.EnrollCertTypeExtension); if (ext != null) { // Try a V1 template structure, just a string: string decodedName = Interop.Crypto.DerStringToManagedString(ext.RawData); // If this doesn't match, maybe a V2 template will if (StringComparer.OrdinalIgnoreCase.Equals(templateName, decodedName)) { return true; } } ext = FindExtension(cert, Oids.CertificateTemplate); if (ext != null) { DerSequenceReader reader = new DerSequenceReader(ext.RawData); // SEQUENCE ( // OID oid, // INTEGER major, // INTEGER minor OPTIONAL // ) if (reader.PeekTag() == (byte)DerSequenceReader.DerTag.ObjectIdentifier) { Oid oid = reader.ReadOid(); if (StringComparer.Ordinal.Equals(templateName, oid.Value)) { return true; } } } return false; }); }
public static NuGetPackageOwners Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
private string FormatSubjectAlternativeName(byte[] rawData) { // Because SubjectAlternativeName is a commonly parsed structure, we'll // specifically format this one. And we'll match the OpenSSL format, which // includes not localizing any of the values (or respecting the multiLine boolean) // // The intent here is to be functionally equivalent to OpenSSL GENERAL_NAME_print. // The end size of this string is hard to predict. // * dNSName values have a tag that takes four characters to represent ("DNS:") // and then their payload is ASCII encoded (so one byte -> one char), so they // work out to be about equal (in chars) to their DER encoded length (in bytes). // * iPAddress values have a tag that takes 11 characters ("IP Address:") and then // grow from 4 bytes to up to 15 characters for IPv4, or 16 bytes to 47 characters // for IPv6 // // So use a List<string> and just Concat them all when we're done, and we reduce the // number of times we copy the header values (vs pointers to the header values). List <string> segments = new List <string>(); try { // SubjectAltName ::= GeneralNames // // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // // GeneralName ::= CHOICE { // otherName [0] OtherName, // rfc822Name [1] IA5String, // dNSName [2] IA5String, // x400Address [3] ORAddress, // directoryName [4] Name, // ediPartyName [5] EDIPartyName, // uniformResourceIdentifier [6] IA5String, // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } // // OtherName::= SEQUENCE { // type - id OBJECT IDENTIFIER, // value[0] EXPLICIT ANY DEFINED BY type - id } DerSequenceReader altNameReader = new DerSequenceReader(rawData); while (altNameReader.HasData) { if (segments.Count != 0) { segments.Add(CommaSpace); } byte tag = altNameReader.PeekTag(); if ((tag & DerSequenceReader.ContextSpecificTagFlag) == 0) { // All GeneralName values need the ContextSpecific flag. return(null); } GeneralNameType nameType = (GeneralNameType)(tag & DerSequenceReader.TagNumberMask); bool needsConstructedFlag = false; switch (nameType) { case GeneralNameType.OtherName: case GeneralNameType.X400Address: case GeneralNameType.DirectoryName: case GeneralNameType.EdiPartyName: needsConstructedFlag = true; break; } if (needsConstructedFlag && (tag & DerSequenceReader.ConstructedFlag) == 0) { // All of the SEQUENCE types require the constructed bit, // or OpenSSL will have refused to print it. return(null); } switch (nameType) { case GeneralNameType.OtherName: segments.Add("othername:<unsupported>"); altNameReader.SkipValue(); break; case GeneralNameType.Rfc822Name: segments.Add("email:"); segments.Add(altNameReader.ReadIA5String()); break; case GeneralNameType.DnsName: segments.Add("DNS:"); segments.Add(altNameReader.ReadIA5String()); break; case GeneralNameType.X400Address: segments.Add("X400Name:<unsupported>"); altNameReader.SkipValue(); break; case GeneralNameType.DirectoryName: // OpenSSL supports printing one of these, but the logic lives in X509Certificates, // and it isn't very common. So we'll skip this one until someone asks for it. segments.Add("DirName:<unsupported>"); altNameReader.SkipValue(); break; case GeneralNameType.EdiPartyName: segments.Add("EdiPartyName:<unsupported>"); altNameReader.SkipValue(); break; case GeneralNameType.UniformResourceIdentifier: segments.Add("URI:"); segments.Add(altNameReader.ReadIA5String()); break; case GeneralNameType.IPAddress: segments.Add("IP Address"); byte[] ipAddressBytes = altNameReader.ReadOctetString(); if (ipAddressBytes.Length == 4) { // Add the colon and dotted-decimal representation of IPv4. segments.Add( $":{ipAddressBytes[0]}.{ipAddressBytes[1]}.{ipAddressBytes[2]}.{ipAddressBytes[3]}"); } else if (ipAddressBytes.Length == 16) { // Print the IP Address value as colon separated UInt16 hex values without leading zeroes. // 20 01 0D B8 AC 10 FE 01 00 00 00 00 00 00 00 00 // // IP Address:2001:DB8:AC10:FE01:0:0:0:0 for (int i = 0; i < ipAddressBytes.Length; i += 2) { segments.Add($":{ipAddressBytes[i] << 8 | ipAddressBytes[i + 1]:X}"); } } else { segments.Add(":<invalid>"); } break; case GeneralNameType.RegisteredId: segments.Add("Registered ID:"); segments.Add(altNameReader.ReadOidAsString()); break; default: // A new extension to GeneralName could legitimately hit this, // but it's correct to say that until we know what that is that // the pretty-print has failed, and we should fall back to hex. // // But it could also simply be poorly encoded user data. return(null); } } return(string.Concat(segments)); } catch (CryptographicException) { return(null); } }
public static PolicyInformation Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static Accuracy Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }
public static GeneralName Read(byte[] bytes) { var reader = DerSequenceReader.CreateForPayload(bytes); return(Read(reader)); }