Merge pull request #19 from NicolasConstant/topic_better-validation
Topic better validation
This commit is contained in:
commit
79ae28acae
7 changed files with 51 additions and 27 deletions
|
@ -90,7 +90,7 @@ namespace BirdsiteLive.Domain
|
|||
var date = DateTime.UtcNow.ToUniversalTime();
|
||||
var httpDate = date.ToString("r");
|
||||
|
||||
var digest = ComputeSha256Hash(json);
|
||||
var digest = _cryptoService.ComputeSha256Hash(json);
|
||||
|
||||
var signature = _cryptoService.SignAndGetSignatureHeader(date, actorUrl, targetHost, digest, usedInbox);
|
||||
|
||||
|
@ -113,15 +113,6 @@ namespace BirdsiteLive.Domain
|
|||
return response.StatusCode;
|
||||
}
|
||||
|
||||
static string ComputeSha256Hash(string rawData)
|
||||
{
|
||||
// Create a SHA256
|
||||
using (SHA256 sha256Hash = SHA256.Create())
|
||||
{
|
||||
// ComputeHash - returns byte array
|
||||
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using BirdsiteLive.Domain.Factories;
|
||||
|
||||
|
@ -8,6 +9,7 @@ namespace BirdsiteLive.Domain
|
|||
{
|
||||
string GetUserPem(string id);
|
||||
string SignAndGetSignatureHeader(DateTime date, string actor, string host, string digest, string inbox);
|
||||
string ComputeSha256Hash(string data);
|
||||
}
|
||||
|
||||
public class CryptoService : ICryptoService
|
||||
|
@ -49,5 +51,16 @@ namespace BirdsiteLive.Domain
|
|||
var header = "keyId=\"" + actor + "\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest\",signature=\"" + sig64 + "\"";
|
||||
return header;
|
||||
}
|
||||
|
||||
public string ComputeSha256Hash(string data)
|
||||
{
|
||||
// Create a SHA256
|
||||
using (SHA256 sha256Hash = SHA256.Create())
|
||||
{
|
||||
// ComputeHash - returns byte array
|
||||
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(data));
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@ namespace BirdsiteLive.Domain
|
|||
public interface IUserService
|
||||
{
|
||||
Actor GetUser(TwitterUser twitterUser);
|
||||
Task<bool> FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityFollow activity);
|
||||
Task<bool> UndoFollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityUndoFollow activity);
|
||||
Task<bool> FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityFollow activity, string body);
|
||||
Task<bool> UndoFollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityUndoFollow activity, string body);
|
||||
}
|
||||
|
||||
public class UserService : IUserService
|
||||
|
@ -79,10 +79,10 @@ namespace BirdsiteLive.Domain
|
|||
return user;
|
||||
}
|
||||
|
||||
public async Task<bool> FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityFollow activity)
|
||||
public async Task<bool> FollowRequestedAsync(string signature, string method, string path, string queryString, Dictionary<string, string> requestHeaders, ActivityFollow activity, string body)
|
||||
{
|
||||
// Validate
|
||||
var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders);
|
||||
var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders, body);
|
||||
if (!sigValidation.SignatureIsValidated) return false;
|
||||
|
||||
// Save Follow in DB
|
||||
|
@ -130,10 +130,10 @@ namespace BirdsiteLive.Domain
|
|||
}
|
||||
|
||||
public async Task<bool> UndoFollowRequestedAsync(string signature, string method, string path, string queryString,
|
||||
Dictionary<string, string> requestHeaders, ActivityUndoFollow activity)
|
||||
Dictionary<string, string> requestHeaders, ActivityUndoFollow activity, string body)
|
||||
{
|
||||
// Validate
|
||||
var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders);
|
||||
var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders, body);
|
||||
if (!sigValidation.SignatureIsValidated) return false;
|
||||
|
||||
// Save Follow in DB
|
||||
|
@ -162,8 +162,22 @@ namespace BirdsiteLive.Domain
|
|||
return result == HttpStatusCode.Accepted;
|
||||
}
|
||||
|
||||
private async Task<SignatureValidationResult> ValidateSignature(string actor, string rawSig, string method, string path, string queryString, Dictionary<string, string> requestHeaders)
|
||||
private async Task<SignatureValidationResult> ValidateSignature(string actor, string rawSig, string method, string path, string queryString, Dictionary<string, string> requestHeaders, string body)
|
||||
{
|
||||
//Check Date Validity
|
||||
var date = requestHeaders["date"];
|
||||
var d = DateTime.Parse(date).ToUniversalTime();
|
||||
var now = DateTime.UtcNow;
|
||||
var delta = Math.Abs((d - now).TotalSeconds);
|
||||
if (delta > 30) return new SignatureValidationResult { SignatureIsValidated = false };
|
||||
|
||||
//Check Digest
|
||||
var digest = requestHeaders["digest"];
|
||||
var digestHash = digest.Split(new [] {"SHA-256="},StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
|
||||
var calculatedDigestHash = _cryptoService.ComputeSha256Hash(body);
|
||||
if (digestHash != calculatedDigestHash) return new SignatureValidationResult { SignatureIsValidated = false };
|
||||
|
||||
//Check Signature
|
||||
var signatures = rawSig.Split(',');
|
||||
var signature_header = new Dictionary<string, string>();
|
||||
foreach (var signature in signatures)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UserSecretsId>d21486de-a812-47eb-a419-05682bb68856</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<Version>0.1.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace BirdsiteLive.Controllers
|
|||
case "Follow":
|
||||
{
|
||||
var succeeded = await _userService.FollowRequestedAsync(signature, r.Method, r.Path,
|
||||
r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityFollow);
|
||||
r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityFollow, body);
|
||||
if (succeeded) return Accepted();
|
||||
else return Unauthorized();
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ namespace BirdsiteLive.Controllers
|
|||
if (activity is ActivityUndoFollow)
|
||||
{
|
||||
var succeeded = await _userService.UndoFollowRequestedAsync(signature, r.Method, r.Path,
|
||||
r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityUndoFollow);
|
||||
r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityUndoFollow, body);
|
||||
if (succeeded) return Accepted();
|
||||
else return Unauthorized();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace BirdsiteLive.Controllers
|
|||
[Route("/nodeinfo/{id}.json")]
|
||||
public IActionResult NodeInfo(string id)
|
||||
{
|
||||
var version = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(3);
|
||||
|
||||
if (id == "2.0")
|
||||
{
|
||||
var nodeInfo = new NodeInfoV20
|
||||
|
@ -66,7 +68,7 @@ namespace BirdsiteLive.Controllers
|
|||
software = new Software()
|
||||
{
|
||||
name = "birdsitelive",
|
||||
version = "0.1.0"
|
||||
version = version
|
||||
},
|
||||
protocols = new[]
|
||||
{
|
||||
|
@ -101,7 +103,7 @@ namespace BirdsiteLive.Controllers
|
|||
software = new SoftwareV21()
|
||||
{
|
||||
name = "birdsitelive",
|
||||
version = "0.1.0",
|
||||
version = version,
|
||||
repository = "https://github.com/NicolasConstant/BirdsiteLive"
|
||||
},
|
||||
protocols = new[]
|
||||
|
|
|
@ -36,11 +36,14 @@
|
|||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
<a href="https://github.com/NicolasConstant/BirdsiteLive">Github</a> @*<a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>*@
|
||||
</div>
|
||||
</footer>
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
|
||||
<a href="https://github.com/NicolasConstant/BirdsiteLive">Github</a> @*<a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>*@
|
||||
|
||||
<span style="float: right;">BirdsiteLIVE @System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(3)</span>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
|
|
Reference in a new issue