2 // PKCS7.cs: PKCS #7 - Cryptographic Message Syntax Standard
3 // http://www.rsasecurity.com/rsalabs/pkcs/pkcs-7/index.html
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Security.Cryptography;
35 using Mono.Security.X509;
37 namespace Mono.Security {
48 public const string rsaEncryption = "1.2.840.113549.1.1.1";
50 public const string data = "1.2.840.113549.1.7.1";
51 public const string signedData = "1.2.840.113549.1.7.2";
52 public const string envelopedData = "1.2.840.113549.1.7.3";
53 public const string signedAndEnvelopedData = "1.2.840.113549.1.7.4";
54 public const string digestedData = "1.2.840.113549.1.7.5";
55 public const string encryptedData = "1.2.840.113549.1.7.6";
57 public const string contentType = "1.2.840.113549.1.9.3";
58 public const string messageDigest = "1.2.840.113549.1.9.4";
59 public const string signingTime = "1.2.840.113549.1.9.5";
60 public const string countersignature = "1.2.840.113549.1.9.6";
71 static public ASN1 Attribute (string oid, ASN1 value)
73 ASN1 attr = new ASN1 (0x30);
74 attr.Add (ASN1Convert.FromOid (oid));
75 ASN1 aset = attr.Add (new ASN1 (0x31));
80 static public ASN1 AlgorithmIdentifier (string oid)
82 ASN1 ai = new ASN1 (0x30);
83 ai.Add (ASN1Convert.FromOid (oid));
84 ai.Add (new ASN1 (0x05)); // NULL
88 static public ASN1 AlgorithmIdentifier (string oid, ASN1 parameters)
90 ASN1 ai = new ASN1 (0x30);
91 ai.Add (ASN1Convert.FromOid (oid));
97 * IssuerAndSerialNumber ::= SEQUENCE {
99 * serialNumber CertificateSerialNumber
102 static public ASN1 IssuerAndSerialNumber (X509Certificate x509)
106 ASN1 cert = new ASN1 (x509.RawData);
109 while (tbs < cert[0].Count) {
110 ASN1 e = cert[0][tbs++];
113 else if (e.Tag == 0x30) {
121 ASN1 iasn = new ASN1 (0x30);
128 * ContentInfo ::= SEQUENCE {
129 * contentType ContentType,
130 * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
132 * ContentType ::= OBJECT IDENTIFIER
134 public class ContentInfo {
136 private string contentType;
137 private ASN1 content;
139 public ContentInfo ()
141 content = new ASN1 (0xA0);
144 public ContentInfo (string oid) : this ()
149 public ContentInfo (byte[] data)
150 : this (new ASN1 (data)) {}
152 public ContentInfo (ASN1 asn1)
154 // SEQUENCE with 1 or 2 elements
155 if ((asn1.Tag != 0x30) || ((asn1.Count < 1) && (asn1.Count > 2)))
156 throw new ArgumentException ("Invalid ASN1");
157 if (asn1[0].Tag != 0x06)
158 throw new ArgumentException ("Invalid contentType");
159 contentType = ASN1Convert.ToOid (asn1[0]);
160 if (asn1.Count > 1) {
161 if (asn1[1].Tag != 0xA0)
162 throw new ArgumentException ("Invalid content");
168 get { return GetASN1(); }
171 public ASN1 Content {
172 get { return content; }
173 set { content = value; }
176 public string ContentType {
177 get { return contentType; }
178 set { contentType = value; }
181 internal ASN1 GetASN1 ()
183 // ContentInfo ::= SEQUENCE {
184 ASN1 contentInfo = new ASN1 (0x30);
185 // contentType ContentType, -> ContentType ::= OBJECT IDENTIFIER
186 contentInfo.Add (ASN1Convert.FromOid (contentType));
187 // content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
188 if ((content != null) && (content.Count > 0))
189 contentInfo.Add (content);
193 public byte[] GetBytes ()
195 return GetASN1 ().GetBytes ();
200 * EncryptedData ::= SEQUENCE {
201 * version INTEGER {edVer0(0)} (edVer0),
202 * encryptedContentInfo EncryptedContentInfo
205 public class EncryptedData {
206 private byte _version;
207 private ContentInfo _content;
208 private ContentInfo _encryptionAlgorithm;
209 private byte[] _encrypted;
211 public EncryptedData ()
216 public EncryptedData (byte[] data)
217 : this (new ASN1 (data))
221 public EncryptedData (ASN1 asn1) : this ()
223 if ((asn1.Tag != 0x30) || (asn1.Count < 2))
224 throw new ArgumentException ("Invalid EncryptedData");
226 if (asn1 [0].Tag != 0x02)
227 throw new ArgumentException ("Invalid version");
228 _version = asn1 [0].Value [0];
230 ASN1 encryptedContentInfo = asn1 [1];
231 if (encryptedContentInfo.Tag != 0x30)
232 throw new ArgumentException ("missing EncryptedContentInfo");
234 ASN1 contentType = encryptedContentInfo [0];
235 if (contentType.Tag != 0x06)
236 throw new ArgumentException ("missing EncryptedContentInfo.ContentType");
237 _content = new ContentInfo (ASN1Convert.ToOid (contentType));
239 ASN1 contentEncryptionAlgorithm = encryptedContentInfo [1];
240 if (contentEncryptionAlgorithm.Tag != 0x30)
241 throw new ArgumentException ("missing EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier");
242 _encryptionAlgorithm = new ContentInfo (ASN1Convert.ToOid (contentEncryptionAlgorithm [0]));
243 _encryptionAlgorithm.Content = contentEncryptionAlgorithm [1];
245 ASN1 encryptedContent = encryptedContentInfo [2];
246 if (encryptedContent.Tag != 0x80)
247 throw new ArgumentException ("missing EncryptedContentInfo.EncryptedContent");
248 _encrypted = encryptedContent.Value;
252 get { return GetASN1(); }
255 public ContentInfo ContentInfo {
256 get { return _content; }
259 public ContentInfo EncryptionAlgorithm {
260 get { return _encryptionAlgorithm; }
263 public byte[] EncryptedContent {
265 if (_encrypted == null)
267 return (byte[]) _encrypted.Clone ();
271 public byte Version {
272 get { return _version; }
273 set { _version = value; }
278 internal ASN1 GetASN1 ()
283 public byte[] GetBytes ()
285 return GetASN1 ().GetBytes ();
290 * EnvelopedData ::= SEQUENCE {
292 * recipientInfos RecipientInfos,
293 * encryptedContentInfo EncryptedContentInfo
296 * RecipientInfos ::= SET OF RecipientInfo
298 * EncryptedContentInfo ::= SEQUENCE {
299 * contentType ContentType,
300 * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
301 * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
304 * EncryptedContent ::= OCTET STRING
307 public class EnvelopedData {
308 private byte _version;
309 private ContentInfo _content;
310 private ContentInfo _encryptionAlgorithm;
311 private ArrayList _recipientInfos;
312 private byte[] _encrypted;
314 public EnvelopedData ()
317 _content = new ContentInfo ();
318 _encryptionAlgorithm = new ContentInfo ();
319 _recipientInfos = new ArrayList ();
322 public EnvelopedData (byte[] data)
323 : this (new ASN1 (data))
327 public EnvelopedData (ASN1 asn1) : this ()
329 if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 3))
330 throw new ArgumentException ("Invalid EnvelopedData");
332 if (asn1[0][0].Tag != 0x02)
333 throw new ArgumentException ("Invalid version");
334 _version = asn1[0][0].Value[0];
338 ASN1 recipientInfos = asn1 [0][1];
339 if (recipientInfos.Tag != 0x31)
340 throw new ArgumentException ("missing RecipientInfos");
341 for (int i=0; i < recipientInfos.Count; i++) {
342 ASN1 recipientInfo = recipientInfos [i];
343 _recipientInfos.Add (new RecipientInfo (recipientInfo));
346 ASN1 encryptedContentInfo = asn1[0][2];
347 if (encryptedContentInfo.Tag != 0x30)
348 throw new ArgumentException ("missing EncryptedContentInfo");
350 ASN1 contentType = encryptedContentInfo [0];
351 if (contentType.Tag != 0x06)
352 throw new ArgumentException ("missing EncryptedContentInfo.ContentType");
353 _content = new ContentInfo (ASN1Convert.ToOid (contentType));
355 ASN1 contentEncryptionAlgorithm = encryptedContentInfo [1];
356 if (contentEncryptionAlgorithm.Tag != 0x30)
357 throw new ArgumentException ("missing EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier");
358 _encryptionAlgorithm = new ContentInfo (ASN1Convert.ToOid (contentEncryptionAlgorithm [0]));
359 _encryptionAlgorithm.Content = contentEncryptionAlgorithm [1];
361 ASN1 encryptedContent = encryptedContentInfo [2];
362 if (encryptedContent.Tag != 0x80)
363 throw new ArgumentException ("missing EncryptedContentInfo.EncryptedContent");
364 _encrypted = encryptedContent.Value;
367 public ArrayList RecipientInfos {
368 get { return _recipientInfos; }
372 get { return GetASN1(); }
375 public ContentInfo ContentInfo {
376 get { return _content; }
379 public ContentInfo EncryptionAlgorithm {
380 get { return _encryptionAlgorithm; }
383 public byte[] EncryptedContent {
385 if (_encrypted == null)
387 return (byte[]) _encrypted.Clone ();
391 public byte Version {
392 get { return _version; }
393 set { _version = value; }
396 internal ASN1 GetASN1 ()
398 // SignedData ::= SEQUENCE {
399 ASN1 signedData = new ASN1 (0x30);
400 // version Version -> Version ::= INTEGER
401 /* byte[] ver = { _version };
402 signedData.Add (new ASN1 (0x02, ver));
403 // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
404 ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
405 if (hashAlgorithm != null) {
406 string hashOid = CryptoConfig.MapNameToOid (hashAlgorithm);
407 digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
410 // contentInfo ContentInfo,
411 ASN1 ci = contentInfo.ASN1;
413 if ((mda == null) && (hashAlgorithm != null)) {
414 // automatically add the messageDigest authenticated attribute
415 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
416 byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
417 ASN1 md = new ASN1 (0x30);
418 mda = Attribute (messageDigest, md.Add (new ASN1 (0x04, idcHash)));
419 signerInfo.AuthenticatedAttributes.Add (mda);
422 // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
423 if (certs.Count > 0) {
424 ASN1 a0 = signedData.Add (new ASN1 (0xA0));
425 foreach (X509Certificate x in certs)
426 a0.Add (new ASN1 (x.RawData));
428 // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
429 if (crls.Count > 0) {
430 ASN1 a1 = signedData.Add (new ASN1 (0xA1));
431 foreach (byte[] crl in crls)
432 a1.Add (new ASN1 (crl));
434 // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
435 ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
436 if (signerInfo.Key != null)
437 signerInfos.Add (signerInfo.ASN1);*/
441 public byte[] GetBytes () {
442 return GetASN1 ().GetBytes ();
446 /* RecipientInfo ::= SEQUENCE {
448 * issuerAndSerialNumber IssuerAndSerialNumber,
449 * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
450 * encryptedKey EncryptedKey
453 * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
455 * EncryptedKey ::= OCTET STRING
457 public class RecipientInfo {
459 private int _version;
463 private string _issuer;
464 private byte[] _serial;
466 public RecipientInfo () {}
468 public RecipientInfo (ASN1 data)
470 if (data.Tag != 0x30)
471 throw new ArgumentException ("Invalid RecipientInfo");
473 ASN1 version = data [0];
474 if (version.Tag != 0x02)
475 throw new ArgumentException ("missing Version");
476 _version = version.Value [0];
478 // issuerAndSerialNumber IssuerAndSerialNumber
479 ASN1 subjectIdentifierType = data [1];
480 if ((subjectIdentifierType.Tag == 0x80) && (_version == 3)) {
481 _ski = subjectIdentifierType.Value;
484 _issuer = X501.ToString (subjectIdentifierType [0]);
485 _serial = subjectIdentifierType [1].Value;
488 ASN1 keyEncryptionAlgorithm = data [2];
489 _oid = ASN1Convert.ToOid (keyEncryptionAlgorithm [0]);
491 ASN1 encryptedKey = data [3];
492 _key = encryptedKey.Value;
503 return (byte[]) _key.Clone ();
507 public byte[] SubjectKeyIdentifier {
511 return (byte[]) _ski.Clone ();
515 public string Issuer {
516 get { return _issuer; }
519 public byte[] Serial {
523 return (byte[]) _serial.Clone ();
528 get { return _version; }
533 * SignedData ::= SEQUENCE {
535 * digestAlgorithms DigestAlgorithmIdentifiers,
536 * contentInfo ContentInfo,
537 * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
538 * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
539 * signerInfos SignerInfos
542 public class SignedData {
543 private byte version;
544 private string hashAlgorithm;
545 private ContentInfo contentInfo;
546 private X509CertificateCollection certs;
547 private ArrayList crls;
548 private SignerInfo signerInfo;
555 contentInfo = new ContentInfo ();
556 certs = new X509CertificateCollection ();
557 crls = new ArrayList ();
558 signerInfo = new SignerInfo ();
563 public SignedData (byte[] data)
564 : this (new ASN1 (data))
568 public SignedData (ASN1 asn1)
570 if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 4))
571 throw new ArgumentException ("Invalid SignedData");
573 if (asn1[0][0].Tag != 0x02)
574 throw new ArgumentException ("Invalid version");
575 version = asn1[0][0].Value[0];
577 contentInfo = new ContentInfo (asn1[0][2]);
580 certs = new X509CertificateCollection ();
581 if (asn1[0][n].Tag == 0xA0) {
582 for (int i=0; i < asn1[0][n].Count; i++)
583 certs.Add (new X509Certificate (asn1[0][n][i].GetBytes ()));
587 crls = new ArrayList ();
588 if (asn1[0][n].Tag == 0xA1) {
589 for (int i=0; i < asn1[0][n].Count; i++)
590 crls.Add (asn1[0][n][i].GetBytes ());
594 if (asn1[0][n].Count > 0)
595 signerInfo = new SignerInfo (asn1[0][n]);
597 signerInfo = new SignerInfo ();
599 // Exchange hash algorithm Oid from SignerInfo
600 if (signerInfo.HashName != null) {
601 HashName = OidToName(signerInfo.HashName);
604 // Check if SignerInfo has authenticated attributes
605 mda = (signerInfo.AuthenticatedAttributes.Count > 0);
609 get { return GetASN1(); }
612 public X509CertificateCollection Certificates {
613 get { return certs; }
616 public ContentInfo ContentInfo {
617 get { return contentInfo; }
620 public ArrayList Crls {
624 public string HashName {
625 get { return hashAlgorithm; }
626 // todo add validation
628 hashAlgorithm = value;
629 signerInfo.HashName = value;
633 public SignerInfo SignerInfo {
634 get { return signerInfo; }
637 public byte Version {
638 get { return version; }
639 set { version = value; }
642 public bool UseAuthenticatedAttributes {
647 public bool VerifySignature (AsymmetricAlgorithm aa)
653 RSAPKCS1SignatureDeformatter r = new RSAPKCS1SignatureDeformatter (aa);
654 r.SetHashAlgorithm (hashAlgorithm);
655 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
657 byte[] signature = signerInfo.Signature;
661 ASN1 asn = new ASN1 (0x31);
662 foreach (ASN1 attr in signerInfo.AuthenticatedAttributes)
665 hash = ha.ComputeHash (asn.GetBytes ());
667 hash = ha.ComputeHash (contentInfo.Content[0].Value);
670 if (hash != null && signature != null) {
671 return r.VerifySignature (hash, signature);
676 internal string OidToName (string oid)
679 case "1.3.14.3.2.26" :
681 case "1.2.840.113549.2.2" :
683 case "1.2.840.113549.2.5" :
685 case "2.16.840.1.101.3.4.1" :
687 case "2.16.840.1.101.3.4.2" :
689 case "2.16.840.1.101.3.4.3" :
698 internal ASN1 GetASN1 ()
700 // SignedData ::= SEQUENCE {
701 ASN1 signedData = new ASN1 (0x30);
702 // version Version -> Version ::= INTEGER
703 byte[] ver = { version };
704 signedData.Add (new ASN1 (0x02, ver));
705 // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
706 ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
707 if (hashAlgorithm != null) {
708 string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
709 digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
712 // contentInfo ContentInfo,
713 ASN1 ci = contentInfo.ASN1;
715 if (!signed && (hashAlgorithm != null)) {
717 // Use authenticated attributes for signature
719 // Automatically add the contentType authenticated attribute
720 ASN1 ctattr = Attribute (Oid.contentType, ci[0]);
721 signerInfo.AuthenticatedAttributes.Add (ctattr);
723 // Automatically add the messageDigest authenticated attribute
724 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
725 byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
726 ASN1 md = new ASN1 (0x30);
727 ASN1 mdattr = Attribute (Oid.messageDigest, md.Add (new ASN1 (0x04, idcHash)));
728 signerInfo.AuthenticatedAttributes.Add (mdattr);
730 // Don't use authenticated attributes for signature -- signature is content
731 RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (signerInfo.Key);
732 r.SetHashAlgorithm (hashAlgorithm);
733 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
734 byte[] sig = ha.ComputeHash (ci[1][0].Value);
735 signerInfo.Signature = r.CreateSignature (sig);
740 // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
741 if (certs.Count > 0) {
742 ASN1 a0 = signedData.Add (new ASN1 (0xA0));
743 foreach (X509Certificate x in certs)
744 a0.Add (new ASN1 (x.RawData));
746 // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
747 if (crls.Count > 0) {
748 ASN1 a1 = signedData.Add (new ASN1 (0xA1));
749 foreach (byte[] crl in crls)
750 a1.Add (new ASN1 (crl));
752 // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
753 ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
754 if (signerInfo.Key != null)
755 signerInfos.Add (signerInfo.ASN1);
759 public byte[] GetBytes ()
761 return GetASN1 ().GetBytes ();
766 * SignerInfo ::= SEQUENCE {
768 * issuerAndSerialNumber IssuerAndSerialNumber,
769 * digestAlgorithm DigestAlgorithmIdentifier,
770 * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
771 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
772 * encryptedDigest EncryptedDigest,
773 * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
776 * For version == 3 issuerAndSerialNumber may be replaced by ...
778 public class SignerInfo {
780 private byte version;
781 private X509Certificate x509;
782 private string hashAlgorithm;
783 private AsymmetricAlgorithm key;
784 private ArrayList authenticatedAttributes;
785 private ArrayList unauthenticatedAttributes;
786 private byte[] signature;
787 private string issuer;
788 private byte[] serial;
794 authenticatedAttributes = new ArrayList ();
795 unauthenticatedAttributes = new ArrayList ();
798 public SignerInfo (byte[] data)
799 : this (new ASN1 (data)) {}
802 public SignerInfo (ASN1 asn1) : this ()
804 if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 5))
805 throw new ArgumentException ("Invalid SignedData");
808 if (asn1[0][0].Tag != 0x02)
809 throw new ArgumentException ("Invalid version");
810 version = asn1[0][0].Value[0];
812 // issuerAndSerialNumber IssuerAndSerialNumber
813 ASN1 subjectIdentifierType = asn1 [0][1];
814 if ((subjectIdentifierType.Tag == 0x80) && (version == 3)) {
815 ski = subjectIdentifierType.Value;
818 issuer = X501.ToString (subjectIdentifierType [0]);
819 serial = subjectIdentifierType [1].Value;
822 // digestAlgorithm DigestAlgorithmIdentifier
823 ASN1 digestAlgorithm = asn1 [0][2];
824 hashAlgorithm = ASN1Convert.ToOid (digestAlgorithm [0]);
826 // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL
828 ASN1 authAttributes = asn1 [0][n];
829 if (authAttributes.Tag == 0xA0) {
831 for (int i=0; i < authAttributes.Count; i++)
832 authenticatedAttributes.Add (authAttributes [i]);
835 // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier
837 // ASN1 digestEncryptionAlgorithm = asn1 [0][n++];
838 // string digestEncryptionAlgorithmOid = ASN1Convert.ToOid (digestEncryptionAlgorithm [0]);
840 // encryptedDigest EncryptedDigest
841 ASN1 encryptedDigest = asn1 [0][n++];
842 if (encryptedDigest.Tag == 0x04)
843 signature = encryptedDigest.Value;
845 // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
846 ASN1 unauthAttributes = asn1 [0][n];
847 if ((unauthAttributes != null) && (unauthAttributes.Tag == 0xA1)) {
848 for (int i=0; i < unauthAttributes.Count; i++)
849 unauthenticatedAttributes.Add (unauthAttributes [i]);
853 public string IssuerName {
854 get { return issuer; }
857 public byte[] SerialNumber {
861 return (byte[]) serial.Clone ();
865 public byte[] SubjectKeyIdentifier {
869 return (byte[]) ski.Clone ();
874 get { return GetASN1(); }
877 public ArrayList AuthenticatedAttributes {
878 get { return authenticatedAttributes; }
881 public X509Certificate Certificate {
883 set { x509 = value; }
886 public string HashName {
887 get { return hashAlgorithm; }
888 set { hashAlgorithm = value; }
891 public AsymmetricAlgorithm Key {
896 public byte[] Signature {
898 if (signature == null)
900 return (byte[]) signature.Clone ();
905 signature = (byte[]) value.Clone ();
910 public ArrayList UnauthenticatedAttributes {
911 get { return unauthenticatedAttributes; }
914 public byte Version {
915 get { return version; }
916 set { version = value; }
919 internal ASN1 GetASN1 ()
921 if ((key == null) || (hashAlgorithm == null))
923 byte[] ver = { version };
924 ASN1 signerInfo = new ASN1 (0x30);
925 // version Version -> Version ::= INTEGER
926 signerInfo.Add (new ASN1 (0x02, ver));
927 // issuerAndSerialNumber IssuerAndSerialNumber,
928 signerInfo.Add (PKCS7.IssuerAndSerialNumber (x509));
929 // digestAlgorithm DigestAlgorithmIdentifier,
930 string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
931 signerInfo.Add (AlgorithmIdentifier (hashOid));
932 // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
934 if (authenticatedAttributes.Count > 0) {
935 aa = signerInfo.Add (new ASN1 (0xA0));
936 foreach (ASN1 attr in authenticatedAttributes)
939 // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
941 signerInfo.Add (AlgorithmIdentifier (PKCS7.Oid.rsaEncryption));
944 // Calculate the signature here; otherwise it must be set from SignedData
945 RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (key);
946 r.SetHashAlgorithm (hashAlgorithm);
947 byte[] tbs = aa.GetBytes ();
948 tbs [0] = 0x31; // not 0xA0 for signature
949 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
950 byte[] tbsHash = ha.ComputeHash (tbs);
951 signature = r.CreateSignature (tbsHash);
954 else if (key is DSA) {
955 throw new NotImplementedException ("not yet");
958 throw new CryptographicException ("Unknown assymetric algorithm");
959 // encryptedDigest EncryptedDigest,
960 signerInfo.Add (new ASN1 (0x04, signature));
961 // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
962 if (unauthenticatedAttributes.Count > 0) {
963 ASN1 ua = signerInfo.Add (new ASN1 (0xA1));
964 foreach (ASN1 attr in unauthenticatedAttributes)
970 public byte[] GetBytes ()
972 return GetASN1 ().GetBytes ();