using Microsoft.AspNetCore.Cryptography.KeyDerivation; using Microsoft.IdentityModel.Tokens; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IdentityModel.Tokens.Jwt; using System.IO; using System.Security.Claims; using System.Security.Cryptography; using System.Text; namespace TEAMModelOS.SDK.Extension { public class Utils { private static RNGCryptoServiceProvider _random = new RNGCryptoServiceProvider(); public static string HashedPassword(string password, string salt) { byte[] hashBytes = KeyDerivation.Pbkdf2( password: password, salt: Encoding.UTF8.GetBytes(salt), //SHA1鹽(8-20字節),SHA256(32字節) prf: KeyDerivationPrf.HMACSHA1, iterationCount: 10000, //hash次數,越多次代表破解難度變高,但效能會差點 numBytesRequested: 256 / 8 //指定得出結果長度 ); string hashText = BitConverter.ToString(hashBytes).Replace("-", string.Empty); return hashText; } /// /// 建立真隨機字串(CSPRNG),適用密碼、鹽 /// /// 長度 /// 要限制的字元串(長度需大於等於8),如果為null或者小於8,預設為"abcdefghijklmnopqrstuvwxyz1234567890" /// public static string CreatSaltString(int stringLength, string key = null) { ReadOnlySpan span; if (key == null || key.Length < 8) span = "abcdefghijklmnopqrstuvwxyz1234567890"; else span = key.AsSpan(); int length = span.Length; StringBuilder randomString = new StringBuilder(length); for (int i = 0; i < stringLength; ++i) { randomString.Append(span[SetRandomSeeds(length)]); } return randomString.ToString(); } /// /// 建立真隨機整數數字(CSPRNG),適用亂數、隨機編號 /// /// 最大值 public static int CreatSaltInt(int max) { var bytes = new byte[4]; _random.GetBytes(bytes); int value = BitConverter.ToInt32(bytes, 0); value = value % (max + 1); if (value < 0) value = -value; return value; } /// /// 建立真隨機整數數字(CSPRNG),適用亂數、隨機編號 /// /// 最小值 /// 最大值 public static int CreatSaltInt(int min, int max) { int value = CreatSaltInt(max - min) + min; return value; } /// /// 剖析連接字串 /// /// /// public static Dictionary ParseConnectionString(string connectionString) { var d = new Dictionary(); foreach (var item in connectionString.Split(';', StringSplitOptions.RemoveEmptyEntries)) { var a = item.IndexOf('='); d.Add(item.Substring(0, a), item.Substring(a + 1)); } return d; } #region 圖片處理 /// /// 判斷圖片格式 /// /// 傳入Stream,注意請自行釋放 /// public static (bool, string) ImageValidateByStream(Stream stream) { int length = 20; BinaryReader br = new BinaryReader(stream); StringBuilder stringBuilder = new StringBuilder(); while (length > 0) { byte tempByte = br.ReadByte(); stringBuilder.Append(Convert.ToString(tempByte, 16)); stringBuilder.Append(","); length--; } stream.Position = 0; //指針回歸為0 string fileheader = stringBuilder.ToString().ToUpper(); if (string.IsNullOrWhiteSpace(fileheader)) return (false, ""); if (fileheader.StartsWith("FF,D8,") || fileheader.StartsWith("42,4D,")) return (true, "jpg"); if (fileheader.StartsWith("89,50,4E,47,D,A,1A,A,")) return (true, "png"); if (fileheader.StartsWith("47,49,46,38,39,61,") || fileheader.StartsWith("47,49,46,38,37,61,")) return (true, "gif"); //if (fileheader.StartsWith("4D,4D") || fileheader.StartsWith("49,49") || fileheader.StartsWith("46,4F,52,4D")) // return (true, "tif"); return (false, ""); } #endregion #region private private static int SetRandomSeeds(int length) { decimal maxValue = (decimal)long.MaxValue; byte[] array = new byte[8]; _random.GetBytes(array); return (int)(Math.Abs(BitConverter.ToInt64(array, 0)) / maxValue * length); } #endregion } }