// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Security.Cryptography.X509Certificates;
-
-namespace System.Security.Cryptography.X509Certificates.Asn1
+namespace System.Security.Cryptography.Asn1
{
- internal partial struct X501AttributeAsn
+ internal partial struct AttributeAsn
{
- public X501AttributeAsn(X501Attribute attribute)
+ public AttributeAsn(AsnEncodedData attribute)
{
if (attribute == null)
{
throw new ArgumentNullException(nameof(attribute));
}
- AttrId = attribute.Oid;
+ AttrType = new Oid(attribute.Oid);
AttrValues = new[] { new ReadOnlyMemory<byte>(attribute.RawData) };
}
}
AttributeValue ::= ANY
-->
<asn:ObjectIdentifier name="AttrType" />
- <asn:AnyValue name="AttrValues" />
+ <asn:SetOf name="AttrValues">
+ <asn:AnyValue />
+ </asn:SetOf>
</asn:Sequence>
\ No newline at end of file
using System;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.Asn1;
internal partial struct AttributeAsn
{
internal Oid AttrType;
- internal ReadOnlyMemory<byte> AttrValues;
+ internal ReadOnlyMemory<byte>[] AttrValues;
internal void Encode(AsnWriter writer)
{
writer.PushSequence(tag);
writer.WriteObjectIdentifier(AttrType);
- writer.WriteEncodedValue(AttrValues);
+
+ writer.PushSetOf();
+ for (int i = 0; i < AttrValues.Length; i++)
+ {
+ writer.WriteEncodedValue(AttrValues[i]);
+ }
+ writer.PopSetOf();
+
writer.PopSequence(tag);
}
decoded = default;
AsnReader sequenceReader = reader.ReadSequence(expectedTag);
+ AsnReader collectionReader;
decoded.AttrType = sequenceReader.ReadObjectIdentifier();
- decoded.AttrValues = sequenceReader.GetEncodedValue();
+
+ // Decode SEQUENCE OF for AttrValues
+ {
+ collectionReader = sequenceReader.ReadSetOf();
+ var tmpList = new List<ReadOnlyMemory<byte>>();
+ ReadOnlyMemory<byte> tmpItem;
+
+ while (collectionReader.HasData)
+ {
+ tmpItem = collectionReader.GetEncodedValue();
+ tmpList.Add(tmpItem);
+ }
+
+ decoded.AttrValues = tmpList.ToArray();
+ }
+
sequenceReader.ThrowIfNotEmpty();
}
<Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs</Link>
<DependentUpon>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</DependentUpon>
</Compile>
+ <Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1\AttributeAsn.manual.cs">
+ <Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.manual.cs</Link>
+ <DependentUpon>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</DependentUpon>
+ </Compile>
<AsnXml Include="$(CommonPath)\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml">
<Link>Common\System\Security\Cryptography\Asn1\EncryptedPrivateKeyInfoAsn.xml</Link>
</AsnXml>
using (var writer = new AsnWriter(AsnEncodingRules.DER))
{
- writer.PushSetOf();
writer.WriteOctetString(dataHash);
- writer.PopSetOf();
-
signedAttrs.Add(
new AttributeAsn
{
AttrType = new Oid(Oids.MessageDigest, Oids.MessageDigest),
- AttrValues = writer.Encode(),
+ AttrValues = new[] { new ReadOnlyMemory<byte>(writer.Encode()) },
});
}
{
using (var writer = new AsnWriter(AsnEncodingRules.DER))
{
- writer.PushSetOf();
writer.WriteObjectIdentifier(contentTypeOid);
- writer.PopSetOf();
-
signedAttrs.Add(
new AttributeAsn
{
AttrType = new Oid(Oids.ContentType, Oids.ContentType),
- AttrValues = writer.Encode(),
+ AttrValues = new[] { new ReadOnlyMemory<byte>(writer.Encode()) },
});
}
}
foreach (CryptographicAttributeObject attributeObject in attributes)
{
- using (var writer = new AsnWriter(AsnEncodingRules.DER))
+ AttributeAsn newAttr = new AttributeAsn
{
- writer.PushSetOf();
-
- foreach (AsnEncodedData objectValue in attributeObject.Values)
- {
- writer.WriteEncodedValue(objectValue.RawData);
- }
+ AttrType = attributeObject.Oid,
+ AttrValues = new ReadOnlyMemory<byte>[attributeObject.Values.Count],
+ };
- writer.PopSetOf();
-
- AttributeAsn newAttr = new AttributeAsn
- {
- AttrType = attributeObject.Oid,
- AttrValues = writer.Encode(),
- };
-
- signedAttrs.Add(newAttr);
+ for (int i = 0; i < attributeObject.Values.Count; i++)
+ {
+ newAttr.AttrValues[i] = attributeObject.Values[i].RawData;
}
+
+ signedAttrs.Add(newAttr);
}
return signedAttrs;
foreach (AttributeAsn attr in attrs)
{
- writer.PushSequence();
- writer.WriteObjectIdentifier(attr.AttrType);
- writer.WriteEncodedValue(attr.AttrValues);
- writer.PopSequence();
+ attr.Encode(writer);
}
writer.PopSetOf();
if (existingAttribute == -1)
{
// create a new attribute
- AttributeAsn newUnsignedAttr;
- using (AsnWriter writer = new AsnWriter(AsnEncodingRules.BER))
- {
- writer.PushSetOf();
- writer.WriteEncodedValue(unsignedAttribute.RawData);
- writer.PopSetOf();
-
- newUnsignedAttr = new AttributeAsn
- {
- AttrType = new Oid(unsignedAttribute.Oid),
- AttrValues = writer.Encode(),
- };
- }
-
+ AttributeAsn newUnsignedAttr = new AttributeAsn(unsignedAttribute);
int newAttributeIdx;
if (mySigner.UnsignedAttributes == null)
{
// merge with existing attribute
ref AttributeAsn modifiedAttr = ref mySigner.UnsignedAttributes[existingAttribute];
-
- using (AsnWriter writer = new AsnWriter(AsnEncodingRules.BER))
- {
- writer.PushSetOf();
-
- AsnReader reader = new AsnReader(modifiedAttr.AttrValues, AsnEncodingRules.BER);
- AsnReader collReader = reader.ReadSetOf();
-
- reader.ThrowIfNotEmpty();
-
- // re-add old values
- while (collReader.HasData)
- {
- writer.WriteEncodedValue(collReader.GetEncodedValue());
- }
-
- writer.WriteEncodedValue(unsignedAttribute.RawData);
-
- writer.PopSetOf();
- modifiedAttr.AttrValues = writer.Encode();
- }
+ int newIndex = modifiedAttr.AttrValues.Length;
+ Array.Resize(ref modifiedAttr.AttrValues, newIndex + 1);
+ modifiedAttr.AttrValues[newIndex] = unsignedAttribute.RawData;
}
// Re-normalize the document
}
else
{
- RemoveAttributeValueWithoutIndexChecking(ref mySigner.UnsignedAttributes[outerIndex], innerIndex);
+ PkcsHelpers.RemoveAt(ref mySigner.UnsignedAttributes[outerIndex].AttrValues, innerIndex);
}
// Re-normalize the document
{
if (attributeAsn.AttrType.Value == Oids.CounterSigner)
{
- AsnReader reader = new AsnReader(attributeAsn.AttrValues, AsnEncodingRules.BER);
- AsnReader collReader = reader.ReadSetOf();
-
- reader.ThrowIfNotEmpty();
-
- while (collReader.HasData)
+ foreach (ReadOnlyMemory<byte> attrValue in attributeAsn.AttrValues)
{
- SignerInfoAsn.Decode(collReader, out SignerInfoAsn parsedData);
+ SignerInfoAsn parsedData = SignerInfoAsn.Decode(attrValue, AsnEncodingRules.BER);
SignerInfo signerInfo = new SignerInfo(ref parsedData, _document)
{
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
{
- writer.PushSetOf();
newSignerInfo.Encode(writer);
- writer.PopSetOf();
newUnsignedAttr = new AttributeAsn
{
AttrType = new Oid(Oids.CounterSigner, Oids.CounterSigner),
- AttrValues = writer.Encode(),
+ AttrValues = new[] { new ReadOnlyMemory<byte>(writer.Encode()) },
};
}
if (attributeAsn.AttrType.Value == Oids.CounterSigner)
{
- AsnReader reader = new AsnReader(attributeAsn.AttrValues, AsnEncodingRules.BER);
- AsnReader collReader = reader.ReadSetOf();
-
- reader.ThrowIfNotEmpty();
-
- int j = 0;
-
- while (collReader.HasData)
+ if (index < csIndex + attributeAsn.AttrValues.Length)
{
- collReader.GetEncodedValue();
-
- if (csIndex == index)
+ removeAttrIdx = i;
+ removeValueIndex = index - csIndex;
+ if (removeValueIndex == 0 && attributeAsn.AttrValues.Length == 1)
{
- removeAttrIdx = i;
- removeValueIndex = j;
+ removeWholeAttr = true;
}
-
- csIndex++;
- j++;
- }
-
- if (removeValueIndex == 0 && j == 1)
- {
- removeWholeAttr = true;
- }
-
- if (removeAttrIdx >= 0)
- {
break;
}
+
+ csIndex += attributeAsn.AttrValues.Length;
}
}
}
else
{
- RemoveAttributeValueWithoutIndexChecking(ref unsignedAttrs[removeAttrIdx], removeValueIndex);
+ PkcsHelpers.RemoveAt(ref unsignedAttrs[removeAttrIdx].AttrValues, removeValueIndex);
}
}
private static CryptographicAttributeObject MakeAttribute(AttributeAsn attribute)
{
Oid type = new Oid(attribute.AttrType);
-
- ReadOnlyMemory<byte> attrSetBytes = attribute.AttrValues;
-
- AsnReader reader = new AsnReader(attrSetBytes, AsnEncodingRules.BER);
- AsnReader collReader = reader.ReadSetOf();
-
- reader.ThrowIfNotEmpty();
-
AsnEncodedDataCollection valueColl = new AsnEncodedDataCollection();
- while (collReader.HasData)
+ foreach (ReadOnlyMemory<byte> attrValue in attribute.AttrValues)
{
- byte[] attrBytes = collReader.GetEncodedValue().ToArray();
- valueColl.Add(PkcsHelpers.CreateBestPkcs9AttributeObjectAvailable(type, attrBytes));
+ valueColl.Add(PkcsHelpers.CreateBestPkcs9AttributeObjectAvailable(type, attrValue.ToArray()));
}
return new CryptographicAttributeObject(type, valueColl);
return -1;
}
- private static int FindAttributeValueIndexByEncodedData(ReadOnlyMemory<byte> attributeValues, ReadOnlySpan<byte> asnEncodedData, out bool isOnlyValue)
+ private static int FindAttributeValueIndexByEncodedData(ReadOnlyMemory<byte>[] attributeValues, ReadOnlySpan<byte> asnEncodedData, out bool isOnlyValue)
{
- AsnReader reader = new AsnReader(attributeValues, AsnEncodingRules.BER);
- AsnReader collReader = reader.ReadSetOf();
-
- reader.ThrowIfNotEmpty();
-
- for (int i = 0; collReader.HasData; i++)
+ for (int i = 0; i < attributeValues.Length; i++)
{
- ReadOnlySpan<byte> data = collReader.GetEncodedValue().Span;
+ ReadOnlySpan<byte> data = attributeValues[i].Span;
if (data.SequenceEqual(asnEncodedData))
{
- isOnlyValue = i == 0 && !collReader.HasData;
+ isOnlyValue = attributeValues.Length == 1;
return i;
}
}
isOnlyValue = false;
return (-1, -1);
}
-
- private static void RemoveAttributeValueWithoutIndexChecking(ref AttributeAsn modifiedAttr, int removeValueIndex)
- {
- // Using BER rules to avoid resorting
- using (AsnWriter writer = new AsnWriter(AsnEncodingRules.BER))
- {
- writer.PushSetOf();
-
- AsnReader reader = new AsnReader(modifiedAttr.AttrValues, writer.RuleSet);
- AsnReader collReader = reader.ReadSetOf();
-
- reader.ThrowIfNotEmpty();
-
- int i = 0;
-
- while (collReader.HasData)
- {
- ReadOnlyMemory<byte> encodedValue = collReader.GetEncodedValue();
-
- if (i != removeValueIndex)
- {
- writer.WriteEncodedValue(encodedValue);
- }
-
- i++;
- }
-
- writer.PopSetOf();
- modifiedAttr.AttrValues = writer.Encode();
- }
- }
}
}
<Link>Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.manual.cs</Link>
<DependentUpon>Common\System\Security\Cryptography\Asn1\AlgorithmIdentifierAsn.xml</DependentUpon>
</Compile>
+ <AsnXml Include="$(CommonPath)\System\Security\Cryptography\Asn1\AttributeAsn.xml">
+ <Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</Link>
+ </AsnXml>
+ <Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs">
+ <Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs</Link>
+ <DependentUpon>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</DependentUpon>
+ </Compile>
+ <Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1\AttributeAsn.manual.cs">
+ <Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.manual.cs</Link>
+ <DependentUpon>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</DependentUpon>
+ </Compile>
<AsnXml Include="$(CommonPath)\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml">
<Link>Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml</Link>
</AsnXml>
<DependentUpon>System\Security\Cryptography\X509Certificates\Asn1\ValidityAsn.xml</DependentUpon>
</Compile>
<Compile Include="System\Security\Cryptography\X509Certificates\Asn1\ValidityAsn.manual.cs" />
- <AsnXml Include="System\Security\Cryptography\X509Certificates\Asn1\X501AttributeAsn.xml" />
- <Compile Include="System\Security\Cryptography\X509Certificates\Asn1\X501AttributeAsn.xml.cs">
- <DependentUpon>System\Security\Cryptography\X509Certificates\Asn1\X501AttributeAsn.xml</DependentUpon>
- </Compile>
- <Compile Include="System\Security\Cryptography\X509Certificates\Asn1\X501AttributeAsn.manual.cs" />
<AsnXml Include="System\Security\Cryptography\X509Certificates\Asn1\AccessDescriptionAsn.xml" />
<Compile Include="System\Security\Cryptography\X509Certificates\Asn1\AccessDescriptionAsn.xml.cs">
<DependentUpon>System\Security\Cryptography\X509Certificates\Asn1\AccessDescriptionAsn.xml</DependentUpon>
<Compile Include="$(CommonPath)\System\Security\Cryptography\SecKeyPair.cs">
<Link>Common\System\Security\Cryptography\SecKeyPair.cs</Link>
</Compile>
- <AsnXml Include="$(CommonPath)\System\Security\Cryptography\Asn1\AttributeAsn.xml">
- <Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</Link>
- </AsnXml>
- <Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs">
- <Link>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml.cs</Link>
- <DependentUpon>Common\System\Security\Cryptography\Asn1\AttributeAsn.xml</DependentUpon>
- </Compile>
<AsnXml Include="$(CommonPath)\System\Security\Cryptography\Asn1\CurveAsn.xml">
<Link>Common\System\Security\Cryptography\Asn1\CurveAsn.xml</Link>
</AsnXml>
<asn:AnyValue name="Subject" universalTagNumber="16" />
<asn:AsnType name="SubjectPublicKeyInfo" typeName="System.Security.Cryptography.Asn1.SubjectPublicKeyInfoAsn" />
<asn:SetOf name="Attributes" implicitTag="0">
- <asn:AsnType typeName="System.Security.Cryptography.X509Certificates.Asn1.X501AttributeAsn" />
+ <asn:AsnType typeName="System.Security.Cryptography.Asn1.AttributeAsn" />
</asn:SetOf>
</asn:Sequence>
\ No newline at end of file
internal System.Numerics.BigInteger Version;
internal ReadOnlyMemory<byte> Subject;
internal System.Security.Cryptography.Asn1.SubjectPublicKeyInfoAsn SubjectPublicKeyInfo;
- internal System.Security.Cryptography.X509Certificates.Asn1.X501AttributeAsn[] Attributes;
+ internal System.Security.Cryptography.Asn1.AttributeAsn[] Attributes;
internal void Encode(AsnWriter writer)
{
// Decode SEQUENCE OF for Attributes
{
collectionReader = sequenceReader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0));
- var tmpList = new List<System.Security.Cryptography.X509Certificates.Asn1.X501AttributeAsn>();
- System.Security.Cryptography.X509Certificates.Asn1.X501AttributeAsn tmpItem;
+ var tmpList = new List<System.Security.Cryptography.Asn1.AttributeAsn>();
+ System.Security.Cryptography.Asn1.AttributeAsn tmpItem;
while (collectionReader.HasData)
{
- System.Security.Cryptography.X509Certificates.Asn1.X501AttributeAsn.Decode(collectionReader, out tmpItem);
+ System.Security.Cryptography.Asn1.AttributeAsn.Decode(collectionReader, out tmpItem);
tmpList.Add(tmpItem);
}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8" ?>
-<asn:Sequence
- xmlns:asn="http://schemas.dot.net/asnxml/201808/"
- name="X501AttributeAsn"
- namespace="System.Security.Cryptography.X509Certificates.Asn1">
-
- <!--
- https://tools.ietf.org/html/rfc2986#section-4.1
-
- Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
- type ATTRIBUTE.&id({IOSet}),
- values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
- }
- -->
- <asn:ObjectIdentifier name="AttrId" />
- <asn:SetOf name="AttrValues">
- <asn:AnyValue />
- </asn:SetOf>
-</asn:Sequence>
\ No newline at end of file
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using System.Security.Cryptography.Asn1;
-
-namespace System.Security.Cryptography.X509Certificates.Asn1
-{
- [StructLayout(LayoutKind.Sequential)]
- internal partial struct X501AttributeAsn
- {
- internal Oid AttrId;
- internal ReadOnlyMemory<byte>[] AttrValues;
-
- internal void Encode(AsnWriter writer)
- {
- Encode(writer, Asn1Tag.Sequence);
- }
-
- internal void Encode(AsnWriter writer, Asn1Tag tag)
- {
- writer.PushSequence(tag);
-
- writer.WriteObjectIdentifier(AttrId);
-
- writer.PushSetOf();
- for (int i = 0; i < AttrValues.Length; i++)
- {
- writer.WriteEncodedValue(AttrValues[i]);
- }
- writer.PopSetOf();
-
- writer.PopSequence(tag);
- }
-
- internal static X501AttributeAsn Decode(ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
- {
- return Decode(Asn1Tag.Sequence, encoded, ruleSet);
- }
-
- internal static X501AttributeAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
- {
- AsnReader reader = new AsnReader(encoded, ruleSet);
-
- Decode(reader, expectedTag, out X501AttributeAsn decoded);
- reader.ThrowIfNotEmpty();
- return decoded;
- }
-
- internal static void Decode(AsnReader reader, out X501AttributeAsn decoded)
- {
- if (reader == null)
- throw new ArgumentNullException(nameof(reader));
-
- Decode(reader, Asn1Tag.Sequence, out decoded);
- }
-
- internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out X501AttributeAsn decoded)
- {
- if (reader == null)
- throw new ArgumentNullException(nameof(reader));
-
- decoded = default;
- AsnReader sequenceReader = reader.ReadSequence(expectedTag);
- AsnReader collectionReader;
-
- decoded.AttrId = sequenceReader.ReadObjectIdentifier();
-
- // Decode SEQUENCE OF for AttrValues
- {
- collectionReader = sequenceReader.ReadSetOf();
- var tmpList = new List<ReadOnlyMemory<byte>>();
- ReadOnlyMemory<byte> tmpItem;
-
- while (collectionReader.HasData)
- {
- tmpItem = collectionReader.GetEncodedValue();
- tmpList.Add(tmpItem);
- }
-
- decoded.AttrValues = tmpList.ToArray();
- }
-
-
- sequenceReader.ThrowIfNotEmpty();
- }
- }
-}
Version = 0,
Subject = this.Subject.RawData,
SubjectPublicKeyInfo = spki,
- Attributes = Attributes.Select(a => new X501AttributeAsn(a)).ToArray(),
+ Attributes = Attributes.Select(a => new AttributeAsn(a)).ToArray(),
};
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))