aboutsummaryrefslogtreecommitdiff
path: root/Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2023-10-12 22:09:49 +0800
committerchai <215380520@qq.com>2023-10-12 22:09:49 +0800
commit8d2a2cd5de40e2b94ef5007c32832ed9a063dc40 (patch)
treea63dfbe815855925c9fb8f2804bd6ccfeffbd2eb /Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs
parentdd0c5d50e377d9be1e728463670908a6c9d2c14f (diff)
+hazel-networking
Diffstat (limited to 'Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs')
-rw-r--r--Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs84
1 files changed, 84 insertions, 0 deletions
diff --git a/Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs b/Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs
new file mode 100644
index 0000000..1fa7f17
--- /dev/null
+++ b/Tools/Hazel-Networking/Hazel/Dtls/PrfSha256.cs
@@ -0,0 +1,84 @@
+using System.Text;
+using System.Security.Cryptography;
+
+namespace Hazel.Dtls
+{
+ /// <summary>
+ /// Common Psuedorandom Function labels for TLS
+ /// </summary>
+ public struct PrfLabel
+ {
+ public static readonly ByteSpan MASTER_SECRET = LabelToBytes("master secert");
+ public static readonly ByteSpan KEY_EXPANSION = LabelToBytes("key expansion");
+ public static readonly ByteSpan CLIENT_FINISHED = LabelToBytes("client finished");
+ public static readonly ByteSpan SERVER_FINISHED = LabelToBytes("server finished");
+
+ /// <summary>
+ /// Convert a text label to a byte sequence
+ /// </summary>
+ public static ByteSpan LabelToBytes(string label)
+ {
+ return Encoding.ASCII.GetBytes(label);
+ }
+ }
+
+ /// <summary>
+ /// The P_SHA256 Psuedorandom Function
+ /// </summary>
+ public struct PrfSha256
+ {
+ /// <summary>
+ /// Expand a secret key
+ /// </summary>
+ /// <param name="output">Output span. Length determines how much data to generate</param>
+ /// <param name="key">Original key to expand</param>
+ /// <param name="label">Label (treated as a salt)</param>
+ /// <param name="initialSeed">Seed for expansion (treated as a salt)</param>
+ public static void ExpandSecret(ByteSpan output, ByteSpan key, string label, ByteSpan initialSeed)
+ {
+ ExpandSecret(output, key, PrfLabel.LabelToBytes(label), initialSeed);
+ }
+
+ /// <summary>
+ /// Expand a secret key
+ /// </summary>
+ /// <param name="output">Output span. Length determines how much data to generate</param>
+ /// <param name="key">Original key to expand</param>
+ /// <param name="label">Label (treated as a salt)</param>
+ /// <param name="initialSeed">Seed for expansion (treated as a salt)</param>
+ public static void ExpandSecret(ByteSpan output, ByteSpan key, ByteSpan label, ByteSpan initialSeed)
+ {
+ ByteSpan writer = output;
+
+ byte[] roundSeed = new byte[label.Length + initialSeed.Length];
+ label.CopyTo(roundSeed);
+ initialSeed.CopyTo(roundSeed, label.Length);
+
+ byte[] hashA = roundSeed;
+
+ using (HMACSHA256 hmac = new HMACSHA256(key.ToArray()))
+ {
+ byte[] input = new byte[hmac.OutputBlockSize + roundSeed.Length];
+ new ByteSpan(roundSeed).CopyTo(input, hmac.OutputBlockSize);
+
+ while (writer.Length > 0)
+ {
+ // Update hashA
+ hashA = hmac.ComputeHash(hashA);
+
+ // generate hash input
+ new ByteSpan(hashA).CopyTo(input);
+
+ ByteSpan roundOutput = hmac.ComputeHash(input);
+ if (roundOutput.Length > writer.Length)
+ {
+ roundOutput = roundOutput.Slice(0, writer.Length);
+ }
+
+ roundOutput.CopyTo(writer);
+ writer = writer.Slice(roundOutput.Length);
+ }
+ }
+ }
+ }
+}