CipherUtilities.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.CryptoPro;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Kisa;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nist;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Nsri;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Ntt;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Oiw;
  12. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.Pkcs;
  13. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
  14. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement;
  15. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests;
  16. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Encodings;
  17. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
  18. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators;
  19. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs;
  20. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes;
  21. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Paddings;
  22. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  23. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Security
  24. {
  25. /// <remarks>
  26. /// Cipher Utility class contains methods that can not be specifically grouped into other classes.
  27. /// </remarks>
  28. public sealed class CipherUtilities
  29. {
  30. private enum CipherAlgorithm {
  31. AES,
  32. ARC4,
  33. ARIA,
  34. BLOWFISH,
  35. CAMELLIA,
  36. CAST5,
  37. CAST6,
  38. CHACHA,
  39. CHACHA20_POLY1305,
  40. CHACHA7539,
  41. DES,
  42. DESEDE,
  43. ELGAMAL,
  44. GOST28147,
  45. HC128,
  46. HC256,
  47. IDEA,
  48. NOEKEON,
  49. PBEWITHSHAAND128BITRC4,
  50. PBEWITHSHAAND40BITRC4,
  51. RC2,
  52. RC5,
  53. RC5_64,
  54. RC6,
  55. RIJNDAEL,
  56. RSA,
  57. SALSA20,
  58. SEED,
  59. SERPENT,
  60. SKIPJACK,
  61. SM4,
  62. TEA,
  63. THREEFISH_256,
  64. THREEFISH_512,
  65. THREEFISH_1024,
  66. TNEPRES,
  67. TWOFISH,
  68. VMPC,
  69. VMPC_KSA3,
  70. XTEA,
  71. };
  72. private enum CipherMode { ECB, NONE, CBC, CCM, CFB, CTR, CTS, EAX, GCM, GOFB, OCB, OFB, OPENPGPCFB, SIC };
  73. private enum CipherPadding
  74. {
  75. NOPADDING,
  76. RAW,
  77. ISO10126PADDING,
  78. ISO10126D2PADDING,
  79. ISO10126_2PADDING,
  80. ISO7816_4PADDING,
  81. ISO9797_1PADDING,
  82. ISO9796_1,
  83. ISO9796_1PADDING,
  84. OAEP,
  85. OAEPPADDING,
  86. OAEPWITHMD5ANDMGF1PADDING,
  87. OAEPWITHSHA1ANDMGF1PADDING,
  88. OAEPWITHSHA_1ANDMGF1PADDING,
  89. OAEPWITHSHA224ANDMGF1PADDING,
  90. OAEPWITHSHA_224ANDMGF1PADDING,
  91. OAEPWITHSHA256ANDMGF1PADDING,
  92. OAEPWITHSHA_256ANDMGF1PADDING,
  93. OAEPWITHSHA256ANDMGF1WITHSHA256PADDING,
  94. OAEPWITHSHA_256ANDMGF1WITHSHA_256PADDING,
  95. OAEPWITHSHA256ANDMGF1WITHSHA1PADDING,
  96. OAEPWITHSHA_256ANDMGF1WITHSHA_1PADDING,
  97. OAEPWITHSHA384ANDMGF1PADDING,
  98. OAEPWITHSHA_384ANDMGF1PADDING,
  99. OAEPWITHSHA512ANDMGF1PADDING,
  100. OAEPWITHSHA_512ANDMGF1PADDING,
  101. PKCS1,
  102. PKCS1PADDING,
  103. PKCS5,
  104. PKCS5PADDING,
  105. PKCS7,
  106. PKCS7PADDING,
  107. TBCPADDING,
  108. WITHCTS,
  109. X923PADDING,
  110. ZEROBYTEPADDING,
  111. };
  112. private static readonly IDictionary algorithms = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  113. private static readonly IDictionary oids = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateHashtable();
  114. static CipherUtilities()
  115. {
  116. // Signal to obfuscation tools not to change enum constants
  117. ((CipherAlgorithm)Enums.GetArbitraryValue(typeof(CipherAlgorithm))).ToString();
  118. ((CipherMode)Enums.GetArbitraryValue(typeof(CipherMode))).ToString();
  119. ((CipherPadding)Enums.GetArbitraryValue(typeof(CipherPadding))).ToString();
  120. // TODO Flesh out the list of aliases
  121. algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "AES/CBC/PKCS7PADDING";
  122. algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "AES/CBC/PKCS7PADDING";
  123. algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "AES/CBC/PKCS7PADDING";
  124. algorithms[NistObjectIdentifiers.IdAes128Ccm.Id] = "AES/CCM/NOPADDING";
  125. algorithms[NistObjectIdentifiers.IdAes192Ccm.Id] = "AES/CCM/NOPADDING";
  126. algorithms[NistObjectIdentifiers.IdAes256Ccm.Id] = "AES/CCM/NOPADDING";
  127. algorithms[NistObjectIdentifiers.IdAes128Cfb.Id] = "AES/CFB/NOPADDING";
  128. algorithms[NistObjectIdentifiers.IdAes192Cfb.Id] = "AES/CFB/NOPADDING";
  129. algorithms[NistObjectIdentifiers.IdAes256Cfb.Id] = "AES/CFB/NOPADDING";
  130. algorithms[NistObjectIdentifiers.IdAes128Ecb.Id] = "AES/ECB/PKCS7PADDING";
  131. algorithms[NistObjectIdentifiers.IdAes192Ecb.Id] = "AES/ECB/PKCS7PADDING";
  132. algorithms[NistObjectIdentifiers.IdAes256Ecb.Id] = "AES/ECB/PKCS7PADDING";
  133. algorithms["AES//PKCS7"] = "AES/ECB/PKCS7PADDING";
  134. algorithms["AES//PKCS7PADDING"] = "AES/ECB/PKCS7PADDING";
  135. algorithms["AES//PKCS5"] = "AES/ECB/PKCS7PADDING";
  136. algorithms["AES//PKCS5PADDING"] = "AES/ECB/PKCS7PADDING";
  137. algorithms[NistObjectIdentifiers.IdAes128Gcm.Id] = "AES/GCM/NOPADDING";
  138. algorithms[NistObjectIdentifiers.IdAes192Gcm.Id] = "AES/GCM/NOPADDING";
  139. algorithms[NistObjectIdentifiers.IdAes256Gcm.Id] = "AES/GCM/NOPADDING";
  140. algorithms[NistObjectIdentifiers.IdAes128Ofb.Id] = "AES/OFB/NOPADDING";
  141. algorithms[NistObjectIdentifiers.IdAes192Ofb.Id] = "AES/OFB/NOPADDING";
  142. algorithms[NistObjectIdentifiers.IdAes256Ofb.Id] = "AES/OFB/NOPADDING";
  143. algorithms[NsriObjectIdentifiers.id_aria128_cbc.Id] = "ARIA/CBC/PKCS7PADDING";
  144. algorithms[NsriObjectIdentifiers.id_aria192_cbc.Id] = "ARIA/CBC/PKCS7PADDING";
  145. algorithms[NsriObjectIdentifiers.id_aria256_cbc.Id] = "ARIA/CBC/PKCS7PADDING";
  146. algorithms[NsriObjectIdentifiers.id_aria128_ccm.Id] = "ARIA/CCM/NOPADDING";
  147. algorithms[NsriObjectIdentifiers.id_aria192_ccm.Id] = "ARIA/CCM/NOPADDING";
  148. algorithms[NsriObjectIdentifiers.id_aria256_ccm.Id] = "ARIA/CCM/NOPADDING";
  149. algorithms[NsriObjectIdentifiers.id_aria128_cfb.Id] = "ARIA/CFB/NOPADDING";
  150. algorithms[NsriObjectIdentifiers.id_aria192_cfb.Id] = "ARIA/CFB/NOPADDING";
  151. algorithms[NsriObjectIdentifiers.id_aria256_cfb.Id] = "ARIA/CFB/NOPADDING";
  152. algorithms[NsriObjectIdentifiers.id_aria128_ctr.Id] = "ARIA/CTR/NOPADDING";
  153. algorithms[NsriObjectIdentifiers.id_aria192_ctr.Id] = "ARIA/CTR/NOPADDING";
  154. algorithms[NsriObjectIdentifiers.id_aria256_ctr.Id] = "ARIA/CTR/NOPADDING";
  155. algorithms[NsriObjectIdentifiers.id_aria128_ecb.Id] = "ARIA/ECB/PKCS7PADDING";
  156. algorithms[NsriObjectIdentifiers.id_aria192_ecb.Id] = "ARIA/ECB/PKCS7PADDING";
  157. algorithms[NsriObjectIdentifiers.id_aria256_ecb.Id] = "ARIA/ECB/PKCS7PADDING";
  158. algorithms["ARIA//PKCS7"] = "ARIA/ECB/PKCS7PADDING";
  159. algorithms["ARIA//PKCS7PADDING"] = "ARIA/ECB/PKCS7PADDING";
  160. algorithms["ARIA//PKCS5"] = "ARIA/ECB/PKCS7PADDING";
  161. algorithms["ARIA//PKCS5PADDING"] = "ARIA/ECB/PKCS7PADDING";
  162. algorithms[NsriObjectIdentifiers.id_aria128_gcm.Id] = "ARIA/GCM/NOPADDING";
  163. algorithms[NsriObjectIdentifiers.id_aria192_gcm.Id] = "ARIA/GCM/NOPADDING";
  164. algorithms[NsriObjectIdentifiers.id_aria256_gcm.Id] = "ARIA/GCM/NOPADDING";
  165. algorithms[NsriObjectIdentifiers.id_aria128_ofb.Id] = "ARIA/OFB/NOPADDING";
  166. algorithms[NsriObjectIdentifiers.id_aria192_ofb.Id] = "ARIA/OFB/NOPADDING";
  167. algorithms[NsriObjectIdentifiers.id_aria256_ofb.Id] = "ARIA/OFB/NOPADDING";
  168. algorithms["RSA/ECB/PKCS1"] = "RSA//PKCS1PADDING";
  169. algorithms["RSA/ECB/PKCS1PADDING"] = "RSA//PKCS1PADDING";
  170. algorithms[PkcsObjectIdentifiers.RsaEncryption.Id] = "RSA//PKCS1PADDING";
  171. algorithms[PkcsObjectIdentifiers.IdRsaesOaep.Id] = "RSA//OAEPPADDING";
  172. algorithms[OiwObjectIdentifiers.DesCbc.Id] = "DES/CBC";
  173. algorithms[OiwObjectIdentifiers.DesCfb.Id] = "DES/CFB";
  174. algorithms[OiwObjectIdentifiers.DesEcb.Id] = "DES/ECB";
  175. algorithms[OiwObjectIdentifiers.DesOfb.Id] = "DES/OFB";
  176. algorithms[OiwObjectIdentifiers.DesEde.Id] = "DESEDE";
  177. algorithms["TDEA"] = "DESEDE";
  178. algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDE/CBC";
  179. algorithms[PkcsObjectIdentifiers.RC2Cbc.Id] = "RC2/CBC";
  180. algorithms["1.3.6.1.4.1.188.7.1.1.2"] = "IDEA/CBC";
  181. algorithms["1.2.840.113533.7.66.10"] = "CAST5/CBC";
  182. algorithms["RC4"] = "ARC4";
  183. algorithms["ARCFOUR"] = "ARC4";
  184. algorithms["1.2.840.113549.3.4"] = "ARC4";
  185. algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEWITHSHAAND128BITRC4";
  186. algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEWITHSHAAND128BITRC4";
  187. algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEWITHSHAAND40BITRC4";
  188. algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEWITHSHAAND40BITRC4";
  189. algorithms["PBEWITHSHA1ANDDES"] = "PBEWITHSHA1ANDDES-CBC";
  190. algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEWITHSHA1ANDDES-CBC";
  191. algorithms["PBEWITHSHA1ANDRC2"] = "PBEWITHSHA1ANDRC2-CBC";
  192. algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEWITHSHA1ANDRC2-CBC";
  193. algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
  194. algorithms["PBEWITHSHAAND3KEYTRIPLEDES"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
  195. algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
  196. algorithms["PBEWITHSHA1ANDDESEDE"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
  197. algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC";
  198. algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC";
  199. algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEWITHSHAAND128BITRC2-CBC";
  200. algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEWITHSHAAND128BITRC2-CBC";
  201. algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEWITHSHAAND40BITRC2-CBC";
  202. algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEWITHSHAAND40BITRC2-CBC";
  203. algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC";
  204. algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC";
  205. algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC";
  206. algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC";
  207. algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC";
  208. algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC";
  209. algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEWITHSHA256AND128BITAES-CBC-BC";
  210. algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEWITHSHA256AND192BITAES-CBC-BC";
  211. algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEWITHSHA256AND256BITAES-CBC-BC";
  212. algorithms["GOST"] = "GOST28147";
  213. algorithms["GOST-28147"] = "GOST28147";
  214. algorithms[CryptoProObjectIdentifiers.GostR28147Cbc.Id] = "GOST28147/CBC/PKCS7PADDING";
  215. algorithms["RC5-32"] = "RC5";
  216. algorithms[NttObjectIdentifiers.IdCamellia128Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
  217. algorithms[NttObjectIdentifiers.IdCamellia192Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
  218. algorithms[NttObjectIdentifiers.IdCamellia256Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
  219. algorithms[KisaObjectIdentifiers.IdSeedCbc.Id] = "SEED/CBC/PKCS7PADDING";
  220. algorithms["1.3.6.1.4.1.3029.1.2"] = "BLOWFISH/CBC";
  221. algorithms["CHACHA20"] = "CHACHA7539";
  222. algorithms[PkcsObjectIdentifiers.IdAlgAeadChaCha20Poly1305.Id] = "CHACHA20-POLY1305";
  223. }
  224. private CipherUtilities()
  225. {
  226. }
  227. /// <summary>
  228. /// Returns a ObjectIdentifier for a give encoding.
  229. /// </summary>
  230. /// <param name="mechanism">A string representation of the encoding.</param>
  231. /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
  232. // TODO Don't really want to support this
  233. public static DerObjectIdentifier GetObjectIdentifier(
  234. string mechanism)
  235. {
  236. if (mechanism == null)
  237. throw new ArgumentNullException("mechanism");
  238. mechanism = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.ToUpperInvariant(mechanism);
  239. string aliased = (string) algorithms[mechanism];
  240. if (aliased != null)
  241. mechanism = aliased;
  242. return (DerObjectIdentifier) oids[mechanism];
  243. }
  244. public static ICollection Algorithms
  245. {
  246. get { return oids.Keys; }
  247. }
  248. public static IBufferedCipher GetCipher(
  249. DerObjectIdentifier oid)
  250. {
  251. return GetCipher(oid.Id);
  252. }
  253. public static IBufferedCipher GetCipher(
  254. string algorithm)
  255. {
  256. if (algorithm == null)
  257. throw new ArgumentNullException("algorithm");
  258. algorithm = BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.ToUpperInvariant(algorithm);
  259. {
  260. string aliased = (string) algorithms[algorithm];
  261. if (aliased != null)
  262. algorithm = aliased;
  263. }
  264. IBasicAgreement iesAgreement = null;
  265. if (algorithm == "IES")
  266. {
  267. iesAgreement = new DHBasicAgreement();
  268. }
  269. else if (algorithm == "ECIES")
  270. {
  271. iesAgreement = new ECDHBasicAgreement();
  272. }
  273. if (iesAgreement != null)
  274. {
  275. return new BufferedIesCipher(
  276. new IesEngine(
  277. iesAgreement,
  278. new Kdf2BytesGenerator(
  279. new Sha1Digest()),
  280. new HMac(
  281. new Sha1Digest())));
  282. }
  283. if (BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.StartsWith(algorithm, "PBE"))
  284. {
  285. if (BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.EndsWith(algorithm, "-CBC"))
  286. {
  287. if (algorithm == "PBEWITHSHA1ANDDES-CBC")
  288. {
  289. return new PaddedBufferedBlockCipher(
  290. new CbcBlockCipher(new DesEngine()));
  291. }
  292. else if (algorithm == "PBEWITHSHA1ANDRC2-CBC")
  293. {
  294. return new PaddedBufferedBlockCipher(
  295. new CbcBlockCipher(new RC2Engine()));
  296. }
  297. else if (Strings.IsOneOf(algorithm,
  298. "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"))
  299. {
  300. return new PaddedBufferedBlockCipher(
  301. new CbcBlockCipher(new DesEdeEngine()));
  302. }
  303. else if (Strings.IsOneOf(algorithm,
  304. "PBEWITHSHAAND128BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC"))
  305. {
  306. return new PaddedBufferedBlockCipher(
  307. new CbcBlockCipher(new RC2Engine()));
  308. }
  309. }
  310. else if (BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.EndsWith(algorithm, "-BC") || BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.EndsWith(algorithm, "-OPENSSL"))
  311. {
  312. if (Strings.IsOneOf(algorithm,
  313. "PBEWITHSHAAND128BITAES-CBC-BC",
  314. "PBEWITHSHAAND192BITAES-CBC-BC",
  315. "PBEWITHSHAAND256BITAES-CBC-BC",
  316. "PBEWITHSHA256AND128BITAES-CBC-BC",
  317. "PBEWITHSHA256AND192BITAES-CBC-BC",
  318. "PBEWITHSHA256AND256BITAES-CBC-BC",
  319. "PBEWITHMD5AND128BITAES-CBC-OPENSSL",
  320. "PBEWITHMD5AND192BITAES-CBC-OPENSSL",
  321. "PBEWITHMD5AND256BITAES-CBC-OPENSSL"))
  322. {
  323. return new PaddedBufferedBlockCipher(
  324. new CbcBlockCipher(new AesEngine()));
  325. }
  326. }
  327. }
  328. string[] parts = algorithm.Split('/');
  329. IAeadCipher aeadCipher = null;
  330. IBlockCipher blockCipher = null;
  331. IAsymmetricBlockCipher asymBlockCipher = null;
  332. IStreamCipher streamCipher = null;
  333. string algorithmName = parts[0];
  334. {
  335. string aliased = (string)algorithms[algorithmName];
  336. if (aliased != null)
  337. algorithmName = aliased;
  338. }
  339. CipherAlgorithm cipherAlgorithm;
  340. try
  341. {
  342. cipherAlgorithm = (CipherAlgorithm)Enums.GetEnumValue(typeof(CipherAlgorithm), algorithmName);
  343. }
  344. catch (ArgumentException)
  345. {
  346. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  347. }
  348. switch (cipherAlgorithm)
  349. {
  350. case CipherAlgorithm.AES:
  351. blockCipher = new AesEngine();
  352. break;
  353. case CipherAlgorithm.ARC4:
  354. streamCipher = new RC4Engine();
  355. break;
  356. case CipherAlgorithm.ARIA:
  357. blockCipher = new AriaEngine();
  358. break;
  359. case CipherAlgorithm.BLOWFISH:
  360. blockCipher = new BlowfishEngine();
  361. break;
  362. case CipherAlgorithm.CAMELLIA:
  363. blockCipher = new CamelliaEngine();
  364. break;
  365. case CipherAlgorithm.CAST5:
  366. blockCipher = new Cast5Engine();
  367. break;
  368. case CipherAlgorithm.CAST6:
  369. blockCipher = new Cast6Engine();
  370. break;
  371. case CipherAlgorithm.CHACHA:
  372. streamCipher = new ChaChaEngine();
  373. break;
  374. case CipherAlgorithm.CHACHA20_POLY1305:
  375. aeadCipher = new ChaCha20Poly1305();
  376. break;
  377. case CipherAlgorithm.CHACHA7539:
  378. streamCipher = new ChaCha7539Engine();
  379. break;
  380. case CipherAlgorithm.DES:
  381. blockCipher = new DesEngine();
  382. break;
  383. case CipherAlgorithm.DESEDE:
  384. blockCipher = new DesEdeEngine();
  385. break;
  386. case CipherAlgorithm.ELGAMAL:
  387. asymBlockCipher = new ElGamalEngine();
  388. break;
  389. case CipherAlgorithm.GOST28147:
  390. blockCipher = new Gost28147Engine();
  391. break;
  392. case CipherAlgorithm.HC128:
  393. streamCipher = new HC128Engine();
  394. break;
  395. case CipherAlgorithm.HC256:
  396. streamCipher = new HC256Engine();
  397. break;
  398. case CipherAlgorithm.IDEA:
  399. blockCipher = new IdeaEngine();
  400. break;
  401. case CipherAlgorithm.NOEKEON:
  402. blockCipher = new NoekeonEngine();
  403. break;
  404. case CipherAlgorithm.PBEWITHSHAAND128BITRC4:
  405. case CipherAlgorithm.PBEWITHSHAAND40BITRC4:
  406. streamCipher = new RC4Engine();
  407. break;
  408. case CipherAlgorithm.RC2:
  409. blockCipher = new RC2Engine();
  410. break;
  411. case CipherAlgorithm.RC5:
  412. blockCipher = new RC532Engine();
  413. break;
  414. case CipherAlgorithm.RC5_64:
  415. blockCipher = new RC564Engine();
  416. break;
  417. case CipherAlgorithm.RC6:
  418. blockCipher = new RC6Engine();
  419. break;
  420. case CipherAlgorithm.RIJNDAEL:
  421. blockCipher = new RijndaelEngine();
  422. break;
  423. case CipherAlgorithm.RSA:
  424. asymBlockCipher = new RsaBlindedEngine();
  425. break;
  426. case CipherAlgorithm.SALSA20:
  427. streamCipher = new Salsa20Engine();
  428. break;
  429. case CipherAlgorithm.SEED:
  430. blockCipher = new SeedEngine();
  431. break;
  432. case CipherAlgorithm.SERPENT:
  433. blockCipher = new SerpentEngine();
  434. break;
  435. case CipherAlgorithm.SKIPJACK:
  436. blockCipher = new SkipjackEngine();
  437. break;
  438. case CipherAlgorithm.SM4:
  439. blockCipher = new SM4Engine();
  440. break;
  441. case CipherAlgorithm.TEA:
  442. blockCipher = new TeaEngine();
  443. break;
  444. case CipherAlgorithm.THREEFISH_256:
  445. blockCipher = new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256);
  446. break;
  447. case CipherAlgorithm.THREEFISH_512:
  448. blockCipher = new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512);
  449. break;
  450. case CipherAlgorithm.THREEFISH_1024:
  451. blockCipher = new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024);
  452. break;
  453. case CipherAlgorithm.TNEPRES:
  454. blockCipher = new TnepresEngine();
  455. break;
  456. case CipherAlgorithm.TWOFISH:
  457. blockCipher = new TwofishEngine();
  458. break;
  459. case CipherAlgorithm.VMPC:
  460. streamCipher = new VmpcEngine();
  461. break;
  462. case CipherAlgorithm.VMPC_KSA3:
  463. streamCipher = new VmpcKsa3Engine();
  464. break;
  465. case CipherAlgorithm.XTEA:
  466. blockCipher = new XteaEngine();
  467. break;
  468. default:
  469. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  470. }
  471. if (aeadCipher != null)
  472. {
  473. if (parts.Length > 1)
  474. throw new ArgumentException("Modes and paddings cannot be applied to AEAD ciphers");
  475. return new BufferedAeadCipher(aeadCipher);
  476. }
  477. if (streamCipher != null)
  478. {
  479. if (parts.Length > 1)
  480. throw new ArgumentException("Modes and paddings not used for stream ciphers");
  481. return new BufferedStreamCipher(streamCipher);
  482. }
  483. bool cts = false;
  484. bool padded = true;
  485. IBlockCipherPadding padding = null;
  486. IAeadBlockCipher aeadBlockCipher = null;
  487. if (parts.Length > 2)
  488. {
  489. if (streamCipher != null)
  490. throw new ArgumentException("Paddings not used for stream ciphers");
  491. string paddingName = parts[2];
  492. CipherPadding cipherPadding;
  493. if (paddingName == "")
  494. {
  495. cipherPadding = CipherPadding.RAW;
  496. }
  497. else if (paddingName == "X9.23PADDING")
  498. {
  499. cipherPadding = CipherPadding.X923PADDING;
  500. }
  501. else
  502. {
  503. try
  504. {
  505. cipherPadding = (CipherPadding)Enums.GetEnumValue(typeof(CipherPadding), paddingName);
  506. }
  507. catch (ArgumentException)
  508. {
  509. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  510. }
  511. }
  512. switch (cipherPadding)
  513. {
  514. case CipherPadding.NOPADDING:
  515. padded = false;
  516. break;
  517. case CipherPadding.RAW:
  518. break;
  519. case CipherPadding.ISO10126PADDING:
  520. case CipherPadding.ISO10126D2PADDING:
  521. case CipherPadding.ISO10126_2PADDING:
  522. padding = new ISO10126d2Padding();
  523. break;
  524. case CipherPadding.ISO7816_4PADDING:
  525. case CipherPadding.ISO9797_1PADDING:
  526. padding = new ISO7816d4Padding();
  527. break;
  528. case CipherPadding.ISO9796_1:
  529. case CipherPadding.ISO9796_1PADDING:
  530. asymBlockCipher = new ISO9796d1Encoding(asymBlockCipher);
  531. break;
  532. case CipherPadding.OAEP:
  533. case CipherPadding.OAEPPADDING:
  534. asymBlockCipher = new OaepEncoding(asymBlockCipher);
  535. break;
  536. case CipherPadding.OAEPWITHMD5ANDMGF1PADDING:
  537. asymBlockCipher = new OaepEncoding(asymBlockCipher, new MD5Digest());
  538. break;
  539. case CipherPadding.OAEPWITHSHA1ANDMGF1PADDING:
  540. case CipherPadding.OAEPWITHSHA_1ANDMGF1PADDING:
  541. asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha1Digest());
  542. break;
  543. case CipherPadding.OAEPWITHSHA224ANDMGF1PADDING:
  544. case CipherPadding.OAEPWITHSHA_224ANDMGF1PADDING:
  545. asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha224Digest());
  546. break;
  547. case CipherPadding.OAEPWITHSHA256ANDMGF1PADDING:
  548. case CipherPadding.OAEPWITHSHA_256ANDMGF1PADDING:
  549. case CipherPadding.OAEPWITHSHA256ANDMGF1WITHSHA256PADDING:
  550. case CipherPadding.OAEPWITHSHA_256ANDMGF1WITHSHA_256PADDING:
  551. asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest());
  552. break;
  553. case CipherPadding.OAEPWITHSHA256ANDMGF1WITHSHA1PADDING:
  554. case CipherPadding.OAEPWITHSHA_256ANDMGF1WITHSHA_1PADDING:
  555. asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest(), new Sha1Digest(), null);
  556. break;
  557. case CipherPadding.OAEPWITHSHA384ANDMGF1PADDING:
  558. case CipherPadding.OAEPWITHSHA_384ANDMGF1PADDING:
  559. asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha384Digest());
  560. break;
  561. case CipherPadding.OAEPWITHSHA512ANDMGF1PADDING:
  562. case CipherPadding.OAEPWITHSHA_512ANDMGF1PADDING:
  563. asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha512Digest());
  564. break;
  565. case CipherPadding.PKCS1:
  566. case CipherPadding.PKCS1PADDING:
  567. asymBlockCipher = new Pkcs1Encoding(asymBlockCipher);
  568. break;
  569. case CipherPadding.PKCS5:
  570. case CipherPadding.PKCS5PADDING:
  571. case CipherPadding.PKCS7:
  572. case CipherPadding.PKCS7PADDING:
  573. padding = new Pkcs7Padding();
  574. break;
  575. case CipherPadding.TBCPADDING:
  576. padding = new TbcPadding();
  577. break;
  578. case CipherPadding.WITHCTS:
  579. cts = true;
  580. break;
  581. case CipherPadding.X923PADDING:
  582. padding = new X923Padding();
  583. break;
  584. case CipherPadding.ZEROBYTEPADDING:
  585. padding = new ZeroBytePadding();
  586. break;
  587. default:
  588. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  589. }
  590. }
  591. string mode = "";
  592. if (parts.Length > 1)
  593. {
  594. mode = parts[1];
  595. int di = GetDigitIndex(mode);
  596. string modeName = di >= 0 ? mode.Substring(0, di) : mode;
  597. try
  598. {
  599. CipherMode cipherMode = modeName == ""
  600. ? CipherMode.NONE
  601. : (CipherMode)Enums.GetEnumValue(typeof(CipherMode), modeName);
  602. switch (cipherMode)
  603. {
  604. case CipherMode.ECB:
  605. case CipherMode.NONE:
  606. break;
  607. case CipherMode.CBC:
  608. blockCipher = new CbcBlockCipher(blockCipher);
  609. break;
  610. case CipherMode.CCM:
  611. aeadBlockCipher = new CcmBlockCipher(blockCipher);
  612. break;
  613. case CipherMode.CFB:
  614. {
  615. int bits = (di < 0)
  616. ? 8 * blockCipher.GetBlockSize()
  617. : int.Parse(mode.Substring(di));
  618. blockCipher = new CfbBlockCipher(blockCipher, bits);
  619. break;
  620. }
  621. case CipherMode.CTR:
  622. blockCipher = new SicBlockCipher(blockCipher);
  623. break;
  624. case CipherMode.CTS:
  625. cts = true;
  626. blockCipher = new CbcBlockCipher(blockCipher);
  627. break;
  628. case CipherMode.EAX:
  629. aeadBlockCipher = new EaxBlockCipher(blockCipher);
  630. break;
  631. case CipherMode.GCM:
  632. aeadBlockCipher = new GcmBlockCipher(blockCipher);
  633. break;
  634. case CipherMode.GOFB:
  635. blockCipher = new GOfbBlockCipher(blockCipher);
  636. break;
  637. case CipherMode.OCB:
  638. aeadBlockCipher = new OcbBlockCipher(blockCipher, CreateBlockCipher(cipherAlgorithm));
  639. break;
  640. case CipherMode.OFB:
  641. {
  642. int bits = (di < 0)
  643. ? 8 * blockCipher.GetBlockSize()
  644. : int.Parse(mode.Substring(di));
  645. blockCipher = new OfbBlockCipher(blockCipher, bits);
  646. break;
  647. }
  648. case CipherMode.OPENPGPCFB:
  649. blockCipher = new OpenPgpCfbBlockCipher(blockCipher);
  650. break;
  651. case CipherMode.SIC:
  652. if (blockCipher.GetBlockSize() < 16)
  653. {
  654. throw new ArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
  655. }
  656. blockCipher = new SicBlockCipher(blockCipher);
  657. break;
  658. default:
  659. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  660. }
  661. }
  662. catch (ArgumentException)
  663. {
  664. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  665. }
  666. }
  667. if (aeadBlockCipher != null)
  668. {
  669. if (cts)
  670. throw new SecurityUtilityException("CTS mode not valid for AEAD ciphers.");
  671. if (padded && parts.Length > 2 && parts[2] != "")
  672. throw new SecurityUtilityException("Bad padding specified for AEAD cipher.");
  673. return new BufferedAeadBlockCipher(aeadBlockCipher);
  674. }
  675. if (blockCipher != null)
  676. {
  677. if (cts)
  678. {
  679. return new CtsBlockCipher(blockCipher);
  680. }
  681. if (padding != null)
  682. {
  683. return new PaddedBufferedBlockCipher(blockCipher, padding);
  684. }
  685. if (!padded || blockCipher.IsPartialBlockOkay)
  686. {
  687. return new BufferedBlockCipher(blockCipher);
  688. }
  689. return new PaddedBufferedBlockCipher(blockCipher);
  690. }
  691. if (asymBlockCipher != null)
  692. {
  693. return new BufferedAsymmetricBlockCipher(asymBlockCipher);
  694. }
  695. throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
  696. }
  697. public static string GetAlgorithmName(
  698. DerObjectIdentifier oid)
  699. {
  700. return (string) algorithms[oid.Id];
  701. }
  702. private static int GetDigitIndex(
  703. string s)
  704. {
  705. for (int i = 0; i < s.Length; ++i)
  706. {
  707. if (char.IsDigit(s[i]))
  708. return i;
  709. }
  710. return -1;
  711. }
  712. private static IBlockCipher CreateBlockCipher(CipherAlgorithm cipherAlgorithm)
  713. {
  714. switch (cipherAlgorithm)
  715. {
  716. case CipherAlgorithm.AES: return new AesEngine();
  717. case CipherAlgorithm.ARIA: return new AriaEngine();
  718. case CipherAlgorithm.BLOWFISH: return new BlowfishEngine();
  719. case CipherAlgorithm.CAMELLIA: return new CamelliaEngine();
  720. case CipherAlgorithm.CAST5: return new Cast5Engine();
  721. case CipherAlgorithm.CAST6: return new Cast6Engine();
  722. case CipherAlgorithm.DES: return new DesEngine();
  723. case CipherAlgorithm.DESEDE: return new DesEdeEngine();
  724. case CipherAlgorithm.GOST28147: return new Gost28147Engine();
  725. case CipherAlgorithm.IDEA: return new IdeaEngine();
  726. case CipherAlgorithm.NOEKEON: return new NoekeonEngine();
  727. case CipherAlgorithm.RC2: return new RC2Engine();
  728. case CipherAlgorithm.RC5: return new RC532Engine();
  729. case CipherAlgorithm.RC5_64: return new RC564Engine();
  730. case CipherAlgorithm.RC6: return new RC6Engine();
  731. case CipherAlgorithm.RIJNDAEL: return new RijndaelEngine();
  732. case CipherAlgorithm.SEED: return new SeedEngine();
  733. case CipherAlgorithm.SERPENT: return new SerpentEngine();
  734. case CipherAlgorithm.SKIPJACK: return new SkipjackEngine();
  735. case CipherAlgorithm.SM4: return new SM4Engine();
  736. case CipherAlgorithm.TEA: return new TeaEngine();
  737. case CipherAlgorithm.THREEFISH_256: return new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256);
  738. case CipherAlgorithm.THREEFISH_512: return new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512);
  739. case CipherAlgorithm.THREEFISH_1024: return new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024);
  740. case CipherAlgorithm.TNEPRES: return new TnepresEngine();
  741. case CipherAlgorithm.TWOFISH: return new TwofishEngine();
  742. case CipherAlgorithm.XTEA: return new XteaEngine();
  743. default:
  744. throw new SecurityUtilityException("Cipher " + cipherAlgorithm + " not recognised or not a block cipher");
  745. }
  746. }
  747. }
  748. }
  749. #pragma warning restore
  750. #endif