using Edge.Core.Parser.BinaryParser.Util; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace ShengJuDesFireEv1CpuCardKeyLoader { public interface IKeyLoader { DecryptedKeySet Get(EncryptedBase64KeySet input); } public class DecryptedKeySet { public byte[] RootKey { get; set; } public byte[] 文件1读密钥 { get; set; } public byte[] 文件1读写密钥 { get; set; } public byte[] 文件2读密钥 { get; set; } public byte[] 文件2读写密钥 { get; set; } public byte[] 文件3读密钥 { get; set; } public byte[] 文件3读写密钥 { get; set; } public byte[] 文件4读密钥 { get; set; } public byte[] 文件4读写密钥 { get; set; } } public class InputBase64PlainKeySet { public string RootKey { get; set; } public string 文件1读密钥 { get; set; } public string 文件1读写密钥 { get; set; } public string 文件2读密钥 { get; set; } public string 文件2读写密钥 { get; set; } public string 文件3读密钥 { get; set; } public string 文件3读写密钥 { get; set; } public string 文件4读密钥 { get; set; } public string 文件4读写密钥 { get; set; } public string Description { get; set; } } public class EncryptedBase64KeySet { public string RootKey { get; set; } public string 文件1读密钥 { get; set; } public string 文件1读写密钥 { get; set; } public string 文件2读密钥 { get; set; } public string 文件2读写密钥 { get; set; } public string 文件3读密钥 { get; set; } public string 文件3读写密钥 { get; set; } public string 文件4读密钥 { get; set; } public string 文件4读写密钥 { get; set; } public string Description { get; set; } } public class LocalNetworkMacBasedEncryptionKeyLoader : IKeyLoader { private ILogger logger = NullLogger.Instance; public LocalNetworkMacBasedEncryptionKeyLoader(ILogger logger) { this.logger = logger; } /// <summary> /// </summary> /// <returns></returns> private byte[] GetEncryptionKeySeed() { var nics = NetworkInterface.GetAllNetworkInterfaces() .Where(i => i.SupportsMulticast && i.Supports(NetworkInterfaceComponent.IPv4) && i.NetworkInterfaceType == NetworkInterfaceType.Ethernet); List<byte[]> macAddresses = new List<byte[]>(); string logStr = ""; for (int i = 0; i < nics.Count(); i++) { var adapter = nics.ElementAt(i); IPInterfaceProperties properties = adapter.GetIPProperties(); // .GetIPInterfaceProperties(); logStr += $"===========Ethernet {i}: {adapter.Description}==========={Environment.NewLine}"; logStr += $" Interface type .......................... : {adapter.NetworkInterfaceType}" + Environment.NewLine; logStr += $" OperationalStatus ....................... : {adapter.OperationalStatus}" + Environment.NewLine; logStr += $" IpAddresses ....................... : " + $"{properties.UnicastAddresses.Select(ad => ad.Address).Where(ad => ad.AddressFamily == AddressFamily.InterNetwork).Select(i => i.ToString()).Aggregate("", (acc, n) => acc + ", " + n)}" + Environment.NewLine; logStr += $" Physical address ........................ : 0x{adapter.GetPhysicalAddress().GetAddressBytes().ToHexLogString()}" + Environment.NewLine; if (adapter.Description.Contains("Virtual", StringComparison.OrdinalIgnoreCase) || adapter.Description.Contains("docker", StringComparison.OrdinalIgnoreCase)) { logStr += " --->>Virutal Device<<---" + Environment.NewLine; continue; } macAddresses.Add(adapter.GetPhysicalAddress().GetAddressBytes()); } this.logger.LogInformation($"KeyLoader is preparing for GetEncryptionKey: {Environment.NewLine}{logStr}"); if (!macAddresses.Any()) throw new ArgumentException("Failed to generate Encryption Key from local Ethernet NetworkInterface mac addresses"); List<byte> raw = new List<byte>(); for (int i = 0; i < macAddresses[0].Length; i++) { byte accu = 0; for (int j = 0; j < macAddresses.Count; j++) { accu ^= macAddresses[j][i]; } raw.Add(accu); } //var base64Encoded = Convert.ToBase64String(raw.ToArray()); this.logger.LogInformation("raw EncryptionKey seed hex: 0x" + raw.ToHexLogString());// + ", base64 encoded: " + base64Encoded); return raw.ToArray(); } /// <summary> /// Get the 16 bytes encryption key /// </summary> /// <returns></returns> protected virtual byte[] GetEncryptionKey() { var encryptionKeySeed = this.GetEncryptionKeySeed(); byte[] symmetricKey = encryptionKeySeed.Concat(Enumerable.Range(0, 16 - encryptionKeySeed.Length).Select(i => (byte)i)).ToArray(); return symmetricKey; } public DecryptedKeySet Get(EncryptedBase64KeySet input) { var output = new DecryptedKeySet(); if (!string.IsNullOrEmpty(input.RootKey)) { Span<byte> buffer = new Span<byte>(new byte[input.RootKey.Length]); if (Convert.TryFromBase64String(input.RootKey, buffer, out int bytesWritten)) output.RootKey = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped RootKey must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件1读写密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件1读写密钥.Length]); if (Convert.TryFromBase64String(input.文件1读写密钥, buffer, out int bytesWritten)) output.文件1读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件1读写密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件1读密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件1读密钥.Length]); if (Convert.TryFromBase64String(input.文件1读写密钥, buffer, out int bytesWritten)) output.文件1读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件1读密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件2读写密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件2读写密钥.Length]); if (Convert.TryFromBase64String(input.文件2读写密钥, buffer, out int bytesWritten)) output.文件2读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件2读写密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件2读密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件2读密钥.Length]); if (Convert.TryFromBase64String(input.文件2读密钥, buffer, out int bytesWritten)) output.文件2读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件2读密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件3读写密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件3读写密钥.Length]); if (Convert.TryFromBase64String(input.文件3读写密钥, buffer, out int bytesWritten)) output.文件3读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件3读写密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件3读密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件3读密钥.Length]); if (Convert.TryFromBase64String(input.文件3读密钥, buffer, out int bytesWritten)) output.文件3读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件3读密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件4读写密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件4读写密钥.Length]); if (Convert.TryFromBase64String(input.文件4读写密钥, buffer, out int bytesWritten)) output.文件4读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件4读写密钥 must be Base64 encodeded format before get decrypting"); } if (!string.IsNullOrEmpty(input.文件4读密钥)) { Span<byte> buffer = new Span<byte>(new byte[input.文件4读密钥.Length]); if (Convert.TryFromBase64String(input.文件4读密钥, buffer, out int bytesWritten)) output.文件4读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray()); else throw new ArgumentException("the encryped 文件4读密钥 must be Base64 encodeded format before get decrypting"); } return output; } /// <summary> /// /// </summary> /// <param name="input">will be converted to UTF8 bytes and then for encryption</param> /// <param name="enableHash">if set to true, the raw input will be SHA256 firstly and then for encrypting, otherwise, the raw input will be used encrypting directly.</param> /// <returns></returns> public byte[] EncryptString(string input, bool enableHash = true) { if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input)); return this.EncryptBytes(Encoding.UTF8.GetBytes(input), enableHash); } /// <summary> /// /// </summary> /// <param name="input">will be converted to UTF8 bytes and then encrypt</param> /// <returns>base64 encoded bytes</returns> public string EncryptStringToBase64(string input) { if (string.IsNullOrEmpty(input)) return null; return Convert.ToBase64String(this.EncryptString(input)); } /// <summary> /// /// </summary> /// <param name="input">the raw input for encrypting</param> /// <param name="enableHash">if set to true, the raw input will be SHA256 firstly and then for encrypting, otherwise, the raw input will be used encrypting directly.</param> /// <returns></returns> public byte[] EncryptBytes(byte[] input, bool enableHash = true) { byte[] hashedInput = null; if (enableHash) using (SHA256 hash = SHA256Managed.Create()) hashedInput = hash.ComputeHash(input); else hashedInput = input; byte[] symmetricKey = this.GetEncryptionKey(); using (MemoryStream ms = new MemoryStream()) { using (Aes aes = Aes.Create()) { //byte[] symmetricKey = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; aes.Key = symmetricKey; byte[] iv = aes.IV; ms.Write(iv, 0, iv.Length); using (CryptoStream cryptoStream = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(hashedInput); } } var encryptedBytes = ms.ToArray();//.Take(16).ToArray(); this.logger.LogInformation($"RawBytes: 0x{input.ToHexLogString()} encrypted to 0x{encryptedBytes.ToHexLogString()}"); return encryptedBytes; } } /// <summary> /// /// </summary> /// <param name="input">the encrypted data</param> /// <returns>return the first 16 bytes from the decrypted data</returns> public byte[] Decrypt(byte[] input) { byte[] symmetricKey = this.GetEncryptionKey(); return this.Decrypt(input, symmetricKey); } /// <summary> /// Decrypt the encrypted data by key. /// </summary> /// <param name="input">the encrypted data</param> /// <param name="key">the key for decryption</param> /// <returns>the decrypted data</returns> public byte[] Decrypt(byte[] input, byte[] key) { byte[] symmetricKey = key; using (MemoryStream ms = new MemoryStream(input)) { using (Aes aes = Aes.Create()) { byte[] iv = new byte[aes.IV.Length]; int numBytesToRead = aes.IV.Length; int numBytesRead = 0; while (numBytesToRead > 0) { int n = ms.Read(iv, numBytesRead, numBytesToRead); if (n == 0) break; numBytesRead += n; numBytesToRead -= n; } //byte[] symmetricKey ={ // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; using (CryptoStream cryptoStream = new CryptoStream(ms, aes.CreateDecryptor(symmetricKey, iv), CryptoStreamMode.Read)) { using (MemoryStream outputMs = new MemoryStream()) { cryptoStream.CopyTo(outputMs); return outputMs.ToArray();//.Take(16).ToArray(); } //using (var decryptReader = new Text(cryptoStream)) //{ // string decryptedMessage = decryptReader.ReadToEnd(); // Console.WriteLine($"The decrypted original message: {decryptedMessage}, base64 decode to: 0x{Convert.FromBase64String(decryptedMessage).ToHexLogString()}"); // return Convert.FromBase64String(decryptedMessage); //} } } } } } }