internal static void Decode(AsnReader reader, out SignedAttributesSet decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; Asn1Tag tag = reader.PeekTag(); AsnReader collectionReader; if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { // Decode SEQUENCE OF for SignedAttributes { collectionReader = reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0)); var tmpList = new List <System.Security.Cryptography.Asn1.AttributeAsn>(); System.Security.Cryptography.Asn1.AttributeAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.AttributeAsn.Decode(collectionReader, out tmpItem); tmpList.Add(tmpItem); } decoded.SignedAttributes = tmpList.ToArray(); } } else { throw new CryptographicException(); } }
internal SignerInfo(ref SignerInfoAsn parsedData, SignedCms ownerDocument) { Version = parsedData.Version; SignerIdentifier = new SubjectIdentifier(parsedData.Sid); _digestAlgorithm = parsedData.DigestAlgorithm.Algorithm; _signedAttributesMemory = parsedData.SignedAttributes; _signatureAlgorithm = parsedData.SignatureAlgorithm.Algorithm; _signatureAlgorithmParameters = parsedData.SignatureAlgorithm.Parameters; _signature = parsedData.SignatureValue; _unsignedAttributes = parsedData.UnsignedAttributes; if (_signedAttributesMemory.HasValue) { SignedAttributesSet signedSet = SignedAttributesSet.Decode( _signedAttributesMemory.Value, AsnEncodingRules.BER); _signedAttributes = signedSet.SignedAttributes; Debug.Assert(_signedAttributes != null); } _document = ownerDocument; }
internal SignerInfoAsn Sign( ReadOnlyMemory <byte> data, string contentTypeOid, bool silent, out X509Certificate2Collection chainCerts) { HashAlgorithmName hashAlgorithmName = PkcsHelpers.GetDigestAlgorithm(DigestAlgorithm); IncrementalHash hasher = IncrementalHash.CreateHash(hashAlgorithmName); hasher.AppendData(data.Span); byte[] dataHash = hasher.GetHashAndReset(); SignerInfoAsn newSignerInfo = new SignerInfoAsn(); newSignerInfo.DigestAlgorithm.Algorithm = DigestAlgorithm; // If the user specified attributes (not null, count > 0) we need attributes. // If the content type is null we're counter-signing, and need the message digest attr. // If the content type is otherwise not-data we need to record it as the content-type attr. if (SignedAttributes?.Count > 0 || contentTypeOid != Oids.Pkcs7Data) { List <AttributeAsn> signedAttrs = BuildAttributes(SignedAttributes); using (var writer = new AsnWriter(AsnEncodingRules.DER)) { writer.WriteOctetString(dataHash); signedAttrs.Add( new AttributeAsn { AttrType = new Oid(Oids.MessageDigest, Oids.MessageDigest), AttrValues = new[] { new ReadOnlyMemory <byte>(writer.Encode()) }, }); } if (contentTypeOid != null) { using (var writer = new AsnWriter(AsnEncodingRules.DER)) { writer.WriteObjectIdentifier(contentTypeOid); signedAttrs.Add( new AttributeAsn { AttrType = new Oid(Oids.ContentType, Oids.ContentType), AttrValues = new[] { new ReadOnlyMemory <byte>(writer.Encode()) }, }); } } // Use the serializer/deserializer to DER-normalize the attribute order. SignedAttributesSet signedAttrsSet = new SignedAttributesSet(); signedAttrsSet.SignedAttributes = PkcsHelpers.NormalizeAttributeSet( signedAttrs.ToArray(), normalized => hasher.AppendData(normalized)); // Since this contains user data in a context where BER is permitted, use BER. // There shouldn't be any observable difference here between BER and DER, though, // since the top level fields were written by NormalizeSet. using (AsnWriter attrsWriter = new AsnWriter(AsnEncodingRules.BER)) { signedAttrsSet.Encode(attrsWriter); newSignerInfo.SignedAttributes = attrsWriter.Encode(); } dataHash = hasher.GetHashAndReset(); } switch (SignerIdentifierType) { case SubjectIdentifierType.IssuerAndSerialNumber: byte[] serial = Certificate.GetSerialNumber(); Array.Reverse(serial); newSignerInfo.Sid.IssuerAndSerialNumber = new IssuerAndSerialNumberAsn { Issuer = Certificate.IssuerName.RawData, SerialNumber = serial, }; newSignerInfo.Version = 1; break; case SubjectIdentifierType.SubjectKeyIdentifier: newSignerInfo.Sid.SubjectKeyIdentifier = PkcsPal.Instance.GetSubjectKeyIdentifier(Certificate); newSignerInfo.Version = 3; break; case SubjectIdentifierType.NoSignature: newSignerInfo.Sid.IssuerAndSerialNumber = new IssuerAndSerialNumberAsn { Issuer = SubjectIdentifier.DummySignerEncodedValue, SerialNumber = new byte[1], }; newSignerInfo.Version = 1; break; default: Debug.Fail($"Unresolved SignerIdentifierType value: {SignerIdentifierType}"); throw new CryptographicException(); } if (UnsignedAttributes != null && UnsignedAttributes.Count > 0) { List <AttributeAsn> attrs = BuildAttributes(UnsignedAttributes); newSignerInfo.UnsignedAttributes = PkcsHelpers.NormalizeAttributeSet(attrs.ToArray()); } bool signed; Oid signatureAlgorithm; ReadOnlyMemory <byte> signatureValue; if (SignerIdentifierType == SubjectIdentifierType.NoSignature) { signatureAlgorithm = new Oid(Oids.NoSignature, null); signatureValue = dataHash; signed = true; } else { signed = CmsSignature.Sign( dataHash, hashAlgorithmName, Certificate, PrivateKey, silent, out signatureAlgorithm, out signatureValue); } if (!signed) { throw new CryptographicException(SR.Cryptography_Cms_CannotDetermineSignatureAlgorithm); } newSignerInfo.SignatureValue = signatureValue; newSignerInfo.SignatureAlgorithm.Algorithm = signatureAlgorithm; X509Certificate2Collection certs = new X509Certificate2Collection(); certs.AddRange(Certificates); if (SignerIdentifierType != SubjectIdentifierType.NoSignature) { if (IncludeOption == X509IncludeOption.EndCertOnly) { certs.Add(Certificate); } else if (IncludeOption != X509IncludeOption.None) { X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; if (!chain.Build(Certificate)) { foreach (X509ChainStatus status in chain.ChainStatus) { if (status.Status == X509ChainStatusFlags.PartialChain) { throw new CryptographicException(SR.Cryptography_Cms_IncompleteCertChain); } } } X509ChainElementCollection elements = chain.ChainElements; int count = elements.Count; int last = count - 1; if (last == 0) { // If there's always one cert treat it as EE, not root. last = -1; } for (int i = 0; i < count; i++) { X509Certificate2 cert = elements[i].Certificate; if (i == last && IncludeOption == X509IncludeOption.ExcludeRoot && cert.SubjectName.RawData.AsSpan().SequenceEqual(cert.IssuerName.RawData)) { break; } certs.Add(cert); } } } chainCerts = certs; return(newSignerInfo); }
private static void DecodeCore(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out SignedAttributesSet decoded) { decoded = default; Asn1Tag tag = reader.PeekTag(); AsnValueReader collectionReader; if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { // Decode SEQUENCE OF for SignedAttributes { collectionReader = reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0)); var tmpList = new List <System.Security.Cryptography.Asn1.AttributeAsn>(); System.Security.Cryptography.Asn1.AttributeAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.AttributeAsn.Decode(ref collectionReader, rebind, out tmpItem); tmpList.Add(tmpItem); } decoded.SignedAttributes = tmpList.ToArray(); } } else { throw new CryptographicException(); } }
internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out SignedAttributesSet decoded) { try { DecodeCore(ref reader, rebind, out decoded); } catch (AsnContentException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } }