Skip to content

Commit e4bb893

Browse files
committed
Basic optimizations
1 parent 7a33d95 commit e4bb893

File tree

3 files changed

+47
-37
lines changed

3 files changed

+47
-37
lines changed

Lib.Net.Http.WebPush/Authentication/VapidAuthentication.cs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
using System;
22
using System.Text;
3-
using System.Collections.Generic;
3+
using System.Globalization;
44
using System.Security.Cryptography;
5-
using Newtonsoft.Json;
65
using Org.BouncyCastle.Math;
76
using Org.BouncyCastle.Crypto.Parameters;
87
using Org.BouncyCastle.Crypto.Signers;
@@ -42,29 +41,29 @@ internal WebPushSchemeHeadersValues(string authenticationHeaderValueParameter, s
4241

4342
#region Fields
4443
private const string URI_SCHEME_HTTPS = "https";
45-
private const string AUDIENCE_CLAIM = "aud";
46-
private const string EXPIRATION_CLAIM = "exp";
47-
private const string SUBJECT_CLAIM = "sub";
48-
private const char JWT_SEPARATOR = '.';
49-
50-
private const string P256ECDSA_PREFIX = "p256ecdsa=";
51-
private const string VAPID_AUTHENTICATION_HEADER_VALUE_PARAMETER_FORMAT = "t={0}, k={1}";
5244

5345
private const int DEFAULT_EXPIRATION = 43200;
5446
private const int MAXIMUM_EXPIRATION = 86400;
5547

48+
private const string JWT_HEADER = "{\"typ\":\"JWT\",\"alg\":\"ES256\"}";
49+
private const string JWT_SEPARATOR = ".";
50+
private const string JWT_BODY_AUDIENCE_PART = "{\"aud\":\"";
51+
private const string JWT_BODY_EXPIRATION_PART = "\",\"exp\":";
52+
private const string JWT_BODY_SUBJECT_PART = ",\"sub\":\"";
53+
private const string JWT_BODY_WITH_SUBJECT_CLOSING = "\"}";
54+
private const string JWT_BODY_WITHOUT_SUBJECT_CLOSING = "}";
55+
56+
private const string P256ECDSA_PREFIX = "p256ecdsa=";
57+
private const string VAPID_AUTHENTICATION_HEADER_VALUE_PARAMETER_FORMAT = "t={0}, k={1}";
58+
5659
private string _subject;
5760
private string _publicKey;
5861
private string _privateKey;
5962
private ECPrivateKeyParameters _privateSigningKey;
6063
private int _expiration;
6164

6265
private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0);
63-
private static readonly Dictionary<string, string> _jwtHeader = new Dictionary<string, string>
64-
{
65-
{ "typ", "JWT" },
66-
{ "alg", "ES256" }
67-
};
66+
private static readonly string _jwtHeaderSegment = UrlBase64Converter.ToUrlBase64String(Encoding.UTF8.GetBytes(JWT_HEADER));
6867
#endregion
6968

7069
#region Properties
@@ -212,25 +211,28 @@ private string GetToken(string audience)
212211
throw new ArgumentException(nameof(audience), "Audience should be an absolute URL");
213212
}
214213

215-
Dictionary<string, object> jwtBody = GetJwtBody(audience);
214+
string jwtBodySegment = GetJwtBodySegment(audience);
216215

217-
return GenerateJwtToken(_jwtHeader, jwtBody);
216+
return GenerateJwtToken(jwtBodySegment);
218217
}
219218

220-
private Dictionary<string, object> GetJwtBody(string audience)
219+
private string GetJwtBodySegment(string audience)
221220
{
222-
Dictionary<string, object> jwtBody = new Dictionary<string, object>
223-
{
224-
{ AUDIENCE_CLAIM, audience },
225-
{ EXPIRATION_CLAIM, GetAbsoluteExpiration(_expiration) }
226-
};
221+
StringBuilder jwtBodyBuilder = new StringBuilder();
222+
223+
jwtBodyBuilder.Append(JWT_BODY_AUDIENCE_PART).Append(audience)
224+
.Append(JWT_BODY_EXPIRATION_PART).Append(GetAbsoluteExpiration(_expiration).ToString(CultureInfo.InvariantCulture));
227225

228226
if (_subject != null)
229227
{
230-
jwtBody.Add(SUBJECT_CLAIM, _subject);
228+
jwtBodyBuilder.Append(JWT_BODY_SUBJECT_PART).Append(_subject).Append(JWT_BODY_WITH_SUBJECT_CLOSING);
229+
}
230+
else
231+
{
232+
jwtBodyBuilder.Append(JWT_BODY_WITHOUT_SUBJECT_CLOSING);
231233
}
232234

233-
return jwtBody;
235+
return UrlBase64Converter.ToUrlBase64String(Encoding.UTF8.GetBytes(jwtBodyBuilder.ToString()));
234236
}
235237

236238
private static long GetAbsoluteExpiration(int expirationSeconds)
@@ -240,11 +242,9 @@ private static long GetAbsoluteExpiration(int expirationSeconds)
240242
return (long)unixEpochOffset.TotalSeconds + expirationSeconds;
241243
}
242244

