CipherUtilities.cs 32 KB

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