123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- using System;
- using System.Text;
- using System.IO;
- using System.Security.Cryptography;
- using System.Security.Cryptography.X509Certificates;
- using System.Security.Cryptography.Pkcs;
- namespace FastReport.Export.Pdf
- {
- public partial class PDFExport : ExportBase
- {
- byte[] pDF_PK = {
- 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A,
- 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA,
- 0x01, 0x08, 0x2E, 0x2E, 0x00, 0xB6, 0xD0,
- 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE,
- 0x64, 0x53, 0x69, 0x7A };
- private long encBits;
- private byte[] encKey;
- private byte[] oPass;
- private byte[] uPass;
- private string RC4CryptString(string source, byte[] key, long id)
- {
- byte[] k = new byte[21];
- Array.Copy(key, 0, k, 0, 16);
- k[16] = (byte)id;
- k[17] = (byte)(id >> 8);
- k[18] = (byte)(id >> 16);
- byte[] s = new byte[16];
- System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
- Array.Copy(md5.ComputeHash(k), s, 16);
- RC4 rc4 = new RC4();
- rc4.Start(s);
- byte[] src = ExportUtils.StringToByteArray(source);
- byte[] target = rc4.Crypt(src);
- return ExportUtils.StringFromByteArray(target);
- }
- private void RC4CryptStream(Stream source, Stream target, byte[] key, long id)
- {
- byte[] k = new byte[21];
- Array.Copy(key, 0, k, 0, 16);
- k[16] = (byte)id;
- k[17] = (byte)(id >> 8);
- k[18] = (byte)(id >> 16);
- byte[] s = new byte[16];
- System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
- Array.Copy(md5.ComputeHash(k), s, 16);
- byte[] buffSource = new byte[source.Length];
- source.Position = 0;
- source.Read(buffSource, 0, (int)source.Length);
- RC4 rc4 = new RC4();
- rc4.Start(s);
- byte[] buffTarget = rc4.Crypt(buffSource);
- target.Write(buffTarget, 0, buffTarget.Length);
- }
- private byte[] PadPassword(string password)
- {
- byte[] p = ExportUtils.StringToByteArray(password);
- byte[] result = new byte[32];
- int l = p.Length < 32 ? p.Length : 32;
- for (int i = 0; i < l; i++)
- result[i] = p[i];
- if (l < 32)
- for (int i = l; i < 32; i++)
- result[i] = pDF_PK[i - l];
- return result;
- }
- private void PrepareKeys()
- {
- encBits = -64; // 0xFFFFFFC0;
- if (allowPrint)
- encBits += 4;
- if (allowModify)
- encBits += 8;
- if (allowCopy)
- encBits += 16;
- if (allowAnnotate)
- encBits += 32;
- // OWNER KEY
- if (String.IsNullOrEmpty(ownerPassword))
- ownerPassword = userPassword;
- byte[] p = PadPassword(ownerPassword);
- System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
- md5.Initialize();
- byte[] s = new byte[16];
- md5.TransformBlock(p, 0, 32, p, 0);
- md5.TransformFinalBlock(p, 0, 0);
- Array.Copy(md5.Hash, s, 16);
- for (byte i = 1; i <= 50; i++)
- {
- md5.Initialize();
- Array.Copy(md5.ComputeHash(s), 0, s, 0, 16);
- }
- RC4 rc4 = new RC4();
- p = PadPassword(userPassword);
- rc4.Start(s);
- byte[] s1 = rc4.Crypt(p);
- byte[] p1 = new byte[16];
- for (byte i = 1; i <= 19; i++)
- {
- for (byte j = 1; j <= 16; j++)
- p1[j - 1] = (byte)(s[j - 1] ^ i);
- rc4.Start(p1);
- s1 = rc4.Crypt(s1);
- }
- oPass = new byte[32];
- Array.Copy(s1, oPass, 32);
- // ENCRYPTION KEY
- p = PadPassword(userPassword);
- md5.Initialize();
- md5.TransformBlock(p, 0, 32, p, 0);
- md5.TransformBlock(oPass, 0, 32, oPass, 0);
- byte[] ext = new byte[4];
- ext[0] = (byte)encBits;
- ext[1] = (byte)(encBits >> 8);
- ext[2] = (byte)(encBits >> 16);
- ext[3] = (byte)(encBits >> 24);
- md5.TransformBlock(ext, 0, 4, ext, 0);
- byte[] fid = new byte[16];
- for (byte i = 1; i <= 16; i++)
- fid[i - 1] = Convert.ToByte(String.Concat(fileID[i * 2 - 2], fileID[i * 2 - 1]), 16);
- md5.TransformBlock(fid, 0, 16, fid, 0);
- md5.TransformFinalBlock(ext, 0, 0);
- Array.Copy(md5.Hash, 0, s, 0, 16);
- for (byte i = 1; i <= 50; i++)
- {
- md5.Initialize();
- Array.Copy(md5.ComputeHash(s), 0, s, 0, 16);
- }
- encKey = new byte[16];
- Array.Copy(s, 0, encKey, 0, 16);
- // USER KEY
- md5.Initialize();
- md5.TransformBlock(pDF_PK, 0, 32, pDF_PK, 0);
- md5.TransformBlock(fid, 0, 16, fid, 0);
- md5.TransformFinalBlock(fid, 0, 0);
- Array.Copy(md5.Hash, s, 16);
- s1 = new byte[16];
- Array.Copy(encKey, s1, 16);
- rc4.Start(s1);
- s = rc4.Crypt(s);
- p1 = new byte[16];
- for (byte i = 1; i <= 19; i++)
- {
- for (byte j = 1; j <= 16; j++)
- p1[j - 1] = (byte)(s1[j - 1] ^ i);
- rc4.Start(p1);
- s = rc4.Crypt(s);
- }
- uPass = new byte[32];
- Array.Copy(s, 0, uPass, 0, 16);
- }
- private string GetEncryptionDescriptor()
- {
- StringBuilder sb = new StringBuilder();
- sb.AppendLine("/Encrypt <<");
- sb.AppendLine("/Filter /Standard");
- sb.AppendLine("/V 2");
- sb.AppendLine("/R 3");
- sb.AppendLine("/Length 128");
- sb.AppendLine("/P " + encBits.ToString());
- sb.Append("/O (");
- EscapeSpecialChar(ExportUtils.StringFromByteArray(oPass), sb);
- sb.AppendLine(")");
- sb.Append("/U (");
- EscapeSpecialChar(ExportUtils.StringFromByteArray(uPass), sb);
- sb.AppendLine(")");
- sb.AppendLine(">>");
- return sb.ToString();
- }
- #region DigitalSignature
- private struct SignatureDictIndicies
- {
- public long byteRangeIndex;
- public long contentsIndex;
- }
- private byte[] MSSign(X509Certificate2 cert, byte[] data)
- {
- ContentInfo content = new ContentInfo(new Oid("1.2.840.113549.1.7.1"), data);
- SignedCms signedCms = new SignedCms(content, true);
- CmsSigner signer = new CmsSigner(cert);
- //signer.DigestAlgorithm = new Oid(CryptoConfig.MapNameToOID("SHA256"));
- signedCms.ComputeSignature(signer);
- return signedCms.Encode();
- }
- private SignatureDictIndicies AddSignatureDict(ReportComponentBase report_obj)
- {
- SignatureDictIndicies res = new SignatureDictIndicies();
- if (digitalSignCertificate != null && report_obj == null)
- {
- int sigSize = 16384;
- long objNo = UpdateXRef();
- StringBuilder sb = new StringBuilder();
- sb.AppendLine(ObjNumber(objNo));
- sb.Append("<<");
- sb.Append("/Type/Sig");
- sb.Append("/Filter/Adobe.PPKLite");
- sb.Append("/SubFilter/adbe.pkcs7.detached");
- sb.Append("/Reason");
- if (digitalSignReason == null)
- digitalSignReason = "";
- PrepareString(digitalSignReason, encKey, encrypted, objNo, sb);
- sb.Append("/Location");
- if (digitalSignLocation == null)
- digitalSignLocation = "";
- PrepareString(digitalSignLocation, encKey, encrypted, objNo, sb);
- sb.Append("/ContactInfo");
- if (digitalSignContactInfo == null)
- digitalSignContactInfo = "";
- PrepareString(digitalSignContactInfo, encKey, encrypted, objNo, sb);
- sb.Append("/PropBuild<</App<<");
- sb.Append("/Name");
- PrepareString("FastReport.Net", encKey, encrypted, objNo, sb);
- sb.Append(">>>>");
- string date = "D:" + digitalSignCreationDate.ToString("yyyyMMddHHmmss");
- sb.Append("/M(").Append(date).Append(")");
- //PrepareString(date, encKey, encrypted, infoNumber, sb);
- sb.Append("/ByteRange [");
- res.byteRangeIndex = sb.Length + xRef[(int)objNo - 1];
- sb.Append(new string(' ', 81));
- sb.Append("/Contents<");
- res.contentsIndex = sb.Length + xRef[(int)objNo - 1];
- sb.Append(new string('0', sigSize));
- sb.AppendLine(">>>");
- sb.AppendLine("endobj");
- Write(pdf, sb.ToString());
- AddSignatureAppearence(objNo, report_obj);
- }
- else
- {
- AddSignatureAppearence(-1, report_obj);
- }
- return res;
- }
- private long AddSignatureAppearenceLayer(string right, string top)
- {
- return AddSignatureAppearenceLayer(right, top, "% DSBlank\n");
- }
- private long AddSignatureAppearenceLayer(string right, string top, string streamContent)
- {
- long res = UpdateXRef();
- StringBuilder sb = new StringBuilder();
- sb.AppendLine(ObjNumber(res));
- sb.Append("<<");
- sb.Append("/Type/XObject");
- sb.Append("/Subtype/Form");
- sb.Append("/Resources<<>>");
- sb.Append(String.Format("/BBox[0 0 {0} {1}]", right, top));
- sb.Append("/FormType 1");
- sb.AppendLine("/Matrix [1 0 0 1 0 0]");
- Write(pdf, sb.ToString());
- using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray(streamContent)))
- {
- WritePDFStream(pdf, ms, 0, compressed, encrypted, false, true);
- }
- return res;
- }
- private long AddSignatureAppearenceLayersContainer(string right, string top)
- {
- long layerN0 = AddSignatureAppearenceLayer(right, top);
- long layerN2 = AddSignatureAppearenceLayer(right, top);
- long res = UpdateXRef();
- StringBuilder sb = new StringBuilder();
- sb.Append("<<");
- sb.Append("/Type/XObject");
- sb.Append("/Subtype/Form");
- sb.Append("/Resources<</XObject << /n0" + ObjNumberRef(layerN0) +
- " /n2" + ObjNumberRef(layerN2) + ">>>>");
- sb.Append(String.Format("/BBox[0 0 {0} {1}]", right, top));
- sb.Append("/FormType 1");
- sb.AppendLine("/Matrix [1 0 0 1 0 0]");
- Write(pdf, sb.ToString());
- 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")))
- {
- WritePDFStream(pdf, ms, 0, compressed, encrypted, false, true);
- }
- return res;
- }
- private long AddEmptyAppearence()
- {
- long res = UpdateXRef();
- StringBuilder sb = new StringBuilder();
- sb.AppendLine(ObjNumber(res));
- sb.Append("<<");
- sb.Append("/Type/XObject");
- sb.Append("/Subtype/Form");
- sb.Append("/Resources<<>>");
- sb.Append("/BBox[0 0 0 0]");
- sb.Append("/FormType 1");
- sb.AppendLine("/Matrix [1 0 0 1 0 0]");
- Write(pdf, sb.ToString());
- using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray("% DSBlank\n")))
- {
- WritePDFStream(pdf, ms, 0, compressed, encrypted, false, true);
- }
- return res;
- }
- private int signaturesCount = 0;
- private void AddSignatureAppearence(long sigObjNo, ReportComponentBase report_obj)
- {
- ++signaturesCount;
- long appearence = AddEmptyAppearence();
- long objNo = UpdateXRef();
- acroFormsRefs.Add(objNo);
- StringBuilder sb = new StringBuilder();
- sb.AppendLine(ObjNumber(objNo));
- sb.Append("<<");
- sb.Append("/FT/Sig");
- sb.Append("/T");
- PrepareString(string.Format("Signature{0}", signaturesCount), encKey, encrypted, objNo, sb);
- if (sigObjNo >= 0)
- {
- sb.Append("/V ");
- sb.Append(ObjNumberRef(sigObjNo));
- }
- sb.Append("/F 132");
- sb.Append("/Type/Annot");
- sb.Append("/Subtype/Widget");
- if (report_obj == null)
- {
- sb.Append("/Rect[0 0 0 0]");
- }
- else
- {
- string left = FloatToString(GetLeft(report_obj.AbsLeft));
- string bottom = FloatToString(GetTop(report_obj.AbsTop + report_obj.Height));
- string right = FloatToString(GetLeft(report_obj.AbsLeft + report_obj.Width));
- string top = FloatToString(GetTop(report_obj.AbsTop));
- sb.Append(String.Format("/Rect[{0} {1} {2} {3}]", left, bottom, right, top));
- }
- UpdateXRef(objNo);
- sb.Append("/AP<</N " + ObjNumberRef(appearence) + ">>");
- pageAnnots.Append(ObjNumberRef(objNo) + " ");
- sb.Append("/DR<<>>");
- sb.AppendLine(">>");
- sb.AppendLine("endobj");
- Write(pdf, sb.ToString());
- }
- private string BytesToHex(byte[] bytes)
- {
- StringBuilder sb = new StringBuilder();
- foreach (byte b in bytes)
- {
- sb.Append(ExportUtils.ByteToHex(b).ToLower());
- }
- return sb.ToString();
- }
- private void AddSignature(X509Certificate2 cert)
- {
- pdf.Flush();
- pdf.Seek(digitalSignByteRange[0], SeekOrigin.Begin);
- byte[] data = new byte[digitalSignByteRange[1] + digitalSignByteRange[3]];
- pdf.Read(data, 0, (int)digitalSignByteRange[1]);
- pdf.Seek(digitalSignByteRange[2], SeekOrigin.Begin);
- pdf.Read(data, (int)digitalSignByteRange[1], (int)digitalSignByteRange[3]);
- if (cert != null)
- {
- byte[] signature = Encoding.ASCII.GetBytes(BytesToHex(MSSign(cert, data)));
- if (signature.Length > 16384)
- {
- throw new OverflowException("Signature value was too big");
- }
- pdf.Flush();
- pdf.Seek(signatureDictIndicies.contentsIndex, SeekOrigin.Begin);
- pdf.Write(signature, 0, signature.Length);
- }
- }
- #endregion // DigitalSignature
- }
- internal class RC4
- {
- private byte[] fKey;
- public void Start(byte[] key)
- {
- byte[] k = new byte[256];
- int l = key.GetLength(0);
- if (key.Length > 0 && l <= 256)
- {
- for (int i = 0; i < 256; i++)
- {
- fKey[i] = (byte)i;
- k[i] = key[i % l];
- }
- }
- byte j = 0;
- for (int i = 0; i < 256; i++)
- {
- j = (byte)(j + fKey[i] + k[i]);
- byte tmp = fKey[i];
- fKey[i] = fKey[j];
- fKey[j] = tmp;
- }
- }
- public byte[] Crypt(byte[] source)
- {
- byte i = 0;
- byte j = 0;
- int l = source.GetLength(0);
- byte[] result = new byte[l];
- for (int k = 0; k < l; k++)
- {
- i = (byte)(i + 1);
- j = (byte)(j + fKey[i]);
- byte tmp = fKey[i];
- fKey[i] = fKey[j];
- fKey[j] = tmp;
- result[k] = (byte)(source[k] ^ fKey[(byte)(fKey[i] + fKey[j])]);
- }
- return result;
- }
- public RC4()
- {
- fKey = new byte[256];
- }
- }
- }
|