using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using API_NetFramework.Models; using Swashbuckle.Application; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Web; using System.Web.Configuration; namespace SecuringWebApiUsingApiKey.Middleware { public static class StringCipher { // This constant is used to determine the keysize of the encryption algorithm in bits. // We divide this by 8 within the code below to get the equivalent number of bytes. private const int Keysize = 256; // This constant determines the number of iterations for the password bytes generation function. private const int DerivationIterations = 1000; public static string Encrypt(string plainText, string passPhrase) { // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text // so that the same Salt and IV values can be used when decrypting. var saltStringBytes = Generate256BitsOfRandomEntropy(); var ivStringBytes = Generate256BitsOfRandomEntropy(); var plainTextBytes = Encoding.UTF8.GetBytes(plainText); using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations)) { var keyBytes = password.GetBytes(Keysize / 8); using (var symmetricKey = new RijndaelManaged()) { symmetricKey.BlockSize = 256; symmetricKey.Mode = CipherMode.CBC; symmetricKey.Padding = PaddingMode.PKCS7; using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes)) { using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes. var cipherTextBytes = saltStringBytes; cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray(); cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray(); memoryStream.Close(); cryptoStream.Close(); return Convert.ToBase64String(cipherTextBytes); } } } } } } public static string Decrypt(string cipherText, string passPhrase) { // Get the complete stream of bytes that represent: // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText] var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText); // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes. var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray(); // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes. var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray(); // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string. var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray(); using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations)) { var keyBytes = password.GetBytes(Keysize / 8); using (var symmetricKey = new RijndaelManaged()) { symmetricKey.BlockSize = 256; symmetricKey.Mode = CipherMode.CBC; symmetricKey.Padding = PaddingMode.PKCS7; using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes)) { using (var memoryStream = new MemoryStream(cipherTextBytes)) { using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) using (var streamReader = new StreamReader(cryptoStream, Encoding.UTF8)) { return streamReader.ReadToEnd(); } } } } } } private static byte[] Generate256BitsOfRandomEntropy() { var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits. using (var rngCsp = new RNGCryptoServiceProvider()) { // Fill the array with cryptographically secure random bytes. rngCsp.GetBytes(randomBytes); } return randomBytes; } } public static class ApiKeyMiddleware { public static string[] apikeys; public static string GetValue( string key) { string res = WebConfigurationManager.AppSettings[key]; return res; } private static bool checkfunction(string apikey, string function) { string decryptstring = SecuringWebApiUsingApiKey.Middleware.StringCipher.Decrypt(apikey, "OnDoc01"); if ( decryptstring.Contains(function)) { return true; } else return false; } public static Boolean Authorized(HttpRequestMessage request, string function) { if (GetValue("AuthCheck") == "Yes") { apikeys = GetValue("APIKeys").ToString().Split(','); for (int i = 0; i < apikeys.Length; i++) { apikeys[i] = apikeys[i].Replace(Environment.NewLine, ""); } IEnumerable> queryParams = request.GetQueryNameValuePairs(); var key = queryParams.FirstOrDefault(x => x.Key == "api_key"); if (apikeys.Contains(key.Value) && checkfunction(key.Value,function)==true) { return true; } try { IEnumerable headerValues = request.Headers.GetValues("api_key"); string apikey = headerValues.FirstOrDefault(); if (apikeys.Contains(apikey) && checkfunction(apikey,function)==true) { return true; } } catch { } try { if (request.Headers.Authorization.Scheme == "Bearer" && apikeys.Contains(request.Headers.Authorization.Parameter.ToString()) && checkfunction(request.Headers.Authorization.Parameter.ToString(),function)==true) { return true; } } catch { APILogging.Log(request, "Unberechtigter Zugriff", LogLevelType.Error); return false; } } APILogging.Log(request, "Unberechtigter Zugriff", LogLevelType.Error); return false; } //private readonly RequestDelegate _next; //private const string APIKEYNAME = "ApiKey"; //public ApiKeyMiddleware(RequestDelegate next) //{ // _next = next; //} //public async Task InvokeAsync(Microsoft.AspNetCore.Http.HttpContext context) //{ // var appSettings = context.RequestServices.GetRequiredService(); // string apiCheck = GetValue("ApiCheck"); // if (apiCheck == "e913aab4-c2c5-4e33-ad24-d25848f748e7") // { // await _next(context); // return; // } // if (!context.Request.Headers.TryGetValue(APIKEYNAME, out var extractedApiKey)) // { // context.Response.StatusCode = 401; // await context.Response.WriteAsync("Api Key was not provided. (Using ApiKeyMiddleware) "); // return; // } // var apiKey = GetValue(APIKEYNAME); // string[] keys = apiKey.Split(','); // bool tokenok = false; // for (int i = 0; i < keys.Length; i++) // if (keys[i] == extractedApiKey) // { // tokenok = true; // break; // } // //if (!apiKey.Equals(extractedApiKey)) // if (!tokenok) // { // context.Response.StatusCode = 401; // await context.Response.WriteAsync // ("Unauthorized client. (Using ApiKeyMiddleware)"); // return; // } // await _next(context); //} } }