-
Notifications
You must be signed in to change notification settings - Fork 6
/
Driver License Tests.cs
348 lines (294 loc) · 15.3 KB
/
Driver License Tests.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
// ReSharper disable PossibleNullReferenceException
// ReSharper disable CheckNamespace
// ReSharper disable StringLiteralTypo
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using IntegrationTests.Framework;
using IntegrationTests.Framework.Fixtures;
using Telegram.Bot;
using Telegram.Bot.Passport;
using Telegram.Bot.Passport.Request;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.Passport;
using Telegram.Bot.Types.ReplyMarkups;
using Xunit;
using Xunit.Abstractions;
namespace IntegrationTests
{
[Collection("Driver license")]
[TestCaseOrderer(Constants.TestCaseOrderer, Constants.AssemblyName)]
public class DriverLicenseTests : IClassFixture<EntityFixture<Update>>
{
private ITelegramBotClient BotClient => _fixture.BotClient;
private readonly TestsFixture _fixture;
private readonly EntityFixture<Update> _classFixture;
private readonly ITestOutputHelper _output;
public DriverLicenseTests(TestsFixture fixture, EntityFixture<Update> classFixture, ITestOutputHelper output)
{
_fixture = fixture;
_classFixture = classFixture;
_output = output;
}
[OrderedFact("Should generate passport authorization request link")]
public async Task Should_Generate_Auth_Link()
{
const string publicKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0VElWoQA2SK1csG2/sY/\n" +
"wlssO1bjXRx+t+JlIgS6jLPCefyCAcZBv7ElcSPJQIPEXNwN2XdnTc2wEIjZ8bTg\n" +
"BlBqXppj471bJeX8Mi2uAxAqOUDuvGuqth+mq7DMqol3MNH5P9FO6li7nZxI1FX3\n" +
"9u2r/4H4PXRiWx13gsVQRL6Clq2jcXFHc9CvNaCQEJX95jgQFAybal216EwlnnVV\n" +
"giT/TNsfFjW41XJZsHUny9k+dAfyPzqAk54cgrvjgAHJayDWjapq90Fm/+e/DVQ6\n" +
"BHGkV0POQMkkBrvvhAIQu222j+03frm9b2yZrhX/qS01lyjW4VaQytGV0wlewV6B\n" +
"FwIDAQAB\n" +
"-----END PUBLIC KEY-----";
PassportScope scope = new PassportScope(new[]
{
new PassportScopeElementOne(PassportEnums.Scope.DriverLicense)
{
Selfie = true,
Translation = true,
},
});
AuthorizationRequestParameters authReq = new AuthorizationRequestParameters(
botId: _fixture.BotUser.Id,
publicKey: publicKey,
nonce: "Test nonce for driver license",
scope: scope
);
await BotClient.SendTextMessageAsync(
_fixture.SupergroupChat,
"Share your *driver license* in addition to *a selfie with it* and *a translation scan* " +
"with bot using Telegram Passport.\n\n" +
"1. Click inline button\n" +
"2. Open link in browser to so it redirects you to Telegram Passport\n" +
"3. Authorize bot to access the info",
ParseMode.Markdown,
replyMarkup: (InlineKeyboardMarkup) InlineKeyboardButton.WithUrl(
"Share via Passport",
$"https://telegrambots.github.io/Telegram.Bot.Extensions.Passport/redirect.html?{authReq.Query}"
)
);
Update passportUpdate = await _fixture.UpdateReceiver.GetPassportUpdate();
_classFixture.Entity = passportUpdate;
}
[OrderedFact("Should validate driver license values in the Passport massage")]
public void Should_Validate_Passport_Update()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
EncryptedPassportElement encryptedElement = Assert.Single(passportData.Data);
Assert.NotNull(encryptedElement);
Assert.Equal("driver_license", encryptedElement.Type);
Assert.Equal(PassportEnums.Scope.DriverLicense, encryptedElement.Type);
Assert.NotEmpty(encryptedElement.Data);
Assert.NotEmpty(encryptedElement.Hash);
Assert.NotNull(encryptedElement.FrontSide);
Assert.NotEmpty(encryptedElement.FrontSide.FileId);
Assert.InRange(encryptedElement.FrontSide.FileSize, 1_000, 50_000_000);
Assert.NotNull(encryptedElement.ReverseSide);
Assert.NotEmpty(encryptedElement.ReverseSide.FileId);
Assert.InRange(encryptedElement.ReverseSide.FileSize, 1_000, 50_000_000);
Assert.NotNull(encryptedElement.Selfie);
Assert.NotEmpty(encryptedElement.Selfie.FileId);
Assert.InRange(encryptedElement.Selfie.FileSize, 1_000, 50_000_000);
Assert.NotNull(encryptedElement.Translation);
Assert.NotEmpty(encryptedElement.Translation);
Assert.All(encryptedElement.Translation, Assert.NotNull);
Assert.All(
encryptedElement.Translation,
translation => Assert.NotEmpty(translation.FileId)
);
Assert.All(
encryptedElement.Translation,
translation => Assert.InRange(translation.FileSize, 1_000, 50_000_000)
);
Assert.NotNull(passportData.Credentials);
Assert.NotEmpty(passportData.Credentials.Data);
Assert.NotEmpty(passportData.Credentials.Hash);
Assert.NotEmpty(passportData.Credentials.Secret);
}
[OrderedFact("Should decrypt and validate credentials")]
public void Should_Decrypt_Credentials()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
EncryptedPassportElement element = passportData.Data.Single();
RSA key = EncryptionKey.ReadAsRsa();
IDecrypter decrypter = new Decrypter();
Credentials credentials = decrypter.DecryptCredentials(passportData.Credentials, key);
Assert.NotNull(credentials);
Assert.Equal("Test nonce for driver license", credentials.Nonce);
Assert.NotNull(credentials.SecureData);
// decryption of document data in 'driver_license' element requires accompanying DataCredentials
Assert.NotNull(credentials.SecureData.DriverLicense);
Assert.NotNull(credentials.SecureData.DriverLicense.Data);
Assert.NotEmpty(credentials.SecureData.DriverLicense.Data.Secret);
Assert.NotEmpty(credentials.SecureData.DriverLicense.Data.DataHash);
// decryption of front side file in 'driver_license' element requires accompanying FileCredentials
Assert.NotNull(credentials.SecureData.DriverLicense.FrontSide);
Assert.NotEmpty(credentials.SecureData.DriverLicense.FrontSide.Secret);
Assert.NotEmpty(credentials.SecureData.DriverLicense.FrontSide.FileHash);
// decryption of optional selfie file in 'driver_license' element requires accompanying FileCredentials
Assert.NotNull(credentials.SecureData.DriverLicense.Selfie);
Assert.NotEmpty(credentials.SecureData.DriverLicense.Selfie.Secret);
Assert.NotEmpty(credentials.SecureData.DriverLicense.Selfie.FileHash);
// decryption of optional translation file in 'driver_license' element requires accompanying FileCredentials
Assert.Equal(
element.Translation.Length,
credentials.SecureData.DriverLicense.Translation.Length
);
}
[OrderedFact("Should decrypt document data of 'driver_license' element")]
public void Should_Decrypt_Document_Data()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
EncryptedPassportElement element = passportData.Data.Single();
RSA key = EncryptionKey.ReadAsRsa();
IDecrypter decrypter = new Decrypter();
Credentials credentials = decrypter.DecryptCredentials(passportData.Credentials, key);
IdDocumentData licenseDoc = decrypter.DecryptData<IdDocumentData>(
encryptedData: element.Data,
dataCredentials: credentials.SecureData.DriverLicense.Data
);
Assert.NotEmpty(licenseDoc.DocumentNo);
if (string.IsNullOrEmpty(licenseDoc.ExpiryDate))
{
Assert.Null(licenseDoc.Expiry);
}
else
{
Assert.NotNull(licenseDoc.Expiry);
}
}
[OrderedFact("Should decrypt front side photo file of 'driver_license' element")]
public async Task Should_Decrypt_Front_Side_File()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
RSA key = EncryptionKey.ReadAsRsa();
EncryptedPassportElement element = passportData.Data.Single();
IDecrypter decrypter = new Decrypter();
Credentials credentials = decrypter.DecryptCredentials(passportData.Credentials, key);
File encryptedFileInfo;
string decryptedFilePath = System.IO.Path.GetTempFileName();
using (System.IO.Stream decryptedFile = System.IO.File.OpenWrite(decryptedFilePath))
{
encryptedFileInfo = await BotClient.DownloadAndDecryptPassportFileAsync(
element.FrontSide,
credentials.SecureData.DriverLicense.FrontSide,
decryptedFile
);
}
_output.WriteLine("Front side JPEG file is written to \"{0}\".", decryptedFilePath);
Assert.NotEmpty(encryptedFileInfo.FilePath);
Assert.NotEmpty(encryptedFileInfo.FileId);
Assert.InRange(encryptedFileInfo.FileSize, 1_000, 50_000_000);
}
[OrderedFact("Should decrypt reverse side photo file of 'driver_license' element")]
public async Task Should_Decrypt_Reverse_Side_File()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
RSA key = EncryptionKey.ReadAsRsa();
EncryptedPassportElement element = passportData.Data.Single();
IDecrypter decrypter = new Decrypter();
Credentials credentials = decrypter.DecryptCredentials(passportData.Credentials, key);
File encryptedFileInfo;
string decryptedFilePath = System.IO.Path.GetTempFileName();
using (System.IO.Stream
encryptedContent = new System.IO.MemoryStream(element.ReverseSide.FileSize),
decryptedFile = System.IO.File.OpenWrite(decryptedFilePath)
)
{
encryptedFileInfo = await BotClient.GetInfoAndDownloadFileAsync(
element.ReverseSide.FileId,
encryptedContent
);
encryptedContent.Position = 0;
await decrypter.DecryptFileAsync(
encryptedContent,
credentials.SecureData.DriverLicense.ReverseSide,
decryptedFile
);
}
_output.WriteLine("Reverse side JPEG file is written to \"{0}\".", decryptedFilePath);
Assert.NotEmpty(encryptedFileInfo.FilePath);
Assert.NotEmpty(encryptedFileInfo.FileId);
Assert.InRange(encryptedFileInfo.FileSize, 1_000, 50_000_000);
}
[OrderedFact("Should decrypt selfie photo file of 'driver_license' element and send it to chat")]
public async Task Should_Decrypt_Selfie_File()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
RSA key = EncryptionKey.ReadAsRsa();
EncryptedPassportElement element = passportData.Data.Single();
IDecrypter decrypter = new Decrypter();
Credentials credentials = decrypter.DecryptCredentials(passportData.Credentials, key);
byte[] encryptedContent;
{
File encryptedFileInfo = await BotClient.GetFileAsync(element.Selfie.FileId);
Assert.NotEmpty(encryptedFileInfo.FilePath);
Assert.NotEmpty(encryptedFileInfo.FileId);
Assert.InRange(encryptedFileInfo.FileSize, 1_000, 50_000_000);
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(encryptedFileInfo.FileSize))
{
await BotClient.DownloadFileAsync(encryptedFileInfo.FilePath, stream);
encryptedContent = stream.ToArray();
}
}
byte[] selfieContent = decrypter.DecryptFile(
encryptedContent,
credentials.SecureData.DriverLicense.Selfie
);
Assert.NotEmpty(selfieContent);
using (System.IO.Stream stream = new System.IO.MemoryStream(selfieContent))
{
await BotClient.SendPhotoAsync(
_fixture.SupergroupChat,
stream,
"selfie with driver license",
replyToMessageId: update.Message.MessageId
);
}
}
[OrderedFact("Should decrypt translation photo files of 'driver_license' element")]
public async Task Should_Decrypt_Translation_File()
{
Update update = _classFixture.Entity;
PassportData passportData = update.Message.PassportData;
RSA key = EncryptionKey.ReadAsRsa();
EncryptedPassportElement element = passportData.Data.Single();
IDecrypter decrypter = new Decrypter();
Credentials credentials = decrypter.DecryptCredentials(passportData.Credentials, key);
for (int i = 0; i < element.Translation.Length; i++)
{
PassportFile passportFile = element.Translation[i];
FileCredentials fileCredentials = credentials.SecureData.DriverLicense.Translation[i];
byte[] encryptedContent;
{
File encryptedFileInfo = await BotClient.GetFileAsync(passportFile.FileId);
Assert.NotEmpty(encryptedFileInfo.FilePath);
Assert.NotEmpty(encryptedFileInfo.FileId);
Assert.InRange(encryptedFileInfo.FileSize, 1_000, 50_000_000);
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(encryptedFileInfo.FileSize))
{
await BotClient.DownloadFileAsync(encryptedFileInfo.FilePath, stream);
encryptedContent = stream.ToArray();
}
}
byte[] translationContent = decrypter.DecryptFile(
encryptedContent,
fileCredentials
);
Assert.NotEmpty(translationContent);
string decryptedFilePath = System.IO.Path.GetTempFileName();
await System.IO.File.WriteAllBytesAsync(decryptedFilePath, translationContent);
_output.WriteLine("Translation JPEG file is written to \"{0}\".", decryptedFilePath);
}
}
}
}