Skip to content

Commit 8f7791d

Browse files
committed
Moved OTP to PwEntry
1 parent ece725f commit 8f7791d

File tree

4 files changed

+146
-144
lines changed

4 files changed

+146
-144
lines changed

KPCLib.xunit/PassXYZLibTests.cs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,39 @@ public void ListItemsTests()
6868
PwGroup pg = passxyz.PxDb.RootGroup;
6969
foreach (var item in pg.Items)
7070
{
71-
Debug.WriteLine($"{item.Description}\t{item.Name}");
72-
if(!item.IsGroup)
71+
if(item.IsGroup)
7372
{
74-
if(PxDefs.IsPxEntry((PwEntry)item))
75-
{
76-
var entry = new PxEntry((PwEntry)item);
77-
if (entry.Totp == null)
78-
{
79-
entry.UpdateOtpUrl("otpauth://totp/Google%3Apxentry_test%40gmail.com?secret=JBSWY3DPEHPK3PXP&issuer=Google");
80-
var Totp = entry.Totp;
81-
Debug.WriteLine($"Token={entry.Token}");
82-
Assert.NotNull(Totp);
83-
}
84-
}
73+
Debug.WriteLine($"{item.Description}\t{item.Name}/");
8574
}
75+
else
76+
{
77+
Debug.WriteLine($"{item.Description}\t{item.Name}");
78+
}
79+
}
80+
}
81+
82+
[Fact (Skip = "test manually")]
83+
/// <summary>
84+
/// This test computes a token using a secret.
85+
/// The result can be verified at the below website:
86+
/// https://totp.danhersam.com/
87+
/// </summary>
88+
public void TokenGenerateTests()
89+
{
90+
var entry = new PwEntry();
91+
if (entry.Totp == null)
92+
{
93+
entry.UpdateOtpUrl("otpauth://totp/Google%3Apxentry_test%40gmail.com?secret=JBSWY3DPEHPK3PXP&issuer=Google");
94+
var Totp = entry.Totp;
95+
Debug.WriteLine($"Token={entry.Token}\tProgress={entry.Progress}");
96+
Assert.NotNull(Totp);
97+
}
98+
99+
int i = 0;
100+
for (i = 0; i < 30; i++)
101+
{
102+
Debug.WriteLine($"Token={entry.Token}\tProgress={entry.Progress}");
103+
System.Threading.Thread.Sleep(3000);
86104
}
87105
}
88106

KPCLib.xunit/PxEntryTests.cs

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,10 @@ namespace KPCLib.xunit
1515
public class PxEntryTests
1616
{
1717
[Fact]
18-
public void PxEntryOtpInitTests()
18+
public void PxEntryInitTests()
1919
{
20-
const string secret = "MyTestSecret";
2120
var entry = new PxEntry();
22-
if(entry.Totp == null)
23-
{
24-
entry.Totp = new PureOtp.Totp(Encoding.UTF8.GetBytes(secret));
25-
}
26-
if (entry.Token == String.Empty) { entry.Token = entry.Totp.ComputeTotp(); }
27-
var isGood = entry.Totp.VerifyTotp(entry.Token, out var timeStepMatched, VerificationWindow.RfcSpecifiedNetworkDelay);
28-
Debug.WriteLine($"Token={entry.Token}");
29-
Assert.True(isGood);
30-
}
31-
32-
[Fact]
33-
/// <summary>
34-
/// This test computes a token using a secret.
35-
/// The result can be verified at the below website:
36-
/// https://totp.danhersam.com/
37-
/// </summary>
38-
public void PxEntryTokenGenerateTests()
39-
{
40-
var entry = new PxEntry();
41-
if (entry.Totp == null)
42-
{
43-
entry.UpdateOtpUrl("otpauth://totp/Google%3Apxentry_test%40gmail.com?secret=JBSWY3DPEHPK3PXP&issuer=Google");
44-
var Totp = entry.Totp;
45-
Debug.WriteLine($"Token={entry.Token}");
46-
Assert.NotNull(Totp);
47-
}
21+
Assert.NotNull(entry);
4822
}
4923
}
5024
}

KPCLib/PassXYZLib/PxEntry.cs

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -105,108 +105,5 @@ public override string ToString()
105105

