Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.07 KB | None | 0 0
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5.  
  6. namespace cryptolab
  7. {
  8. /// <summary>
  9. /// Utilidades criptográficas
  10. /// </summary>
  11. public static class CryptoUtils
  12. {
  13. /// <summary>
  14. /// Pacote contendo dados encriptados, juntamente com um HMAC
  15. /// para verificacao da integridade e assinatura digital para reconhecer
  16. /// o criador do documento
  17. /// </summary>
  18. public class EncryptedPacket
  19. {
  20. /// <summary>
  21. /// Chave se sessão utilizada para encryptar os dados
  22. /// Essa chave é encryptada utilizando a chave pública do receptor
  23. /// </summary>
  24. /// <value></value>
  25. public byte[] EncryptedSessionKey { get; set; }
  26.  
  27. /// <summary>
  28. /// Vetor de inicializacao do AES
  29. /// </summary>
  30. /// <value></value>
  31. public byte[] IV { get; set; }
  32.  
  33. /// <summary>
  34. /// Dados encryptados utilizando a SessionKey (Decriptada) e IV
  35. /// </summary>
  36. /// <value></value>
  37. public byte[] EncryptedData { get; set; }
  38.  
  39. /// <summary>
  40. /// HMAC para verificar integridade da mensagem (a chave do HMAC é a SessionKey)
  41. /// </summary>
  42. /// <value></value>
  43. public byte[] HMAC { get; set; }
  44.  
  45. /// <summary>
  46. /// Assinatura do sender, compare-a ao HMAC com a chave pública do Sender
  47. /// </summary>
  48. /// <value></value>
  49. public byte[] Signature { get; set; }
  50. }
  51.  
  52. /// <summary>
  53. /// Prepara um pacote com dados encryptados com suporte a
  54. /// confidencialidade (Dados encryptados), integridade (HMAC),
  55. /// autenticação e não repúdio (Assinatura Digital)
  56. /// </summary>
  57. /// <param name="data"></param>
  58. /// <param name="senderPrivateKey"></param>
  59. /// <param name="recipientPublicKey"></param>
  60. /// <returns></returns>
  61. public static EncryptedPacket PackEncryptedData(byte[] data, RSAParameters senderPrivateKey, RSAParameters recipientPublicKey)
  62. {
  63. //Número qualquer
  64. var sessionKey = GenerateRandomNumberV2(32);
  65. var iv = GenerateRandomNumberV2(16);
  66.  
  67. //Encrypt data using session key and iv
  68. var encryptedData = EncryptWithAES(data, sessionKey, iv);
  69.  
  70. //The session key will be sended encrypted by the recipient public key (only him will be able to decrypt)
  71. var encryptedSesionKey = EncryptWithRSA(sessionKey, recipientPublicKey);
  72.  
  73. //HMAC based on the session key
  74. var hmac = ComputeHmacSHA256(encryptedData, sessionKey);
  75.  
  76. //And finally the signature of the hmac
  77. var signature = SignData(hmac, senderPrivateKey);
  78.  
  79. return new EncryptedPacket
  80. {
  81. EncryptedSessionKey = encryptedSesionKey,
  82. IV = iv,
  83. EncryptedData = encryptedData,
  84. HMAC = hmac,
  85. Signature = signature
  86. };
  87. }
  88.  
  89. /// <summary>
  90. /// Recupera os dados encryptados do pacote
  91. /// </summary>
  92. /// <param name="packet"></param>
  93. /// <param name="recipientPrivateKey"></param>
  94. /// <param name="senderPublicKey"></param>
  95. /// <returns></returns>
  96. public static byte[] UnpackEncryptedData(EncryptedPacket packet, RSAParameters recipientPrivateKey, RSAParameters senderPublicKey)
  97. {
  98. var decryptedSessionKey = DecryptWithRSA(packet.EncryptedSessionKey, recipientPrivateKey);
  99. var hmacToCheck = ComputeHmacSHA256(packet.EncryptedData, decryptedSessionKey);
  100.  
  101. if (!CompareByteArrays(packet.HMAC, hmacToCheck))
  102. {
  103. throw new CryptographicException("HMAC invalid");
  104. }
  105.  
  106. if (!VerifySignature(packet.HMAC, packet.Signature, senderPublicKey))
  107. {
  108. throw new CryptographicException("Digital signature can not be verified");
  109. }
  110.  
  111. return DecryptWithAES(packet.EncryptedData, decryptedSessionKey, packet.IV);
  112. }
  113.  
  114. /// <summary>
  115. /// Gera números aleatórios utilizando RNGCryptoServiceProvider
  116. /// </summary>
  117. /// <param name="size"></param>
  118. /// <returns></returns>
  119. public static byte[] GenerateRandomNumberV2(int size)
  120. {
  121. using (var rnd = new RNGCryptoServiceProvider())
  122. {
  123. var result = new byte[size];
  124.  
  125. rnd.GetBytes(result);
  126.  
  127. return result;
  128. }
  129. }
  130.  
  131. /// <summary>
  132. /// Calcula um hash SHA-1
  133. /// </summary>
  134. /// <param name="data"></param>
  135. /// <returns></returns>
  136. public static byte[] ComputeSHA1(byte[] data)
  137. {
  138. using (var sha1 = SHA1.Create())
  139. {
  140. return sha1.ComputeHash(data);
  141. }
  142. }
  143.  
  144. /// <summary>
  145. /// Calcula um hash SHA-256
  146. /// </summary>
  147. /// <param name="data"></param>
  148. /// <returns></returns>
  149. public static byte[] ComputeSHA256(byte[] data)
  150. {
  151. using (var sha256 = SHA256.Create())
  152. {
  153. return sha256.ComputeHash(data);
  154. }
  155. }
  156.  
  157. /// <summary>
  158. /// Calcula um hash MD5
  159. /// </summary>
  160. /// <param name="data"></param>
  161. /// <returns></returns>
  162. public static byte[] ComputeMD5(byte[] data)
  163. {
  164. using (var md5 = MD5.Create())
  165. {
  166. return md5.ComputeHash(data);
  167. }
  168. }
  169.  
  170. /// <summary>
  171. /// Calcula um HMAC do tipo SHA-1
  172. /// </summary>
  173. /// <param name="data"></param>
  174. /// <param name="key"></param>
  175. /// <returns></returns>
  176. public static byte[] ComputeHmacSHA1(byte[] data, byte[] key)
  177. {
  178. using (var hmac = new HMACSHA1(key))
  179. {
  180. return hmac.ComputeHash(data);
  181. }
  182. }
  183.  
  184. /// <summary>
  185. /// Calcula HMAC do tipo SHA-256
  186. /// </summary>
  187. /// <param name="data"></param>
  188. /// <param name="key"></param>
  189. /// <returns></returns>
  190. public static byte[] ComputeHmacSHA256(byte[] data, byte[] key)
  191. {
  192. using (var hmac = new HMACSHA256(key))
  193. {
  194. return hmac.ComputeHash(data);
  195. }
  196. }
  197.  
  198. /// <summary>
  199. /// Calcula um HMAC do tipo MD5
  200. /// </summary>
  201. /// <param name="data"></param>
  202. /// <param name="key"></param>
  203. /// <returns></returns>
  204. public static byte[] ComputeHmacMD5(byte[] data, byte[] key)
  205. {
  206. using (var hmac = new HMACMD5(key))
  207. {
  208. return hmac.ComputeHash(data);
  209. }
  210. }
  211.  
  212. /// <summary>
  213. /// Gera password utilizando uma técnica de key derivation
  214. /// </summary>
  215. /// <param name="original"></param>
  216. /// <param name="salt"></param>
  217. /// <param name="numberOfRounds"></param>
  218. /// <returns></returns>
  219. public static byte[] GeneratePassword(byte[] original, byte[] salt, int numberOfRounds)
  220. {
  221. using (var rfc = new Rfc2898DeriveBytes(original, salt, numberOfRounds))
  222. {
  223. return rfc.GetBytes(32);
  224. }
  225. }
  226.  
  227. /// <summary>
  228. /// Gera SALT aleatório para ser utilizado na geração de senhas
  229. /// </summary>
  230. /// <returns></returns>
  231. public static byte[] GenerateSalt()
  232. {
  233. return GenerateRandomNumberV2(32);
  234. }
  235.  
  236. /// <summary>
  237. /// Realiza encrypt utilizando DES
  238. /// </summary>
  239. /// <param name="data"></param>
  240. /// <param name="key"></param>
  241. /// <param name="iv"></param>
  242. /// <returns></returns>
  243. public static byte[] EncryptWithDES(byte[] data, byte[] key, byte[] iv)
  244. {
  245. using (var des = new DESCryptoServiceProvider())
  246. {
  247. return EncryptSymetric(des, data, key, iv);
  248. }
  249. }
  250.  
  251. /// <summary>
  252. /// Realiza decrypt utilizando DES
  253. /// </summary>
  254. /// <param name="data"></param>
  255. /// <param name="key"></param>
  256. /// <param name="iv"></param>
  257. /// <returns></returns>
  258. public static byte[] DecryptWithDES(byte[] data, byte[] key, byte[] iv)
  259. {
  260. using (var des = new DESCryptoServiceProvider())
  261. {
  262. return DecryptSymetric(des, data, key, iv);
  263. }
  264. }
  265.  
  266. /// <summary>
  267. /// Realiza encrypt utilizando 3DES
  268. /// </summary>
  269. /// <param name="data"></param>
  270. /// <param name="key"></param>
  271. /// <param name="iv"></param>
  272. /// <returns></returns>
  273. public static byte[] EncryptWithTripleDES(byte[] data, byte[] key, byte[] iv)
  274. {
  275. using (var tdes = new TripleDESCryptoServiceProvider())
  276. {
  277. return EncryptSymetric(tdes, data, key, iv);
  278. }
  279. }
  280.  
  281. /// <summary>
  282. /// Realiza decrypt utilizando 3DES
  283. /// </summary>
  284. /// <param name="data"></param>
  285. /// <param name="key"></param>
  286. /// <param name="iv"></param>
  287. /// <returns></returns>
  288. public static byte[] DecryptWithTripleDES(byte[] data, byte[] key, byte[] iv)
  289. {
  290. using (var tdes = new TripleDESCryptoServiceProvider())
  291. {
  292. return DecryptSymetric(tdes, data, key, iv);
  293. }
  294. }
  295.  
  296.  
  297. /// <summary>
  298. /// Realiza encrypt utilizando AES
  299. /// </summary>
  300. /// <param name="data"></param>
  301. /// <param name="key"></param>
  302. /// <param name="iv"></param>
  303. /// <returns></returns>
  304. public static byte[] EncryptWithAES(byte[] data, byte[] key, byte[] iv)
  305. {
  306. using (var aes = new AesCryptoServiceProvider())
  307. {
  308. return EncryptSymetric(aes, data, key, iv);
  309. }
  310. }
  311.  
  312. /// <summary>
  313. /// Realiza decrypt utilizando AES
  314. /// </summary>
  315. /// <param name="data"></param>
  316. /// <param name="key"></param>
  317. /// <param name="iv"></param>
  318. /// <returns></returns>
  319. public static byte[] DecryptWithAES(byte[] data, byte[] key, byte[] iv)
  320. {
  321. //using (var aes = new AesCryptoServiceProvider()) //WINAPI
  322. using (var aes = new AesManaged()) //.NET
  323. {
  324. return DecryptSymetric(aes, data, key, iv);
  325. }
  326. }
  327.  
  328. /// <summary>
  329. /// Gera e recupera um par de chaves RSA
  330. /// </summary>
  331. public static (RSAParameters puK, RSAParameters prK) GenerateRSAKeyPair(int keySize = 2048)
  332. {
  333. using (var rsa = new RSACryptoServiceProvider(keySize))
  334. {
  335. rsa.PersistKeyInCsp = false;
  336.  
  337. return (rsa.ExportParameters(false), rsa.ExportParameters(true));
  338. }
  339. }
  340.  
  341. /// <summary>
  342. /// Gera e armazena chaves em um key container do sistema
  343. /// </summary>
  344. /// <param name="containerName"></param>
  345. /// <returns></returns>
  346. public static CspParameters GenerateAndStoreRSAKeys(string containerName)
  347. {
  348. var cspParams = new CspParameters(1);
  349. cspParams.KeyContainerName = containerName;
  350. cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
  351. cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
  352.  
  353. var rsa = new RSACryptoServiceProvider(cspParams)
  354. {
  355. PersistKeyInCsp = true
  356. };
  357.  
  358. return cspParams;
  359. }
  360.  
  361. /// <summary>
  362. /// Remove chaves armazenadas no container informado
  363. /// </summary>
  364. /// <param name="containerName"></param>
  365. public static void RemoveRSAKeysFromContainer(string containerName)
  366. {
  367. var cspParams = new CspParameters { KeyContainerName = containerName };
  368. var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = false };
  369.  
  370. rsa.Clear();
  371. }
  372.  
  373. /// <summary>
  374. /// Realiza encrypt utiliznado chave pública
  375. /// </summary>
  376. /// <param name="data"></param>
  377. /// <param name="publicKey"></param>
  378. /// <returns></returns>
  379. public static byte[] EncryptWithRSA(byte[] data, RSAParameters publicKey)
  380. {
  381. using (var rsa = new RSACryptoServiceProvider(2048))
  382. {
  383. rsa.PersistKeyInCsp = false;
  384. rsa.ImportParameters(publicKey);
  385. return rsa.Encrypt(data, true);
  386. }
  387. }
  388.  
  389. /// <summary>
  390. /// Realiza encrypt utilizando chaves armazenadas no container informado
  391. /// </summary>
  392. /// <param name="data"></param>
  393. /// <param name="containerName"></param>
  394. /// <returns></returns>
  395. public static byte[] EncryptWithRSA(byte[] data, string containerName)
  396. {
  397. using (var rsa = new RSACryptoServiceProvider(2048, new CspParameters { KeyContainerName = containerName }))
  398. {
  399. return rsa.Encrypt(data, false);
  400. }
  401. }
  402.  
  403. /// <summary>
  404. /// Realiza decrypt utilizando chaves armazenadas no container informado
  405. /// </summary>
  406. /// <param name="data"></param>
  407. /// <param name="containerName"></param>
  408. /// <returns></returns>
  409. public static byte[] DecryptWithRSA(byte[] data, string containerName)
  410. {
  411. using (var rsa = new RSACryptoServiceProvider(2048, new CspParameters { KeyContainerName = containerName }))
  412. {
  413. return rsa.Decrypt(data, false);
  414. }
  415. }
  416.  
  417.  
  418. /// <summary>
  419. /// Realiza decrypt utilizando chave privada
  420. /// </summary>
  421. /// <param name="data"></param>
  422. /// <param name="privateKey"></param>
  423. /// <returns></returns>
  424. public static byte[] DecryptWithRSA(byte[] data, RSAParameters privateKey)
  425. {
  426. using (var rsa = new RSACryptoServiceProvider(2048))
  427. {
  428. rsa.PersistKeyInCsp = false;
  429. rsa.ImportParameters(privateKey);
  430. return rsa.Decrypt(data, true);
  431. }
  432. }
  433.  
  434. /// <summary>
  435. /// Calcula assinatura dos dados utilizando a privateKey informada
  436. /// </summary>
  437. /// <param name="hashDataToSign"></param>
  438. /// <param name="privateKey"></param>
  439. /// <returns></returns>
  440. public static byte[] SignData(byte[] hashDataToSign, RSAParameters privateKey)
  441. {
  442. using (var rsa = new RSACryptoServiceProvider(2048))
  443. {
  444. rsa.PersistKeyInCsp = false;
  445. rsa.ImportParameters(privateKey);
  446.  
  447. var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
  448. rsaFormatter.SetHashAlgorithm("SHA256");
  449.  
  450. return rsaFormatter.CreateSignature(hashDataToSign);
  451. }
  452. }
  453.  
  454. /// <summary>
  455. /// Verifica se a assinatura digital é válida, utilizando a chave publicKey informada
  456. /// </summary>
  457. /// <param name="hashOfData"></param>
  458. /// <param name="signature"></param>
  459. /// <param name="publicKey"></param>
  460. /// <returns></returns>
  461. public static bool VerifySignature(byte[] hashOfData, byte[] signature, RSAParameters publicKey)
  462. {
  463. using (var rsa = new RSACryptoServiceProvider(2048))
  464. {
  465. rsa.ImportParameters(publicKey);
  466.  
  467. var rsaFormatter = new RSAPKCS1SignatureDeformatter(rsa);
  468. rsaFormatter.SetHashAlgorithm("SHA256");
  469.  
  470. return rsaFormatter.VerifySignature(hashOfData, signature);
  471. }
  472. }
  473.  
  474. /// <summary>
  475. /// Converte vetor de bytes em formato HEX
  476. /// </summary>
  477. /// <param name="bytes"></param>
  478. /// <returns></returns>
  479. public static string ToHexString(byte[] bytes)
  480. {
  481. var sb = new StringBuilder();
  482.  
  483. foreach (var t in bytes)
  484. {
  485. sb.Append(t.ToString("x2"));
  486. }
  487.  
  488. return sb.ToString();
  489. }
  490.  
  491. /// <summary>
  492. /// Recupera vetor de bytes a partir de uma string em formato HEX
  493. /// </summary>
  494. /// <param name="hexString"></param>
  495. /// <returns></returns>
  496. public static byte[] FromHexString(string hexString)
  497. {
  498. var bytes = new byte[hexString.Length / 2];
  499.  
  500. for (var i = 0; i < bytes.Length; i++)
  501. {
  502. bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
  503. }
  504.  
  505. return bytes;
  506. }
  507.  
  508. /// <summary>
  509. /// Compara conteúdo de dois vetores de bytes (bit a bit)
  510. /// </summary>
  511. /// <param name="array1"></param>
  512. /// <param name="array2"></param>
  513. /// <param name="bytesToCompare"></param>
  514. /// <returns></returns>
  515. public static bool CompareByteArrays(byte[] array1, byte[] array2, int bytesToCompare = 0)
  516. {
  517. if (array1.Length != array2.Length) return false;
  518.  
  519. var length = (bytesToCompare == 0) ? array1.Length : bytesToCompare;
  520. var tailIdx = length - length % sizeof(Int64);
  521.  
  522. //check in 8 byte chunks
  523. for (var i = 0; i < tailIdx; i += sizeof(Int64))
  524. {
  525. if (BitConverter.ToInt64(array1, i) != BitConverter.ToInt64(array2, i)) return false;
  526. }
  527.  
  528. //check the remainder of the array, always shorter than 8 bytes
  529. for (var i = tailIdx; i < length; i++)
  530. {
  531. if (array1[i] != array2[i]) return false;
  532. }
  533.  
  534. return true;
  535. }
  536.  
  537.  
  538. /// ///////////////////////////////////////
  539.  
  540. private static byte[] DecryptSymetric(SymmetricAlgorithm algorithm, byte[] data, byte[] key, byte[] iv)
  541. {
  542. algorithm.Mode = CipherMode.CBC;
  543. algorithm.Padding = PaddingMode.PKCS7;
  544.  
  545. algorithm.Key = key;
  546. algorithm.IV = iv;
  547.  
  548. using (var mem = new MemoryStream())
  549. {
  550. var cryptoStream = new CryptoStream(mem, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
  551.  
  552. cryptoStream.Write(data, 0, data.Length);
  553. cryptoStream.FlushFinalBlock();
  554.  
  555. return mem.ToArray();
  556. }
  557. }
  558.  
  559. private static byte[] EncryptSymetric(SymmetricAlgorithm algorithm, byte[] data, byte[] key, byte[] iv)
  560. {
  561. algorithm.Mode = CipherMode.CBC;
  562. algorithm.Padding = PaddingMode.PKCS7;
  563.  
  564. algorithm.Key = key;
  565. algorithm.IV = iv;
  566.  
  567. using (var mem = new MemoryStream())
  568. {
  569. var cryptoStream = new CryptoStream(mem, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
  570.  
  571. cryptoStream.Write(data, 0, data.Length);
  572. cryptoStream.FlushFinalBlock();
  573.  
  574. return mem.ToArray();
  575. }
  576. }
  577.  
  578.  
  579. }
  580. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement