示例#1
0
        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)
            {
                var m = HeaderRegexes.HeaderSignature.Match(signature);

                signature_header.Add(m.Groups[1].ToString(), m.Groups[2].ToString());
            }

            var key_id    = signature_header["keyId"];
            var headers   = signature_header["headers"];
            var algorithm = signature_header["algorithm"];
            var sig       = Convert.FromBase64String(signature_header["signature"]);

            // Retrieve User
            var remoteUser = await _activityPubService.GetUser(actor);

            // Prepare Key data
            var toDecode = remoteUser.publicKey.publicKeyPem.Trim().Remove(0, remoteUser.publicKey.publicKeyPem.IndexOf('\n'));

            toDecode = toDecode.Remove(toDecode.LastIndexOf('\n')).Replace("\n", "");
            var signKey = ASN1.ToRSA(Convert.FromBase64String(toDecode));

            var toSign = new StringBuilder();

            foreach (var headerKey in headers.Split(' '))
            {
                if (headerKey == "(request-target)")
                {
                    toSign.Append($"(request-target): {method.ToLower()} {path}{queryString}\n");
                }
                else
                {
                    toSign.Append($"{headerKey}: {string.Join(", ", requestHeaders[headerKey])}\n");
                }
            }
            toSign.Remove(toSign.Length - 1, 1);

            // Import key
            var key        = new RSACryptoServiceProvider();
            var rsaKeyInfo = key.ExportParameters(false);

            rsaKeyInfo.Modulus = Convert.FromBase64String(toDecode);
            key.ImportParameters(rsaKeyInfo);

            // Trust and Verify
            var result = signKey.VerifyData(Encoding.UTF8.GetBytes(toSign.ToString()), sig, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

            return(new SignatureValidationResult()
            {
                SignatureIsValidated = result,
                User = remoteUser
            });
        }
    }
        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)
            {
                var splitSig = signature.Replace("\"", string.Empty).Split('=');

                signature_header.Add(splitSig[0], splitSig[1]);
            }

            signature_header["signature"] = signature_header["signature"] + "==";

            var key_id    = signature_header["keyId"];
            var headers   = signature_header["headers"];
            var algorithm = signature_header["algorithm"];
            var sig       = Convert.FromBase64String(signature_header["signature"]);


            var remoteUser = await _activityPubService.GetUser(actor);

            var toDecode = remoteUser.publicKey.publicKeyPem.Trim().Remove(0, remoteUser.publicKey.publicKeyPem.IndexOf('\n'));

            toDecode = toDecode.Remove(toDecode.LastIndexOf('\n')).Replace("\n", "");
            var signKey = ASN1.ToRSA(Convert.FromBase64String(toDecode));

            var toSign = new StringBuilder();

            //var comparisonString = headers.Split(' ').Select(signed_header_name =>
            //{
            //    if (signed_header_name == "(request-target)")
            //        return "(request-target): post /inbox";
            //    else
            //        return $"{signed_header_name}: {r.Headers[signed_header_name.ToUpperInvariant()]}";
            //});

            foreach (var headerKey in headers.Split(' '))
            {
                if (headerKey == "(request-target)")
                {
                    toSign.Append($"(request-target): {method.ToLower()} {path}{queryString}\n");
                }
                else
                {
                    toSign.Append($"{headerKey}: {string.Join(", ", requestHeaders[headerKey])}\n");
                }
            }
            toSign.Remove(toSign.Length - 1, 1);

            //var signKey = ASN1.ToRSA(Convert.FromBase64String(toDecode));

            //new RSACryptoServiceProvider(keyId.publicKey.publicKeyPem);

            //Create a new instance of RSACryptoServiceProvider.
            RSACryptoServiceProvider key = new RSACryptoServiceProvider();

            //Get an instance of RSAParameters from ExportParameters function.
            RSAParameters RSAKeyInfo = key.ExportParameters(false);

            //Set RSAKeyInfo to the public key values.
            RSAKeyInfo.Modulus = Convert.FromBase64String(toDecode);

            key.ImportParameters(RSAKeyInfo);

            var result = signKey.VerifyData(Encoding.UTF8.GetBytes(toSign.ToString()), sig, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

            return(new SignatureValidationResult()
            {
                SignatureIsValidated = result,
                User = remoteUser
            });
        }
    }
示例#3
0
        public async Task <Tuple <bool, string> > VerifyHttpSignature(HttpContext context)
        {
            var signatureHeader = context.Request.Headers["Signature"].FirstOrDefault();

            if (signatureHeader == null)
            {
                return(new Tuple <bool, string>(true, null));
            }
            var parameters = signatureHeader.Replace("\\\"", "\n").Split(',').Select((a) => a.Split(new[] { '=' }, 2)).ToDictionary((a) => a[0], (a) => a[1].Trim('"').Replace("\n", "\\\""));

            if (!parameters.ContainsKey("keyId") || !parameters.ContainsKey("algorithm") || !parameters.ContainsKey("signature"))
            {
                return(new Tuple <bool, string>(false, null));
            }
            if (!parameters.ContainsKey("headers"))
            {
                parameters["headers"] = "date";
            }
            var key = await _entityStore.GetEntity(parameters["keyId"], true);

            if (key == null)
            {
                return(new Tuple <bool, string>(false, null));
            }

            var owner = await _entityStore.GetEntity(key.Data["owner"].First().Id ?? (string)key.Data["owner"].First().Primitive, true);

            if (!owner.Data["publicKey"].Any((a) => a.Id == key.Id))
            {
                return(new Tuple <bool, string>(false, null));
            }

            var stringKey = (string)key.Data["publicKeyPem"].First().Primitive;

            if (!stringKey.StartsWith("-----BEGIN PUBLIC KEY-----"))
            {
                return(new Tuple <bool, string>(false, null));
            }

            var toDecode = stringKey.Trim().Remove(0, stringKey.IndexOf('\n'));

            toDecode = toDecode.Remove(toDecode.LastIndexOf('\n')).Replace("\n", "");

            var signKey = ASN1.ToRSA(Convert.FromBase64String(toDecode));

            var toSign = new StringBuilder();

            foreach (var headerKey in parameters["headers"].Split(' '))
            {
                if (headerKey == "(request-target)")
                {
                    toSign.Append($"(request-target): {context.Request.Method.ToLower()} {context.Request.Path}{context.Request.QueryString}\n");
                }
                else
                {
                    toSign.Append($"{headerKey}: {string.Join(", ", context.Request.Headers[headerKey])}\n");
                }
            }
            toSign.Remove(toSign.Length - 1, 1);

            var signature = Convert.FromBase64String(parameters["signature"]);

            switch (parameters["algorithm"])
            {
            case "rsa-sha256":
                return(new Tuple <bool, string>(signKey.VerifyData(Encoding.UTF8.GetBytes(toSign.ToString()), signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), owner.Id));
            }

            return(new Tuple <bool, string>(false, owner.Id));
        }