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;
554 contentInfo = new ContentInfo ();
555 certs = new X509CertificateCollection ();
556 crls = new ArrayList ();
557 signerInfo = new SignerInfo ();
561 public SignedData (byte[] data)
562 : this (new ASN1 (data))
566 public SignedData (ASN1 asn1)
568 if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 4))
569 throw new ArgumentException ("Invalid SignedData");
571 if (asn1[0][0].Tag != 0x02)
572 throw new ArgumentException ("Invalid version");
573 version = asn1[0][0].Value[0];
575 contentInfo = new ContentInfo (asn1[0][2]);
578 certs = new X509CertificateCollection ();
579 if (asn1[0][n].Tag == 0xA0) {
580 for (int i=0; i < asn1[0][n].Count; i++)
581 certs.Add (new X509Certificate (asn1[0][n][i].GetBytes ()));
585 crls = new ArrayList ();
586 if (asn1[0][n].Tag == 0xA1) {
587 for (int i=0; i < asn1[0][n].Count; i++)
588 crls.Add (asn1[0][n][i].GetBytes ());
592 if (asn1[0][n].Count > 0)
593 signerInfo = new SignerInfo (asn1[0][n]);
595 signerInfo = new SignerInfo ();
597 // Exchange hash algorithm Oid from SignerInfo
598 if (signerInfo.HashName != null) {
599 HashName = OidToName(signerInfo.HashName);
602 // Check if SignerInfo has authenticated attributes
603 mda = (signerInfo.AuthenticatedAttributes.Count > 0);
607 get { return GetASN1(); }
610 public X509CertificateCollection Certificates {
611 get { return certs; }
614 public ContentInfo ContentInfo {
615 get { return contentInfo; }
618 public ArrayList Crls {
622 public string HashName {
623 get { return hashAlgorithm; }
624 // todo add validation
626 hashAlgorithm = value;
627 signerInfo.HashName = value;
631 public SignerInfo SignerInfo {
632 get { return signerInfo; }
635 public byte Version {
636 get { return version; }
637 set { version = value; }
640 public bool UseAuthenticatedAttributes {
645 public bool VerifySignature (AsymmetricAlgorithm aa)
651 RSAPKCS1SignatureDeformatter r = new RSAPKCS1SignatureDeformatter (aa);
652 r.SetHashAlgorithm (hashAlgorithm);
653 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
655 byte[] signature = signerInfo.Signature;
659 ASN1 asn = new ASN1 (0x31);
660 foreach (ASN1 attr in signerInfo.AuthenticatedAttributes)
663 hash = ha.ComputeHash (asn.GetBytes ());
665 hash = ha.ComputeHash (contentInfo.Content[0].Value);
668 if (hash != null && signature != null) {
669 return r.VerifySignature (hash, signature);
674 internal string OidToName (string oid)
677 case "1.3.14.3.2.26" :
679 case "1.2.840.113549.2.2" :
681 case "1.2.840.113549.2.5" :
683 case "2.16.840.1.101.3.4.1" :
685 case "2.16.840.1.101.3.4.2" :
687 case "2.16.840.1.101.3.4.3" :
696 internal ASN1 GetASN1 ()
698 // SignedData ::= SEQUENCE {
699 ASN1 signedData = new ASN1 (0x30);
700 // version Version -> Version ::= INTEGER
701 byte[] ver = { version };
702 signedData.Add (new ASN1 (0x02, ver));
703 // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
704 ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
705 if (hashAlgorithm != null) {
706 string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
707 digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
710 // contentInfo ContentInfo,
711 ASN1 ci = contentInfo.ASN1;
713 if (hashAlgorithm != null) {
715 // Use authenticated attributes for signature
717 // Automatically add the contentType authenticated attribute
718 ASN1 ctattr = Attribute (Oid.contentType, ci[0]);
719 signerInfo.AuthenticatedAttributes.Add (ctattr);
721 // Automatically add the messageDigest authenticated attribute
722 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
723 byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
724 ASN1 md = new ASN1 (0x30);
725 ASN1 mdattr = Attribute (Oid.messageDigest, md.Add (new ASN1 (0x04, idcHash)));
726 signerInfo.AuthenticatedAttributes.Add (mdattr);
728 // Don't use authenticated attributes for signature -- signature is content
729 RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (signerInfo.Key);
730 r.SetHashAlgorithm (hashAlgorithm);
731 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
732 byte[] sig = ha.ComputeHash (ci[1][0].Value);
733 signerInfo.Signature = r.CreateSignature (sig);
737 // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
738 if (certs.Count > 0) {
739 ASN1 a0 = signedData.Add (new ASN1 (0xA0));
740 foreach (X509Certificate x in certs)
741 a0.Add (new ASN1 (x.RawData));
743 // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
744 if (crls.Count > 0) {
745 ASN1 a1 = signedData.Add (new ASN1 (0xA1));
746 foreach (byte[] crl in crls)
747 a1.Add (new ASN1 (crl));
749 // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
750 ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
751 if (signerInfo.Key != null)
752 signerInfos.Add (signerInfo.ASN1);
756 public byte[] GetBytes ()
758 return GetASN1 ().GetBytes ();
763 * SignerInfo ::= SEQUENCE {
765 * issuerAndSerialNumber IssuerAndSerialNumber,
766 * digestAlgorithm DigestAlgorithmIdentifier,
767 * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
768 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
769 * encryptedDigest EncryptedDigest,
770 * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
773 * For version == 3 issuerAndSerialNumber may be replaced by ...
775 public class SignerInfo {
777 private byte version;
778 private X509Certificate x509;
779 private string hashAlgorithm;
780 private AsymmetricAlgorithm key;
781 private ArrayList authenticatedAttributes;
782 private ArrayList unauthenticatedAttributes;
783 private byte[] signature;
784 private string issuer;
785 private byte[] serial;
791 authenticatedAttributes = new ArrayList ();
792 unauthenticatedAttributes = new ArrayList ();
795 public SignerInfo (byte[] data)
796 : this (new ASN1 (data)) {}
799 public SignerInfo (ASN1 asn1) : this ()
801 if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 5))
802 throw new ArgumentException ("Invalid SignedData");
805 if (asn1[0][0].Tag != 0x02)
806 throw new ArgumentException ("Invalid version");
807 version = asn1[0][0].Value[0];
809 // issuerAndSerialNumber IssuerAndSerialNumber
810 ASN1 subjectIdentifierType = asn1 [0][1];
811 if ((subjectIdentifierType.Tag == 0x80) && (version == 3)) {
812 ski = subjectIdentifierType.Value;
815 issuer = X501.ToString (subjectIdentifierType [0]);
816 serial = subjectIdentifierType [1].Value;
819 // digestAlgorithm DigestAlgorithmIdentifier
820 ASN1 digestAlgorithm = asn1 [0][2];
821 hashAlgorithm = ASN1Convert.ToOid (digestAlgorithm [0]);
823 // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL
825 ASN1 authAttributes = asn1 [0][n];
826 if (authAttributes.Tag == 0xA0) {
828 for (int i=0; i < authAttributes.Count; i++)
829 authenticatedAttributes.Add (authAttributes [i]);
832 // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier
834 // ASN1 digestEncryptionAlgorithm = asn1 [0][n++];
835 // string digestEncryptionAlgorithmOid = ASN1Convert.ToOid (digestEncryptionAlgorithm [0]);
837 // encryptedDigest EncryptedDigest
838 ASN1 encryptedDigest = asn1 [0][n++];
839 if (encryptedDigest.Tag == 0x04)
840 signature = encryptedDigest.Value;
842 // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
843 ASN1 unauthAttributes = asn1 [0][n];
844 if ((unauthAttributes != null) && (unauthAttributes.Tag == 0xA1)) {
845 for (int i=0; i < unauthAttributes.Count; i++)
846 unauthenticatedAttributes.Add (unauthAttributes [i]);
850 public string IssuerName {
851 get { return issuer; }
854 public byte[] SerialNumber {
858 return (byte[]) serial.Clone ();
862 public byte[] SubjectKeyIdentifier {
866 return (byte[]) ski.Clone ();
871 get { return GetASN1(); }
874 public ArrayList AuthenticatedAttributes {
875 get { return authenticatedAttributes; }
878 public X509Certificate Certificate {
880 set { x509 = value; }
883 public string HashName {
884 get { return hashAlgorithm; }
885 set { hashAlgorithm = value; }
888 public AsymmetricAlgorithm Key {
893 public byte[] Signature {
895 if (signature == null)
897 return (byte[]) signature.Clone ();
902 signature = (byte[]) value.Clone ();
907 public ArrayList UnauthenticatedAttributes {
908 get { return unauthenticatedAttributes; }
911 public byte Version {
912 get { return version; }
913 set { version = value; }
916 internal ASN1 GetASN1 ()
918 if ((key == null) || (hashAlgorithm == null))
920 byte[] ver = { version };
921 ASN1 signerInfo = new ASN1 (0x30);
922 // version Version -> Version ::= INTEGER
923 signerInfo.Add (new ASN1 (0x02, ver));
924 // issuerAndSerialNumber IssuerAndSerialNumber,
925 signerInfo.Add (PKCS7.IssuerAndSerialNumber (x509));
926 // digestAlgorithm DigestAlgorithmIdentifier,
927 string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
928 signerInfo.Add (AlgorithmIdentifier (hashOid));
929 // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
931 if (authenticatedAttributes.Count > 0) {
932 aa = signerInfo.Add (new ASN1 (0xA0));
933 foreach (ASN1 attr in authenticatedAttributes)
936 // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
938 signerInfo.Add (AlgorithmIdentifier (PKCS7.Oid.rsaEncryption));
941 // Calculate the signature here; otherwise it must be set from SignedData
942 RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (key);
943 r.SetHashAlgorithm (hashAlgorithm);
944 byte[] tbs = aa.GetBytes ();
945 tbs [0] = 0x31; // not 0xA0 for signature
946 HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
947 byte[] tbsHash = ha.ComputeHash (tbs);
948 signature = r.CreateSignature (tbsHash);
951 else if (key is DSA) {
952 throw new NotImplementedException ("not yet");
955 throw new CryptographicException ("Unknown assymetric algorithm");
956 // encryptedDigest EncryptedDigest,
957 signerInfo.Add (new ASN1 (0x04, signature));
958 // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
959 if (unauthenticatedAttributes.Count > 0) {
960 ASN1 ua = signerInfo.Add (new ASN1 (0xA1));
961 foreach (ASN1 attr in unauthenticatedAttributes)
967 public byte[] GetBytes ()
969 return GetASN1 ().GetBytes ();