Skip to content

Commit 1ccd933

Browse files
authored
Merge pull request #2 from ABouveron/test_api_keygen
API implementation
2 parents 23749a0 + 339bf2b commit 1ccd933

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1033
-64
lines changed

.env

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
KEYGEN_ACCOUNT_ID=
2+
KEYGEN_ACCOUNT_ID_LOCALHOST=
3+
KEYGEN_ACCOUNT_ID_OFFICIAL=
4+
KEYGEN_ACCOUNT_EMAIL=
5+
KEYGEN_ACCOUNT_EMAIL_LOCALHOST=
6+
KEYGEN_ACCOUNT_EMAIL_OFFICIAL=
7+
KEYGEN_ACCOUNT_PASSWORD=
8+
KEYGEN_ACCOUNT_PASSWORD_LOCALHOST=
9+
KEYGEN_ACCOUNT_PASSWORD_OFFICIAL=
10+
KEYGEN_ADMIN_TOKEN=
11+
KEYGEN_ADMIN_TOKEN_LOCALHOST=
12+
KEYGEN_ADMIN_TOKEN_OFFICIAL=

.github/workflows/docker-image.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: Docker Image CI
22

33
on:
44
push:
5-
branches: [ "master" ]
5+
branches: [ "master", "test_api_keygen" ]
66
pull_request:
7-
branches: [ "master" ]
7+
branches: [ "master", "test_api_keygen" ]
88

