laatzen/Common/Cryptology/Security/CryptInformation.cs

292 lines
11 KiB
C#

using System;
using System.IO;
using System.Management;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Xylem.Common.CommonCore.Consts;
namespace Xylem.Common.Cryptology.Security
{
/// <summary>
/// Cryptology information container
/// </summary>
public static class CryptInformation
{
/// <summary>
/// Separator for PC name from hardware information
/// </summary>
public const String SeparatorPcFromHwId = @"\";
/// <summary>
/// Get domain from local machine
/// </summary>
/// <returns> domain </returns>
/// <remarks date="2021-Jan-30" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetSysDomain()
{
// Collect key information from HW and user
var userInformation = GetDomainAndUserLoginName();
var userInformationFields = userInformation.Split(Convert.ToChar("\\"));
return userInformationFields[0];
}
/// <summary>
/// Get user login name from local machine
/// </summary>
/// <returns> user login name </returns>
/// <remarks date="2021-Jan-30" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Jun-01" author="Thomas Wiedebusch">
/// - Convert to upper to get rid of the case sensitive user login name.
/// </remarks>
public static String GetSysUserLoginName()
{
// Collect key information from HW and user
var userInformation = GetDomainAndUserLoginName();
var userInformationFields = userInformation.Split(Convert.ToChar("\\"));
return userInformationFields[1].ToUpper();
}
/// <summary>
/// User login name including the domain e.g. "SPXMLU\bauer_marc"
/// </summary>
/// <remarks date="2021-Jan-21" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Jun-01" author="Thomas Wiedebusch">
/// - Private function as user name is case sensitive.
/// </remarks>
private static String GetDomainAndUserLoginName()
{
return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
}
/// <summary>
/// Getting local PC name which is useful for inter-program communication for operators to
/// select the right PC for update operation.
/// </summary>
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetSysPcName()
{
return Environment.MachineName;
}
/// <summary>
/// Getting the PC name out of the system information string which is useful for inter-program
/// communication for operators to select the right PC for update operation.
/// </summary>
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetPcNameFromHwId(String hardwareId)
{
if (!hardwareId.Contains(SeparatorPcFromHwId)) return Constants.StrUnknown;
var hwIdFields = hardwareId.Split(Convert.ToChar(SeparatorPcFromHwId));
return hwIdFields[0];
}
/// <summary>
/// User password hash replaced by random code if user is not registered or valid date is expired
/// </summary>
/// <remarks date="2021-Mar-19" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Mar-22" author="Thomas Wiedebusch">
/// - Replace "-" with blank in random code.
/// </remarks>
public static String GetSysUserPasswordHash(UserInformation sysUser)
{
var randomCode = BitConverter.ToString(Cryptology.BuildRandomValue(32)).Replace("-", "");
// Take the validation date for to decide for new random code.
if (sysUser == null || string.IsNullOrEmpty(sysUser.PasswordHash) ||
DateTimeOffset.Compare(sysUser.ValidDate, DateTimeOffset.Now) < 1) return randomCode;
// if the registration valid date is not outdated, the sys user password shall remain as is
return sysUser.PasswordHash;
}
/// <summary>
/// Check user input for "full name".
/// </summary>
/// <param name="name">full user name for check</param>
/// <returns>true if user name matches the:
/// - Start with capital letter,
/// - one or more lowercase letters,
/// - white space and at least
/// - one trailing word,
/// - double names separated with - or ' are allowed as well as special characters
/// like umlaut in German or Spain...
/// </returns>
/// <remarks date="2021-Feb-08" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Apr-13" author="Thomas Wiedebusch">
/// - Check name for null or empty.
/// </remarks>
public static Boolean CheckUserFullNameFormat(String name)
{
return !string.IsNullOrEmpty(name) && Regex.Match(name, @"\b\p{Lu}[-'\w]+(\s[-'\w]+)+$").Success;
}
/// <summary>
/// Check if the decoding is possible by comparison of the reg user with the sys user.
/// All information needs to be checked including the proper assigned FullName and the pwd hash.
/// </summary>
/// <param name="regUser"></param>
/// <returns>true if all information is set for decoding</returns>
/// <remarks date="2021-Mar-15" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Mar-20" author="Thomas Wiedebusch">
/// - GetSysUserPasswordHash.
/// </remarks>
public static Boolean IsDecodingPossible(UserInformation regUser)
{
if (regUser == null || string.IsNullOrEmpty(regUser.FullName)) return false;
return regUser.Domain == GetSysDomain() &&
regUser.LogInName == GetSysUserLoginName() &&
regUser.HardwareId == GetSysHardwareId() &&
regUser.PasswordHash == GetSysUserPasswordHash(regUser);
}
/// <summary>
/// Read the sys user from Win10 system.
/// </summary>
/// <param name="sysUser"></param>
/// <remarks date="2021-Mar-15" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Mar-19" author="Thomas Wiedebusch">
/// - Take the sys user as input.
/// </remarks>
public static void GetSysUser(UserInformation sysUser)
{
sysUser.Domain = GetSysDomain();
sysUser.LogInName = GetSysUserLoginName();
sysUser.HardwareId = GetSysHardwareId();
sysUser.PasswordHash = GetSysUserPasswordHash(sysUser);
}
/// <summary>
/// Write the user registration from the registration file on the local HDD.
/// </summary>
/// <param name="pathFile"></param>
/// <param name="dbFullRegUser"></param>
/// <returns>true if file exists and user has at least the FullName being set</returns>
/// <remarks date="2021-Mar-15" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static Boolean WriteUserRegistration(String pathFile, UserInformation dbFullRegUser)
{
// Register user to local HDD if the DB user is not identical
if (string.IsNullOrEmpty(pathFile)) return false;
try
{
// Store user registration from ..[User]/AppData/Roaming/Genesis.
var serializedData = JsonConvert.SerializeObject(dbFullRegUser);
var asciiStream = Encoding.UTF8.GetBytes(serializedData);
File.WriteAllBytes(pathFile, asciiStream);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// Read the user registration from the registration file on the local HDD.
/// </summary>
/// <param name="pathFile"></param>
/// <param name="regUser"></param>
/// <returns>true if file exists and user has at least the FullName being set</returns>
/// <remarks date="2021-Mar-15" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Jun-01" author="Thomas Wiedebusch">
/// - Convert to upper to get rid of the case sensitive user login name.
/// </remarks>
public static Boolean ReadUserRegistration(String pathFile, out UserInformation regUser)
{
regUser = null;
try
{
if (!File.Exists(pathFile)) return false;
regUser = new UserInformation();
// load user registration from ..[User]/AppData/Roaming/Genesis
var asciiStream = File.ReadAllBytes(pathFile);
var serializedData = Encoding.UTF8.GetString(asciiStream, 0, asciiStream.Length);
regUser = JsonConvert.DeserializeObject<UserInformation>(serializedData);
regUser.LogInName = regUser.LogInName.ToUpper();
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// Bios version of user PC
/// </summary>
/// <remarks date="2021-Jan-20" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
public static String GetBiosVersion()
{
var bios = new ManagementObjectSearcher("SELECT Version FROM Win32_BIOS");
var biosCollection = bios.Get();
var strBios = new StringBuilder();
foreach (var obj in biosCollection)
{
strBios.Append(obj["Version"]);
}
return strBios.ToString();
}
/// <summary>
/// Hardware identification of user PC based on UUID and processor ID
/// </summary>
/// <remarks date="2021-Jan-20" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2021-Apr-08" author="Thomas Wiedebusch">
/// - Add PC-Name to the HW Id to inform the FwUpdateBuilder operator about the PC.
/// </remarks>
public static String GetSysHardwareId()
{
var strHwId = new StringBuilder();
var pcName = GetSysPcName();
strHwId.Append(pcName);
strHwId.Append(SeparatorPcFromHwId);
var computerSystem = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct");
var computerSystemCollection = computerSystem.Get();
foreach (var obj in computerSystemCollection)
{
strHwId.Append(obj["UUID"]);
}
strHwId.Append("-");
var processorInfo = new ManagementObjectSearcher("SELECT ProcessorID From Win32_processor");
var processorInfoCollection = processorInfo.Get();
foreach (var obj in processorInfoCollection)
{
strHwId.Append(obj["ProcessorID"]);
}
return strHwId.ToString();
}
}
}