validate digest, fix #13
This commit is contained in:
parent
5d86ebf618
commit
20a05e9e9f
4 changed files with 30 additions and 20 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,7 +162,7 @@ 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"];
|
||||
|
@ -171,6 +171,12 @@ namespace BirdsiteLive.Domain
|
|||
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>();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Reference in a new issue