106106
return peNew;
107107
}
108-
109-
#region PxEntrySupportOTP
110-
// Update progress every 3 seconds
111-
public const int TimerStep = 3;
112-
113-
string m_TotpDescription = string.Empty;
114-
public string TotpDescription {
115-
get { return m_TotpDescription; }
116-
set { m_TotpDescription = value; }
117-
}
118-
119-
Totp m_totp = null;
120-
public Totp Totp {
121-
get
122-
{
123-
if(m_totp == null) { SetupTotp(); }
124-
return m_totp;
125-
}
126-
127-
set { m_totp = value; }
128-
}
129-
130-
void SetupTotp()
131-
{
132-
if (this.CustomData != null && this.CustomData.Exists(PxDefs.PxCustomDataOtpUrl))
133-
{
134-
var rawUrl = this.CustomData.Get(PxDefs.PxCustomDataOtpUrl);
135-
var otp = KeyUrl.FromUrl(rawUrl);
136-
if (otp is Totp totp)
137-
{
138-
var url = new Uri(rawUrl);
139-
m_TotpDescription = url.LocalPath.Substring(1);
140-
141-
Totp = totp;
142-
Token = totp.ComputeTotp();
143-
}
144-
}
145-
}
146-
147-
double m_increment = 0.1;
148-
149-
double m_progress = 0;
150-
public double Progress
151-
{
152-
get { return m_progress; }
153-
154-
set
155-
{
156-
SetProperty(ref m_progress, value, "Progress");
157-
}
158-
}
159-
160-
string m_token = string.Empty;
161-
public string Token
162-
{
163-
get
164-
{
165-
if(m_token == string.Empty) { SetupTotp(); }
166-
return m_token;
167-
}
168-
169-
set
170-
{
171-
SetProperty(ref m_token, value, "Token", () => {
172-
var remaining = Totp.RemainingSeconds();
173-
Progress = 0;
174-
if (remaining > TimerStep)
175-
{
176-
m_increment = (double)TimerStep / remaining;
177-
}
178-
179-
Debug.WriteLine($"Token is changed! RemainingSeconds={remaining}, increment={m_increment}");
180-
});
181-
}
182-
}
183-
184-
public void UpdateToken()
185-
{
186-
if(Totp != null)
187-
{
188-
Token = Totp.ComputeTotp();
189-
if (Progress <= 1)
190-
{
191-
Progress += m_increment;
192-
}
193-
}
194-
}
195-
196-
/// <summary>
197-
/// Update the OTP Url.
198-
/// If it is new, create a PxOtpUrl key in CustomData.
199-
/// Since CustomData is readonly, it can only be set at this level.
200-
/// </summary>
201-
/// <param name="url">OTP Url which cannot be <c>null</c>.</param>
202-
/// <returns>true - success, false - failure</returns>
203-
public void UpdateOtpUrl(string url)
204-
{
205-
if (url == null) { Debug.Assert(false); throw new ArgumentNullException("url"); }
206-
207-
this.CustomData.Set(PxDefs.PxCustomDataOtpUrl, url);
208-
}
209-
210-
#endregion
211108
}
212109
}

KPCLib/PwEntry.cs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ You should have received a copy of the GNU General Public License
2525
using System.Drawing;
2626
#endif
2727

28+
using PureOtp;
29+
2830
using KeePassLib.Collections;
2931
using KeePassLib.Interfaces;
3032
using KeePassLib.Security;
@@ -283,6 +285,117 @@ internal set
283285
public EventHandler<ObjectTouchedEventArgs> Touched;
284286

285287
#if KPCLib
288+
289+
#region PxEntrySupportOTP
290+
// Update progress every 3 seconds
291+
public const int TimerStep = 3;
292+
293+
string m_TotpDescription = string.Empty;
294+
public string TotpDescription
295+
{
296+
get { return m_TotpDescription; }
297+
set { m_TotpDescription = value; }
298+
}
299+
300+
Totp m_totp = null;
301+
public Totp Totp
302+
{
303+
get
304+
{
305+
if (m_totp == null) { SetupTotp(); }
306+
return m_totp;
307+
}
308+
309+
set { m_totp = value; }
310+
}
311+
312+
void SetupTotp()
313+
{
314+
if (this.CustomData != null && this.CustomData.Exists(PassXYZLib.PxDefs.PxCustomDataOtpUrl))
315+
{
316+
var rawUrl = this.CustomData.Get(PassXYZLib.PxDefs.PxCustomDataOtpUrl);
317+
var otp = KeyUrl.FromUrl(rawUrl);
318+
if (otp is Totp totp)
319+
{
320+
var url = new Uri(rawUrl);
321+
m_TotpDescription = url.LocalPath.Substring(1);
322+
323+
Totp = totp;
324+
Token = totp.ComputeTotp();
325+
}
326+
}
327+
}
328+
329+
double m_increment = 0.1;
330+
331+
double m_progress = 0;
332+
public double Progress
333+
{
334+
get
335+
{
336+
if (m_totp == null) { SetupTotp(); }
337+
return m_progress;
338+
}
339+
340+
set
341+
{
342+
SetProperty(ref m_progress, value, "Progress");
343+
}
344+
}
345+
346+
string m_token = string.Empty;
347+
public string Token
348+
{
349+
get
350+
{
351+
if (m_token == string.Empty) { SetupTotp(); }
352+
UpdateToken();
353+
return m_token;
354+
}
355+
356+
set
357+
{
358+
SetProperty(ref m_token, value, "Token", () => {
359+
var remaining = Totp.RemainingSeconds();
360+
Progress = 0;
361+
if (remaining > TimerStep)
362+
{
363+
m_increment = (double)TimerStep / remaining;
364+
}
365+
366+
Debug.WriteLine($"New Token={Token} RemainingSeconds={remaining}, increment={m_increment}");
367+
});
368+
}
369+
}
370+
371+
public void UpdateToken()
372+
{
373+
if (Totp != null)
374+
{
375+
Token = Totp.ComputeTotp();
376+
if (Progress <= 1)
377+
{
378+
Progress += m_increment;
379+
}
380+
}
381+
}
382+
383+
/// <summary>
384+
/// Update the OTP Url.
385+
/// If it is new, create a PxOtpUrl key in CustomData.
386+
/// Since CustomData is readonly, it can only be set at this level.
387+
/// </summary>
388+
/// <param name="url">OTP Url which cannot be <c>null</c>.</param>
389+
/// <returns>true - success, false - failure</returns>
390+
public void UpdateOtpUrl(string url)
391+
{
392+
if (url == null) { Debug.Assert(false); throw new ArgumentNullException("url"); }
393+
394+
this.CustomData.Set(PassXYZLib.PxDefs.PxCustomDataOtpUrl, url);
395+
}
396+
397+
#endregion
398+
286399
public override string Description
287400
{
288401
get {

0 commit comments

Comments
 (0)