-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDecryption.cs
185 lines (161 loc) · 6.68 KB
/
Decryption.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
using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using Net.Pkcs11Interop.Common;
using Net.Pkcs11Interop.HighLevelAPI;
namespace SCCrypto
{
public class Decryption
{
public const int NO_KEY_FOUND = -1;
public const int DECRYPTION_FAILED = -2;
// LinkedList filled with the Data to Encrypt
// Tuple is (subjectName,pubKeyHash,Cipher)
// A dictionary containing data to dercypt ordered by public key hash
private Dictionary<byte[], LinkedList<Tuple<string, byte[]>>> fastDataToDecrypt;
private int remaining;
private SmartCard smartCard;
public Decryption(SmartCard smartCard, List<Tuple<string, byte[], byte[]>> dataToDecrypt)
{
Tuple<string, byte[], byte[]> data;
this.smartCard = smartCard;
remaining = dataToDecrypt.Count;
fastDataToDecrypt = new Dictionary<byte[], LinkedList<Tuple<string, byte[]>>>(new ArrayEqualityCompare());
for (int i = 0; i < dataToDecrypt.Count; i++)
{
data = dataToDecrypt[i];
if (!fastDataToDecrypt.ContainsKey(data.Item2))
{
fastDataToDecrypt.Add(data.Item2, new LinkedList<Tuple<string, byte[]>>());
}
fastDataToDecrypt[data.Item2].AddLast(new Tuple<string, byte[]>(data.Item1, data.Item3));
}
}
// return remaining, cipher and decrypted data
public Tuple<int,byte[],byte[]> Do()
{
byte[] plainText, Cipher;
int selection;
Tuple<List<Certificate>,List<Slot>> certsAndSlots;
List<Certificate> certs;
List<Slot> slots;
Certificate cert;
Slot slot;
do
{
// get Available Keys
certsAndSlots = smartCard.getAvailableCertsAndSlots();
certs = certsAndSlots.Item1;
slots = certsAndSlots.Item2;
// Remove notused keys
for (int i = certs.Count - 1; i >= 0; i--)
{
cert = certs[i];
if (!fastDataToDecrypt.ContainsKey(cert.CkaSubPubKeyHash))
{
certs.RemoveAt(i);
slots.RemoveAt(i);
}
}
// Offer Keys
// if empty print users
if (certs.Count == 0)
{
// list needed Keys and wait for response
smartCard.settings.userIO.outputListAbort(getNeededKeys());
}
// Select Key
selection = OfferKeys(certs, slots);
} while (selection == -1);
cert = certs[selection];
slot = slots[selection];
Cipher = fastDataToDecrypt[cert.CkaSubPubKeyHash].Last.Value.Item2;
// DoDecryption
plainText = DoDecrypt(Cipher,cert.CkaId,slot);
//if fail return error
if (plainText == null) return new Tuple<int, byte[], byte[]>(DECRYPTION_FAILED, null, null);
// Remvoe deciphered text
//if success
remaining--;
var list = fastDataToDecrypt[cert.CkaSubPubKeyHash];
list.RemoveLast();
if (list.Count == 0) fastDataToDecrypt.Remove(cert.CkaSubPubKeyHash);
// return Encryption, PublicKey and remaining Datasets
return new Tuple<int, byte[], byte[]>(remaining, Cipher, plainText);
}
private int OfferKeys(List<Certificate> certs, List<Slot> slots)
{
TokenInfo info;
List<string> choices = new List<string>();
for (int i = 0; i < certs.Count; i++)
{
// TODO String aufarbeiten
string certStr = certs[i].Get509Certificate().SubjectDN.ToString();
string certLabel = certs[i].CkaLabel;
info = slots[i].GetTokenInfo();
string tokenInfo = info.Label + " / " + info.ManufacturerId + " / " + info.Model + " / " + info.SerialNumber + " / " + info.UtcTimeString;
choices.Add(certStr + " / " + certLabel + " / " + tokenInfo);
}
return smartCard.settings.userIO.selectFromList(choices);
}
private byte[] DoDecrypt( byte[] cipher, byte[] keyID, Slot slot)
{
byte[] result;
Session session = slot.OpenSession(SessionType.ReadWrite);
ObjectHandle keyhandle;
byte[] PW;
bool loop = true;
while (loop)
{
// read PIN, allow for break
PW = smartCard.settings.userIO.ReadPW("Please enter the PIN for the slected token!");
if (PW == null)
{
// print error
smartCard.settings.userIO.outputText("Failed reading the PIN!");
return null;
}
try
{
session.Login(CKU.CKU_USER, PW);
for (int i = 0; i < PW.Length; i++) PW[i] = 0;
loop = false;
} catch (Pkcs11Exception e)
{
switch (e.RV)
{
case CKR.CKR_PIN_INCORRECT:
smartCard.settings.userIO.outputText("Incorret PIN! Try again!");
break;
default:
smartCard.settings.userIO.outputText(String.Format("Nonrecoverable Error: 0x{0:X} !",e.RV));
session.CloseSession();
return null;
}
}
}
// get keyhandle
keyhandle = SmartCard.getKeyID(session, keyID);
if (keyhandle == null)
{
smartCard.settings.userIO.outputText("Slected Key could not be found on the token!");
return null;
}
result = session.Decrypt(new Mechanism(CKM.CKM_RSA_PKCS), keyhandle, cipher);
session.Logout();
session.CloseSession();
return result;
}
private List<string> getNeededKeys()
{
List<string> ret = new List<string>();
foreach (KeyValuePair<byte[], LinkedList<Tuple<string, byte[]>>> kp in fastDataToDecrypt)
{
// read first owner and publickeyhash
ret.Add(String.Format("{0} / {1}",kp.Value.First.Value.Item1, Convert.ToBase64String(kp.Key)));
}
return ret;
}
}
}