You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.4 KiB
162 lines
4.4 KiB
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) |
|
#pragma warning disable |
|
using System; |
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Generators; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities; |
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.OpenSsl |
|
{ |
|
internal sealed class PemUtilities |
|
{ |
|
private enum PemBaseAlg { AES_128, AES_192, AES_256, BF, DES, DES_EDE, DES_EDE3, RC2, RC2_40, RC2_64 }; |
|
private enum PemMode { CBC, CFB, ECB, OFB }; |
|
|
|
static PemUtilities() |
|
{ |
|
// Signal to obfuscation tools not to change enum constants |
|
((PemBaseAlg)Enums.GetArbitraryValue(typeof(PemBaseAlg))).ToString(); |
|
((PemMode)Enums.GetArbitraryValue(typeof(PemMode))).ToString(); |
|
} |
|
|
|
private static void ParseDekAlgName( |
|
string dekAlgName, |
|
out PemBaseAlg baseAlg, |
|
out PemMode mode) |
|
{ |
|
try |
|
{ |
|
mode = PemMode.ECB; |
|
|
|
if (dekAlgName == "DES-EDE" || dekAlgName == "DES-EDE3") |
|
{ |
|
baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName); |
|
return; |
|
} |
|
|
|
int pos = dekAlgName.LastIndexOf('-'); |
|
if (pos >= 0) |
|
{ |
|
baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName.Substring(0, pos)); |
|
mode = (PemMode)Enums.GetEnumValue(typeof(PemMode), dekAlgName.Substring(pos + 1)); |
|
return; |
|
} |
|
} |
|
catch (ArgumentException) |
|
{ |
|
} |
|
|
|
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName); |
|
} |
|
|
|
internal static byte[] Crypt( |
|
bool encrypt, |
|
byte[] bytes, |
|
char[] password, |
|
string dekAlgName, |
|
byte[] iv) |
|
{ |
|
PemBaseAlg baseAlg; |
|
PemMode mode; |
|
ParseDekAlgName(dekAlgName, out baseAlg, out mode); |
|
|
|
string padding; |
|
switch (mode) |
|
{ |
|
case PemMode.CBC: |
|
case PemMode.ECB: |
|
padding = "PKCS5Padding"; |
|
break; |
|
case PemMode.CFB: |
|
case PemMode.OFB: |
|
padding = "NoPadding"; |
|
break; |
|
default: |
|
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName); |
|
} |
|
|
|
string algorithm; |
|
|
|
byte[] salt = iv; |
|
switch (baseAlg) |
|
{ |
|
case PemBaseAlg.AES_128: |
|
case PemBaseAlg.AES_192: |
|
case PemBaseAlg.AES_256: |
|
algorithm = "AES"; |
|
if (salt.Length > 8) |
|
{ |
|
salt = new byte[8]; |
|
Array.Copy(iv, 0, salt, 0, salt.Length); |
|
} |
|
break; |
|
case PemBaseAlg.BF: |
|
algorithm = "BLOWFISH"; |
|
break; |
|
case PemBaseAlg.DES: |
|
algorithm = "DES"; |
|
break; |
|
case PemBaseAlg.DES_EDE: |
|
case PemBaseAlg.DES_EDE3: |
|
algorithm = "DESede"; |
|
break; |
|
case PemBaseAlg.RC2: |
|
case PemBaseAlg.RC2_40: |
|
case PemBaseAlg.RC2_64: |
|
algorithm = "RC2"; |
|
break; |
|
default: |
|
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName); |
|
} |
|
|
|
string cipherName = algorithm + "/" + mode + "/" + padding; |
|
IBufferedCipher cipher = CipherUtilities.GetCipher(cipherName); |
|
|
|
ICipherParameters cParams = GetCipherParameters(password, baseAlg, salt); |
|
|
|
if (mode != PemMode.ECB) |
|
{ |
|
cParams = new ParametersWithIV(cParams, iv); |
|
} |
|
|
|
cipher.Init(encrypt, cParams); |
|
|
|
return cipher.DoFinal(bytes); |
|
} |
|
|
|
private static ICipherParameters GetCipherParameters( |
|
char[] password, |
|
PemBaseAlg baseAlg, |
|
byte[] salt) |
|
{ |
|
string algorithm; |
|
int keyBits; |
|
switch (baseAlg) |
|
{ |
|
case PemBaseAlg.AES_128: keyBits = 128; algorithm = "AES128"; break; |
|
case PemBaseAlg.AES_192: keyBits = 192; algorithm = "AES192"; break; |
|
case PemBaseAlg.AES_256: keyBits = 256; algorithm = "AES256"; break; |
|
case PemBaseAlg.BF: keyBits = 128; algorithm = "BLOWFISH"; break; |
|
case PemBaseAlg.DES: keyBits = 64; algorithm = "DES"; break; |
|
case PemBaseAlg.DES_EDE: keyBits = 128; algorithm = "DESEDE"; break; |
|
case PemBaseAlg.DES_EDE3: keyBits = 192; algorithm = "DESEDE3"; break; |
|
case PemBaseAlg.RC2: keyBits = 128; algorithm = "RC2"; break; |
|
case PemBaseAlg.RC2_40: keyBits = 40; algorithm = "RC2"; break; |
|
case PemBaseAlg.RC2_64: keyBits = 64; algorithm = "RC2"; break; |
|
default: |
|
return null; |
|
} |
|
|
|
OpenSslPbeParametersGenerator pGen = new OpenSslPbeParametersGenerator(); |
|
|
|
pGen.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt); |
|
|
|
return pGen.GenerateDerivedParameters(algorithm, keyBits); |
|
} |
|
} |
|
} |
|
#pragma warning restore |
|
#endif
|
|
|