Skip to content

Commit 635af5c

Browse files
authored
chore: BREAKING 💥 refactor dependencies and update BouncyCastle.Cryptography to the latest (#34)
1 parent 3c16712 commit 635af5c

22 files changed

+403
-242
lines changed

‎README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
Use NuGet to add a dependency on this library.
2929

3030
See: [https://www.nuget.org/packages/net-questdb-client/](https://www.nuget.org/packages/net-questdb-client/)
31+
(Optional) to use the client with TCP protocol authentication add NuGet refrence to [https://www.nuget.org/packages/net-questdb-client-tcp-auth/](https://www.nuget.org/packages/net-questdb-client-tcp-auth/)
3132

3233
## Usage
3334

@@ -121,6 +122,8 @@ using var sender = Sender.New("https::addr=localhost:9009;tls_verify=unsafe_off;
121122

122123
#### TCP Authentication
123124

125+
💥 From net-questdb-client Version 2.1.0, if you want to use TCP Authentication, you must add a reference to [https://www.nuget.org/packages/net-questdb-client-tcp-auth/](https://www.nuget.org/packages/net-questdb-client-tcp-auth/).
126+
124127
```csharp
125128
using var sender = Sender.New("tcps::addr=localhost:9009;tls_verify=unsafe_off;username=admin;token=NgdiOWDoQNUP18WOnb1xkkEG5TzPYMda5SiUOvT1K0U=;");
126129
```
@@ -147,7 +150,7 @@ The config string format is:
147150
| `max_buf_size` | `104857600` | Maximum size of the byte buffer in bytes. If exceeded, an exception will be thrown. |
148151
| `username` | | The username for authentication. Used for Basic Authentication and TCP JWK Authentication. |
149152
| `password` | | The password for authentication. Used for Basic Authentication. |
150-
| `token` | | The token for authentication. Used for Token Authentication and TCP JWK Authentication. |
153+
| `token` | | The token for authentication. Used for Token Authentication and TCP JWK Authentication, needs additional reference to `net-questdb-client-tcp-auth` assembly |
151154
| `token_x` | | Un-used. |
152155
| `token_y` | | Un-used. |
153156
| `tls_verify` | `on` | Denotes whether TLS certificates should or should not be verifed. Options are on/unsafe_off. |
@@ -203,6 +206,11 @@ The config string format is:
203206
No. This client is for writing data only. For querying, see
204207
the [Query & SQL overview](https://questdb.io/docs/reference/sql/overview/)
205208

209+
### I updated from version < 2.0.0 and now have error `Could not load QuestDB.Secp256r1SignatureGenerator, please add a reference to assembly "net-client-questdb-tcp-auth\"`
210+
211+
Since Version 2.1.0, in order to use TCP authentication, an additional NuGet package is required [https://www.nuget.org/packages/net-questdb-client-tcp-auth/](https://www.nuget.org/packages/net-questdb-client-tcp-auth/).
212+
This was changed to remove the dependency on `BouncyCastle.Cryptography` from the main library, since it was only required for TCP authentication.
213+
206214
### Where do I report issues with the client?
207215

208216
If something is not working as expected, please open

‎global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "6.0.0",
3+
"version": "9.0.0",
44
"rollForward": "latestMajor",
55
"allowPrerelease": true
66
}

‎net-questdb-client.sln

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-streaming", "src\ex
2121
EndProject
2222
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-auth-http-tls", "src\example-auth-http-tls\example-auth-http-tls.csproj", "{24D93DBB-3783-423F-81CC-6B9BFD33F6CD}"
2323
EndProject
24+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "net-client-questdb-tcp-auth", "src\net-client-questdb-tcp-auth\net-client-questdb-tcp-auth.csproj", "{EF86C5A3-71BE-4D9C-9647-B1A50751F244}"
25+
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "net-questdb-client-tcp-auth-test", "src\net-questdb-client-tcp-auth-tests\net-questdb-client-tcp-auth-tests.csproj", "{628A6AE1-C0D4-4A40-98DF-1F094BD60203}"
27+
EndProject
2428
Global
2529
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2630
Debug|Any CPU = Debug|Any CPU
@@ -66,5 +70,13 @@ Global
6670
{24D93DBB-3783-423F-81CC-6B9BFD33F6CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
6771
{24D93DBB-3783-423F-81CC-6B9BFD33F6CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
6872
{24D93DBB-3783-423F-81CC-6B9BFD33F6CD}.Release|Any CPU.Build.0 = Release|Any CPU
73+
{EF86C5A3-71BE-4D9C-9647-B1A50751F244}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
74+
{EF86C5A3-71BE-4D9C-9647-B1A50751F244}.Debug|Any CPU.Build.0 = Debug|Any CPU
75+
{EF86C5A3-71BE-4D9C-9647-B1A50751F244}.Release|Any CPU.ActiveCfg = Release|Any CPU
76+
{EF86C5A3-71BE-4D9C-9647-B1A50751F244}.Release|Any CPU.Build.0 = Release|Any CPU
77+
{628A6AE1-C0D4-4A40-98DF-1F094BD60203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
78+
{628A6AE1-C0D4-4A40-98DF-1F094BD60203}.Debug|Any CPU.Build.0 = Debug|Any CPU
79+
{628A6AE1-C0D4-4A40-98DF-1F094BD60203}.Release|Any CPU.ActiveCfg = Release|Any CPU
80+
{628A6AE1-C0D4-4A40-98DF-1F094BD60203}.Release|Any CPU.Build.0 = Release|Any CPU
6981
EndGlobalSection
7082
EndGlobal

‎src/dummy-http-server/dummy-http-server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<RootNamespace>dummy_http_server</RootNamespace>

‎src/example-auth-http-tls/example-auth-http-tls.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
5+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
66
<RootNamespace>example_auth_http_tls</RootNamespace>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<Nullable>enable</Nullable>

‎src/example-auth-tls/example-auth-tls.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
88
<Title>QuestDB client - Example with Authentication and TLS</Title>
99
<Description>Authentication and TLS example using the QuestDB ILP protocol client</Description>
10-
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
10+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
1111
<OutputType>Exe</OutputType>
1212
</PropertyGroup>
1313

‎src/example-basic/example-basic.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
88
<Title>QuestDB client - Basic Example</Title>
99
<Description>Basic example using the QuestDB ILP protocol client</Description>
10-
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
10+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
1111
<OutputType>Exe</OutputType>
1212
</PropertyGroup>
1313

‎src/example-streaming/example-streaming.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
5+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
66
<RootNamespace>example_streaming</RootNamespace>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<Nullable>enable</Nullable>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Org.BouncyCastle.Asn1.Sec;
2+
using Org.BouncyCastle.Crypto.Parameters;
3+
using Org.BouncyCastle.Math;
4+
using Org.BouncyCastle.Security;
5+
6+
namespace QuestDB;
7+
8+
public class Secp256r1SignatureGenerator : ISignatureGenerator
9+
{
10+
public byte[] GenerateSignature(byte[] privateKey, byte[] buffer, int bufferLen)
11+
{
12+
var p = SecNamedCurves.GetByName("secp256r1");
13+
var parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
14+
var priKey = new ECPrivateKeyParameters(
15+
"ECDSA",
16+
new BigInteger(1, privateKey), // d
17+
parameters);
18+
19+
var ecdsa = SignerUtilities.GetSigner("SHA-256withECDSA");
20+
ecdsa.Init(true, priKey);
21+
ecdsa.BlockUpdate(buffer, 0, bufferLen);
22+
var signature = ecdsa.GenerateSignature();
23+
return signature;
24+
}
25+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
5+
<RootNamespace>net_client_questdb_tcp</RootNamespace>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\net-questdb-client\net-questdb-client.csproj" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0"/>
16+
</ItemGroup>
17+
</Project>

‎src/net-questdb-client-benchmarks/net-questdb-client-benchmarks.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net6.0</TargetFramework>
5+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
66
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
77
<RootNamespace>net_questdb_client_benchmarks</RootNamespace>
88
<ImplicitUsings>enable</ImplicitUsings>
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*******************************************************************************
2+
* ___ _ ____ ____
3+
* / _ \ _ _ ___ ___| |_| _ \| __ )
4+
* | | | | | | |/ _ \/ __| __| | | | _ \
5+
* | |_| | |_| | __/\__ \ |_| |_| | |_) |
6+
* \__\_\\__,_|\___||___/\__|____/|____/
7+
*
8+
* Copyright (c) 2014-2019 Appsicle
9+
* Copyright (c) 2019-2024 QuestDB
10+
*
11+
* Licensed under the Apache License, Version 2.0 (the "License");
12+
* you may not use this file except in compliance with the License.
13+
* You may obtain a copy of the License at
14+
*
15+
* http://www.apache.org/licenses/LICENSE-2.0
16+
*
17+
* Unless required by applicable law or agreed to in writing, software
18+
* distributed under the License is distributed on an "AS IS" BASIS,
19+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20+
* See the License for the specific language governing permissions and
21+
* limitations under the License.
22+
*
23+
******************************************************************************/
24+
25+
26+
using System.Net;
27+
using System.Text;
28+
using NUnit.Framework;
29+
using Org.BouncyCastle.Asn1.Sec;
30+
using Org.BouncyCastle.Crypto.Parameters;
31+
using Org.BouncyCastle.Math;
32+
using Org.BouncyCastle.Security;
33+
using QuestDB;
34+
using QuestDB.Utils;
35+
36+
namespace net_questdb_client_tests;
37+
38+
public class TcpTests
39+
{
40+
private readonly IPAddress _host = IPAddress.Loopback;
41+
private readonly int _port = 29472;
42+
43+
[Test]
44+
public async Task Authenticate()
45+
{
46+
using var srv = CreateTcpListener(_port);
47+
srv.WithAuth("testUser1", "Vs4e-cOLsVCntsMrZiAGAZtrkPXO00uoRLuA3d7gEcI=",
48+
"ANhR2AZSs4ar9urE5AZrJqu469X0r7gZ1BBEdcrAuL_6");
49+
srv.AcceptAsync();
50+
51+
using var sender =
52+
Sender.New(
53+
$"tcp::addr={_host}:{_port};username=testUser1;token=NgdiOWDoQNUP18WOnb1xkkEG5TzPYMda5SiUOvT1K0U=;");
54+
55+
await sender.Table("metric name")
56+
.Symbol("t a g", "v alu, e")
57+
.Column("number", 10)
58+
.Column("string", " -=\"")
59+
.AtAsync(new DateTime(1970, 01, 01, 0, 0, 1));
60+
await sender.SendAsync();
61+
62+
var expected = "metric\\ name,t\\ a\\ g=v\\ alu\\,\\ e number=10i,string=\" -=\\\"\" 1000000000\n";
63+
WaitAssert(srv, expected);
64+
}
65+
66+
[Test]
67+
public async Task AuthFailWrongKid()
68+
{
69+
using var srv = CreateTcpListener(_port);
70+
srv.WithAuth("testUser1", "Vs4e-cOLsVCntsMrZiAGAZtrkPXO00uoRLuA3d7gEcI=",
71+
"ANhR2AZSs4ar9urE5AZrJqu469X0r7gZ1BBEdcrAuL_6");
72+
srv.AcceptAsync();
73+
74+
Assert.That(
75+
() => Sender.New($"tcp::addr={_host}:{_port};username=invalid;token=foo=;")
76+
,
77+
Throws.TypeOf<AggregateException>().With.InnerException.TypeOf<IngressError>().With.Message
78+
.Contains("Authentication failed")
79+
);
80+
}
81+
82+
[Test]
83+
public async Task AuthFailBadKey()
84+
{
85+
using var srv = CreateTcpListener(_port);
86+
srv.WithAuth("testUser1", "Vs4e-cOLsVCntsMrZiAGAZtrkPXO00uoRLuA3d7gEcI=",
87+
"ANhR2AZSs4ar9urE5AZrJqu469X0r7gZ1BBEdcrAuL_6");
88+
srv.AcceptAsync();
89+
90+
using var sender = Sender.New(
91+
$"tcp::addr={_host}:{_port};username=testUser1;token=ZOvHHNQBGvZuiCLt7CmWt0tTlsnjm9F3O3C749wGT_M=;");
92+
93+
Assert.That(
94+
async () =>
95+
{
96+
for (var i = 0; i < 10; i++)
97+
{
98+
await sender.Table("metric name")
99+
.Symbol("t a g", "v alu, e")
100+
.Column("number", 10)
101+
.Column("string", " -=\"")
102+
.AtAsync(new DateTime(1970, 01, 01, 0, 0, 1));
103+
await sender.SendAsync();
104+
Thread.Sleep(10);
105+
}
106+
107+
Assert.Fail();
108+
},
109+
Throws.TypeOf<IngressError>().With.Message
110+
.Contains("Could not write data to server.")
111+
);
112+
}
113+
114+
[Test]
115+
public void EcdsaSignatureLoop()
116+
{
117+
var privateKey = Convert.FromBase64String("NgdiOWDoQNUP18WOnb1xkkEG5TzPYMda5SiUOvT1K0U=");
118+
var p = SecNamedCurves.GetByName("secp256r1");
119+
var parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
120+
var priKey = new ECPrivateKeyParameters(
121+
"ECDSA",
122+
new BigInteger(privateKey), // d
123+
parameters);
124+
125+
var m = new byte[512];
126+
for (var i = 0; i < m.Length; i++)
127+
{
128+
m[i] = (byte)i;
129+
}
130+
131+
var ecdsa = SignerUtilities.GetSigner("SHA-256withECDSA");
132+
ecdsa.Init(true, priKey);
133+
ecdsa.BlockUpdate(m, 0, m.Length);
134+
var signature = ecdsa.GenerateSignature();
135+
136+
var pubKey1 = FromBase64String("Vs4e-cOLsVCntsMrZiAGAZtrkPXO00uoRLuA3d7gEcI=");
137+
var pubKey2 = FromBase64String("ANhR2AZSs4ar9urE5AZrJqu469X0r7gZ1BBEdcrAuL_6");
138+
139+
// Verify the signature
140+
var pubKey = new ECPublicKeyParameters(
141+
parameters.Curve.CreatePoint(new BigInteger(pubKey1), new BigInteger(pubKey2)),
142+
parameters);
143+
144+
ecdsa.Init(false, pubKey);
145+
ecdsa.BlockUpdate(m, 0, m.Length);
146+
Assert.That(ecdsa.VerifySignature(signature));
147+
}
148+
149+
private static void WaitAssert(DummyIlpServer srv, string expected)
150+
{
151+
var expectedLen = Encoding.UTF8.GetBytes(expected).Length;
152+
for (var i = 0; i < 500 && srv.TotalReceived < expectedLen; i++)
153+
{
154+
Thread.Sleep(10);
155+
}
156+
157+
Assert.That(srv.GetTextReceived(), Is.EqualTo(expected));
158+
}
159+
160+
private DummyIlpServer CreateTcpListener(int port, bool tls = false)
161+
{
162+
return new DummyIlpServer(port, tls);
163+
}
164+
165+
private byte[] FromBase64String(string text)
166+
{
167+
return DummyIlpServer.FromBase64String(text);
168+
}
169+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
5+
<RootNamespace>net_questdb_client_tcp_auth_tests</RootNamespace>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<IsPackable>false</IsPackable>
9+
<AssemblyName>net-questdb-client-tcp-auth-tests</AssemblyName>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0"/>
14+
<PackageReference Include="NUnit" Version="3.13.3"/>
15+
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/>
16+
<PackageReference Include="NUnit.Analyzers" Version="3.3.0"/>
17+
<PackageReference Include="coverlet.collector" Version="3.1.2"/>
18+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0"/>
19+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1"/>
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\dummy-http-server\dummy-http-server.csproj"/>
24+
<ProjectReference Include="..\net-client-questdb-tcp-auth\net-client-questdb-tcp-auth.csproj" />
25+
<ProjectReference Include="..\net-questdb-client-tests\net-questdb-client-tests.csproj" />
26+
<ProjectReference Include="..\net-questdb-client\net-questdb-client.csproj"/>
27+
</ItemGroup>
28+
29+
<ItemGroup>
30+
<None Update="certificate.pfx">
31+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
32+
</None>
33+
<None Update="config.json">
34+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
35+
</None>
36+
</ItemGroup>
37+
38+
</Project>

0 commit comments

Comments
 (0)