KeyLoader.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. using Edge.Core.Parser.BinaryParser.Util;
  2. using Microsoft.Extensions.Logging;
  3. using Microsoft.Extensions.Logging.Abstractions;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Net.NetworkInformation;
  9. using System.Net.Sockets;
  10. using System.Security.Cryptography;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. namespace ShengJuDesFireEv1CpuCardKeyLoader
  14. {
  15. public interface IKeyLoader
  16. {
  17. DecryptedKeySet Get(EncryptedBase64KeySet input);
  18. }
  19. public class DecryptedKeySet
  20. {
  21. public byte[] RootKey { get; set; }
  22. public byte[] 文件1读密钥 { get; set; }
  23. public byte[] 文件1读写密钥 { get; set; }
  24. public byte[] 文件2读密钥 { get; set; }
  25. public byte[] 文件2读写密钥 { get; set; }
  26. public byte[] 文件3读密钥 { get; set; }
  27. public byte[] 文件3读写密钥 { get; set; }
  28. public byte[] 文件4读密钥 { get; set; }
  29. public byte[] 文件4读写密钥 { get; set; }
  30. }
  31. public class InputBase64PlainKeySet
  32. {
  33. public string RootKey { get; set; }
  34. public string 文件1读密钥 { get; set; }
  35. public string 文件1读写密钥 { get; set; }
  36. public string 文件2读密钥 { get; set; }
  37. public string 文件2读写密钥 { get; set; }
  38. public string 文件3读密钥 { get; set; }
  39. public string 文件3读写密钥 { get; set; }
  40. public string 文件4读密钥 { get; set; }
  41. public string 文件4读写密钥 { get; set; }
  42. public string Description { get; set; }
  43. }
  44. public class EncryptedBase64KeySet
  45. {
  46. public string RootKey { get; set; }
  47. public string 文件1读密钥 { get; set; }
  48. public string 文件1读写密钥 { get; set; }
  49. public string 文件2读密钥 { get; set; }
  50. public string 文件2读写密钥 { get; set; }
  51. public string 文件3读密钥 { get; set; }
  52. public string 文件3读写密钥 { get; set; }
  53. public string 文件4读密钥 { get; set; }
  54. public string 文件4读写密钥 { get; set; }
  55. public string Description { get; set; }
  56. }
  57. public class LocalNetworkMacBasedEncryptionKeyLoader : IKeyLoader
  58. {
  59. private ILogger logger = NullLogger.Instance;
  60. public LocalNetworkMacBasedEncryptionKeyLoader(ILogger logger)
  61. {
  62. this.logger = logger;
  63. }
  64. /// <summary>
  65. /// </summary>
  66. /// <returns></returns>
  67. private byte[] GetEncryptionKeySeed()
  68. {
  69. var nics = NetworkInterface.GetAllNetworkInterfaces()
  70. .Where(i => i.SupportsMulticast && i.Supports(NetworkInterfaceComponent.IPv4) && i.NetworkInterfaceType == NetworkInterfaceType.Ethernet);
  71. List<byte[]> macAddresses = new List<byte[]>();
  72. string logStr = "";
  73. for (int i = 0; i < nics.Count(); i++)
  74. {
  75. var adapter = nics.ElementAt(i);
  76. IPInterfaceProperties properties = adapter.GetIPProperties(); // .GetIPInterfaceProperties();
  77. logStr += $"===========Ethernet {i}: {adapter.Description}==========={Environment.NewLine}";
  78. logStr += $" Interface type .......................... : {adapter.NetworkInterfaceType}" + Environment.NewLine;
  79. logStr += $" OperationalStatus ....................... : {adapter.OperationalStatus}" + Environment.NewLine;
  80. logStr += $" IpAddresses ....................... : " +
  81. $"{properties.UnicastAddresses.Select(ad => ad.Address).Where(ad => ad.AddressFamily == AddressFamily.InterNetwork).Select(i => i.ToString()).Aggregate("", (acc, n) => acc + ", " + n)}" + Environment.NewLine;
  82. logStr += $" Physical address ........................ : 0x{adapter.GetPhysicalAddress().GetAddressBytes().ToHexLogString()}" + Environment.NewLine;
  83. if (adapter.Description.Contains("Virtual", StringComparison.OrdinalIgnoreCase)
  84. || adapter.Description.Contains("docker", StringComparison.OrdinalIgnoreCase))
  85. {
  86. logStr += " --->>Virutal Device<<---" + Environment.NewLine;
  87. continue;
  88. }
  89. macAddresses.Add(adapter.GetPhysicalAddress().GetAddressBytes());
  90. }
  91. this.logger.LogInformation($"KeyLoader is preparing for GetEncryptionKey: {Environment.NewLine}{logStr}");
  92. if (!macAddresses.Any())
  93. throw new ArgumentException("Failed to generate Encryption Key from local Ethernet NetworkInterface mac addresses");
  94. List<byte> raw = new List<byte>();
  95. for (int i = 0; i < macAddresses[0].Length; i++)
  96. {
  97. byte accu = 0;
  98. for (int j = 0; j < macAddresses.Count; j++)
  99. {
  100. accu ^= macAddresses[j][i];
  101. }
  102. raw.Add(accu);
  103. }
  104. //var base64Encoded = Convert.ToBase64String(raw.ToArray());
  105. this.logger.LogInformation("raw EncryptionKey seed hex: 0x" + raw.ToHexLogString());// + ", base64 encoded: " + base64Encoded);
  106. return raw.ToArray();
  107. }
  108. /// <summary>
  109. /// Get the 16 bytes encryption key
  110. /// </summary>
  111. /// <returns></returns>
  112. protected virtual byte[] GetEncryptionKey()
  113. {
  114. var encryptionKeySeed = this.GetEncryptionKeySeed();
  115. byte[] symmetricKey = encryptionKeySeed.Concat(Enumerable.Range(0, 16 - encryptionKeySeed.Length).Select(i => (byte)i)).ToArray();
  116. return symmetricKey;
  117. }
  118. public DecryptedKeySet Get(EncryptedBase64KeySet input)
  119. {
  120. var output = new DecryptedKeySet();
  121. if (!string.IsNullOrEmpty(input.RootKey))
  122. {
  123. Span<byte> buffer = new Span<byte>(new byte[input.RootKey.Length]);
  124. if (Convert.TryFromBase64String(input.RootKey, buffer, out int bytesWritten))
  125. output.RootKey = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  126. else
  127. throw new ArgumentException("the encryped RootKey must be Base64 encodeded format before get decrypting");
  128. }
  129. if (!string.IsNullOrEmpty(input.文件1读写密钥))
  130. {
  131. Span<byte> buffer = new Span<byte>(new byte[input.文件1读写密钥.Length]);
  132. if (Convert.TryFromBase64String(input.文件1读写密钥, buffer, out int bytesWritten))
  133. output.文件1读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  134. else
  135. throw new ArgumentException("the encryped 文件1读写密钥 must be Base64 encodeded format before get decrypting");
  136. }
  137. if (!string.IsNullOrEmpty(input.文件1读密钥))
  138. {
  139. Span<byte> buffer = new Span<byte>(new byte[input.文件1读密钥.Length]);
  140. if (Convert.TryFromBase64String(input.文件1读写密钥, buffer, out int bytesWritten))
  141. output.文件1读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  142. else
  143. throw new ArgumentException("the encryped 文件1读密钥 must be Base64 encodeded format before get decrypting");
  144. }
  145. if (!string.IsNullOrEmpty(input.文件2读写密钥))
  146. {
  147. Span<byte> buffer = new Span<byte>(new byte[input.文件2读写密钥.Length]);
  148. if (Convert.TryFromBase64String(input.文件2读写密钥, buffer, out int bytesWritten))
  149. output.文件2读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  150. else
  151. throw new ArgumentException("the encryped 文件2读写密钥 must be Base64 encodeded format before get decrypting");
  152. }
  153. if (!string.IsNullOrEmpty(input.文件2读密钥))
  154. {
  155. Span<byte> buffer = new Span<byte>(new byte[input.文件2读密钥.Length]);
  156. if (Convert.TryFromBase64String(input.文件2读密钥, buffer, out int bytesWritten))
  157. output.文件2读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  158. else
  159. throw new ArgumentException("the encryped 文件2读密钥 must be Base64 encodeded format before get decrypting");
  160. }
  161. if (!string.IsNullOrEmpty(input.文件3读写密钥))
  162. {
  163. Span<byte> buffer = new Span<byte>(new byte[input.文件3读写密钥.Length]);
  164. if (Convert.TryFromBase64String(input.文件3读写密钥, buffer, out int bytesWritten))
  165. output.文件3读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  166. else
  167. throw new ArgumentException("the encryped 文件3读写密钥 must be Base64 encodeded format before get decrypting");
  168. }
  169. if (!string.IsNullOrEmpty(input.文件3读密钥))
  170. {
  171. Span<byte> buffer = new Span<byte>(new byte[input.文件3读密钥.Length]);
  172. if (Convert.TryFromBase64String(input.文件3读密钥, buffer, out int bytesWritten))
  173. output.文件3读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  174. else
  175. throw new ArgumentException("the encryped 文件3读密钥 must be Base64 encodeded format before get decrypting");
  176. }
  177. if (!string.IsNullOrEmpty(input.文件4读写密钥))
  178. {
  179. Span<byte> buffer = new Span<byte>(new byte[input.文件4读写密钥.Length]);
  180. if (Convert.TryFromBase64String(input.文件4读写密钥, buffer, out int bytesWritten))
  181. output.文件4读写密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  182. else
  183. throw new ArgumentException("the encryped 文件4读写密钥 must be Base64 encodeded format before get decrypting");
  184. }
  185. if (!string.IsNullOrEmpty(input.文件4读密钥))
  186. {
  187. Span<byte> buffer = new Span<byte>(new byte[input.文件4读密钥.Length]);
  188. if (Convert.TryFromBase64String(input.文件4读密钥, buffer, out int bytesWritten))
  189. output.文件4读密钥 = this.Decrypt(buffer.ToArray().Take(bytesWritten).ToArray());
  190. else
  191. throw new ArgumentException("the encryped 文件4读密钥 must be Base64 encodeded format before get decrypting");
  192. }
  193. return output;
  194. }
  195. /// <summary>
  196. ///
  197. /// </summary>
  198. /// <param name="input">will be converted to UTF8 bytes and then for encryption</param>
  199. /// <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>
  200. /// <returns></returns>
  201. public byte[] EncryptString(string input, bool enableHash = true)
  202. {
  203. if (string.IsNullOrEmpty(input)) throw new ArgumentNullException(nameof(input));
  204. return this.EncryptBytes(Encoding.UTF8.GetBytes(input), enableHash);
  205. }
  206. /// <summary>
  207. ///
  208. /// </summary>
  209. /// <param name="input">will be converted to UTF8 bytes and then encrypt</param>
  210. /// <returns>base64 encoded bytes</returns>
  211. public string EncryptStringToBase64(string input)
  212. {
  213. if (string.IsNullOrEmpty(input)) return null;
  214. return Convert.ToBase64String(this.EncryptString(input));
  215. }
  216. /// <summary>
  217. ///
  218. /// </summary>
  219. /// <param name="input">the raw input for encrypting</param>
  220. /// <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>
  221. /// <returns></returns>
  222. public byte[] EncryptBytes(byte[] input, bool enableHash = true)
  223. {
  224. byte[] hashedInput = null;
  225. if (enableHash)
  226. using (SHA256 hash = SHA256Managed.Create())
  227. hashedInput = hash.ComputeHash(input);
  228. else
  229. hashedInput = input;
  230. byte[] symmetricKey = this.GetEncryptionKey();
  231. using (MemoryStream ms = new MemoryStream())
  232. {
  233. using (Aes aes = Aes.Create())
  234. {
  235. //byte[] symmetricKey = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  236. // 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
  237. aes.Key = symmetricKey;
  238. byte[] iv = aes.IV;
  239. ms.Write(iv, 0, iv.Length);
  240. using (CryptoStream cryptoStream = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
  241. {
  242. cryptoStream.Write(hashedInput);
  243. }
  244. }
  245. var encryptedBytes = ms.ToArray();//.Take(16).ToArray();
  246. this.logger.LogInformation($"RawBytes: 0x{input.ToHexLogString()} encrypted to 0x{encryptedBytes.ToHexLogString()}");
  247. return encryptedBytes;
  248. }
  249. }
  250. /// <summary>
  251. ///
  252. /// </summary>
  253. /// <param name="input">the encrypted data</param>
  254. /// <returns>return the first 16 bytes from the decrypted data</returns>
  255. public byte[] Decrypt(byte[] input)
  256. {
  257. byte[] symmetricKey = this.GetEncryptionKey();
  258. return this.Decrypt(input, symmetricKey);
  259. }
  260. /// <summary>
  261. /// Decrypt the encrypted data by key.
  262. /// </summary>
  263. /// <param name="input">the encrypted data</param>
  264. /// <param name="key">the key for decryption</param>
  265. /// <returns>the decrypted data</returns>
  266. public byte[] Decrypt(byte[] input, byte[] key)
  267. {
  268. byte[] symmetricKey = key;
  269. using (MemoryStream ms = new MemoryStream(input))
  270. {
  271. using (Aes aes = Aes.Create())
  272. {
  273. byte[] iv = new byte[aes.IV.Length];
  274. int numBytesToRead = aes.IV.Length;
  275. int numBytesRead = 0;
  276. while (numBytesToRead > 0)
  277. {
  278. int n = ms.Read(iv, numBytesRead, numBytesToRead);
  279. if (n == 0) break;
  280. numBytesRead += n;
  281. numBytesToRead -= n;
  282. }
  283. //byte[] symmetricKey ={
  284. // 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  285. // 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
  286. using (CryptoStream cryptoStream = new CryptoStream(ms, aes.CreateDecryptor(symmetricKey, iv), CryptoStreamMode.Read))
  287. {
  288. using (MemoryStream outputMs = new MemoryStream())
  289. {
  290. cryptoStream.CopyTo(outputMs);
  291. return outputMs.ToArray();//.Take(16).ToArray();
  292. }
  293. //using (var decryptReader = new Text(cryptoStream))
  294. //{
  295. // string decryptedMessage = decryptReader.ReadToEnd();
  296. // Console.WriteLine($"The decrypted original message: {decryptedMessage}, base64 decode to: 0x{Convert.FromBase64String(decryptedMessage).ToHexLogString()}");
  297. // return Convert.FromBase64String(decryptedMessage);
  298. //}
  299. }
  300. }
  301. }
  302. }
  303. }
  304. }