PEMUtilities.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  9. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.OpenSsl
  10. {
  11. internal sealed class PemUtilities
  12. {
  13. private enum PemBaseAlg { AES_128, AES_192, AES_256, BF, DES, DES_EDE, DES_EDE3, RC2, RC2_40, RC2_64 };
  14. private enum PemMode { CBC, CFB, ECB, OFB };
  15. static PemUtilities()
  16. {
  17. // Signal to obfuscation tools not to change enum constants
  18. ((PemBaseAlg)Enums.GetArbitraryValue(typeof(PemBaseAlg))).ToString();
  19. ((PemMode)Enums.GetArbitraryValue(typeof(PemMode))).ToString();
  20. }
  21. private static void ParseDekAlgName(
  22. string dekAlgName,
  23. out PemBaseAlg baseAlg,
  24. out PemMode mode)
  25. {
  26. try
  27. {
  28. mode = PemMode.ECB;
  29. if (dekAlgName == "DES-EDE" || dekAlgName == "DES-EDE3")
  30. {
  31. baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName);
  32. return;
  33. }
  34. int pos = dekAlgName.LastIndexOf('-');
  35. if (pos >= 0)
  36. {
  37. baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName.Substring(0, pos));
  38. mode = (PemMode)Enums.GetEnumValue(typeof(PemMode), dekAlgName.Substring(pos + 1));
  39. return;
  40. }
  41. }
  42. catch (ArgumentException)
  43. {
  44. }
  45. throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
  46. }
  47. internal static byte[] Crypt(
  48. bool encrypt,
  49. byte[] bytes,
  50. char[] password,
  51. string dekAlgName,
  52. byte[] iv)
  53. {
  54. PemBaseAlg baseAlg;
  55. PemMode mode;
  56. ParseDekAlgName(dekAlgName, out baseAlg, out mode);
  57. string padding;
  58. switch (mode)
  59. {
  60. case PemMode.CBC:
  61. case PemMode.ECB:
  62. padding = "PKCS5Padding";
  63. break;
  64. case PemMode.CFB:
  65. case PemMode.OFB:
  66. padding = "NoPadding";
  67. break;
  68. default:
  69. throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
  70. }
  71. string algorithm;
  72. byte[] salt = iv;
  73. switch (baseAlg)
  74. {
  75. case PemBaseAlg.AES_128:
  76. case PemBaseAlg.AES_192:
  77. case PemBaseAlg.AES_256:
  78. algorithm = "AES";
  79. if (salt.Length > 8)
  80. {
  81. salt = new byte[8];
  82. Array.Copy(iv, 0, salt, 0, salt.Length);
  83. }
  84. break;
  85. case PemBaseAlg.BF:
  86. algorithm = "BLOWFISH";
  87. break;
  88. case PemBaseAlg.DES:
  89. algorithm = "DES";
  90. break;
  91. case PemBaseAlg.DES_EDE:
  92. case PemBaseAlg.DES_EDE3:
  93. algorithm = "DESede";
  94. break;
  95. case PemBaseAlg.RC2:
  96. case PemBaseAlg.RC2_40:
  97. case PemBaseAlg.RC2_64:
  98. algorithm = "RC2";
  99. break;
  100. default:
  101. throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
  102. }
  103. string cipherName = algorithm + "/" + mode + "/" + padding;
  104. IBufferedCipher cipher = CipherUtilities.GetCipher(cipherName);
  105. ICipherParameters cParams = GetCipherParameters(password, baseAlg, salt);
  106. if (mode != PemMode.ECB)
  107. {
  108. cParams = new ParametersWithIV(cParams, iv);
  109. }
  110. cipher.Init(encrypt, cParams);
  111. return cipher.DoFinal(bytes);
  112. }
  113. private static ICipherParameters GetCipherParameters(
  114. char[] password,
  115. PemBaseAlg baseAlg,
  116. byte[] salt)
  117. {
  118. string algorithm;
  119. int keyBits;
  120. switch (baseAlg)
  121. {
  122. case PemBaseAlg.AES_128: keyBits = 128; algorithm = "AES128"; break;
  123. case PemBaseAlg.AES_192: keyBits = 192; algorithm = "AES192"; break;
  124. case PemBaseAlg.AES_256: keyBits = 256; algorithm = "AES256"; break;
  125. case PemBaseAlg.BF: keyBits = 128; algorithm = "BLOWFISH"; break;
  126. case PemBaseAlg.DES: keyBits = 64; algorithm = "DES"; break;
  127. case PemBaseAlg.DES_EDE: keyBits = 128; algorithm = "DESEDE"; break;
  128. case PemBaseAlg.DES_EDE3: keyBits = 192; algorithm = "DESEDE3"; break;
  129. case PemBaseAlg.RC2: keyBits = 128; algorithm = "RC2"; break;
  130. case PemBaseAlg.RC2_40: keyBits = 40; algorithm = "RC2"; break;
  131. case PemBaseAlg.RC2_64: keyBits = 64; algorithm = "RC2"; break;
  132. default:
  133. return null;
  134. }
  135. OpenSslPbeParametersGenerator pGen = new OpenSslPbeParametersGenerator();
  136. pGen.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt);
  137. return pGen.GenerateDerivedParameters(algorithm, keyBits);
  138. }
  139. }
  140. }
  141. #pragma warning restore
  142. #endif