Improve hebe-dotnet implementation
This commit is contained in:
parent
a99ca50a31
commit
ea76fd6100
4 changed files with 43 additions and 18 deletions
|
@ -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))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue