PKCS7.cs 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. //
  2. // PKCS7.cs: PKCS #7 - Cryptographic Message Syntax Standard
  3. // http://www.rsasecurity.com/rsalabs/pkcs/pkcs-7/index.html
  4. //
  5. // Authors:
  6. // Sebastien Pouliot <sebastien@ximian.com>
  7. // Daniel Granath <dgranath#gmail.com>
  8. //
  9. // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
  10. // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Collections;
  33. using System.Security.Cryptography;
  34. using Mono.Security.X509;
  35. namespace Mono.Security {
  36. #if INSIDE_CORLIB
  37. internal
  38. #else
  39. public
  40. #endif
  41. sealed class PKCS7 {
  42. public class Oid {
  43. // pkcs 1
  44. public const string rsaEncryption = "1.2.840.113549.1.1.1";
  45. // pkcs 7
  46. public const string data = "1.2.840.113549.1.7.1";
  47. public const string signedData = "1.2.840.113549.1.7.2";
  48. public const string envelopedData = "1.2.840.113549.1.7.3";
  49. public const string signedAndEnvelopedData = "1.2.840.113549.1.7.4";
  50. public const string digestedData = "1.2.840.113549.1.7.5";
  51. public const string encryptedData = "1.2.840.113549.1.7.6";
  52. // pkcs 9
  53. public const string contentType = "1.2.840.113549.1.9.3";
  54. public const string messageDigest = "1.2.840.113549.1.9.4";
  55. public const string signingTime = "1.2.840.113549.1.9.5";
  56. public const string countersignature = "1.2.840.113549.1.9.6";
  57. public Oid ()
  58. {
  59. }
  60. }
  61. private PKCS7 ()
  62. {
  63. }
  64. static public ASN1 Attribute (string oid, ASN1 value)
  65. {
  66. ASN1 attr = new ASN1 (0x30);
  67. attr.Add (ASN1Convert.FromOid (oid));
  68. ASN1 aset = attr.Add (new ASN1 (0x31));
  69. aset.Add (value);
  70. return attr;
  71. }
  72. static public ASN1 AlgorithmIdentifier (string oid)
  73. {
  74. ASN1 ai = new ASN1 (0x30);
  75. ai.Add (ASN1Convert.FromOid (oid));
  76. ai.Add (new ASN1 (0x05)); // NULL
  77. return ai;
  78. }
  79. static public ASN1 AlgorithmIdentifier (string oid, ASN1 parameters)
  80. {
  81. ASN1 ai = new ASN1 (0x30);
  82. ai.Add (ASN1Convert.FromOid (oid));
  83. ai.Add (parameters);
  84. return ai;
  85. }
  86. /*
  87. * IssuerAndSerialNumber ::= SEQUENCE {
  88. * issuer Name,
  89. * serialNumber CertificateSerialNumber
  90. * }
  91. */
  92. static public ASN1 IssuerAndSerialNumber (X509Certificate x509)
  93. {
  94. ASN1 issuer = null;
  95. ASN1 serial = null;
  96. ASN1 cert = new ASN1 (x509.RawData);
  97. int tbs = 0;
  98. bool flag = false;
  99. while (tbs < cert[0].Count) {
  100. ASN1 e = cert[0][tbs++];
  101. if (e.Tag == 0x02)
  102. serial = e;
  103. else if (e.Tag == 0x30) {
  104. if (flag) {
  105. issuer = e;
  106. break;
  107. }
  108. flag = true;
  109. }
  110. }
  111. ASN1 iasn = new ASN1 (0x30);
  112. iasn.Add (issuer);
  113. iasn.Add (serial);
  114. return iasn;
  115. }
  116. /*
  117. * ContentInfo ::= SEQUENCE {
  118. * contentType ContentType,
  119. * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
  120. * }
  121. * ContentType ::= OBJECT IDENTIFIER
  122. */
  123. public class ContentInfo {
  124. private string contentType;
  125. private ASN1 content;
  126. public ContentInfo ()
  127. {
  128. content = new ASN1 (0xA0);
  129. }
  130. public ContentInfo (string oid) : this ()
  131. {
  132. contentType = oid;
  133. }
  134. public ContentInfo (byte[] data)
  135. : this (new ASN1 (data)) {}
  136. public ContentInfo (ASN1 asn1)
  137. {
  138. // SEQUENCE with 1 or 2 elements
  139. if ((asn1.Tag != 0x30) || ((asn1.Count < 1) && (asn1.Count > 2)))
  140. throw new ArgumentException ("Invalid ASN1");
  141. if (asn1[0].Tag != 0x06)
  142. throw new ArgumentException ("Invalid contentType");
  143. contentType = ASN1Convert.ToOid (asn1[0]);
  144. if (asn1.Count > 1) {
  145. if (asn1[1].Tag != 0xA0)
  146. throw new ArgumentException ("Invalid content");
  147. content = asn1[1];
  148. }
  149. }
  150. public ASN1 ASN1 {
  151. get { return GetASN1(); }
  152. }
  153. public ASN1 Content {
  154. get { return content; }
  155. set { content = value; }
  156. }
  157. public string ContentType {
  158. get { return contentType; }
  159. set { contentType = value; }
  160. }
  161. internal ASN1 GetASN1 ()
  162. {
  163. // ContentInfo ::= SEQUENCE {
  164. ASN1 contentInfo = new ASN1 (0x30);
  165. // contentType ContentType, -> ContentType ::= OBJECT IDENTIFIER
  166. contentInfo.Add (ASN1Convert.FromOid (contentType));
  167. // content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
  168. if ((content != null) && (content.Count > 0))
  169. contentInfo.Add (content);
  170. return contentInfo;
  171. }
  172. public byte[] GetBytes ()
  173. {
  174. return GetASN1 ().GetBytes ();
  175. }
  176. }
  177. /*
  178. * EncryptedData ::= SEQUENCE {
  179. * version INTEGER {edVer0(0)} (edVer0),
  180. * encryptedContentInfo EncryptedContentInfo
  181. * }
  182. */
  183. public class EncryptedData {
  184. private byte _version;
  185. private ContentInfo _content;
  186. private ContentInfo _encryptionAlgorithm;
  187. private byte[] _encrypted;
  188. public EncryptedData ()
  189. {
  190. _version = 0;
  191. }
  192. public EncryptedData (byte[] data)
  193. : this (new ASN1 (data))
  194. {
  195. }
  196. public EncryptedData (ASN1 asn1) : this ()
  197. {
  198. if ((asn1.Tag != 0x30) || (asn1.Count < 2))
  199. throw new ArgumentException ("Invalid EncryptedData");
  200. if (asn1 [0].Tag != 0x02)
  201. throw new ArgumentException ("Invalid version");
  202. _version = asn1 [0].Value [0];
  203. ASN1 encryptedContentInfo = asn1 [1];
  204. if (encryptedContentInfo.Tag != 0x30)
  205. throw new ArgumentException ("missing EncryptedContentInfo");
  206. ASN1 contentType = encryptedContentInfo [0];
  207. if (contentType.Tag != 0x06)
  208. throw new ArgumentException ("missing EncryptedContentInfo.ContentType");
  209. _content = new ContentInfo (ASN1Convert.ToOid (contentType));
  210. ASN1 contentEncryptionAlgorithm = encryptedContentInfo [1];
  211. if (contentEncryptionAlgorithm.Tag != 0x30)
  212. throw new ArgumentException ("missing EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier");
  213. _encryptionAlgorithm = new ContentInfo (ASN1Convert.ToOid (contentEncryptionAlgorithm [0]));
  214. _encryptionAlgorithm.Content = contentEncryptionAlgorithm [1];
  215. ASN1 encryptedContent = encryptedContentInfo [2];
  216. if (encryptedContent.Tag != 0x80)
  217. throw new ArgumentException ("missing EncryptedContentInfo.EncryptedContent");
  218. _encrypted = encryptedContent.Value;
  219. }
  220. public ASN1 ASN1 {
  221. get { return GetASN1(); }
  222. }
  223. public ContentInfo ContentInfo {
  224. get { return _content; }
  225. }
  226. public ContentInfo EncryptionAlgorithm {
  227. get { return _encryptionAlgorithm; }
  228. }
  229. public byte[] EncryptedContent {
  230. get {
  231. if (_encrypted == null)
  232. return null;
  233. return (byte[]) _encrypted.Clone ();
  234. }
  235. }
  236. public byte Version {
  237. get { return _version; }
  238. set { _version = value; }
  239. }
  240. // methods
  241. internal ASN1 GetASN1 ()
  242. {
  243. return null;
  244. }
  245. public byte[] GetBytes ()
  246. {
  247. return GetASN1 ().GetBytes ();
  248. }
  249. }
  250. /*
  251. * EnvelopedData ::= SEQUENCE {
  252. * version Version,
  253. * recipientInfos RecipientInfos,
  254. * encryptedContentInfo EncryptedContentInfo
  255. * }
  256. *
  257. * RecipientInfos ::= SET OF RecipientInfo
  258. *
  259. * EncryptedContentInfo ::= SEQUENCE {
  260. * contentType ContentType,
  261. * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
  262. * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
  263. * }
  264. *
  265. * EncryptedContent ::= OCTET STRING
  266. *
  267. */
  268. public class EnvelopedData {
  269. private byte _version;
  270. private ContentInfo _content;
  271. private ContentInfo _encryptionAlgorithm;
  272. private ArrayList _recipientInfos;
  273. private byte[] _encrypted;
  274. public EnvelopedData ()
  275. {
  276. _version = 0;
  277. _content = new ContentInfo ();
  278. _encryptionAlgorithm = new ContentInfo ();
  279. _recipientInfos = new ArrayList ();
  280. }
  281. public EnvelopedData (byte[] data)
  282. : this (new ASN1 (data))
  283. {
  284. }
  285. public EnvelopedData (ASN1 asn1) : this ()
  286. {
  287. if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 3))
  288. throw new ArgumentException ("Invalid EnvelopedData");
  289. if (asn1[0][0].Tag != 0x02)
  290. throw new ArgumentException ("Invalid version");
  291. _version = asn1[0][0].Value[0];
  292. // recipientInfos
  293. ASN1 recipientInfos = asn1 [0][1];
  294. if (recipientInfos.Tag != 0x31)
  295. throw new ArgumentException ("missing RecipientInfos");
  296. for (int i=0; i < recipientInfos.Count; i++) {
  297. ASN1 recipientInfo = recipientInfos [i];
  298. _recipientInfos.Add (new RecipientInfo (recipientInfo));
  299. }
  300. ASN1 encryptedContentInfo = asn1[0][2];
  301. if (encryptedContentInfo.Tag != 0x30)
  302. throw new ArgumentException ("missing EncryptedContentInfo");
  303. ASN1 contentType = encryptedContentInfo [0];
  304. if (contentType.Tag != 0x06)
  305. throw new ArgumentException ("missing EncryptedContentInfo.ContentType");
  306. _content = new ContentInfo (ASN1Convert.ToOid (contentType));
  307. ASN1 contentEncryptionAlgorithm = encryptedContentInfo [1];
  308. if (contentEncryptionAlgorithm.Tag != 0x30)
  309. throw new ArgumentException ("missing EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier");
  310. _encryptionAlgorithm = new ContentInfo (ASN1Convert.ToOid (contentEncryptionAlgorithm [0]));
  311. _encryptionAlgorithm.Content = contentEncryptionAlgorithm [1];
  312. ASN1 encryptedContent = encryptedContentInfo [2];
  313. if (encryptedContent.Tag != 0x80)
  314. throw new ArgumentException ("missing EncryptedContentInfo.EncryptedContent");
  315. _encrypted = encryptedContent.Value;
  316. }
  317. public ArrayList RecipientInfos {
  318. get { return _recipientInfos; }
  319. }
  320. public ASN1 ASN1 {
  321. get { return GetASN1(); }
  322. }
  323. public ContentInfo ContentInfo {
  324. get { return _content; }
  325. }
  326. public ContentInfo EncryptionAlgorithm {
  327. get { return _encryptionAlgorithm; }
  328. }
  329. public byte[] EncryptedContent {
  330. get {
  331. if (_encrypted == null)
  332. return null;
  333. return (byte[]) _encrypted.Clone ();
  334. }
  335. }
  336. public byte Version {
  337. get { return _version; }
  338. set { _version = value; }
  339. }
  340. internal ASN1 GetASN1 ()
  341. {
  342. // SignedData ::= SEQUENCE {
  343. ASN1 signedData = new ASN1 (0x30);
  344. // version Version -> Version ::= INTEGER
  345. /* byte[] ver = { _version };
  346. signedData.Add (new ASN1 (0x02, ver));
  347. // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
  348. ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
  349. if (hashAlgorithm != null) {
  350. string hashOid = CryptoConfig.MapNameToOid (hashAlgorithm);
  351. digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
  352. }
  353. // contentInfo ContentInfo,
  354. ASN1 ci = contentInfo.ASN1;
  355. signedData.Add (ci);
  356. if ((mda == null) && (hashAlgorithm != null)) {
  357. // automatically add the messageDigest authenticated attribute
  358. HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
  359. byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
  360. ASN1 md = new ASN1 (0x30);
  361. mda = Attribute (messageDigest, md.Add (new ASN1 (0x04, idcHash)));
  362. signerInfo.AuthenticatedAttributes.Add (mda);
  363. }
  364. // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
  365. if (certs.Count > 0) {
  366. ASN1 a0 = signedData.Add (new ASN1 (0xA0));
  367. foreach (X509Certificate x in certs)
  368. a0.Add (new ASN1 (x.RawData));
  369. }
  370. // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  371. if (crls.Count > 0) {
  372. ASN1 a1 = signedData.Add (new ASN1 (0xA1));
  373. foreach (byte[] crl in crls)
  374. a1.Add (new ASN1 (crl));
  375. }
  376. // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
  377. ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
  378. if (signerInfo.Key != null)
  379. signerInfos.Add (signerInfo.ASN1);*/
  380. return signedData;
  381. }
  382. public byte[] GetBytes () {
  383. return GetASN1 ().GetBytes ();
  384. }
  385. }
  386. /* RecipientInfo ::= SEQUENCE {
  387. * version Version,
  388. * issuerAndSerialNumber IssuerAndSerialNumber,
  389. * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
  390. * encryptedKey EncryptedKey
  391. * }
  392. *
  393. * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  394. *
  395. * EncryptedKey ::= OCTET STRING
  396. */
  397. public class RecipientInfo {
  398. private int _version;
  399. private string _oid;
  400. private byte[] _key;
  401. private byte[] _ski;
  402. private string _issuer;
  403. private byte[] _serial;
  404. public RecipientInfo () {}
  405. public RecipientInfo (ASN1 data)
  406. {
  407. if (data.Tag != 0x30)
  408. throw new ArgumentException ("Invalid RecipientInfo");
  409. ASN1 version = data [0];
  410. if (version.Tag != 0x02)
  411. throw new ArgumentException ("missing Version");
  412. _version = version.Value [0];
  413. // issuerAndSerialNumber IssuerAndSerialNumber
  414. ASN1 subjectIdentifierType = data [1];
  415. if ((subjectIdentifierType.Tag == 0x80) && (_version == 3)) {
  416. _ski = subjectIdentifierType.Value;
  417. }
  418. else {
  419. _issuer = X501.ToString (subjectIdentifierType [0]);
  420. _serial = subjectIdentifierType [1].Value;
  421. }
  422. ASN1 keyEncryptionAlgorithm = data [2];
  423. _oid = ASN1Convert.ToOid (keyEncryptionAlgorithm [0]);
  424. ASN1 encryptedKey = data [3];
  425. _key = encryptedKey.Value;
  426. }
  427. public string Oid {
  428. get { return _oid; }
  429. }
  430. public byte[] Key {
  431. get {
  432. if (_key == null)
  433. return null;
  434. return (byte[]) _key.Clone ();
  435. }
  436. }
  437. public byte[] SubjectKeyIdentifier {
  438. get {
  439. if (_ski == null)
  440. return null;
  441. return (byte[]) _ski.Clone ();
  442. }
  443. }
  444. public string Issuer {
  445. get { return _issuer; }
  446. }
  447. public byte[] Serial {
  448. get {
  449. if (_serial == null)
  450. return null;
  451. return (byte[]) _serial.Clone ();
  452. }
  453. }
  454. public int Version {
  455. get { return _version; }
  456. }
  457. }
  458. /*
  459. * SignedData ::= SEQUENCE {
  460. * version Version,
  461. * digestAlgorithms DigestAlgorithmIdentifiers,
  462. * contentInfo ContentInfo,
  463. * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
  464. * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  465. * signerInfos SignerInfos
  466. * }
  467. */
  468. public class SignedData {
  469. private byte version;
  470. private string hashAlgorithm;
  471. private ContentInfo contentInfo;
  472. private X509CertificateCollection certs;
  473. private ArrayList crls;
  474. private SignerInfo signerInfo;
  475. private bool mda;
  476. private bool signed;
  477. public SignedData ()
  478. {
  479. version = 1;
  480. contentInfo = new ContentInfo ();
  481. certs = new X509CertificateCollection ();
  482. crls = new ArrayList ();
  483. signerInfo = new SignerInfo ();
  484. mda = true;
  485. signed = false;
  486. }
  487. public SignedData (byte[] data)
  488. : this (new ASN1 (data))
  489. {
  490. }
  491. public SignedData (ASN1 asn1)
  492. {
  493. if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 4))
  494. throw new ArgumentException ("Invalid SignedData");
  495. if (asn1[0][0].Tag != 0x02)
  496. throw new ArgumentException ("Invalid version");
  497. version = asn1[0][0].Value[0];
  498. contentInfo = new ContentInfo (asn1[0][2]);
  499. int n = 3;
  500. certs = new X509CertificateCollection ();
  501. if (asn1[0][n].Tag == 0xA0) {
  502. for (int i=0; i < asn1[0][n].Count; i++)
  503. certs.Add (new X509Certificate (asn1[0][n][i].GetBytes ()));
  504. n++;
  505. }
  506. crls = new ArrayList ();
  507. if (asn1[0][n].Tag == 0xA1) {
  508. for (int i=0; i < asn1[0][n].Count; i++)
  509. crls.Add (asn1[0][n][i].GetBytes ());
  510. n++;
  511. }
  512. if (asn1[0][n].Count > 0)
  513. signerInfo = new SignerInfo (asn1[0][n]);
  514. else
  515. signerInfo = new SignerInfo ();
  516. // Exchange hash algorithm Oid from SignerInfo
  517. if (signerInfo.HashName != null) {
  518. HashName = OidToName(signerInfo.HashName);
  519. }
  520. // Check if SignerInfo has authenticated attributes
  521. mda = (signerInfo.AuthenticatedAttributes.Count > 0);
  522. }
  523. public ASN1 ASN1 {
  524. get { return GetASN1(); }
  525. }
  526. public X509CertificateCollection Certificates {
  527. get { return certs; }
  528. }
  529. public ContentInfo ContentInfo {
  530. get { return contentInfo; }
  531. }
  532. public ArrayList Crls {
  533. get { return crls; }
  534. }
  535. public string HashName {
  536. get { return hashAlgorithm; }
  537. // todo add validation
  538. set {
  539. hashAlgorithm = value;
  540. signerInfo.HashName = value;
  541. }
  542. }
  543. public SignerInfo SignerInfo {
  544. get { return signerInfo; }
  545. }
  546. public byte Version {
  547. get { return version; }
  548. set { version = value; }
  549. }
  550. public bool UseAuthenticatedAttributes {
  551. get { return mda; }
  552. set { mda = value; }
  553. }
  554. public bool VerifySignature (AsymmetricAlgorithm aa)
  555. {
  556. if (aa == null) {
  557. return false;
  558. }
  559. RSAPKCS1SignatureDeformatter r = new RSAPKCS1SignatureDeformatter (aa);
  560. r.SetHashAlgorithm (hashAlgorithm);
  561. HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
  562. byte[] signature = signerInfo.Signature;
  563. byte[] hash = null;
  564. if (mda) {
  565. ASN1 asn = new ASN1 (0x31);
  566. foreach (ASN1 attr in signerInfo.AuthenticatedAttributes)
  567. asn.Add (attr);
  568. hash = ha.ComputeHash (asn.GetBytes ());
  569. } else {
  570. hash = ha.ComputeHash (contentInfo.Content[0].Value);
  571. }
  572. if (hash != null && signature != null) {
  573. return r.VerifySignature (hash, signature);
  574. }
  575. return false;
  576. }
  577. internal string OidToName (string oid)
  578. {
  579. switch (oid) {
  580. case "1.3.14.3.2.26" :
  581. return "SHA1";
  582. case "1.2.840.113549.2.2" :
  583. return "MD2";
  584. case "1.2.840.113549.2.5" :
  585. return "MD5";
  586. case "2.16.840.1.101.3.4.1" :
  587. return "SHA256";
  588. case "2.16.840.1.101.3.4.2" :
  589. return "SHA384";
  590. case "2.16.840.1.101.3.4.3" :
  591. return "SHA512";
  592. default :
  593. break;
  594. }
  595. // Unknown Oid
  596. return oid;
  597. }
  598. internal ASN1 GetASN1 ()
  599. {
  600. // SignedData ::= SEQUENCE {
  601. ASN1 signedData = new ASN1 (0x30);
  602. // version Version -> Version ::= INTEGER
  603. byte[] ver = { version };
  604. signedData.Add (new ASN1 (0x02, ver));
  605. // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
  606. ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
  607. if (hashAlgorithm != null) {
  608. string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
  609. digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
  610. }
  611. // contentInfo ContentInfo,
  612. ASN1 ci = contentInfo.ASN1;
  613. signedData.Add (ci);
  614. if (!signed && (hashAlgorithm != null)) {
  615. if (mda) {
  616. // Use authenticated attributes for signature
  617. // Automatically add the contentType authenticated attribute
  618. ASN1 ctattr = Attribute (Oid.contentType, ci[0]);
  619. signerInfo.AuthenticatedAttributes.Add (ctattr);
  620. // Automatically add the messageDigest authenticated attribute
  621. HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
  622. byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
  623. ASN1 md = new ASN1 (0x30);
  624. ASN1 mdattr = Attribute (Oid.messageDigest, md.Add (new ASN1 (0x04, idcHash)));
  625. signerInfo.AuthenticatedAttributes.Add (mdattr);
  626. } else {
  627. // Don't use authenticated attributes for signature -- signature is content
  628. RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (signerInfo.Key);
  629. r.SetHashAlgorithm (hashAlgorithm);
  630. HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
  631. byte[] sig = ha.ComputeHash (ci[1][0].Value);
  632. signerInfo.Signature = r.CreateSignature (sig);
  633. }
  634. signed = true;
  635. }
  636. // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
  637. if (certs.Count > 0) {
  638. ASN1 a0 = signedData.Add (new ASN1 (0xA0));
  639. foreach (X509Certificate x in certs)
  640. a0.Add (new ASN1 (x.RawData));
  641. }
  642. // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  643. if (crls.Count > 0) {
  644. ASN1 a1 = signedData.Add (new ASN1 (0xA1));
  645. foreach (byte[] crl in crls)
  646. a1.Add (new ASN1 (crl));
  647. }
  648. // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
  649. ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
  650. if (signerInfo.Key != null)
  651. signerInfos.Add (signerInfo.ASN1);
  652. return signedData;
  653. }
  654. public byte[] GetBytes ()
  655. {
  656. return GetASN1 ().GetBytes ();
  657. }
  658. }
  659. /*
  660. * SignerInfo ::= SEQUENCE {
  661. * version Version,
  662. * issuerAndSerialNumber IssuerAndSerialNumber,
  663. * digestAlgorithm DigestAlgorithmIdentifier,
  664. * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
  665. * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
  666. * encryptedDigest EncryptedDigest,
  667. * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
  668. * }
  669. *
  670. * For version == 3 issuerAndSerialNumber may be replaced by ...
  671. */
  672. public class SignerInfo {
  673. private byte version;
  674. private X509Certificate x509;
  675. private string hashAlgorithm;
  676. private AsymmetricAlgorithm key;
  677. private ArrayList authenticatedAttributes;
  678. private ArrayList unauthenticatedAttributes;
  679. private byte[] signature;
  680. private string issuer;
  681. private byte[] serial;
  682. private byte[] ski;
  683. public SignerInfo ()
  684. {
  685. version = 1;
  686. authenticatedAttributes = new ArrayList ();
  687. unauthenticatedAttributes = new ArrayList ();
  688. }
  689. public SignerInfo (byte[] data)
  690. : this (new ASN1 (data)) {}
  691. // TODO: INCOMPLETE
  692. public SignerInfo (ASN1 asn1) : this ()
  693. {
  694. if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 5))
  695. throw new ArgumentException ("Invalid SignedData");
  696. // version Version
  697. if (asn1[0][0].Tag != 0x02)
  698. throw new ArgumentException ("Invalid version");
  699. version = asn1[0][0].Value[0];
  700. // issuerAndSerialNumber IssuerAndSerialNumber
  701. ASN1 subjectIdentifierType = asn1 [0][1];
  702. if ((subjectIdentifierType.Tag == 0x80) && (version == 3)) {
  703. ski = subjectIdentifierType.Value;
  704. }
  705. else {
  706. issuer = X501.ToString (subjectIdentifierType [0]);
  707. serial = subjectIdentifierType [1].Value;
  708. }
  709. // digestAlgorithm DigestAlgorithmIdentifier
  710. ASN1 digestAlgorithm = asn1 [0][2];
  711. hashAlgorithm = ASN1Convert.ToOid (digestAlgorithm [0]);
  712. // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL
  713. int n = 3;
  714. ASN1 authAttributes = asn1 [0][n];
  715. if (authAttributes.Tag == 0xA0) {
  716. n++;
  717. for (int i=0; i < authAttributes.Count; i++)
  718. authenticatedAttributes.Add (authAttributes [i]);
  719. }
  720. // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier
  721. n++;
  722. // ASN1 digestEncryptionAlgorithm = asn1 [0][n++];
  723. // string digestEncryptionAlgorithmOid = ASN1Convert.ToOid (digestEncryptionAlgorithm [0]);
  724. // encryptedDigest EncryptedDigest
  725. ASN1 encryptedDigest = asn1 [0][n++];
  726. if (encryptedDigest.Tag == 0x04)
  727. signature = encryptedDigest.Value;
  728. // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
  729. ASN1 unauthAttributes = asn1 [0][n];
  730. if ((unauthAttributes != null) && (unauthAttributes.Tag == 0xA1)) {
  731. for (int i=0; i < unauthAttributes.Count; i++)
  732. unauthenticatedAttributes.Add (unauthAttributes [i]);
  733. }
  734. }
  735. public string IssuerName {
  736. get { return issuer; }
  737. }
  738. public byte[] SerialNumber {
  739. get {
  740. if (serial == null)
  741. return null;
  742. return (byte[]) serial.Clone ();
  743. }
  744. }
  745. public byte[] SubjectKeyIdentifier {
  746. get {
  747. if (ski == null)
  748. return null;
  749. return (byte[]) ski.Clone ();
  750. }
  751. }
  752. public ASN1 ASN1 {
  753. get { return GetASN1(); }
  754. }
  755. public ArrayList AuthenticatedAttributes {
  756. get { return authenticatedAttributes; }
  757. }
  758. public X509Certificate Certificate {
  759. get { return x509; }
  760. set { x509 = value; }
  761. }
  762. public string HashName {
  763. get { return hashAlgorithm; }
  764. set { hashAlgorithm = value; }
  765. }
  766. public AsymmetricAlgorithm Key {
  767. get { return key; }
  768. set { key = value; }
  769. }
  770. public byte[] Signature {
  771. get {
  772. if (signature == null)
  773. return null;
  774. return (byte[]) signature.Clone ();
  775. }
  776. set {
  777. if (value != null) {
  778. signature = (byte[]) value.Clone ();
  779. }
  780. }
  781. }
  782. public ArrayList UnauthenticatedAttributes {
  783. get { return unauthenticatedAttributes; }
  784. }
  785. public byte Version {
  786. get { return version; }
  787. set { version = value; }
  788. }
  789. internal ASN1 GetASN1 ()
  790. {
  791. if ((key == null) || (hashAlgorithm == null))
  792. return null;
  793. byte[] ver = { version };
  794. ASN1 signerInfo = new ASN1 (0x30);
  795. // version Version -> Version ::= INTEGER
  796. signerInfo.Add (new ASN1 (0x02, ver));
  797. // issuerAndSerialNumber IssuerAndSerialNumber,
  798. signerInfo.Add (PKCS7.IssuerAndSerialNumber (x509));
  799. // digestAlgorithm DigestAlgorithmIdentifier,
  800. string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
  801. signerInfo.Add (AlgorithmIdentifier (hashOid));
  802. // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
  803. ASN1 aa = null;
  804. if (authenticatedAttributes.Count > 0) {
  805. aa = signerInfo.Add (new ASN1 (0xA0));
  806. authenticatedAttributes.Sort(new SortedSet ());
  807. foreach (ASN1 attr in authenticatedAttributes)
  808. aa.Add (attr);
  809. }
  810. // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
  811. if (key is RSA) {
  812. signerInfo.Add (AlgorithmIdentifier (PKCS7.Oid.rsaEncryption));
  813. if (aa != null) {
  814. // Calculate the signature here; otherwise it must be set from SignedData
  815. RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (key);
  816. r.SetHashAlgorithm (hashAlgorithm);
  817. byte[] tbs = aa.GetBytes ();
  818. tbs [0] = 0x31; // not 0xA0 for signature
  819. HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
  820. byte[] tbsHash = ha.ComputeHash (tbs);
  821. signature = r.CreateSignature (tbsHash);
  822. }
  823. }
  824. else if (key is DSA) {
  825. throw new NotImplementedException ("not yet");
  826. }
  827. else
  828. throw new CryptographicException ("Unknown assymetric algorithm");
  829. // encryptedDigest EncryptedDigest,
  830. signerInfo.Add (new ASN1 (0x04, signature));
  831. // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
  832. if (unauthenticatedAttributes.Count > 0) {
  833. ASN1 ua = signerInfo.Add (new ASN1 (0xA1));
  834. unauthenticatedAttributes.Sort(new SortedSet ());
  835. foreach (ASN1 attr in unauthenticatedAttributes)
  836. ua.Add (attr);
  837. }
  838. return signerInfo;
  839. }
  840. public byte[] GetBytes ()
  841. {
  842. return GetASN1 ().GetBytes ();
  843. }
  844. }
  845. internal class SortedSet : IComparer {
  846. public int Compare (object x, object y)
  847. {
  848. if (x == null)
  849. return (y == null) ? 0 : -1;
  850. else if (y == null)
  851. return 1;
  852. ASN1 xx = x as ASN1;
  853. ASN1 yy = y as ASN1;
  854. if ((xx == null) || (yy == null)) {
  855. throw new ArgumentException (("Invalid objects."));
  856. }
  857. byte[] xb = xx.GetBytes ();
  858. byte[] yb = yy.GetBytes ();
  859. for (int i = 0; i < xb.Length; i++) {
  860. if (i == yb.Length)
  861. break;
  862. if (xb[i] == yb[i])
  863. continue;
  864. return (xb[i] < yb[i]) ? -1 : 1;
  865. }
  866. // The arrays are equal up to the shortest of them.
  867. if (xb.Length > yb.Length)
  868. return 1;
  869. else if (xb.Length < yb.Length)
  870. return -1;
  871. return 0;
  872. }
  873. }
  874. }
  875. }