using System; using System.Collections; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.CryptoPro; using Org.BouncyCastle.Asn1.Kisa; using Org.BouncyCastle.Asn1.Misc; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Ntt; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Security; public sealed class ParameterUtilities { private static readonly IDictionary algorithms; private static readonly IDictionary basicIVSizes; private ParameterUtilities() { } static ParameterUtilities() { algorithms = Platform.CreateHashtable(); basicIVSizes = Platform.CreateHashtable(); AddAlgorithm("AES", "AESWRAP"); AddAlgorithm("AES128", "2.16.840.1.101.3.4.2", NistObjectIdentifiers.IdAes128Cbc, NistObjectIdentifiers.IdAes128Cfb, NistObjectIdentifiers.IdAes128Ecb, NistObjectIdentifiers.IdAes128Ofb, NistObjectIdentifiers.IdAes128Wrap); AddAlgorithm("AES192", "2.16.840.1.101.3.4.22", NistObjectIdentifiers.IdAes192Cbc, NistObjectIdentifiers.IdAes192Cfb, NistObjectIdentifiers.IdAes192Ecb, NistObjectIdentifiers.IdAes192Ofb, NistObjectIdentifiers.IdAes192Wrap); AddAlgorithm("AES256", "2.16.840.1.101.3.4.42", NistObjectIdentifiers.IdAes256Cbc, NistObjectIdentifiers.IdAes256Cfb, NistObjectIdentifiers.IdAes256Ecb, NistObjectIdentifiers.IdAes256Ofb, NistObjectIdentifiers.IdAes256Wrap); AddAlgorithm("BLOWFISH", "1.3.6.1.4.1.3029.1.2"); AddAlgorithm("CAMELLIA", "CAMELLIAWRAP"); AddAlgorithm("CAMELLIA128", NttObjectIdentifiers.IdCamellia128Cbc, NttObjectIdentifiers.IdCamellia128Wrap); AddAlgorithm("CAMELLIA192", NttObjectIdentifiers.IdCamellia192Cbc, NttObjectIdentifiers.IdCamellia192Wrap); AddAlgorithm("CAMELLIA256", NttObjectIdentifiers.IdCamellia256Cbc, NttObjectIdentifiers.IdCamellia256Wrap); AddAlgorithm("CAST5", "1.2.840.113533.7.66.10"); AddAlgorithm("CAST6"); AddAlgorithm("DES", OiwObjectIdentifiers.DesCbc, OiwObjectIdentifiers.DesCfb, OiwObjectIdentifiers.DesEcb, OiwObjectIdentifiers.DesOfb); AddAlgorithm("DESEDE", "DESEDEWRAP", "TDEA", OiwObjectIdentifiers.DesEde, PkcsObjectIdentifiers.IdAlgCms3DesWrap); AddAlgorithm("DESEDE3", PkcsObjectIdentifiers.DesEde3Cbc); AddAlgorithm("GOST28147", "GOST", "GOST-28147", CryptoProObjectIdentifiers.GostR28147Cbc); AddAlgorithm("HC128"); AddAlgorithm("HC256"); AddAlgorithm("IDEA", "1.3.6.1.4.1.188.7.1.1.2"); AddAlgorithm("NOEKEON"); AddAlgorithm("RC2", PkcsObjectIdentifiers.RC2Cbc, PkcsObjectIdentifiers.IdAlgCmsRC2Wrap); AddAlgorithm("RC4", "ARC4", "1.2.840.113549.3.4"); AddAlgorithm("RC5", "RC5-32"); AddAlgorithm("RC5-64"); AddAlgorithm("RC6"); AddAlgorithm("RIJNDAEL"); AddAlgorithm("SALSA20"); AddAlgorithm("SEED", KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap, KisaObjectIdentifiers.IdSeedCbc); AddAlgorithm("SERPENT"); AddAlgorithm("SKIPJACK"); AddAlgorithm("SM4"); AddAlgorithm("TEA"); AddAlgorithm("THREEFISH-256"); AddAlgorithm("THREEFISH-512"); AddAlgorithm("THREEFISH-1024"); AddAlgorithm("TNEPRES"); AddAlgorithm("TWOFISH"); AddAlgorithm("VMPC"); AddAlgorithm("VMPC-KSA3"); AddAlgorithm("XTEA"); AddBasicIVSizeEntries(8, "BLOWFISH", "DES", "DESEDE", "DESEDE3"); AddBasicIVSizeEntries(16, "AES", "AES128", "AES192", "AES256", "CAMELLIA", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "NOEKEON", "SEED", "SM4"); } private static void AddAlgorithm(string canonicalName, params object[] aliases) { algorithms[canonicalName] = canonicalName; foreach (object obj in aliases) { algorithms[obj.ToString()] = canonicalName; } } private static void AddBasicIVSizeEntries(int size, params string[] algorithms) { foreach (string key in algorithms) { basicIVSizes.Add(key, size); } } public static string GetCanonicalAlgorithmName(string algorithm) { return (string)algorithms[Platform.ToUpperInvariant(algorithm)]; } public static KeyParameter CreateKeyParameter(DerObjectIdentifier algOid, byte[] keyBytes) { return CreateKeyParameter(algOid.Id, keyBytes, 0, keyBytes.Length); } public static KeyParameter CreateKeyParameter(string algorithm, byte[] keyBytes) { return CreateKeyParameter(algorithm, keyBytes, 0, keyBytes.Length); } public static KeyParameter CreateKeyParameter(DerObjectIdentifier algOid, byte[] keyBytes, int offset, int length) { return CreateKeyParameter(algOid.Id, keyBytes, offset, length); } public static KeyParameter CreateKeyParameter(string algorithm, byte[] keyBytes, int offset, int length) { if (algorithm == null) { throw new ArgumentNullException("algorithm"); } string canonicalAlgorithmName = GetCanonicalAlgorithmName(algorithm); if (canonicalAlgorithmName == null) { throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); } switch (canonicalAlgorithmName) { case "DES": return new DesParameters(keyBytes, offset, length); case "DESEDE": case "DESEDE3": return new DesEdeParameters(keyBytes, offset, length); case "RC2": return new RC2Parameters(keyBytes, offset, length); default: return new KeyParameter(keyBytes, offset, length); } } public static ICipherParameters GetCipherParameters(DerObjectIdentifier algOid, ICipherParameters key, Asn1Object asn1Params) { return GetCipherParameters(algOid.Id, key, asn1Params); } public static ICipherParameters GetCipherParameters(string algorithm, ICipherParameters key, Asn1Object asn1Params) { if (algorithm == null) { throw new ArgumentNullException("algorithm"); } string canonicalAlgorithmName = GetCanonicalAlgorithmName(algorithm); if (canonicalAlgorithmName == null) { throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); } byte[] array = null; try { int num = FindBasicIVSize(canonicalAlgorithmName); if (num == -1) { switch (canonicalAlgorithmName) { default: goto end_IL_0030; case "RIJNDAEL": case "SKIPJACK": case "TWOFISH": break; case "CAST5": array = Cast5CbcParameters.GetInstance(asn1Params).GetIV(); goto end_IL_0030; case "IDEA": array = IdeaCbcPar.GetInstance(asn1Params).GetIV(); goto end_IL_0030; case "RC2": array = RC2CbcParameter.GetInstance(asn1Params).GetIV(); goto end_IL_0030; } } array = ((Asn1OctetString)asn1Params).GetOctets(); end_IL_0030:; } catch (Exception innerException) { throw new ArgumentException("Could not process ASN.1 parameters", innerException); } if (array != null) { return new ParametersWithIV(key, array); } throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); } public static Asn1Encodable GenerateParameters(DerObjectIdentifier algID, SecureRandom random) { return GenerateParameters(algID.Id, random); } public static Asn1Encodable GenerateParameters(string algorithm, SecureRandom random) { if (algorithm == null) { throw new ArgumentNullException("algorithm"); } string canonicalAlgorithmName = GetCanonicalAlgorithmName(algorithm); if (canonicalAlgorithmName == null) { throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."); } int num = FindBasicIVSize(canonicalAlgorithmName); if (num != -1) { return CreateIVOctetString(random, num); } return canonicalAlgorithmName switch { "CAST5" => new Cast5CbcParameters(CreateIV(random, 8), 128), "IDEA" => new IdeaCbcPar(CreateIV(random, 8)), "RC2" => new RC2CbcParameter(CreateIV(random, 8)), _ => throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised."), }; } public static ICipherParameters WithRandom(ICipherParameters cp, SecureRandom random) { if (random != null) { cp = new ParametersWithRandom(cp, random); } return cp; } private static Asn1OctetString CreateIVOctetString(SecureRandom random, int ivLength) { return new DerOctetString(CreateIV(random, ivLength)); } private static byte[] CreateIV(SecureRandom random, int ivLength) { byte[] array = new byte[ivLength]; random.NextBytes(array); return array; } private static int FindBasicIVSize(string canonicalName) { if (!basicIVSizes.Contains(canonicalName)) { return -1; } return (int)basicIVSizes[canonicalName]; } }