|
|
using Newtonsoft.Json.Linq; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Azure.Identity; using Azure.Security.KeyVault.Secrets;
namespace CDP { public class Helpers { public static byte[] GenerateAES256Key() { using (Aes aesAlg = Aes.Create()) { aesAlg.KeySize = 256; aesAlg.GenerateKey(); return aesAlg.Key; } }
// hashes a string and removes the dashes (-)
public static string HashToHex(string str) { using (SHA256 sha256Hash = SHA256.Create()) { byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(str)); return BitConverter.ToString(bytes).Replace("-", string.Empty).ToLower(); } }
// takes a short hash and converts it to normal hash.
// Circle Auth uses hashes stored as hex...use this to convert to that format.
public static string ConvertShortHashToHex(string shortHash) { // Add padding characters ('=') to the short hash if needed
while (shortHash.Length % 4 != 0) { shortHash += "="; }
// Decode the Base64 short hash to bytes
byte[] hashBytes = Convert.FromBase64String(shortHash);
// Convert the bytes to a hexadecimal string
string hexHash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
return hexHash; }
// Generates an AES Key and converts it to base64
public static string GenerateAES256KeyToBase64() { return Convert.ToBase64String(GenerateAES256Key()); }
// Generates a guid, removes the - and then converts it to base64
public static string GenerateShortGuid() { Guid guid = Guid.NewGuid(); byte[] bytes = guid.ToByteArray();
string shortGuid = Convert.ToBase64String(bytes);
// Remove padding characters from the end of the Base64 string
shortGuid = shortGuid.TrimEnd('=');
return shortGuid; } public static Guid LengthenShortGuid(string shortGuid) { // Add padding characters to the end of the Base64 string, if needed
while (shortGuid.Length % 4 != 0) { shortGuid += "="; }
// Convert the Base64 string back to bytes
byte[] bytes = Convert.FromBase64String(shortGuid);
// Create a new GUID from the bytes
Guid guid = new Guid(bytes);
return guid; }
public static bool VerifyData(string originalMessage, string signedMessage) { bool success = false; using (var rsa = new RSACryptoServiceProvider()) { var encoder = new UTF8Encoding(); byte[] bytesToVerify = encoder.GetBytes(originalMessage); byte[] signedBytes = Convert.FromBase64String(signedMessage); try { rsa.FromXmlString(Constants.PublicKey);
SHA512Managed Hash = new SHA512Managed();
byte[] hashedData = Hash.ComputeHash(signedBytes);
success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes); } catch (CryptographicException e) { Console.WriteLine(e.Message); } finally { rsa.PersistKeyInCsp = false; } } return success; } public static string ComputeSignature(string stringToSign, string secret) { using (var hmacsha256 = new HMACSHA256(System.Text.ASCIIEncoding.UTF8.GetBytes(secret))) { var bytes = Encoding.ASCII.GetBytes(stringToSign); var hashedBytes = hmacsha256.ComputeHash(bytes); return Convert.ToBase64String(hashedBytes); } }
public static async Task<dynamic> GetSession(string sessionId) { string toSign = string.Format($"?s={sessionId}"); string sig = Helpers.ComputeSignature(toSign, Constants.CDPWriteKey); string URL = string.Format($"https://circleauth.gocircle.ai/api/session/{toSign}&signature={sig}");
try { HttpClient client = new HttpClient(); client.Timeout = new TimeSpan(0, 1, 0, 0); client.DefaultRequestHeaders.Add("x-ua-appKey", Constants.CDPAppKey); var response = await client.GetAsync(URL); if (response.StatusCode == System.Net.HttpStatusCode.OK) { string responseString = await response.Content.ReadAsStringAsync(); dynamic obj = JObject.Parse(responseString); dynamic data = obj.data;
return data; } } catch (Exception e) { Console.WriteLine(e.Message); }
return null; }
public static async Task<Boolean> ExpireSession(string sessionId, string userId) { try { var dataObj = new { sessionID = sessionId, userID = userId }; var sig = Helpers.ComputeSignature(JsonConvert.SerializeObject(dataObj), Constants.CDPWriteKey); var obj = new { data = dataObj, signature = sig };
HttpClient client = new HttpClient(); client.Timeout = new TimeSpan(0, 1, 0, 0); client.DefaultRequestHeaders.Add("x-ua-appKey", Constants.CDPAppKey); var content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json");
var r = client.PostAsync("https://circleaccess.circlesecurity.ai/api/user/session/expire", content).Result; return r.StatusCode == HttpStatusCode.OK; } catch (Exception e) { Console.WriteLine(e); } return false; }
/// <summary>
/// this is the HASH that Circle Auth likes, it's just a SHA265 in hex.
/// </summary>
public static string HashText(string rawData) { try { // Create a SHA256
using SHA256 sha256Hash = SHA256.Create(); byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData)); StringBuilder builder = new(); for (int i = 0; i < bytes.Length; i++) { builder.Append(bytes[i].ToString("x2")); } return builder.ToString(); } catch (Exception ex) { return null; } } public static string HashAndShortenText(string text) { // Hash the email address using SHA-256
using (SHA256 sha256 = SHA256.Create()) { byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(text));
string shortHash = Convert.ToBase64String(hashBytes);
// make the short hash URL friendly
shortHash = shortHash.Replace("+", "-").Replace("/", "_");
// Remove padding characters from the end of the Base64 string
shortHash = shortHash.TrimEnd('=');
return shortHash; } } public static async Task<SingleLogin> CreateSession(string customerAppKey, string returnURL, string payloadJson, string webHook = "") { var client = new HttpClient();
// wacky hack since I can't declare anonymous variables without initializing them
var payloadObject = new { Test = "123" };
var dataObj = new { payload = payloadJson, customerAppKey = customerAppKey, customID = "blahORama", returnUrl = returnURL, mobileUrl = returnURL, webhookUrl = webHook };
var sig = Helpers.ComputeSignature(JsonConvert.SerializeObject(dataObj), Constants.CDPWriteKey); var obj = new { data = dataObj, signature = sig }; string json = JsonConvert.SerializeObject(obj);
client.DefaultRequestHeaders.Add("x-ua-appKey", Constants.CDPAppKey); HttpContent c = new StringContent(json, Encoding.UTF8, "application/json"); var response = await client.PostAsync(new Uri("https://circleaccess.circlesecurity.ai/api/single/create"), c);
SingleLogin sl = new SingleLogin(); if (response.StatusCode == System.Net.HttpStatusCode.OK) { string body = response.Content.ReadAsStringAsync().Result; //right!
dynamic stuff = JObject.Parse(body); sl.QRCodeUrl = stuff.data.qrcode.ToString(); sl.LoginId = stuff.data.singleLoginID.ToString(); return sl; }
return null; } }
public class KeyVaultService { private readonly string _keyVaultUrl;
public KeyVaultService(string keyVaultUrl) { _keyVaultUrl = keyVaultUrl; }
public async Task SetSecretAsync(string secretName, string secretValue) { #if DEBUG
var client = new SecretClient(new Uri(_keyVaultUrl), new VisualStudioCredential()); #else
var client = new SecretClient(new Uri(_keyVaultUrl), new DefaultAzureCredential()); #endif
// Set the secret in the Key Vault
await client.SetSecretAsync(secretName, secretValue); } public async Task<string> GetSecretAsync(string secretName) { #if DEBUG
var client = new SecretClient(new Uri(_keyVaultUrl), new VisualStudioCredential()); #else
var client = new SecretClient(new Uri(_keyVaultUrl), new DefaultAzureCredential()); #endif
// Set the secret in the Key Vault
KeyVaultSecret kvs = await client.GetSecretAsync(secretName); return kvs.Value; } }
public class SingleLogin { public string QRCodeUrl { get; set; } public string LoginId { get; set; } public SingleLogin() { }
public override string ToString() { return QRCodeUrl; } }
}
|