This repository was archived by the owner on Dec 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathKeyGeneration.cs
More file actions
96 lines (90 loc) · 3.67 KB
/
KeyGeneration.cs
File metadata and controls
96 lines (90 loc) · 3.67 KB
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
using System;
using System.Security.Cryptography;
using System.Linq;
namespace OtpSharp
{
/// <summary>
/// Helpers to work with keys
/// </summary>
public static class KeyGeneration
{
/// <summary>
/// Generates a random key in accordance with the RFC recommened length for each algorithm
/// </summary>
/// <param name="length">Key length</param>
/// <returns>The generated key</returns>
public static byte[] GenerateRandomKey(int length)
{
byte[] key = new byte[length];
#if NET35
var rnd = System.Security.Cryptography.RandomNumberGenerator.Create();
#else
using (var rnd = System.Security.Cryptography.RandomNumberGenerator.Create())
{
#endif
rnd.GetBytes(key);
return key;
#if NET35
#else
}
#endif
}
/// <summary>
/// Generates a random key in accordance with the RFC recommened length for each algorithm
/// </summary>
/// <param name="mode">HashMode</param>
/// <returns>Key</returns>
public static byte[] GenerateRandomKey(OtpHashMode mode = OtpHashMode.Sha1)
{
return GenerateRandomKey(LengthForMode(mode));
}
/// <summary>
/// Uses the procedure defined in RFC 4226 section 7.5 to derive a key from the master key
/// </summary>
/// <param name="masterKey">The master key from which to derive a device specific key</param>
/// <param name="publicIdentifier">The public identifier that is unique to the authenticating device</param>
/// <param name="mode">The hash mode to use. This will determine the resulting key lenght. The default is sha-1 (as per the RFC) which is 20 bytes</param>
/// <returns>Derived key</returns>
public static byte[] DeriveKeyFromMaster(IKeyProvider masterKey, byte[] publicIdentifier, OtpHashMode mode = OtpHashMode.Sha1)
{
if (masterKey == null)
throw new ArgumentNullException("masterKey");
return masterKey.ComputeHmac(mode, publicIdentifier);
}
/// <summary>
/// Uses the procedure defined in RFC 4226 section 7.5 to derive a key from the master key
/// </summary>
/// <param name="masterKey">The master key from which to derive a device specific key</param>
/// <param name="serialNumber">A serial number that is unique to the authenticating device</param>
/// <param name="mode">The hash mode to use. This will determine the resulting key lenght. The default is sha-1 (as per the RFC) which is 20 bytes</param>
/// <returns>Derived key</returns>
public static byte[] DeriveKeyFromMaster(IKeyProvider masterKey, int serialNumber, OtpHashMode mode = OtpHashMode.Sha1)
{
return DeriveKeyFromMaster(masterKey, KeyUtilities.GetBigEndianBytes(serialNumber), mode);
}
private static HashAlgorithm GetHashAlgorithmForMode(OtpHashMode mode)
{
switch (mode)
{
case OtpHashMode.Sha256:
return SHA256.Create();
case OtpHashMode.Sha512:
return SHA512.Create();
default: //case OtpHashMode.Sha1:
return SHA1.Create();
}
}
private static int LengthForMode(OtpHashMode mode)
{
switch (mode)
{
case OtpHashMode.Sha256:
return 32;
case OtpHashMode.Sha512:
return 64;
default: //case OtpHashMode.Sha1:
return 20;
}
}
}
}