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 ();