PKCS7.cs 27 KB

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