using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
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, int) ImageValidateByStream(Stream stream)
{
int length = 10240;
byte[] bytes = new byte[length];
BinaryReader br = new BinaryReader(stream);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++)
{
byte tempByte = br.ReadByte();
bytes[i] = tempByte;
stringBuilder.Append(Convert.ToString(tempByte, 16));
stringBuilder.Append(",");
}
stream.Position = 0; //指針回歸為0
string fileheader = stringBuilder.ToString().ToUpper();
if (string.IsNullOrWhiteSpace(fileheader))
return (false, "", 0);
if (fileheader.StartsWith("FF,D8,") || fileheader.StartsWith("42,4D,"))
{
int i = 2;
int depth;
while (true)
{
int marker = (bytes[i] & 0xff) << 8 | (bytes[i + 1] & 0xff);
int size = (bytes[i + 2] & 0xff) << 8 | (bytes[i + 3] & 0xff);
if (marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 && marker != 0xffc8)
{
depth = (bytes[i + 4] & 0xff) * (bytes[i + 9] & 0xff);
break;
}
else i += size + 2;
}
return (true, "jpg", depth);
}
if (fileheader.StartsWith("89,50,4E,47,D,A,1A,A,"))
{
int depth = bytes[24] & 0xff;
if ((bytes[25] & 0xff) == 2) depth *= 3;
else if ((bytes[25] & 0xff) == 6) depth *= 4;
return (true, "png", depth);
}
if (fileheader.StartsWith("47,49,46,38,39,61,") || fileheader.StartsWith("47,49,46,38,37,61,"))
return (true, "gif", 0);
if (fileheader.StartsWith("1,0,0,0,"))
return (true, "emf", 0);
if (fileheader.StartsWith("1,0,9,0,0,3"))
return (true, "wmf", 0);
//if (fileheader.StartsWith("4D,4D") || fileheader.StartsWith("49,49") || fileheader.StartsWith("46,4F,52,4D"))
// return (true, "tif");
return (false, "", 0);
}
///
/// 轉換EMF為PNG格式
///
///
///
public static string ConvertEMFtoPNG(Stream stream)
{
using var image = Image.FromStream(stream);
//GDI+報錯,Azure Web App沙箱不支持GDI+部分權限
//using var nbase64ms = new MemoryStream();
//image.Save(nbase64ms, ImageFormat.Png); //保存為PNG格式
//byte[] data = nbase64ms.ToArray();
//string base64 = Convert.ToBase64String(data);
//return base64;
//Azure Web App沙箱不支持GDI+渲染部分EMF指令,可以出圖但會是空白
var pngimage = new Bitmap(image.Width, image.Height);
using (var graphics = Graphics.FromImage(pngimage))
{
graphics.CompositingQuality = CompositingQuality.HighSpeed;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(image, 0, 0, image.Width, image.Height);
using var nbase64ms = new MemoryStream();
pngimage.Save(nbase64ms, ImageFormat.Png); //保存為PNG格式
byte[] data = nbase64ms.ToArray();
string base64 = Convert.ToBase64String(data);
return base64;
}
}
#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
}
}