Improve hebe-dotnet implementation

This commit is contained in:
MRmlik12 2021-10-03 17:37:08 +02:00
parent a99ca50a31
commit ea76fd6100
4 changed files with 43 additions and 18 deletions

View file

@ -1,9 +1,10 @@
using System;
using Wulkanowy.UonetRequestSigner.Hebe.Exceptions;
using Xunit;
namespace Wulkanowy.UonetRequestSigner.Hebe.Tests
{
public class SignerTest
public class TestSigner
{
private const string FullUrl = "/powiatwulkanowy/123456/api/mobile/register/hebe";
private const string Fingerprint = "7EBA57E1DDBA1C249D097A9FF1C9CCDD45351A6A";
@ -11,16 +12,25 @@ namespace Wulkanowy.UonetRequestSigner.Hebe.Tests
private const string Body = "{}";
[Fact]
public void SignCert()
public void TestSigner_ChecksHeaders()
{
var (digest, cannonicalUrl, signature) = Signer.GetSignatureValues(Fingerprint, PrivateKey, Body, FullUrl, new DateTime(2020, 4, 14, 4, 14, 16));
var (digest, canonicalUrl, signature) = Signer.GetSignatureValues(Fingerprint, PrivateKey, Body, FullUrl, new DateTime(2020, 4, 14, 4, 14, 16));
Assert.Equal("SHA-256=RBNvo1WzZ4oRRq0W9+hknpT7T8If536DEMBg9hyq/4o=", digest);
Assert.Equal("api%2fmobile%2fregister%2fhebe", cannonicalUrl);
Assert.Equal("api%2fmobile%2fregister%2fhebe", canonicalUrl);
Assert.Equal("keyId=\"7EBA57E1DDBA1C249D097A9FF1C9CCDD45351A6A\"," +
"headers=\"vCanonicalUrl Digest vDate\"," +
"algorithm=\"sha256withrsa\"," +
"signature=Base64(SHA256withRSA(mIVNkthTzTHmmXG1qxv1Jpt3uRlyhbj7VHysbCNpl0zXCCzuwTXsuCrfjexDDXsyJVo/LznQKOyvOaW4tEfrBobxtbtTnp7zYi54bdvAZa3pvM02yvkH4i/DvTLDKRO0R9UDZ1LraGrOTsIe3m3mQ21NOynVqCKadeqod8Y7l4YUlVYEmrtq/7xbCwr0qdne6G67eY4Amj6ffbG3TkVLpUrEETBnAC7oFjGYKhcRyvltAi+lcv6omANz1gwELf+Vmsa8NwFo/YGwY3R23z15athU/1iC1JcrECBLC8nRM1+KlvyIqx2HX6RG5R1cMOwBWVg6pRKUdrhxYbQ+VQ8Cag==))",
signature);
}
[Fact]
public void TestSignCert_TrowsNotMatchedUrlException()
{
Assert.Throws<NotMatchedUrlException>(() =>
Signer.GetSignatureValues(Fingerprint, PrivateKey, Body, "/example/path",
new DateTime(2020, 4, 14, 4, 14, 16))
);
}
}
}

View file

@ -0,0 +1,11 @@
using System;
namespace Wulkanowy.UonetRequestSigner.Hebe.Exceptions
{
public class NotMatchedUrlException : Exception
{
public NotMatchedUrlException(string value) : base($"{value} is not matched with regex")
{
}
}
}

View file

@ -5,16 +5,17 @@ using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Web;
using Wulkanowy.UonetRequestSigner.Hebe.Exceptions;
namespace Wulkanowy.UonetRequestSigner.Hebe
{
public static class Signer
{
public static (string digest, string cannonicalUrl, string signature) GetSignatureValues(string fingerprint, string privateKey,
public static (string digest, string canonicalUrl, string signature) GetSignatureValues(string fingerprint, string privateKey,
string body, string requestPath, DateTime timestamp)
{
string digest = GetDigest(body);
string formattedTimestamp = timestamp.ToString("ddd, dd MMM yyyy hh:mm:ss 'GMT'");
var digest = GetDigest(body);
var formattedTimestamp = timestamp.ToString("ddd, dd MMM yyyy hh:mm:ss 'GMT'");
var headers = GetHeaders(requestPath, formattedTimestamp, digest);
var headersName = from header in headers select header.Item1;
@ -24,26 +25,28 @@ namespace Wulkanowy.UonetRequestSigner.Hebe
(
$"SHA-256={digest}",
headers[0].Item2,
$"keyId=\"{fingerprint}\",headers=\"{String.Join(" ", headersName.ToArray())}\",algorithm=\"sha256withrsa\"," +
$"signature=Base64(SHA256withRSA({GetSignatureValues(String.Join("", headersValue.ToArray()), privateKey)}))"
$"keyId=\"{fingerprint}\",headers=\"{string.Join(" ", headersName.ToArray())}\",algorithm=\"sha256withrsa\"," +
$"signature=Base64(SHA256withRSA({GetSignatureValues(string.Join("", headersValue.ToArray()), privateKey)}))"
);
}
private static List<(string, string)> GetHeaders(string url, string date, string digest)
{
var headers = new List<(string header, string value)>();
headers.Add(("vCanonicalUrl", GetEncodedPath(url)));
headers.Add(("Digest", digest));
headers.Add(("vDate", date));
var headers = new List<(string header, string value)>
{
("vCanonicalUrl", GetEncodedPath(url)),
("Digest", digest),
("vDate", date)
};
return headers;
}
private static string GetEncodedPath(string path)
{
var rx = Regex.Match(path, "(api/mobile/.+)");
if (rx.Value == null)
throw new Exception("The url is not finded!");
if (!rx.Success)
throw new NotMatchedUrlException(path);
return HttpUtility.UrlEncode(rx.Value);
}
@ -56,9 +59,9 @@ namespace Wulkanowy.UonetRequestSigner.Hebe
return Convert.ToBase64String(data);
}
private static string GetSignatureValues(string values, string privKey)
private static string GetSignatureValues(string values, string privateKey)
{
var blk = Convert.FromBase64String(privKey);
var blk = Convert.FromBase64String(privateKey);
var provider = new RSACryptoServiceProvider();
provider.ImportPkcs8PrivateKey(new ReadOnlySpan<byte>(blk), out _);
var signedValues = provider.SignData(Encoding.UTF8.GetBytes(values), SHA256.Create());

View file

@ -10,6 +10,7 @@
<PackageLicenseUrl>https://github.com/wulkanowy/uonet-request-signer/blob/master/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/wulkanowy/uonet-request-signer</RepositoryUrl>
<RootNamespace>Wulkanowy.UonetRequestSigner.Hebe</RootNamespace>
<PackageVersion>1.0.1</PackageVersion>
</PropertyGroup>
</Project>