iTextSharp-LGPL/src/core/srcbc/openssl/PEMUtilities.cs

139 lines
3.4 KiB
C#

using System;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.OpenSsl
{
internal sealed class PemUtilities
{
internal static bool ParseDekAlgName(
string dekAlgName,
out string baseAlg,
out string mode)
{
baseAlg = dekAlgName;
mode = "ECB";
if (dekAlgName == "DES-EDE" || dekAlgName == "DES-EDE3")
return true;
int pos = dekAlgName.LastIndexOf('-');
if (pos < 0)
return false;
baseAlg = dekAlgName.Substring(0, pos);
mode = dekAlgName.Substring(pos + 1);
return true;
}
internal static byte[] Crypt(
bool encrypt,
byte[] bytes,
char[] password,
string dekAlgName,
byte[] iv)
{
string baseAlg, mode;
if (!ParseDekAlgName(dekAlgName, out baseAlg, out mode))
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
string padding;
switch (mode)
{
case "CBC":
case "ECB":
padding = "PKCS5Padding";
break;
case "CFB":
case "OFB":
padding = "NoPadding";
break;
default:
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
}
string algorithm;
byte[] salt = iv;
switch (baseAlg)
{
case "AES-128":
case "AES-192":
case "AES-256":
algorithm = "AES";
if (salt.Length > 8)
{
salt = new byte[8];
Array.Copy(iv, 0, salt, 0, salt.Length);
}
break;
case "BF":
algorithm = "BLOWFISH";
break;
case "DES":
algorithm = "DES";
break;
case "DES-EDE":
case "DES-EDE3":
algorithm = "DESede";
break;
case "RC2":
case "RC2-40":
case "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 != "ECB")
{
cParams = new ParametersWithIV(cParams, iv);
}
cipher.Init(encrypt, cParams);
return cipher.DoFinal(bytes);
}
private static ICipherParameters GetCipherParameters(
char[] password,
string baseAlg,
byte[] salt)
{
string algorithm;
int keyBits;
switch (baseAlg)
{
case "AES-128": keyBits = 128; algorithm = "AES128"; break;
case "AES-192": keyBits = 192; algorithm = "AES192"; break;
case "AES-256": keyBits = 256; algorithm = "AES256"; break;
case "BF": keyBits = 128; algorithm = "BLOWFISH"; break;
case "DES": keyBits = 64; algorithm = "DES"; break;
case "DES-EDE": keyBits = 128; algorithm = "DESEDE"; break;
case "DES-EDE3": keyBits = 192; algorithm = "DESEDE3"; break;
case "RC2": keyBits = 128; algorithm = "RC2"; break;
case "RC2-40": keyBits = 40; algorithm = "RC2"; break;
case "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);
}
}
}