-
Notifications
You must be signed in to change notification settings - Fork 3
/
MainForm.cs
379 lines (325 loc) · 12.9 KB
/
MainForm.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
using DevScope.CartaoDeCidadao;
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Collections.Generic;
using System.Net;
using iTextSharp;
using iTextSharp.text.pdf;
using Org.BouncyCastle.Cms;
using System.Collections;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.X509;
using System.Security;
namespace pdfSigner
{
public partial class MainForm : Form
{
private SCWatcher _scWatcher = null;
private delegate void OnShowCitizenInfo();
private delegate void OnHideCitizenInfo();
private List<string> filesToSign = new List<string>();
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fd = new OpenFileDialog();
fd.Multiselect = true; // allow multiple files
fd.Filter = "PDF files (*.pdf)|*.pdf";
fd.ShowDialog();
string[] tempPaths = fd.FileNames;
foreach (string path in tempPaths)
{
lbFilesToSign.Items.Add(path);
}
btnRemoveFile.Enabled = true;
btnSignNow.Enabled = true;
}
private void Form1_Shown(object sender, EventArgs e)
{
// Init Card Reader
try
{
lblStatus.Text = "initializing the card reader...";
ScWatcher_Init();
lblStatus.Text += " OK.";
}
catch
{
lblStatus.Text = "Erro ao iniciar o leitor de cartões!";
}
}
#region CartaoDeCidadao Code
/// <summary>
/// Read the Citizen ID data and sets the class properties
/// </summary>
public void CC_Read_Info()
{
// Public Citizen Identity Data
Id citizen = EIDPT.GetID();
txtIdNumber.Text = citizen.BI;
txtFullName.Text = citizen.FirstName + " " + citizen.Name;
}
/// <summary>
/// Only Reads the photo, set's the class properties and returns the photo
/// </summary>
/// <returns>Citizen photo</returns>
public Image CC_Get_Photo()
{
MemoryStream ms = null;
try
{
Picture picture = EIDPT.GetPicture();
ms = new MemoryStream(picture.Bytes, 0, picture.BytesLength, false);
// JPEG2000 Support provided by CSJ2K (http://csj2k.codeplex.com/)
Image tempImage = CSJ2K.J2kImage.FromStream(ms);
return tempImage;
}
finally
{
ms.Close();
}
}
#endregion
#region Card Reader Code
// Manage
private void ScWatcher_Init()
{
this._scWatcher = SCWatcher.GetInstance(); // Daemon starts when instantiated
this._scWatcher.CardInserted += new SCWatcher.CardInsertedHandler(ScWatcher_CardInserted);
this._scWatcher.CardRemoved += new SCWatcher.CardRemovedHandler(ScWatcher_CardRemoved);
this._scWatcher.ReaderInserted += new SCWatcher.ReaderInsertedHandler(ScWatcher_ReaderInserted);
this._scWatcher.ReaderRemoved += new SCWatcher.ReaderRemovedHandler(ScWatcher_ReaderRemoved);
}
/// <summary>
///
/// </summary>
private void ScWatcher_Stop()
{
if (this._scWatcher != null)
this._scWatcher.Stop();
}
// Events(only for UI update)
/// <summary>
///
/// </summary>
/// <param name="readerName"></param>
/// <param name="cardName"></param>
void ScWatcher_CardInserted(string readerName, string cardName)
{
try
{
EIDPT.Init(readerName);
EIDPT.SetSODChecking(false);
}
catch
{
EIDPT.Exit(ExitMode.LEAVE_CARD);
return;
}
lblStatus.Text = "Card Inserted.";
ShowCitizenInfo();
}
/// <summary>
///
/// </summary>
/// <param name="readerName"></param>
void ScWatcher_CardRemoved(string readerName)
{
EIDPT.Exit(ExitMode.LEAVE_CARD);
lblStatus.Text = "Card Removed.";
HideCitizenInfo();
}
/// <summary>
///
/// </summary>
/// <param name="readerName"></param>
void ScWatcher_ReaderInserted(string readerName)
{
lblStatus.Text = "Card Reader Inserted: " + readerName;
}
/// <summary>
///
/// </summary>
/// <param name="readerName"></param>
void ScWatcher_ReaderRemoved(string readerName)
{
EIDPT.Exit(ExitMode.LEAVE_CARD);
lblStatus.Text = "Card Reader Removed: " + readerName;
}
/// <summary>
///
/// </summary>
/// <param name="errorCode"></param>
/// <param name="errorMessage"></param>
void ScWatcher_OnError(int errorCode, string errorMessage)
{
string messageBoxText = errorMessage;
string caption = "Error " + errorCode;
MessageBox.Show(messageBoxText, caption);
HideCitizenInfo();
}
/* http://stackoverflow.com/questions/2367718/automating-the-invokerequired-code-pattern */
private void ShowCitizenInfo()
{
if (this.InvokeRequired)
{
Invoke(new OnShowCitizenInfo(ShowCitizenInfo));
}
else
{
// Read CC Info
CC_Read_Info();
this.pbPhoto.Image = CC_Get_Photo();
}
}
private void HideCitizenInfo()
{
if (this.InvokeRequired)
{
Invoke(new OnHideCitizenInfo(HideCitizenInfo));
}
else
{
txtIdNumber.Text = "";
txtFullName.Text = "";
this.pbPhoto.Image = null;
}
}
#endregion
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// free the card reader
ScWatcher_Stop();
}
private void btnSign_Click(object sender, EventArgs e)
{
try
{
// Set wait cursor
this.Cursor = Cursors.WaitCursor;
Application.DoEvents();
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
// Get signature certificate for current citizen
X509Certificate2Collection certsToShow = store.Certificates.Find(X509FindType.FindBySubjectName, "Assinatura", false);
X509Certificate2Collection certs = certsToShow.Find(X509FindType.FindBySubjectName, "BI" + txtIdNumber.Text, false);
if (certs.Count <= 0)
{
MessageBox.Show("Certificate not found.",
"Error!",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
var cert = certs[0];
if (cert != null)
{
// Sign every file found on listbox
foreach (string file in lbFilesToSign.Items)
{
try
{
// Get source folder and source filename
string sourceFolder = Path.GetDirectoryName(file);
string filename = Path.GetFileName(file);
lblStatus.Text = "A assinar o file " + filename;
// Create "Signed" sub-folder if doesn't exists
string signedFolder = Path.Combine(sourceFolder, "Signed");
if (!Directory.Exists(signedFolder)) Directory.CreateDirectory(signedFolder);
// Generate destination path for signed file
var signedFile = signedFolder + "/" + filename;
// Convert X509Certificate2 to X509Certificate
X509CertificateParser certParse = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { certParse.ReadCertificate(cert.RawData) };
// Reader and stamper
PdfReader pdfReader = new PdfReader(file);
Stream signedPdf = new FileStream(signedFile, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', null, cbMultiSign.Checked);
// Appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SignatureCreator = "PDF Signer 1.0";
if (txtReason.Text != "") appearance.Reason = txtReason.Text;
if (txtLocation.Text != "") appearance.Location = txtLocation.Text;
// Timestamp
TSAClientBouncyCastle tsc = null;
if (cbSignWithTSA.Checked == true)
{
tsc = new TSAClientBouncyCastle("http://ts.cartaodecidadao.pt/tsa/server", "", "");
}
// Digital signature
X509Certificate2Signature externalSignature = new X509Certificate2Signature(cert, "SHA-1");
MakeSignature.SignDetached(appearance, externalSignature, chain, null, null, tsc, 0, CryptoStandard.CMS);
stamper.Close();
}
catch (System.IO.IOException)
{
MessageBox.Show("File not found",
"Error!",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
}
// Remove all files from listbox
lbFilesToSign.Items.Clear();
btnRemoveFile.Enabled = false;
btnSignNow.Enabled = false;
MessageBox.Show("You have successfully signed the document(s)", "Success!");
}
else
{
MessageBox.Show("Certificate not found.",
"Error!",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
return;
}
}
catch (System.Security.Cryptography.CryptographicException)
{
}
catch (System.Net.WebException)
{
MessageBox.Show("You must have an internet connection to use timestamp server.",
"Error!",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
catch (Exception)
{
MessageBox.Show("Oops.. Something wrong.",
"Error!",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
finally
{
// Set default cursor
this.Cursor = Cursors.Default;
if (lblStatus.Text.Contains("A assinar o file"))
{
lblStatus.Text = "Card Inserted.";
}
}
}
private void btnRemoveFile_Click(object sender, EventArgs e)
{
if (lbFilesToSign.SelectedIndex >= 0)
{
lbFilesToSign.Items.Remove(lbFilesToSign.SelectedItem);
}
if (lbFilesToSign.Items.Count == 0)
{
btnRemoveFile.Enabled = false;
btnSignNow.Enabled = false;
}
}
}
}