99
jobs:
1010

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ example-csharp-licensing-Docker.sln
77
machine.lic
88
license.lic
99
!examples/*
10+
*.env
11+
/typescript

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ RUN dotnet build
66

77
FROM alpine@sha256:25fad2a32ad1f6f510e528448ae1ec69a28ef81916a004d3629874104f8a7f70 as runner
88
RUN apk add dotnet7-runtime
9+
ENV COMPlus_EnableDiagnostics=0
910
WORKDIR /src
1011
COPY --from=builder /src .
12+
RUN apk --no-cache add curl
1113
ENTRYPOINT ["dotnet", "bin/Debug/net7.0/example-csharp-licensing-Docker.dll", "examples/license.lic", "examples/machine.lic", "198e9fe586114844f6a4eaca5069b41a7ed43fb5a2df84892b69826d64573e39"]

Program.cs

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
using JsonSerializer = System.Text.Json.JsonSerializer;
2+
13
namespace example_csharp_licensing_Docker;
24

35
public abstract partial class Program
46
{
57
// Definition of all constant and variables needed to verify and decrypt the license file
6-
private static string _publicKey = "e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788";
7-
8+
private static string _publicKey =
9+
"e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788";
10+
811
// Method to get EUID on Linux
912
[DllImport("libc")]
1013
private static extern uint geteuid();
@@ -19,14 +22,15 @@ public abstract partial class Program
1922
.Get()
2023
.Cast<ManagementObject>()
2124
.First()
22-
.Properties["SerialNumber"]
23-
.Value
24-
.ToString();
25+
.Properties["SerialNumber"].Value.ToString();
2526

26-
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return null;
27+
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
28+
return null;
2729
if (geteuid() != 0)
2830
{
29-
Console.WriteLine("You must be root to get the serial number. Execute again with \"sudo dotnet run\".");
31+
Console.WriteLine(
32+
"You must be root to get the serial number. Execute again with \"sudo dotnet run\"."
33+
);
3034
return null;
3135
}
3236

@@ -41,30 +45,29 @@ public abstract partial class Program
4145
}
4246
}
4347

44-
public static void Main(string[] args)
48+
public static void Main_aux(string[]? args)
4549
{
4650
try
4751
{
4852
string pathLicenseFile;
4953
string pathMachineFile;
5054
string fingerprint;
51-
52-
if (args.Length == 0)
55+
56+
if (args?.Length == 0)
5357
{
5458
pathLicenseFile = "license.lic";
5559
pathMachineFile = "machine.lic";
56-
60+
5761
var serialNumber = GetSerialNumber();
5862
if (serialNumber is null)
5963
{
6064
Console.WriteLine(
61-
"Unable to get serial number. Is your system compatible? Compatible systems list: [Windows, Linux]");
65+
"Unable to get serial number. Is your system compatible? Compatible systems list: [Windows, Linux]"
66+
);
6267
return;
6368
}
64-
else
65-
{
66-
Console.WriteLine("Serial number : " + serialNumber);
67-
}
69+
70+
Console.WriteLine("Serial number : " + serialNumber);
6871

6972
// Compute machine file fingerprint
7073
var hashAlgorithm = new Sha3Digest(512);
@@ -81,20 +84,23 @@ public static void Main(string[] args)
8184
}
8285
else
8386
{
87+
Debug.Assert(args != null, nameof(args) + " != null");
8488
pathLicenseFile = args[0];
8589
pathMachineFile = args[1];
8690
fingerprint = args[2];
8791
}
8892

8993
var licenseKey = File.ReadAllText(pathLicenseFile);
9094
var machineFileRaw = File.ReadAllText(pathMachineFile);
91-
95+
9296
// Parse signed license file (removing cert header, newlines and footer)
9397
string? encodedPayload;
9498
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
9599
encodedPayload = WindowsRegex().Replace(machineFileRaw, "");
96-
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
97-
RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
100+
else if (
101+
RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
102+
|| RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
103+
)
98104
encodedPayload = UnixRegex().Replace(machineFileRaw, "");
99105
else
100106
encodedPayload = null;
@@ -116,9 +122,9 @@ public static void Main(string[] args)
116122
encodedSignature = lic.sig;
117123
algorithm = lic.alg;
118124
}
119-
catch (JsonException e)
125+
catch (Exception e)
120126
{
121-
Console.WriteLine($"Failed to parse machine file: {e.Message}");
127+
Console.WriteLine((object?)$"Failed to parse machine file: {e.Message}");
122128

123129
return;
124130
}
@@ -144,6 +150,7 @@ public static void Main(string[] args)
144150
Console.WriteLine("Machine file is valid! Decrypting...");
145151

146152
// Decrypt license file dataset
153+
// ReSharper disable once NotAccessedVariable
147154
string plaintext;
148155
try
149156
{
@@ -156,7 +163,7 @@ public static void Main(string[] args)
156163
var tag = Convert.FromBase64String(encodedTag);
157164
byte[] secret;
158165

159-
// Hash license key to get decryption secret
166+
// Hash license key to get decryption secret
160167
try
161168
{
162169
var licenseKeyBytes = Encoding.UTF8.GetBytes(licenseKey);
@@ -189,6 +196,7 @@ public static void Main(string[] args)
189196
cipher.DoFinal(output, len);
190197

191198
// Convert decrypted bytes to string
199+
// ReSharper disable once RedundantAssignment
192200
plaintext = Encoding.UTF8.GetString(output);
193201
}
194202
catch (Exception e)
@@ -220,9 +228,32 @@ public static void Main(string[] args)
220228
private static partial Regex UnixRegex();
221229

222230
// Regex used for Windows systems
223-
[GeneratedRegex("(^-----BEGIN MACHINE FILE-----\n|^-----BEGIN MACHINE FILE-----\r\n|\r\n|-----END MACHINE FILE-----\n$|-----END MACHINE FILE-----\r\n$)")]
231+
[GeneratedRegex(
232+
"(^-----BEGIN MACHINE FILE-----\n|^-----BEGIN MACHINE FILE-----\r\n|\r\n|-----END MACHINE FILE-----\n$|-----END MACHINE FILE-----\r\n$)"
233+
)]
224234
private static partial Regex WindowsRegex();
225235

236+
public static async Task Main(string[]? args)
237+
{
238+
if (args == null || args.Length == 0)
239+
{
240+
Main_aux(args);
241+
}
242+
else
243+
{
244+
if (args[0] == "api")
245+
{
246+
Env.Load();
247+
await CheckInternet.CheckInternetAsync();
248+
TestApi.Main_aux();
249+
return;
250+
}
251+
252+
Main_aux(args);
253+
}
254+
}
255+
256+
[SuppressMessage("ReSharper", "InconsistentNaming")]
226257
public class LicenseFile
227258
{
228259
public string? enc { get; set; }

README.md

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,73 @@
22

33
Original repo : https://github.com/ABouveron/example-csharp-cryptographic-machine-files
44

5-
# How to run
5+
# Test official and localhost API
6+
7+
The goal of this project is to be able to contact the API while online & offline. The official API can be contacted while online, and the localhost one will be used when you are offline.
8+
You can only access the dashboard when online.
9+
10+
*Not functional on Windows.*
11+
12+
**Requirements:**
13+
- Docker
14+
- scripts working on Ubuntu (other distributions not tested)
15+
- filling `install.env` with the credentials you want to use in localhost mode
16+
- filling `.env` *\*_OFFICIAL* and *\*_LOCALHOST* variables with the appropriate values
17+
18+
OFFICIAL values can be found on [keygen.sh](https://app.keygen.sh/settings).
19+
A token for the API will be generated on the first run. Execute the run.sh script two times to get both tokens: one while having Internet access and one without.
20+
21+
**Linux:**
22+
23+
```shell
24+
source install.sh
25+
```
26+
27+
```shell
28+
source run.sh
29+
```
30+
In another terminal:
31+
```shell
32+
sudo dotnet run api
33+
```
34+
35+
(You need to run it as root because sending an async ping is limited to root. If not running as root, the official API
36+
cannot be contacted.)
37+
38+
# Run basic offline file verification
39+
640
## Example config:
741

842
**Linux / Windows:**
43+
944
```shell
1045
dotnet run examples/license.lic examples/machine.lic 198e9fe586114844f6a4eaca5069b41a7ed43fb5a2df84892b69826d64573e39
1146
```
1247

1348
## Normal config:
14-
* Your fingerprint should be the hash of the serial number of your machine (you can execute the program to see it) computed with **SHA3_512** ([Online Converter](https://emn178.github.io/online-tools/sha3_512.html)).
49+
50+
* Your fingerprint should be the hash of the serial number of your machine (you can execute the program to see it)
51+
computed with **SHA3_512** ([Online Converter](https://emn178.github.io/online-tools/sha3_512.html)).
1552
* Replace the public key from [keygen.sh](keygen.sh) line 96 of `Program.cs`.
1653
* Get your machine file on [keygen.sh](keygen.sh) and put the raw license key in a new file named `license.lic`.
1754
* Put your `machine.lic` & `license.lic` in the same folder as `Program.cs` and run:
1855

1956
**Linux:**
57+
2058
```shell
2159
sudo dotnet run
2260
```
61+
2362
(You need to run it as root because it needs to access `/dev/sda` to get the serial number of your machine.)
2463

2564
**Windows:**
65+
2666
```shell
2767
dotnet run
2868
```
2969

3070
## Docker:
71+
3172
```shell
3273
docker build . -t license-example-csharp
3374
docker run -it license-example-csharp

Test.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using Xunit.Sdk;
2-
31
namespace example_csharp_licensing_Docker;
42

53
public class Test
@@ -19,8 +17,8 @@ public void UnitTest()
1917
Console.SetOut(stringWriter);
2018

2119
// Run the application
22-
Program.Main(
23-
new string[]
20+
Program.Main_aux(
21+
new[]
2422
{
2523
"examples/license.lic",
2624
"examples/machine.lic",
@@ -34,4 +32,4 @@ public void UnitTest()
3432
const string expectedOutput = "Hello, World!";
3533
Assert.Contains(expectedOutput, output);
3634
}
37-
}
35+
}

Usings.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
global using System.Management;
33
global using System.Runtime.InteropServices;
44
global using System.Text;
5-
global using System.Text.Json;
65
global using System.Text.RegularExpressions;
76
global using NSec.Cryptography;
87
global using Org.BouncyCastle.Crypto.Digests;
@@ -11,3 +10,10 @@
1110
global using Org.BouncyCastle.Crypto.Parameters;
1211
global using Xunit;
1312
global using Xunit.Abstractions;
13+
global using RestSharp;
14+
global using System.Diagnostics.CodeAnalysis;
15+
global using DotNetEnv;
16+
global using Newtonsoft.Json;
17+
global using example_csharp_licensing_Docker.utilities;
18+
global using example_csharp_licensing_Docker.api;
19+
global using System.Net.NetworkInformation;

api/Authentication.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace example_csharp_licensing_Docker.api;
2+
3+
public abstract class Authentication
4+
{
5+
public static void LicenseAuth(
6+
string licenseId,
7+
string licenseKey,
8+
string name,
9+
string platform,
10+
string fingerprint
11+
)
12+
{
13+
var jsonLicenseKeyAuth = new JsonKeygen
14+
{
15+
data = new Data
16+
{
17+
type = "machines",
18+
attributes = new Attributes
19+
{
20+
fingerprint = fingerprint,
21+
platform = platform,
22+
name = name
23+
},
24+
relationships = new Relationships
25+
{
26+
license = new License
27+
{
28+
data = new LicenseData { type = "licenses", id = licenseId }
29+
}
30+
}
31+
}
32+
};
33+
Console.WriteLine(
34+
BashCmd.Execute(
35+
"curl -X POST https://"
36+
+ CheckInternet.Api
37+
+ "/v1/accounts/"
38+
+ System.Environment.GetEnvironmentVariable("KEYGEN_ACCOUNT_ID")
39+
+ "/machines "
40+
+ "-H 'Content-Type: application/vnd.api+json' "
41+
+ "-H 'Accept: application/vnd.api+json' "
42+
+ "-H 'Authorization: License "
43+
+ licenseKey
44+
+ "' "
45+
+ "-d '"
46+
+ JsonConvert.SerializeObject(jsonLicenseKeyAuth)
47+
+ "'"
48+
)
49+
);
50+
}
51+
}

0 commit comments

Comments
 (0)