CipherUtilities.cs 34 KB

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