private async Task <RSA> GetRSAProviderFromCertAsync(RequestSignature reqSignature) { _ = reqSignature ?? throw new ArgumentNullException(nameof(reqSignature)); _ = reqSignature.KeyId ?? throw new InvalidOperationException($"{nameof(reqSignature.KeyId)} is null"); var certUri = new Uri($"{_config.SmartThingsCertUriRoot}{reqSignature.KeyId}"); var certBytes = await _httpClient.GetByteArrayAsync(certUri).ConfigureAwait(false); if (certBytes?.Length > 0) { using X509Certificate2 cert = new(certBytes); return(cert.GetRSAPublicKey()); } return(null); }
public async Task <bool> VerifySignedRequestAsync(HttpRequest request) { _ = request ?? throw new ArgumentNullException(nameof(request)); _logger.LogDebug($"Verifying sign request: {request.Path}"); var reqSignature = RequestSignature.ParseFromHeaderVal(request.Headers["Authorization"].FirstOrDefault()); var hash = GetHash(reqSignature, request); var data = Convert.FromBase64String(reqSignature.Signature); var publicKeyProvider = await GetRSAProviderFromCertAsync(reqSignature).ConfigureAwait(false); if (publicKeyProvider != null) { return(publicKeyProvider.VerifyData(hash, data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); } else { return(false); } }
private static byte[] GetHash(RequestSignature reqSignature, HttpRequest request) { var siginingString = new StringBuilder(); int headerCount = reqSignature.Headers.Count(); for (int i = 0; i < headerCount; i++) { var h = reqSignature.Headers.ElementAt(i); if (h == "(request-target)") { siginingString.Append("(request-target): "); siginingString.Append(request.Method.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); siginingString.Append(' '); siginingString.Append(request.Path); } else { if (!request.Headers.TryGetValue(h, out StringValues vals)) { throw new InvalidOperationException($"Missing {h} header per the auth header!"); } siginingString.Append(h); siginingString.Append(": "); siginingString.Append(vals.FirstOrDefault()); } if (i < (headerCount - 1)) { siginingString.Append('\n'); } } var val = siginingString.ToString(); var encoding = UTF8Encoding.UTF8; return(encoding.GetBytes(val)); }