243-
private string GenerateJwtToken(Dictionary<string, string> jwtHeader, Dictionary<string, object> jwtBody)
245+
private string GenerateJwtToken(string jwtBodySegment)
244246
{
245-
string jwtInput = UrlBase64Converter.ToUrlBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jwtHeader)))
246-
+ JWT_SEPARATOR
247-
+ UrlBase64Converter.ToUrlBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jwtBody)));
247+
string jwtInput = _jwtHeaderSegment + JWT_SEPARATOR + jwtBodySegment;
248248

249249
byte[] jwtInputHash;
250250
using (var sha256Hasher = SHA256.Create())

Lib.Net.Http.WebPush/Internals/ECKeyHelper.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,28 @@ namespace Lib.Net.Http.WebPush.Internals
1212
{
1313
internal static class ECKeyHelper
1414
{
15+
private const string PRIVATE_DER_IDENTIFIER = "1.2.840.10045.3.1.7";
16+
private const string PRIVATE_PEM_KEY_PREFIX = "-----BEGIN EC PRIVATE KEY-----\n";
17+
private const string PRIVATE_PEM_KEY_SUFFIX = "\n-----END EC PRIVATE KEY----";
18+
19+
private const string PUBLIC_DER_IDENTIFIER = "1.2.840.10045.2.1";
20+
private const string PUBLIC_PEM_KEY_PREFIX = "-----BEGIN PUBLIC KEY-----\n";
21+
private const string PUBLIC_PEM_KEY_SUFFIX = "\n-----END PUBLIC KEY-----";
22+
23+
private const string P256_CURVE_NAME = "P-256";
24+
private const string ECDH_ALGORITHM_NAME = "ECDH";
25+
1526
internal static ECPrivateKeyParameters GetECPrivateKeyParameters(byte[] privateKey)
1627
{
1728
Asn1Object derSequence = new DerSequence(
1829
new DerInteger(1),
1930
new DerOctetString(privateKey),
20-
new DerTaggedObject(0, new DerObjectIdentifier("1.2.840.10045.3.1.7"))
31+
new DerTaggedObject(0, new DerObjectIdentifier(PRIVATE_DER_IDENTIFIER))
2132
);
2233

23-
string pemKey = "-----BEGIN EC PRIVATE KEY-----\n"
34+
string pemKey = PRIVATE_PEM_KEY_PREFIX
2435
+ Convert.ToBase64String(derSequence.GetDerEncoded())
25-
+ "\n-----END EC PRIVATE KEY----";
36+
+ PRIVATE_PEM_KEY_SUFFIX;
2637

2738
PemReader pemKeyReader = new PemReader(new StringReader(pemKey));
2839
AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pemKeyReader.ReadObject();
@@ -33,24 +44,24 @@ internal static ECPrivateKeyParameters GetECPrivateKeyParameters(byte[] privateK
3344
internal static ECPublicKeyParameters GetECPublicKeyParameters(byte[] publicKey)
3445
{
3546
Asn1Object derSequence = new DerSequence(
36-
new DerSequence(new DerObjectIdentifier(@"1.2.840.10045.2.1"), new DerObjectIdentifier(@"1.2.840.10045.3.1.7")),
47+
new DerSequence(new DerObjectIdentifier(PUBLIC_DER_IDENTIFIER), new DerObjectIdentifier(PRIVATE_DER_IDENTIFIER)),
3748
new DerBitString(publicKey)
3849
);
3950

40-
string pemKey = "-----BEGIN PUBLIC KEY-----\n"
51+
string pemKey = PUBLIC_PEM_KEY_PREFIX
4152
+ Convert.ToBase64String(derSequence.GetDerEncoded())
42-
+ "\n-----END PUBLIC KEY-----";
53+
+ PUBLIC_PEM_KEY_SUFFIX;
4354

4455
PemReader pemKeyReader = new PemReader(new StringReader(pemKey));
4556
return (ECPublicKeyParameters)pemKeyReader.ReadObject();
4657
}
4758

4859
internal static AsymmetricCipherKeyPair GenerateAsymmetricCipherKeyPair()
4960
{
50-
X9ECParameters ecParameters = NistNamedCurves.GetByName("P-256");
61+
X9ECParameters ecParameters = NistNamedCurves.GetByName(P256_CURVE_NAME);
5162
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameters.Curve, ecParameters.G, ecParameters.N, ecParameters.H, ecParameters.GetSeed());
5263

53-
IAsymmetricCipherKeyPairGenerator keyPairGenerator = GeneratorUtilities.GetKeyPairGenerator("ECDH");
64+
IAsymmetricCipherKeyPairGenerator keyPairGenerator = GeneratorUtilities.GetKeyPairGenerator(ECDH_ALGORITHM_NAME);
5465
keyPairGenerator.Init(new ECKeyGenerationParameters(ecDomainParameters, new SecureRandom()));
5566

5667
return keyPairGenerator.GenerateKeyPair();

Lib.Net.Http.WebPush/Lib.Net.Http.WebPush.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
<LangVersion>latest</LangVersion>
2323
</PropertyGroup>
2424
<ItemGroup>
25-
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
2625
<PackageReference Include="Lib.Net.Http.EncryptedContentEncoding" Version="1.1.0" />
2726
</ItemGroup>
2827
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">

0 commit comments

Comments
 (0)