public static void ReadBoolean_Failure( string description, AsnEncodingRules ruleSet, string inputHex) { _ = description; byte[] inputData = inputHex.HexToByteArray(); AsnReader reader = new AsnReader(inputData, ruleSet); Asn1Tag tag = default(Asn1Tag); if (inputData.Length > 0) { tag = reader.PeekTag(); } if (tag.TagClass == TagClass.Universal) { Assert.Throws <AsnContentException>(() => reader.ReadBoolean()); } else { Assert.Throws <AsnContentException>(() => reader.ReadBoolean(tag)); } if (inputData.Length == 0) { // If we started with nothing, where did the data come from? Assert.False(reader.HasData, "reader.HasData"); } else { // Nothing should have moved Assert.True(reader.HasData, "reader.HasData"); } }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out RecipientEncryptedKeyAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); System.Security.Cryptography.Pkcs.Asn1.KeyAgreeRecipientIdentifierAsn.Decode(sequenceReader, out decoded.Rid); if (sequenceReader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpEncryptedKey)) { decoded.EncryptedKey = tmpEncryptedKey; } else { decoded.EncryptedKey = sequenceReader.ReadOctetString(); } sequenceReader.ThrowIfNotEmpty(); }
public override string DecodeOid(byte[] encodedOid) { Span <byte> emptyInvalidOid = stackalloc byte[2]; emptyInvalidOid[0] = 0x06; emptyInvalidOid[1] = 0x00; // Windows compat. if (emptyInvalidOid.SequenceEqual(encodedOid)) { return(string.Empty); } // Read using BER because the CMS specification says the encoding is BER. AsnReader reader = new AsnReader(encodedOid, AsnEncodingRules.BER); string value = reader.ReadObjectIdentifierAsString(); if (reader.HasData) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } return(value); }
public Pkcs8PrivateKeyInfo( Oid algorithmId, ReadOnlyMemory <byte>?algorithmParameters, ReadOnlyMemory <byte> privateKey, bool skipCopies = false) { if (algorithmId == null) { throw new ArgumentNullException(nameof(algorithmId)); } if (algorithmParameters?.Length > 0) { // Read to ensure that there is precisely one legally encoded value. AsnReader reader = new AsnReader(algorithmParameters.Value, AsnEncodingRules.BER); reader.ReadEncodedValue(); reader.ThrowIfNotEmpty(); } AlgorithmId = algorithmId; AlgorithmParameters = skipCopies ? algorithmParameters : algorithmParameters?.ToArray(); PrivateKeyBytes = skipCopies ? privateKey : privateKey.ToArray(); Attributes = new CryptographicAttributeObjectCollection(); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out MessageImprint decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.HashAlgorithm); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpHashedMessage)) { decoded.HashedMessage = tmpHashedMessage; } else { decoded.HashedMessage = sequenceReader.ReadOctetString(); } sequenceReader.ThrowIfNotEmpty(); }
public static ReadOnlyMemory <byte> DecodeOctetString(ReadOnlyMemory <byte> encodedOctetString) { AsnReader reader = new AsnReader(encodedOctetString, AsnEncodingRules.BER); if (reader.PeekEncodedValue().Length != encodedOctetString.Length) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> primitiveContents)) { return(primitiveContents); } byte[] tooBig = new byte[encodedOctetString.Length]; if (reader.TryCopyOctetStringBytes(tooBig, out int bytesWritten)) { return(tooBig.AsMemory(0, bytesWritten)); } Debug.Fail("TryCopyOctetStringBytes failed with an over-allocated array"); throw new CryptographicException(); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out OriginatorPublicKeyAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.Algorithm); if (sequenceReader.TryGetPrimitiveBitStringValue(out _, out ReadOnlyMemory <byte> tmpPublicKey)) { decoded.PublicKey = tmpPublicKey; } else { decoded.PublicKey = sequenceReader.ReadBitString(out _); } sequenceReader.ThrowIfNotEmpty(); }
public static void TryCopyUTF8StringBytes_Success_CER_MaxPrimitiveLength() { // CER says that the maximum encoding length for a UTF8String primitive // is 1000. // // So we need 0C [1000] { 1000 anythings } // 1000 => 0x3E8, so the length encoding is 82 03 E8. // 1000 + 3 + 1 == 1004 byte[] input = new byte[1004]; input[0] = 0x0C; input[1] = 0x82; input[2] = 0x03; input[3] = 0xE8; // Content input[4] = 0x65; input[5] = 0x65; input[1002] = 0x61; input[1003] = 0x61; byte[] output = new byte[1000]; AsnReader reader = new AsnReader(input, AsnEncodingRules.CER); bool success = reader.TryCopyCharacterStringBytes( UniversalTagNumber.UTF8String, output, out int bytesWritten); Assert.True(success, "reader.TryCopyUTF8StringBytes"); Assert.Equal(1000, bytesWritten); Assert.Equal( input.AsSpan(4).ByteArrayToHex(), output.ByteArrayToHex()); }
/// <summary> /// Decode a ECDSA signature from ASN.1. /// </summary> /// <param name="signature">The signature to decode from ASN.1</param> private static byte[] DecodeECDsa(ReadOnlyMemory <byte> signature) { AsnReader reader = new AsnReader(signature, AsnEncodingRules.DER); var seqReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); var r = seqReader.ReadIntegerBytes(); var s = seqReader.ReadIntegerBytes(); seqReader.ThrowIfNotEmpty(); if (r.Span[0] == 0) { r = r.Slice(1); } if (s.Span[0] == 0) { s = s.Slice(1); } var result = new byte[r.Length + s.Length]; r.CopyTo(new Memory <byte>(result, 0, r.Length)); s.CopyTo(new Memory <byte>(result, r.Length, s.Length)); return(result); }
internal static void Decode <T>(AsnReader reader, out T decoded) where T : KrbETypeInfo2, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); Asn1Tag tag = reader.PeekTag(); AsnReader collectionReader; if (tag.HasSameClassAndValue(Asn1Tag.Sequence)) { // Decode SEQUENCE OF for ETypeInfo { collectionReader = reader.ReadSequence(); var tmpList = new List <KrbETypeInfo2Entry>(); KrbETypeInfo2Entry tmpItem; while (collectionReader.HasData) { KrbETypeInfo2Entry.Decode <KrbETypeInfo2Entry>(collectionReader, out KrbETypeInfo2Entry tmp); tmpItem = tmp; tmpList.Add(tmpItem); } decoded.ETypeInfo = tmpList.ToArray(); } } else { throw new CryptographicException(); } }
internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded) where T : KrbPaEncTsEnc, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader explicitReader; explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); decoded.PaTimestamp = explicitReader.ReadGeneralizedTime(); explicitReader.ThrowIfNotEmpty(); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); if (explicitReader.TryReadInt32(out int tmpPaUSec)) { decoded.PaUSec = tmpPaUSec; } else { explicitReader.ThrowIfNotEmpty(); } explicitReader.ThrowIfNotEmpty(); } sequenceReader.ThrowIfNotEmpty(); }
public static void TagMustBeCorrect_Custom(AsnEncodingRules ruleSet) { byte[] inputData = { 0x87, 2, (byte)'h', (byte)'i' }; AsnReader reader = new AsnReader(inputData, ruleSet); const UniversalTagNumber EncodingType = UniversalTagNumber.UTF8String; AssertExtensions.Throws <ArgumentException>( "expectedTag", () => reader.TryReadPrimitiveCharacterStringBytes(Asn1Tag.Null, out _)); Assert.True(reader.HasData, "HasData after bad universal tag"); Assert.Throws <AsnContentException>( () => reader.TryReadPrimitiveCharacterStringBytes(new Asn1Tag(EncodingType), out _)); Assert.True(reader.HasData, "HasData after default tag"); Assert.Throws <AsnContentException>( () => reader.TryReadPrimitiveCharacterStringBytes(new Asn1Tag(TagClass.Application, 0), out _)); Assert.True(reader.HasData, "HasData after wrong custom class"); Assert.Throws <AsnContentException>( () => reader.TryReadPrimitiveCharacterStringBytes(new Asn1Tag(TagClass.ContextSpecific, 1), out _)); Assert.True(reader.HasData, "HasData after wrong custom tag value"); Assert.True( reader.TryReadPrimitiveCharacterStringBytes( new Asn1Tag(TagClass.ContextSpecific, 7), out ReadOnlyMemory <byte> value)); Assert.Equal("6869", value.ByteArrayToHex()); Assert.False(reader.HasData, "HasData after reading value"); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out Asn1SaslCredentials decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new Asn1SaslCredentials(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (sequenceReader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpMechanism)) { decoded.Mechanism = tmpMechanism; } else { decoded.Mechanism = sequenceReader.ReadOctetString(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.PrimitiveOctetString)) { if (sequenceReader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpCredentials)) { decoded.Credentials = tmpCredentials; } else { decoded.Credentials = sequenceReader.ReadOctetString(); } } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded) where T : KrbFastArmoredReq, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader explicitReader; if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); KrbFastArmor.Decode <KrbFastArmor>(explicitReader, out KrbFastArmor tmpArmor); decoded.Armor = tmpArmor; explicitReader.ThrowIfNotEmpty(); } explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); KrbChecksum.Decode <KrbChecksum>(explicitReader, out KrbChecksum tmpRequestChecksum); decoded.RequestChecksum = tmpRequestChecksum; explicitReader.ThrowIfNotEmpty(); explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 2)); KrbEncryptedData.Decode <KrbEncryptedData>(explicitReader, out KrbEncryptedData tmpEncryptedFastRequest); decoded.EncryptedFastRequest = tmpEncryptedFastRequest; explicitReader.ThrowIfNotEmpty(); sequenceReader.ThrowIfNotEmpty(); }
private static void AssertRdn( AsnReader reader, string atvOid, int offset, Asn1Tag valueTag, byte[] bytes, string label, string stringValue = null) { AsnReader rdn = reader.ReadSetOf(); AsnReader attributeTypeAndValue = rdn.ReadSequence(); Assert.Equal(atvOid, attributeTypeAndValue.ReadObjectIdentifier()); ReadOnlyMemory <byte> value = attributeTypeAndValue.ReadEncodedValue(); ReadOnlySpan <byte> valueSpan = value.Span; Assert.True(Asn1Tag.TryDecode(valueSpan, out Asn1Tag actualTag, out int bytesRead)); Assert.Equal(1, bytesRead); Assert.Equal(valueTag, actualTag); AssertRefSame( ref MemoryMarshal.GetReference(valueSpan), ref bytes[offset], $"{label} is at bytes[{offset}]"); if (stringValue != null) { AsnReader valueReader = new AsnReader(value, AsnEncodingRules.DER); Assert.Equal(stringValue, valueReader.ReadCharacterString((UniversalTagNumber)valueTag.TagValue)); Assert.False(valueReader.HasData, "valueReader.HasData"); } Assert.False(attributeTypeAndValue.HasData, $"attributeTypeAndValue.HasData ({label})"); Assert.False(rdn.HasData, $"rdn.HasData ({label})"); }
public override unsafe void ImportRSAPublicKey(ReadOnlySpan <byte> source, out int bytesRead) { fixed(byte *ptr = &MemoryMarshal.GetReference(source)) { using (MemoryManager <byte> manager = new PointerMemoryManager <byte>(ptr, source.Length)) { AsnReader reader = new AsnReader(manager.Memory, AsnEncodingRules.BER); ReadOnlyMemory <byte> firstElement = reader.PeekEncodedValue(); SafeRsaHandle key = Interop.Crypto.DecodeRsaPublicKey(firstElement.Span); Interop.Crypto.CheckValidOpenSslHandle(key); FreeKey(); _key = new Lazy <SafeRsaHandle>(key); // Use ForceSet instead of the property setter to ensure that LegalKeySizes doesn't interfere // with the already loaded key. ForceSetKeySize(BitsPerByte * Interop.Crypto.RsaSize(key)); bytesRead = firstElement.Length; } } }
public static void TryReadPrimitiveOctetStringBytes_Throws_CER_TooLong() { // CER says that the maximum encoding length for an OctetString primitive // is 1000. // // So we need 04 [1001] { 1001 0x00s } // 1001 => 0x3E9, so the length encoding is 82 03 E9. // 1001 + 3 + 1 == 1005 byte[] input = new byte[1005]; input[0] = 0x04; input[1] = 0x82; input[2] = 0x03; input[3] = 0xE9; AsnReader reader = new AsnReader(input, AsnEncodingRules.CER); Assert.Throws <AsnContentException>( () => reader.TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> contents)); Assert.Throws <AsnContentException>( () => reader.TryReadOctetString(new byte[input.Length], out _)); Assert.Throws <AsnContentException>(() => reader.ReadOctetString()); }
public static void TryGetBitStringBytes_Throws_CER_TooLong() { // CER says that the maximum encoding length for a BitString primitive is // 1000 (999 value bytes and 1 unused bit count byte). // // So we need 03 [1001] { 1001 0x00s } // 1001 => 0x3E9, so the length encoding is 82 03 E9. // 1001 + 3 + 1 == 1005 byte[] input = new byte[1005]; input[0] = 0x03; input[1] = 0x82; input[2] = 0x03; input[3] = 0xE9; AsnReader reader = new AsnReader(input, AsnEncodingRules.CER); Assert.Throws <CryptographicException>( () => { reader.TryGetPrimitiveBitStringValue( out int unusedBitCount, out ReadOnlyMemory <byte> contents); }); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out Asn1ExtendedRequest decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new Asn1ExtendedRequest(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (sequenceReader.TryGetPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out ReadOnlyMemory <byte> tmpName)) { decoded.Name = tmpName; } else { decoded.Name = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 0)); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { if (sequenceReader.TryGetPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 1), out ReadOnlyMemory <byte> tmpValue)) { decoded.Value = tmpValue; } else { decoded.Value = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 1)); } } sequenceReader.ThrowIfNotEmpty(); }
private static bool CanReadNtlmMessage(ReadOnlyMemory <byte> ntlm, out byte[] actualSignature, out BinaryReader reader, out AsnReader asnReader) { asnReader = null; reader = new BinaryReader(new MemoryStream(ntlm.ToArray())); actualSignature = reader.ReadBytes(MessageSignature.Length); if (actualSignature.SequenceEqual(MessageSignature)) { return(true); } asnReader = new AsnReader(ntlm, AsnEncodingRules.DER); var peekTag = asnReader.PeekTag(); if (AsnReader.IsExpectedTag(peekTag, GssApplicationTag, UniversalTagNumber.Sequence)) { return(false); } return(AsnReader.IsExpectedTag(peekTag, NtlmContextTag, UniversalTagNumber.Sequence)); }
internal static string FindHttpAiaRecord(byte[] authorityInformationAccess, string recordTypeOid) { AsnReader reader = new AsnReader(authorityInformationAccess, AsnEncodingRules.DER); AsnReader sequenceReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); while (sequenceReader.HasData) { AccessDescriptionAsn.Decode(sequenceReader, out AccessDescriptionAsn description); if (StringComparer.Ordinal.Equals(description.AccessMethod, recordTypeOid)) { GeneralNameAsn name = description.AccessLocation; if (name.Uri != null && Uri.TryCreate(name.Uri, UriKind.Absolute, out Uri uri) && uri.Scheme == "http") { return(name.Uri); } } } return(null); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out Asn1CompareRequest decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new Asn1CompareRequest(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (sequenceReader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpEntry)) { decoded.Entry = tmpEntry; } else { decoded.Entry = sequenceReader.ReadOctetString(); } Asn1AttributeValueAssertion.Decode(sequenceReader, out decoded.Assertion); sequenceReader.ThrowIfNotEmpty(); }
private static string FindAltNameMatch(byte[] extensionBytes, GeneralNameType matchType, string otherOid) { // If Other, have OID, else, no OID. Debug.Assert( (otherOid == null) == (matchType != GeneralNameType.OtherName), $"otherOid has incorrect nullarity for matchType {matchType}"); Debug.Assert( matchType == GeneralNameType.UniformResourceIdentifier || matchType == GeneralNameType.DnsName || matchType == GeneralNameType.Email || matchType == GeneralNameType.OtherName, $"matchType ({matchType}) is not currently supported"); Debug.Assert( otherOid == null || otherOid == Oids.UserPrincipalName, $"otherOid ({otherOid}) is not supported"); AsnReader reader = new AsnReader(extensionBytes, AsnEncodingRules.DER); AsnReader sequenceReader = reader.ReadSequence(); reader.ThrowIfNotEmpty(); while (sequenceReader.HasData) { GeneralNameAsn.Decode(sequenceReader, out GeneralNameAsn generalName); switch (matchType) { case GeneralNameType.OtherName: // If the OtherName OID didn't match, move to the next entry. if (generalName.OtherName.HasValue && generalName.OtherName.Value.TypeId == otherOid) { // Currently only UPN is supported, which is a UTF8 string per // https://msdn.microsoft.com/en-us/library/ff842518.aspx AsnReader nameReader = new AsnReader(generalName.OtherName.Value.Value, AsnEncodingRules.DER); string udnName = nameReader.ReadCharacterString(UniversalTagNumber.UTF8String); nameReader.ThrowIfNotEmpty(); return(udnName); } break; case GeneralNameType.Rfc822Name: if (generalName.Rfc822Name != null) { return(generalName.Rfc822Name); } break; case GeneralNameType.DnsName: if (generalName.DnsName != null) { return(generalName.DnsName); } break; case GeneralNameType.UniformResourceIdentifier: if (generalName.Uri != null) { return(generalName.Uri); } break; } } return(null); }
private static string X500DistinguishedNameDecode( byte[] encodedName, bool printOid, bool reverse, bool quoteIfNeeded, string dnSeparator, string multiValueSeparator, bool addTrailingDelimiter) { try { AsnReader x500NameReader = new AsnReader(encodedName, AsnEncodingRules.DER); AsnReader x500NameSequenceReader = x500NameReader.ReadSequence(); var rdnReaders = new List <AsnReader>(); x500NameReader.ThrowIfNotEmpty(); while (x500NameSequenceReader.HasData) { // To match Windows' behavior, permit multi-value RDN SETs to not // be DER sorted. rdnReaders.Add(x500NameSequenceReader.ReadSetOf(skipSortOrderValidation: true)); } // We need to allocate a StringBuilder to hold the data as we're building it, and there's the usual // arbitrary process of choosing a number that's "big enough" to minimize reallocations without wasting // too much space in the average case. // // So, let's look at an example of what our output might be. // // GitHub.com's SSL cert has a "pretty long" subject (partially due to the unknown OIDs): // businessCategory=Private Organization // 1.3.6.1.4.1.311.60.2.1.3=US // 1.3.6.1.4.1.311.60.2.1.2=Delaware // serialNumber=5157550 // street=548 4th Street // postalCode=94107 // C=US // ST=California // L=San Francisco // O=GitHub, Inc. // CN=github.com // // Which comes out to 228 characters using OpenSSL's default pretty-print // (openssl x509 -in github.cer -text -noout) // Throw in some "maybe-I-need-to-quote-this" quotes, and a couple of extra/extra-long O/OU values // and round that up to the next programmer number, and you get that 512 should avoid reallocations // in all but the most dire of cases. StringBuilder decodedName = new StringBuilder(512); int entryCount = rdnReaders.Count; bool printSpacing = false; for (int i = 0; i < entryCount; i++) { int loc = reverse ? entryCount - i - 1 : i; // RelativeDistinguishedName ::= // SET SIZE (1..MAX) OF AttributeTypeAndValue // // AttributeTypeAndValue::= SEQUENCE { // type AttributeType, // value AttributeValue } // // AttributeType::= OBJECT IDENTIFIER // // AttributeValue ::= ANY-- DEFINED BY AttributeType if (printSpacing) { decodedName.Append(dnSeparator); } else { printSpacing = true; } AsnReader rdnReader = rdnReaders[loc]; bool hadValue = false; while (rdnReader.HasData) { AsnReader tavReader = rdnReader.ReadSequence(); string oid = tavReader.ReadObjectIdentifier(); string attributeValue = tavReader.ReadAnyAsnString(); tavReader.ThrowIfNotEmpty(); if (hadValue) { decodedName.Append(multiValueSeparator); } else { hadValue = true; } if (printOid) { AppendOid(decodedName, oid); } bool quote = quoteIfNeeded && NeedsQuoting(attributeValue); if (quote) { decodedName.Append('"'); // If the RDN itself had a quote within it, that quote needs to be escaped // with another quote. attributeValue = attributeValue.Replace("\"", "\"\""); } decodedName.Append(attributeValue); if (quote) { decodedName.Append('"'); } } } if (addTrailingDelimiter && decodedName.Length > 0) { decodedName.Append(dnSeparator); } return(decodedName.ToString()); } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } }
internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded) where T : KrbEncTicketPart, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader explicitReader; AsnReader collectionReader; explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); if (explicitReader.TryReadPrimitiveBitStringValue(out _, out ReadOnlyMemory <byte> tmpFlags)) { decoded.Flags = (TicketFlags)tmpFlags.AsLong(); } else { decoded.Flags = (TicketFlags)explicitReader.ReadBitString(out _).AsLong(); } explicitReader.ThrowIfNotEmpty(); explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); KrbEncryptionKey.Decode <KrbEncryptionKey>(explicitReader, out decoded.Key); explicitReader.ThrowIfNotEmpty(); explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 2)); decoded.CRealm = explicitReader.ReadCharacterString(UniversalTagNumber.GeneralString); explicitReader.ThrowIfNotEmpty(); explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3)); KrbPrincipalName.Decode <KrbPrincipalName>(explicitReader, out decoded.CName); explicitReader.ThrowIfNotEmpty(); explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 4)); KrbTransitedEncoding.Decode <KrbTransitedEncoding>(explicitReader, out decoded.Transited); explicitReader.ThrowIfNotEmpty(); explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 5)); decoded.AuthTime = explicitReader.ReadGeneralizedTime(); explicitReader.ThrowIfNotEmpty(); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 6))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 6)); decoded.StartTime = explicitReader.ReadGeneralizedTime(); explicitReader.ThrowIfNotEmpty(); } explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 7)); decoded.EndTime = explicitReader.ReadGeneralizedTime(); explicitReader.ThrowIfNotEmpty(); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 8))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 8)); decoded.RenewTill = explicitReader.ReadGeneralizedTime(); explicitReader.ThrowIfNotEmpty(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 9))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 9)); // Decode SEQUENCE OF for CAddr { collectionReader = explicitReader.ReadSequence(); var tmpList = new List <KrbHostAddress>(); KrbHostAddress tmpItem; while (collectionReader.HasData) { KrbHostAddress.Decode <KrbHostAddress>(collectionReader, out tmpItem); tmpList.Add(tmpItem); } decoded.CAddr = tmpList.ToArray(); } explicitReader.ThrowIfNotEmpty(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 10))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 10)); // Decode SEQUENCE OF for AuthorizationData { collectionReader = explicitReader.ReadSequence(); var tmpList = new List <KrbAuthorizationData>(); KrbAuthorizationData tmpItem; while (collectionReader.HasData) { KrbAuthorizationData.Decode <KrbAuthorizationData>(collectionReader, out tmpItem); tmpList.Add(tmpItem); } decoded.AuthorizationData = tmpList.ToArray(); } explicitReader.ThrowIfNotEmpty(); } sequenceReader.ThrowIfNotEmpty(); }
private static Asn1Tag PeekTag(ReadOnlySequence <byte> request) { AsnReader reader = new AsnReader(request.First, AsnEncodingRules.DER); return(reader.PeekTag()); }
public override RSAParameters ExportParameters(bool includePrivateParameters) { SecKeyPair keys = GetKeys(); if (includePrivateParameters && keys.PrivateKey == null) { throw new CryptographicException(SR.Cryptography_OpenInvalidHandle); } bool gotKeyBlob = Interop.AppleCrypto.TrySecKeyCopyExternalRepresentation( includePrivateParameters ? keys.PrivateKey ! : keys.PublicKey, out byte[] keyBlob); if (!gotKeyBlob) { return(ExportParametersFromLegacyKey(keys, includePrivateParameters)); } try { if (!includePrivateParameters) { // When exporting a key handle opened from a certificate, it seems to // export as a PKCS#1 blob instead of an X509 SubjectPublicKeyInfo blob. // So, check for that. // NOTE: It doesn't affect macOS Mojave when SecCertificateCopyKey API // is used. RSAParameters key; AsnReader reader = new AsnReader(keyBlob, AsnEncodingRules.BER); AsnReader sequenceReader = reader.ReadSequence(); if (sequenceReader.PeekTag().Equals(Asn1Tag.Integer)) { AlgorithmIdentifierAsn ignored = default; RSAKeyFormatHelper.ReadRsaPublicKey(keyBlob, ignored, out key); } else { RSAKeyFormatHelper.ReadSubjectPublicKeyInfo( keyBlob, out int localRead, out key); Debug.Assert(localRead == keyBlob.Length); } return(key); } else { AlgorithmIdentifierAsn ignored = default; RSAKeyFormatHelper.FromPkcs1PrivateKey( keyBlob, ignored, out RSAParameters key); return(key); } } finally { CryptographicOperations.ZeroMemory(keyBlob); } }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out TbsCertificateAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader explicitReader; AsnReader defaultReader; AsnReader collectionReader; if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); if (!explicitReader.TryReadInt32(out decoded.Version)) { explicitReader.ThrowIfNotEmpty(); } explicitReader.ThrowIfNotEmpty(); } else { defaultReader = new AsnReader(s_defaultVersion, AsnEncodingRules.DER); if (!defaultReader.TryReadInt32(out decoded.Version)) { defaultReader.ThrowIfNotEmpty(); } } decoded.SerialNumber = sequenceReader.ReadIntegerBytes(); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.SignatureAlgorithm); if (!sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag((UniversalTagNumber)16))) { throw new CryptographicException(); } decoded.Issuer = sequenceReader.ReadEncodedValue(); System.Security.Cryptography.X509Certificates.Asn1.ValidityAsn.Decode(sequenceReader, out decoded.Validity); if (!sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag((UniversalTagNumber)16))) { throw new CryptographicException(); } decoded.Subject = sequenceReader.ReadEncodedValue(); System.Security.Cryptography.Asn1.SubjectPublicKeyInfoAsn.Decode(sequenceReader, out decoded.SubjectPublicKeyInfo); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { if (sequenceReader.TryReadPrimitiveBitStringValue(new Asn1Tag(TagClass.ContextSpecific, 1), out _, out ReadOnlyMemory <byte> tmpIssuerUniqueId)) { decoded.IssuerUniqueId = tmpIssuerUniqueId; } else { decoded.IssuerUniqueId = sequenceReader.ReadBitString(new Asn1Tag(TagClass.ContextSpecific, 1), out _); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) { if (sequenceReader.TryReadPrimitiveBitStringValue(new Asn1Tag(TagClass.ContextSpecific, 2), out _, out ReadOnlyMemory <byte> tmpSubjectUniqueId)) { decoded.SubjectUniqueId = tmpSubjectUniqueId; } else { decoded.SubjectUniqueId = sequenceReader.ReadBitString(new Asn1Tag(TagClass.ContextSpecific, 2), out _); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 3))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3)); // Decode SEQUENCE OF for Extensions { collectionReader = explicitReader.ReadSequence(); var tmpList = new List <System.Security.Cryptography.Asn1.X509ExtensionAsn>(); System.Security.Cryptography.Asn1.X509ExtensionAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.X509ExtensionAsn.Decode(collectionReader, out tmpItem); tmpList.Add(tmpItem); } decoded.Extensions = tmpList.ToArray(); } explicitReader.ThrowIfNotEmpty(); } sequenceReader.ThrowIfNotEmpty(); }
public byte[]? GetOutgoingBlob(byte[]?incomingBlob) { if (_spnegoMechList == null && incomingBlob.AsSpan().StartsWith(NtlmHeader)) { _ntlmPassthrough = true; // Windows often sends pure NTLM instead of proper Negotiate, handle that as passthrough byte[]? outgoingBlob = _ntlmServer.GetOutgoingBlob(incomingBlob); IsAuthenticated = _ntlmServer.IsAuthenticated; return(outgoingBlob); } Assert.False(_ntlmPassthrough); AsnReader reader = new AsnReader(incomingBlob, AsnEncodingRules.DER); if (_spnegoMechList == null) { AsnReader initialContextTokenReader = reader.ReadSequence(new Asn1Tag(TagClass.Application, 0)); string spNegoOid = initialContextTokenReader.ReadObjectIdentifier(); Assert.Equal(SpnegoOid, spNegoOid); AsnReader negTokenInitReader = initialContextTokenReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenInit)).ReadSequence(); AsnReader mechTypesOuterReader = negTokenInitReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechTypes)); _spnegoMechList = mechTypesOuterReader.PeekEncodedValue().ToArray(); bool hasNtlm = false; bool isNtlmPreferred = false; bool first = true; AsnReader mechTypesReader = mechTypesOuterReader.ReadSequence(); while (mechTypesReader.HasData) { string mechType = mechTypesReader.ReadObjectIdentifier(); if (mechType == NtlmOid) { hasNtlm = true; isNtlmPreferred = first; } first = false; } // Skip context flags, if present if (negTokenInitReader.HasData && negTokenInitReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.ReqFlags))) { negTokenInitReader.ReadSequence(); } byte[]? mechToken = null; if (negTokenInitReader.HasData && negTokenInitReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechToken))) { AsnReader mechTokenReader = negTokenInitReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechToken)); mechToken = mechTokenReader.ReadOctetString(); Assert.False(mechTokenReader.HasData); } byte[]? mechListMIC = null; if (negTokenInitReader.HasData && negTokenInitReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechListMIC))) { AsnReader mechListMICReader = negTokenInitReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenInit.MechListMIC)); mechListMIC = mechListMICReader.ReadOctetString(); Assert.False(mechListMICReader.HasData); } Assert.True(hasNtlm); // If the preferred mechanism was NTLM then proceed with the given token byte[]? outgoingBlob = null; if (isNtlmPreferred && mechToken != null) { Assert.Null(mechListMIC); outgoingBlob = _ntlmServer.GetOutgoingBlob(mechToken); } // Generate reply AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp))) { using (writer.PushSequence()) { using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState))) { if (RequestMIC) { writer.WriteEnumeratedValue(NegState.RequestMic); } else { writer.WriteEnumeratedValue(NegState.AcceptIncomplete); } } using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.SupportedMech))) { writer.WriteObjectIdentifier(NtlmOid); } if (outgoingBlob != null) { using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken))) { writer.WriteOctetString(outgoingBlob); } } } } return(writer.Encode()); } else { AsnReader negTokenRespReader = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp)).ReadSequence(); Assert.True(negTokenRespReader.HasData); NegState?clientState; if (negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState))) { AsnReader valueReader = negTokenRespReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState)); clientState = valueReader.ReadEnumeratedValue <NegState>(); Assert.False(valueReader.HasData); Assert.NotEqual(NegState.Reject, clientState); Assert.NotEqual(NegState.RequestMic, clientState); } // Client should not send mechanism Assert.False(negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.SupportedMech))); byte[]? mechToken = null; if (negTokenRespReader.HasData && negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken))) { AsnReader mechTokenReader = negTokenRespReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken)); mechToken = mechTokenReader.ReadOctetString(); Assert.False(mechTokenReader.HasData); } byte[]? mechListMIC = null; if (negTokenRespReader.HasData && negTokenRespReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.MechListMIC))) { AsnReader mechListMICReader = negTokenRespReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.MechListMIC)); mechListMIC = mechListMICReader.ReadOctetString(); Assert.False(mechListMICReader.HasData); } Assert.NotNull(mechToken); byte[]? outgoingBlob = _ntlmServer.GetOutgoingBlob(mechToken); if (_ntlmServer.IsAuthenticated) { if (RequestMIC) { Assert.NotNull(mechListMIC); } // Validate mechListMIC, if present if (mechListMIC is not null) { _ntlmServer.VerifyMIC(_spnegoMechList, mechListMIC); } } else { Assert.Null(mechListMIC); } // Generate reply AsnWriter writer = new AsnWriter(AsnEncodingRules.DER); using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegotiationToken.NegTokenResp))) { using (writer.PushSequence()) { using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.NegState))) { if (_ntlmServer.IsAuthenticated) { writer.WriteEnumeratedValue(NegState.AcceptCompleted); } else if (outgoingBlob != null) { writer.WriteEnumeratedValue(NegState.AcceptIncomplete); } else { writer.WriteEnumeratedValue(NegState.Reject); } } if (outgoingBlob != null) { using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.ResponseToken))) { writer.WriteOctetString(outgoingBlob); } } if (mechListMIC != null) { using (writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, (int)NegTokenResp.MechListMIC))) { Span <byte> mic = stackalloc byte[16]; _ntlmServer.GetMIC(_spnegoMechList, mic); writer.WriteOctetString(mic); // MS-SPNG section 3.2.5.1 NTLM RC4 Key State for MechListMIC and First Signed Message // specifies that the RC4 sealing keys are reset back to the initial state for the // first message. _ntlmServer.ResetKeys(); } } } } IsAuthenticated = _ntlmServer.IsAuthenticated; return(writer.Encode()); } }
public static void TryCopyIA5StringBytes_Success_CER_MinConstructedLength() { // CER says that the maximum encoding length for a IA5String primitive // is 1000, and that a constructed form must be used for values greater // than 1000 bytes, with segments dividing up for each thousand // [1000, 1000, ..., len%1000]. // // So our smallest constructed form is 1001 bytes, [1000, 1] // // 36 80 (indefinite constructed IA5 string) // 04 82 03 E9 (primitive octet string, 1000 bytes) // [1000 content bytes] // 04 01 (primitive octet string, 1 byte) // pp // 00 00 (end of contents, 0 bytes) // 1011 total. byte[] input = new byte[1011]; int offset = 0; // CONSTRUCTED IA5STRING (Indefinite) input[offset++] = 0x36; input[offset++] = 0x80; // OCTET STRING (1000) input[offset++] = 0x04; input[offset++] = 0x82; input[offset++] = 0x03; input[offset++] = 0xE8; // Primitive 1: (65 65 :: 61 61) (1000) input[offset++] = 0x65; input[offset] = 0x65; offset += 997; input[offset++] = 0x61; input[offset++] = 0x61; // OCTET STRING (1) input[offset++] = 0x04; input[offset++] = 0x01; // Primitive 2: One more byte input[offset] = 0x2E; byte[] expected = new byte[1001]; offset = 0; expected[offset++] = 0x65; expected[offset] = 0x65; offset += 997; expected[offset++] = 0x61; expected[offset++] = 0x61; expected[offset] = 0x2E; byte[] output = new byte[1001]; AsnReader reader = new AsnReader(input, AsnEncodingRules.CER); bool success = reader.TryCopyIA5StringBytes(output, out int bytesWritten); Assert.True(success, "reader.TryCopyIA5StringBytes"); Assert.Equal(1001, bytesWritten); Assert.Equal( expected.ByteArrayToHex(), output.ByteArrayToHex()); }