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
|
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Tunnel
{
public class Keypair
{
public readonly string Public;
public readonly string Private;
private Keypair(string pub, string priv)
{
Public = pub;
Private = priv;
}
public static Keypair Generate()
{
var algoHandle = new IntPtr();
var statusCode = Win32.BCryptOpenAlgorithmProvider(ref algoHandle, Win32.BCRYPT_ECDH_ALGORITHM, null, 0);
if (statusCode > 0)
throw new Win32Exception((int)statusCode);
try
{
var curveType = Win32.BCRYPT_ECC_CURVE_25519 + Char.MinValue;
statusCode = Win32.BCryptSetProperty(algoHandle, Win32.BCRYPT_ECC_CURVE_NAME, curveType, curveType.Length * sizeof(char), 0);
if (statusCode > 0)
throw new Win32Exception((int)statusCode);
var key = new IntPtr();
statusCode = Win32.BCryptGenerateKeyPair(algoHandle, ref key, 255, 0);
if (statusCode > 0)
throw new Win32Exception((int)statusCode);
try
{
statusCode = Win32.BCryptFinalizeKeyPair(key, 0);
if (statusCode > 0)
throw new Win32Exception((int)statusCode);
var keyBlob = new Win32.KeyBlob();
int exportedKeySize = 0;
statusCode = Win32.BCryptExportKey(key, IntPtr.Zero, Win32.BCRYPT_ECCPRIVATE_BLOB, keyBlob, Marshal.SizeOf(typeof(Win32.KeyBlob)), out exportedKeySize);
if (statusCode > 0)
throw new Win32Exception((int)statusCode);
return new Keypair(Convert.ToBase64String(keyBlob.Public), Convert.ToBase64String(keyBlob.Private));
}
finally
{
Win32.BCryptDestroyKey(key);
}
}
finally
{
Win32.BCryptCloseAlgorithmProvider(algoHandle, 0);
}
}
}
}
|