PDFExportCrypt.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. using System;
  2. using System.Text;
  3. using System.IO;
  4. using System.Security.Cryptography;
  5. using System.Security.Cryptography.X509Certificates;
  6. using System.Security.Cryptography.Pkcs;
  7. namespace FastReport.Export.Pdf
  8. {
  9. public partial class PDFExport : ExportBase
  10. {
  11. byte[] pDF_PK = {
  12. 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A,
  13. 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA,
  14. 0x01, 0x08, 0x2E, 0x2E, 0x00, 0xB6, 0xD0,
  15. 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE,
  16. 0x64, 0x53, 0x69, 0x7A };
  17. private long encBits;
  18. private byte[] encKey;
  19. private byte[] oPass;
  20. private byte[] uPass;
  21. private string RC4CryptString(string source, byte[] key, long id)
  22. {
  23. byte[] k = new byte[21];
  24. Array.Copy(key, 0, k, 0, 16);
  25. k[16] = (byte)id;
  26. k[17] = (byte)(id >> 8);
  27. k[18] = (byte)(id >> 16);
  28. byte[] s = new byte[16];
  29. System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  30. Array.Copy(md5.ComputeHash(k), s, 16);
  31. RC4 rc4 = new RC4();
  32. rc4.Start(s);
  33. byte[] src = ExportUtils.StringToByteArray(source);
  34. byte[] target = rc4.Crypt(src);
  35. return ExportUtils.StringFromByteArray(target);
  36. }
  37. private void RC4CryptStream(Stream source, Stream target, byte[] key, long id)
  38. {
  39. byte[] k = new byte[21];
  40. Array.Copy(key, 0, k, 0, 16);
  41. k[16] = (byte)id;
  42. k[17] = (byte)(id >> 8);
  43. k[18] = (byte)(id >> 16);
  44. byte[] s = new byte[16];
  45. System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  46. Array.Copy(md5.ComputeHash(k), s, 16);
  47. byte[] buffSource = new byte[source.Length];
  48. source.Position = 0;
  49. source.Read(buffSource, 0, (int)source.Length);
  50. RC4 rc4 = new RC4();
  51. rc4.Start(s);
  52. byte[] buffTarget = rc4.Crypt(buffSource);
  53. target.Write(buffTarget, 0, buffTarget.Length);
  54. }
  55. private byte[] PadPassword(string password)
  56. {
  57. byte[] p = ExportUtils.StringToByteArray(password);
  58. byte[] result = new byte[32];
  59. int l = p.Length < 32 ? p.Length : 32;
  60. for (int i = 0; i < l; i++)
  61. result[i] = p[i];
  62. if (l < 32)
  63. for (int i = l; i < 32; i++)
  64. result[i] = pDF_PK[i - l];
  65. return result;
  66. }
  67. private void PrepareKeys()
  68. {
  69. encBits = -64; // 0xFFFFFFC0;
  70. if (allowPrint)
  71. encBits += 4;
  72. if (allowModify)
  73. encBits += 8;
  74. if (allowCopy)
  75. encBits += 16;
  76. if (allowAnnotate)
  77. encBits += 32;
  78. // OWNER KEY
  79. if (String.IsNullOrEmpty(ownerPassword))
  80. ownerPassword = userPassword;
  81. byte[] p = PadPassword(ownerPassword);
  82. System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  83. md5.Initialize();
  84. byte[] s = new byte[16];
  85. md5.TransformBlock(p, 0, 32, p, 0);
  86. md5.TransformFinalBlock(p, 0, 0);
  87. Array.Copy(md5.Hash, s, 16);
  88. for (byte i = 1; i <= 50; i++)
  89. {
  90. md5.Initialize();
  91. Array.Copy(md5.ComputeHash(s), 0, s, 0, 16);
  92. }
  93. RC4 rc4 = new RC4();
  94. p = PadPassword(userPassword);
  95. rc4.Start(s);
  96. byte[] s1 = rc4.Crypt(p);
  97. byte[] p1 = new byte[16];
  98. for (byte i = 1; i <= 19; i++)
  99. {
  100. for (byte j = 1; j <= 16; j++)
  101. p1[j - 1] = (byte)(s[j - 1] ^ i);
  102. rc4.Start(p1);
  103. s1 = rc4.Crypt(s1);
  104. }
  105. oPass = new byte[32];
  106. Array.Copy(s1, oPass, 32);
  107. // ENCRYPTION KEY
  108. p = PadPassword(userPassword);
  109. md5.Initialize();
  110. md5.TransformBlock(p, 0, 32, p, 0);
  111. md5.TransformBlock(oPass, 0, 32, oPass, 0);
  112. byte[] ext = new byte[4];
  113. ext[0] = (byte)encBits;
  114. ext[1] = (byte)(encBits >> 8);
  115. ext[2] = (byte)(encBits >> 16);
  116. ext[3] = (byte)(encBits >> 24);
  117. md5.TransformBlock(ext, 0, 4, ext, 0);
  118. byte[] fid = new byte[16];
  119. for (byte i = 1; i <= 16; i++)
  120. fid[i - 1] = Convert.ToByte(String.Concat(fileID[i * 2 - 2], fileID[i * 2 - 1]), 16);
  121. md5.TransformBlock(fid, 0, 16, fid, 0);
  122. md5.TransformFinalBlock(ext, 0, 0);
  123. Array.Copy(md5.Hash, 0, s, 0, 16);
  124. for (byte i = 1; i <= 50; i++)
  125. {
  126. md5.Initialize();
  127. Array.Copy(md5.ComputeHash(s), 0, s, 0, 16);
  128. }
  129. encKey = new byte[16];
  130. Array.Copy(s, 0, encKey, 0, 16);
  131. // USER KEY
  132. md5.Initialize();
  133. md5.TransformBlock(pDF_PK, 0, 32, pDF_PK, 0);
  134. md5.TransformBlock(fid, 0, 16, fid, 0);
  135. md5.TransformFinalBlock(fid, 0, 0);
  136. Array.Copy(md5.Hash, s, 16);
  137. s1 = new byte[16];
  138. Array.Copy(encKey, s1, 16);
  139. rc4.Start(s1);
  140. s = rc4.Crypt(s);
  141. p1 = new byte[16];
  142. for (byte i = 1; i <= 19; i++)
  143. {
  144. for (byte j = 1; j <= 16; j++)
  145. p1[j - 1] = (byte)(s1[j - 1] ^ i);
  146. rc4.Start(p1);
  147. s = rc4.Crypt(s);
  148. }
  149. uPass = new byte[32];
  150. Array.Copy(s, 0, uPass, 0, 16);
  151. }
  152. private string GetEncryptionDescriptor()
  153. {
  154. StringBuilder sb = new StringBuilder();
  155. sb.AppendLine("/Encrypt <<");
  156. sb.AppendLine("/Filter /Standard");
  157. sb.AppendLine("/V 2");
  158. sb.AppendLine("/R 3");
  159. sb.AppendLine("/Length 128");
  160. sb.AppendLine("/P " + encBits.ToString());
  161. sb.Append("/O (");
  162. EscapeSpecialChar(ExportUtils.StringFromByteArray(oPass), sb);
  163. sb.AppendLine(")");
  164. sb.Append("/U (");
  165. EscapeSpecialChar(ExportUtils.StringFromByteArray(uPass), sb);
  166. sb.AppendLine(")");
  167. sb.AppendLine(">>");
  168. return sb.ToString();
  169. }
  170. #region DigitalSignature
  171. private struct SignatureDictIndicies
  172. {
  173. public long byteRangeIndex;
  174. public long contentsIndex;
  175. }
  176. private byte[] MSSign(X509Certificate2 cert, byte[] data)
  177. {
  178. ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1"), data);
  179. SignedCms signedCms = new SignedCms(content, true);
  180. CmsSigner signer = new CmsSigner(cert);
  181. //signer.DigestAlgorithm = new Oid(CryptoConfig.MapNameToOID("SHA256"));
  182. signedCms.ComputeSignature(signer);
  183. return signedCms.Encode();
  184. }
  185. private SignatureDictIndicies AddSignatureDict(ReportComponentBase report_obj)
  186. {
  187. SignatureDictIndicies res = new SignatureDictIndicies();
  188. if (digitalSignCertificate != null && report_obj == null)
  189. {
  190. int sigSize = 16384;
  191. long objNo = UpdateXRef();
  192. StringBuilder sb = new StringBuilder();
  193. sb.AppendLine(ObjNumber(objNo));
  194. sb.Append("<<");
  195. sb.Append("/Type/Sig");
  196. sb.Append("/Filter/Adobe.PPKLite");
  197. sb.Append("/SubFilter/adbe.pkcs7.detached");
  198. sb.Append("/Reason");
  199. if (digitalSignReason == null)
  200. digitalSignReason = "";
  201. PrepareString(digitalSignReason, encKey, encrypted, objNo, sb);
  202. sb.Append("/Location");
  203. if (digitalSignLocation == null)
  204. digitalSignLocation = "";
  205. PrepareString(digitalSignLocation, encKey, encrypted, objNo, sb);
  206. sb.Append("/ContactInfo");
  207. if (digitalSignContactInfo == null)
  208. digitalSignContactInfo = "";
  209. PrepareString(digitalSignContactInfo, encKey, encrypted, objNo, sb);
  210. sb.Append("/PropBuild<</App<<");
  211. sb.Append("/Name");
  212. PrepareString("FastReport.Net", encKey, encrypted, objNo, sb);
  213. sb.Append(">>>>");
  214. string date = "D:" + digitalSignCreationDate.ToString("yyyyMMddHHmmss");
  215. sb.Append("/M(").Append(date).Append(")");
  216. //PrepareString(date, encKey, encrypted, infoNumber, sb);
  217. sb.Append("/ByteRange [");
  218. res.byteRangeIndex = sb.Length + xRef[(int)objNo - 1];
  219. sb.Append(new string(' ', 81));
  220. sb.Append("/Contents<");
  221. res.contentsIndex = sb.Length + xRef[(int)objNo - 1];
  222. sb.Append(new string('0', sigSize));
  223. sb.AppendLine(">>>");
  224. sb.AppendLine("endobj");
  225. Write(pdf, sb.ToString());
  226. AddSignatureAppearence(objNo, report_obj);
  227. }
  228. else
  229. {
  230. AddSignatureAppearence(-1, report_obj);
  231. }
  232. return res;
  233. }
  234. private long AddSignatureAppearenceLayer(string right, string top)
  235. {
  236. return AddSignatureAppearenceLayer(right, top, "% DSBlank\n");
  237. }
  238. private long AddSignatureAppearenceLayer(string right, string top, string streamContent)
  239. {
  240. long res = UpdateXRef();
  241. StringBuilder sb = new StringBuilder();
  242. sb.AppendLine(ObjNumber(res));
  243. sb.Append("<<");
  244. sb.Append("/Type/XObject");
  245. sb.Append("/Subtype/Form");
  246. sb.Append("/Resources<<>>");
  247. sb.Append(String.Format("/BBox[0 0 {0} {1}]", right, top));
  248. sb.Append("/FormType 1");
  249. sb.AppendLine("/Matrix [1 0 0 1 0 0]");
  250. Write(pdf, sb.ToString());
  251. using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray(streamContent)))
  252. {
  253. WritePDFStream(pdf, ms, 0, compressed, encrypted, false, true);
  254. }
  255. return res;
  256. }
  257. private long AddSignatureAppearenceLayersContainer(string right, string top)
  258. {
  259. long layerN0 = AddSignatureAppearenceLayer(right, top);
  260. long layerN2 = AddSignatureAppearenceLayer(right, top);
  261. long res = UpdateXRef();
  262. StringBuilder sb = new StringBuilder();
  263. sb.Append("<<");
  264. sb.Append("/Type/XObject");
  265. sb.Append("/Subtype/Form");
  266. sb.Append("/Resources<</XObject << /n0" + ObjNumberRef(layerN0) +
  267. " /n2" + ObjNumberRef(layerN2) + ">>>>");
  268. sb.Append(String.Format("/BBox[0 0 {0} {1}]", right, top));
  269. sb.Append("/FormType 1");
  270. sb.AppendLine("/Matrix [1 0 0 1 0 0]");
  271. Write(pdf, sb.ToString());
  272. using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray("q 1 0 0 1 0 0 cm /n0 Do Q\nq 1 0 0 1 0 0 cm /n2 Do Q\n")))
  273. {
  274. WritePDFStream(pdf, ms, 0, compressed, encrypted, false, true);
  275. }
  276. return res;
  277. }
  278. private long AddEmptyAppearence()
  279. {
  280. long res = UpdateXRef();
  281. StringBuilder sb = new StringBuilder();
  282. sb.AppendLine(ObjNumber(res));
  283. sb.Append("<<");
  284. sb.Append("/Type/XObject");
  285. sb.Append("/Subtype/Form");
  286. sb.Append("/Resources<<>>");
  287. sb.Append("/BBox[0 0 0 0]");
  288. sb.Append("/FormType 1");
  289. sb.AppendLine("/Matrix [1 0 0 1 0 0]");
  290. Write(pdf, sb.ToString());
  291. using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray("% DSBlank\n")))
  292. {
  293. WritePDFStream(pdf, ms, 0, compressed, encrypted, false, true);
  294. }
  295. return res;
  296. }
  297. private int signaturesCount = 0;
  298. private void AddSignatureAppearence(long sigObjNo, ReportComponentBase report_obj)
  299. {
  300. ++signaturesCount;
  301. long appearence = AddEmptyAppearence();
  302. long objNo = UpdateXRef();
  303. acroFormsRefs.Add(objNo);
  304. StringBuilder sb = new StringBuilder();
  305. sb.AppendLine(ObjNumber(objNo));
  306. sb.Append("<<");
  307. sb.Append("/FT/Sig");
  308. sb.Append("/T");
  309. PrepareString(string.Format("Signature{0}", signaturesCount), encKey, encrypted, objNo, sb);
  310. if (sigObjNo >= 0)
  311. {
  312. sb.Append("/V ");
  313. sb.Append(ObjNumberRef(sigObjNo));
  314. }
  315. sb.Append("/F 132");
  316. sb.Append("/Type/Annot");
  317. sb.Append("/Subtype/Widget");
  318. if (report_obj == null)
  319. {
  320. sb.Append("/Rect[0 0 0 0]");
  321. }
  322. else
  323. {
  324. string left = FloatToString(GetLeft(report_obj.AbsLeft));
  325. string bottom = FloatToString(GetTop(report_obj.AbsTop + report_obj.Height));
  326. string right = FloatToString(GetLeft(report_obj.AbsLeft + report_obj.Width));
  327. string top = FloatToString(GetTop(report_obj.AbsTop));
  328. sb.Append(String.Format("/Rect[{0} {1} {2} {3}]", left, bottom, right, top));
  329. }
  330. UpdateXRef(objNo);
  331. sb.Append("/AP<</N " + ObjNumberRef(appearence) + ">>");
  332. pageAnnots.Append(ObjNumberRef(objNo) + " ");
  333. sb.Append("/DR<<>>");
  334. sb.AppendLine(">>");
  335. sb.AppendLine("endobj");
  336. Write(pdf, sb.ToString());
  337. }
  338. private string BytesToHex(byte[] bytes)
  339. {
  340. StringBuilder sb = new StringBuilder();
  341. foreach (byte b in bytes)
  342. {
  343. sb.Append(ExportUtils.ByteToHex(b).ToLower());
  344. }
  345. return sb.ToString();
  346. }
  347. private void AddSignature(X509Certificate2 cert)
  348. {
  349. pdf.Flush();
  350. pdf.Seek(digitalSignByteRange[0], SeekOrigin.Begin);
  351. byte[] data = new byte[digitalSignByteRange[1] + digitalSignByteRange[3]];
  352. pdf.Read(data, 0, (int)digitalSignByteRange[1]);
  353. pdf.Seek(digitalSignByteRange[2], SeekOrigin.Begin);
  354. pdf.Read(data, (int)digitalSignByteRange[1], (int)digitalSignByteRange[3]);
  355. if (cert != null)
  356. {
  357. byte[] signature = Encoding.ASCII.GetBytes(BytesToHex(MSSign(cert, data)));
  358. if (signature.Length > 16384)
  359. {
  360. throw new OverflowException("Signature value was too big");
  361. }
  362. pdf.Flush();
  363. pdf.Seek(signatureDictIndicies.contentsIndex, SeekOrigin.Begin);
  364. pdf.Write(signature, 0, signature.Length);
  365. }
  366. }
  367. #endregion // DigitalSignature
  368. }
  369. internal class RC4
  370. {
  371. private byte[] fKey;
  372. public void Start(byte[] key)
  373. {
  374. byte[] k = new byte[256];
  375. int l = key.GetLength(0);
  376. if (key.Length > 0 && l <= 256)
  377. {
  378. for (int i = 0; i < 256; i++)
  379. {
  380. fKey[i] = (byte)i;
  381. k[i] = key[i % l];
  382. }
  383. }
  384. byte j = 0;
  385. for (int i = 0; i < 256; i++)
  386. {
  387. j = (byte)(j + fKey[i] + k[i]);
  388. byte tmp = fKey[i];
  389. fKey[i] = fKey[j];
  390. fKey[j] = tmp;
  391. }
  392. }
  393. public byte[] Crypt(byte[] source)
  394. {
  395. byte i = 0;
  396. byte j = 0;
  397. int l = source.GetLength(0);
  398. byte[] result = new byte[l];
  399. for (int k = 0; k < l; k++)
  400. {
  401. i = (byte)(i + 1);
  402. j = (byte)(j + fKey[i]);
  403. byte tmp = fKey[i];
  404. fKey[i] = fKey[j];
  405. fKey[j] = tmp;
  406. result[k] = (byte)(source[k] ^ fKey[(byte)(fKey[i] + fKey[j])]);
  407. }
  408. return result;
  409. }
  410. public RC4()
  411. {
  412. fKey = new byte[256];
  413. }
  414. }
  415. }