-
-
Notifications
You must be signed in to change notification settings - Fork 492
/
Copy pathPasscodeService.cs
205 lines (166 loc) · 5.8 KB
/
PasscodeService.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
//
// Copyright Fela Ameghino 2015-2025
//
// Distributed under the GNU General Public License v3.0. (See accompanying
// file LICENSE or copy at https://www.gnu.org/licenses/gpl-3.0.txt)
//
using System;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using Telegram.Common;
using Telegram.Navigation;
using Telegram.Services.Settings;
using Telegram.Services.Updates;
using Telegram.Views;
using Windows.Security.Cryptography;
namespace Telegram.Services
{
public interface IPasscodeService
{
int RetryIn { get; }
bool IsEnabled { get; }
bool IsSimple { get; }
bool IsLocked { get; }
bool IsBiometricsEnabled { get; set; }
DateTime CloseTime { get; set; }
int AutolockTimeout { get; set; }
bool IsLockscreenRequired { get; }
void Lock(bool biometrics);
void Unlock();
bool TryUnlock(string passcode);
void Set(string passcode, bool simple, int timeout);
void Reset();
}
public partial class PasscodeService : IPasscodeService
{
private readonly PasscodeLockSettings _settingsService;
private double _retryIn;
public PasscodeService(PasscodeLockSettings settingsService)
{
_settingsService = settingsService;
if (_settingsService.RetryCount >= 3)
{
_retryIn = 5000 + (5000 * (Math.Min(_settingsService.RetryCount, 8) - 3));
}
InactivityHelper.Detected += OnInactivityDetected;
}
private void OnInactivityDetected(object sender, EventArgs e)
{
Lock(false);
}
public int RetryIn => (int)Math.Ceiling(UpdateRetryIn() / 1000);
public bool IsEnabled => _settingsService.Hash.Length > 0;
public bool IsSimple => _settingsService.IsSimple;
public bool IsLocked => _settingsService.IsLocked;
public bool IsBiometricsEnabled
{
get => _settingsService.IsHelloEnabled;
set => _settingsService.IsHelloEnabled = value;
}
public DateTime CloseTime
{
get => _settingsService.CloseTime;
set => _settingsService.CloseTime = value;
}
public int AutolockTimeout
{
get => _settingsService.AutolockTimeout;
set => _settingsService.AutolockTimeout = value;
}
public bool IsLockscreenRequired =>
IsEnabled && ((AutolockTimeout > 0 && CloseTime < DateTime.MaxValue && CloseTime > DateTime.UtcNow.AddSeconds(-AutolockTimeout)) || IsLocked);
public void Lock(bool biometrics)
{
if (IsEnabled)
{
_settingsService.IsLocked = true;
_settingsService.CloseTime = DateTime.MaxValue;
Publish(true);
WindowContext.ForEach(window => window.Lock(biometrics));
}
}
public void Unlock()
{
_settingsService.IsLocked = false;
_settingsService.CloseTime = DateTime.MaxValue;
_settingsService.RetryCount = 0;
_settingsService.RetryTime = DateTime.MaxValue;
_retryIn = 0;
Publish(true);
WindowContext.ForEach(window => window.Unlock());
}
public void Set(string passcode, bool simple, int timeout)
{
var salt = CryptographicBuffer.GenerateRandom(256).ToArray();
var data = Utils.ComputeSHA1(Utils.Combine(salt, Encoding.UTF8.GetBytes(passcode), salt));
_settingsService.Hash = data;
_settingsService.Salt = salt;
_settingsService.IsSimple = simple;
_settingsService.AutolockTimeout = timeout;
_settingsService.CloseTime = DateTime.MaxValue;
_settingsService.RetryCount = 0;
_settingsService.RetryTime = DateTime.MaxValue;
_settingsService.IsLocked = false;
Publish(true);
}
public void Reset()
{
_retryIn = 0;
_settingsService.Clear();
Publish(false);
}
private void Publish(bool enabled)
{
var update = new UpdatePasscodeLock(enabled);
foreach (var aggregator in TypeResolver.Current.ResolveAll<IEventAggregator>())
{
aggregator.Publish(update);
}
}
public bool CheckSimple(string passcode)
{
if (passcode != null && passcode.Length == 4)
{
return passcode.All(x => x is >= '0' and <= '9');
}
return false;
}
public bool TryUnlock(string passcode)
{
if (_retryIn > 0)
{
return false;
}
var unlock = Utils.ByteArraysEqual(Utils.ComputeHash(_settingsService.Salt, Encoding.UTF8.GetBytes(passcode)), _settingsService.Hash);
if (unlock)
{
Unlock();
}
else
{
_settingsService.RetryCount++;
if (_settingsService.RetryCount >= 3)
{
_settingsService.RetryTime = DateTime.UtcNow;
_retryIn = 5000 + (5000 * (Math.Min(_settingsService.RetryCount, 8) - 3));
}
}
return unlock;
}
public double UpdateRetryIn()
{
var time = DateTime.UtcNow;
if (time > _settingsService.RetryTime)
{
_retryIn -= (time - _settingsService.RetryTime).TotalMilliseconds;
if (_retryIn < 0)
{
_retryIn = 0;
}
}
_settingsService.RetryTime = time;
return _retryIn;
}
}
}