init commit
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
namespace Org.BouncyCastle.OpenSsl;
|
||||
|
||||
public interface IPasswordFinder
|
||||
{
|
||||
char[] GetPassword();
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Cms;
|
||||
using Org.BouncyCastle.Asn1.CryptoPro;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Security.Certificates;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.Encoders;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
using Org.BouncyCastle.X509;
|
||||
|
||||
namespace Org.BouncyCastle.OpenSsl;
|
||||
|
||||
public class MiscPemGenerator : PemObjectGenerator
|
||||
{
|
||||
private object obj;
|
||||
|
||||
private string algorithm;
|
||||
|
||||
private char[] password;
|
||||
|
||||
private SecureRandom random;
|
||||
|
||||
public MiscPemGenerator(object obj)
|
||||
{
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
public MiscPemGenerator(object obj, string algorithm, char[] password, SecureRandom random)
|
||||
{
|
||||
this.obj = obj;
|
||||
this.algorithm = algorithm;
|
||||
this.password = password;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
private static PemObject CreatePemObject(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException("obj");
|
||||
}
|
||||
if (obj is AsymmetricCipherKeyPair)
|
||||
{
|
||||
return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private);
|
||||
}
|
||||
if (obj is PemObject)
|
||||
{
|
||||
return (PemObject)obj;
|
||||
}
|
||||
if (obj is PemObjectGenerator)
|
||||
{
|
||||
return ((PemObjectGenerator)obj).Generate();
|
||||
}
|
||||
string type;
|
||||
byte[] content;
|
||||
if (obj is X509Certificate)
|
||||
{
|
||||
type = "CERTIFICATE";
|
||||
try
|
||||
{
|
||||
content = ((X509Certificate)obj).GetEncoded();
|
||||
}
|
||||
catch (CertificateEncodingException ex)
|
||||
{
|
||||
throw new IOException("Cannot Encode object: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
else if (obj is X509Crl)
|
||||
{
|
||||
type = "X509 CRL";
|
||||
try
|
||||
{
|
||||
content = ((X509Crl)obj).GetEncoded();
|
||||
}
|
||||
catch (CrlException ex2)
|
||||
{
|
||||
throw new IOException("Cannot Encode object: " + ex2.ToString());
|
||||
}
|
||||
}
|
||||
else if (obj is AsymmetricKeyParameter)
|
||||
{
|
||||
AsymmetricKeyParameter asymmetricKeyParameter = (AsymmetricKeyParameter)obj;
|
||||
if (asymmetricKeyParameter.IsPrivate)
|
||||
{
|
||||
content = EncodePrivateKey(asymmetricKeyParameter, out var keyType);
|
||||
type = keyType + " PRIVATE KEY";
|
||||
}
|
||||
else
|
||||
{
|
||||
type = "PUBLIC KEY";
|
||||
content = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(asymmetricKeyParameter).GetDerEncoded();
|
||||
}
|
||||
}
|
||||
else if (obj is IX509AttributeCertificate)
|
||||
{
|
||||
type = "ATTRIBUTE CERTIFICATE";
|
||||
content = ((X509V2AttributeCertificate)obj).GetEncoded();
|
||||
}
|
||||
else if (obj is Pkcs10CertificationRequest)
|
||||
{
|
||||
type = "CERTIFICATE REQUEST";
|
||||
content = ((Pkcs10CertificationRequest)obj).GetEncoded();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(obj is Org.BouncyCastle.Asn1.Cms.ContentInfo))
|
||||
{
|
||||
throw new PemGenerationException("Object type not supported: " + Platform.GetTypeName(obj));
|
||||
}
|
||||
type = "PKCS7";
|
||||
content = ((Org.BouncyCastle.Asn1.Cms.ContentInfo)obj).GetEncoded();
|
||||
}
|
||||
return new PemObject(type, content);
|
||||
}
|
||||
|
||||
private static PemObject CreatePemObject(object obj, string algorithm, char[] password, SecureRandom random)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException("obj");
|
||||
}
|
||||
if (algorithm == null)
|
||||
{
|
||||
throw new ArgumentNullException("algorithm");
|
||||
}
|
||||
if (password == null)
|
||||
{
|
||||
throw new ArgumentNullException("password");
|
||||
}
|
||||
if (random == null)
|
||||
{
|
||||
throw new ArgumentNullException("random");
|
||||
}
|
||||
if (obj is AsymmetricCipherKeyPair)
|
||||
{
|
||||
return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random);
|
||||
}
|
||||
string text = null;
|
||||
byte[] array = null;
|
||||
if (obj is AsymmetricKeyParameter)
|
||||
{
|
||||
AsymmetricKeyParameter asymmetricKeyParameter = (AsymmetricKeyParameter)obj;
|
||||
if (asymmetricKeyParameter.IsPrivate)
|
||||
{
|
||||
array = EncodePrivateKey(asymmetricKeyParameter, out var keyType);
|
||||
text = keyType + " PRIVATE KEY";
|
||||
}
|
||||
}
|
||||
if (text == null || array == null)
|
||||
{
|
||||
throw new PemGenerationException("Object type not supported: " + Platform.GetTypeName(obj));
|
||||
}
|
||||
string text2 = Platform.ToUpperInvariant(algorithm);
|
||||
if (text2 == "DESEDE")
|
||||
{
|
||||
text2 = "DES-EDE3-CBC";
|
||||
}
|
||||
int num = (Platform.StartsWith(text2, "AES-") ? 16 : 8);
|
||||
byte[] array2 = new byte[num];
|
||||
random.NextBytes(array2);
|
||||
byte[] content = PemUtilities.Crypt(encrypt: true, array, password, text2, array2);
|
||||
IList list = Platform.CreateArrayList(2);
|
||||
list.Add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
|
||||
list.Add(new PemHeader("DEK-Info", text2 + "," + Hex.ToHexString(array2)));
|
||||
return new PemObject(text, list, content);
|
||||
}
|
||||
|
||||
private static byte[] EncodePrivateKey(AsymmetricKeyParameter akp, out string keyType)
|
||||
{
|
||||
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);
|
||||
AlgorithmIdentifier privateKeyAlgorithm = privateKeyInfo.PrivateKeyAlgorithm;
|
||||
DerObjectIdentifier derObjectIdentifier = privateKeyAlgorithm.Algorithm;
|
||||
if (derObjectIdentifier.Equals(X9ObjectIdentifiers.IdDsa))
|
||||
{
|
||||
keyType = "DSA";
|
||||
DsaParameter instance = DsaParameter.GetInstance(privateKeyAlgorithm.Parameters);
|
||||
BigInteger x = ((DsaPrivateKeyParameters)akp).X;
|
||||
BigInteger value = instance.G.ModPow(x, instance.P);
|
||||
return new DerSequence(new DerInteger(0), new DerInteger(instance.P), new DerInteger(instance.Q), new DerInteger(instance.G), new DerInteger(value), new DerInteger(x)).GetEncoded();
|
||||
}
|
||||
if (derObjectIdentifier.Equals(PkcsObjectIdentifiers.RsaEncryption))
|
||||
{
|
||||
keyType = "RSA";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!derObjectIdentifier.Equals(CryptoProObjectIdentifiers.GostR3410x2001) && !derObjectIdentifier.Equals(X9ObjectIdentifiers.IdECPublicKey))
|
||||
{
|
||||
throw new ArgumentException("Cannot handle private key of type: " + Platform.GetTypeName(akp), "akp");
|
||||
}
|
||||
keyType = "EC";
|
||||
}
|
||||
return privateKeyInfo.ParsePrivateKey().GetEncoded();
|
||||
}
|
||||
|
||||
public PemObject Generate()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (algorithm != null)
|
||||
{
|
||||
return CreatePemObject(obj, algorithm, password, random);
|
||||
}
|
||||
return CreatePemObject(obj);
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
throw new PemGenerationException("encoding exception", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Org.BouncyCastle.OpenSsl;
|
||||
|
||||
[Serializable]
|
||||
public class PemException : IOException
|
||||
{
|
||||
public PemException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public PemException(string message, Exception exception)
|
||||
: base(message, exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Cms;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.EC;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
using Org.BouncyCastle.Utilities.Encoders;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
using Org.BouncyCastle.X509;
|
||||
|
||||
namespace Org.BouncyCastle.OpenSsl;
|
||||
|
||||
public class PemReader : Org.BouncyCastle.Utilities.IO.Pem.PemReader
|
||||
{
|
||||
private readonly IPasswordFinder pFinder;
|
||||
|
||||
static PemReader()
|
||||
{
|
||||
}
|
||||
|
||||
public PemReader(TextReader reader)
|
||||
: this(reader, null)
|
||||
{
|
||||
}
|
||||
|
||||
public PemReader(TextReader reader, IPasswordFinder pFinder)
|
||||
: base(reader)
|
||||
{
|
||||
this.pFinder = pFinder;
|
||||
}
|
||||
|
||||
public object ReadObject()
|
||||
{
|
||||
PemObject pemObject = ReadPemObject();
|
||||
if (pemObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (Platform.EndsWith(pemObject.Type, "PRIVATE KEY"))
|
||||
{
|
||||
return ReadPrivateKey(pemObject);
|
||||
}
|
||||
switch (pemObject.Type)
|
||||
{
|
||||
case "PUBLIC KEY":
|
||||
return ReadPublicKey(pemObject);
|
||||
case "RSA PUBLIC KEY":
|
||||
return ReadRsaPublicKey(pemObject);
|
||||
case "CERTIFICATE REQUEST":
|
||||
case "NEW CERTIFICATE REQUEST":
|
||||
return ReadCertificateRequest(pemObject);
|
||||
case "CERTIFICATE":
|
||||
case "X509 CERTIFICATE":
|
||||
return ReadCertificate(pemObject);
|
||||
case "PKCS7":
|
||||
case "CMS":
|
||||
return ReadPkcs7(pemObject);
|
||||
case "X509 CRL":
|
||||
return ReadCrl(pemObject);
|
||||
case "ATTRIBUTE CERTIFICATE":
|
||||
return ReadAttributeCertificate(pemObject);
|
||||
default:
|
||||
throw new IOException("unrecognised object: " + pemObject.Type);
|
||||
}
|
||||
}
|
||||
|
||||
private AsymmetricKeyParameter ReadRsaPublicKey(PemObject pemObject)
|
||||
{
|
||||
RsaPublicKeyStructure instance = RsaPublicKeyStructure.GetInstance(Asn1Object.FromByteArray(pemObject.Content));
|
||||
return new RsaKeyParameters(isPrivate: false, instance.Modulus, instance.PublicExponent);
|
||||
}
|
||||
|
||||
private AsymmetricKeyParameter ReadPublicKey(PemObject pemObject)
|
||||
{
|
||||
return PublicKeyFactory.CreateKey(pemObject.Content);
|
||||
}
|
||||
|
||||
private X509Certificate ReadCertificate(PemObject pemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new X509CertificateParser().ReadCertificate(pemObject.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new PemException("problem parsing cert: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private X509Crl ReadCrl(PemObject pemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new X509CrlParser().ReadCrl(pemObject.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new PemException("problem parsing cert: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private Pkcs10CertificationRequest ReadCertificateRequest(PemObject pemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Pkcs10CertificationRequest(pemObject.Content);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new PemException("problem parsing cert: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private IX509AttributeCertificate ReadAttributeCertificate(PemObject pemObject)
|
||||
{
|
||||
return new X509V2AttributeCertificate(pemObject.Content);
|
||||
}
|
||||
|
||||
private Org.BouncyCastle.Asn1.Cms.ContentInfo ReadPkcs7(PemObject pemObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Org.BouncyCastle.Asn1.Cms.ContentInfo.GetInstance(Asn1Object.FromByteArray(pemObject.Content));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new PemException("problem parsing PKCS7 object: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private object ReadPrivateKey(PemObject pemObject)
|
||||
{
|
||||
string text = pemObject.Type.Substring(0, pemObject.Type.Length - "PRIVATE KEY".Length).Trim();
|
||||
byte[] array = pemObject.Content;
|
||||
IDictionary dictionary = Platform.CreateHashtable();
|
||||
foreach (PemHeader header in pemObject.Headers)
|
||||
{
|
||||
dictionary[header.Name] = header.Value;
|
||||
}
|
||||
string text2 = (string)dictionary["Proc-Type"];
|
||||
if (text2 == "4,ENCRYPTED")
|
||||
{
|
||||
if (pFinder == null)
|
||||
{
|
||||
throw new PasswordException("No password finder specified, but a password is required");
|
||||
}
|
||||
char[] password = pFinder.GetPassword();
|
||||
if (password == null)
|
||||
{
|
||||
throw new PasswordException("Password is null, but a password is required");
|
||||
}
|
||||
string text3 = (string)dictionary["DEK-Info"];
|
||||
string[] array2 = text3.Split(new char[1] { ',' });
|
||||
string dekAlgName = array2[0].Trim();
|
||||
byte[] iv = Hex.Decode(array2[1].Trim());
|
||||
array = PemUtilities.Crypt(encrypt: false, array, password, dekAlgName, iv);
|
||||
}
|
||||
try
|
||||
{
|
||||
Asn1Sequence instance = Asn1Sequence.GetInstance(array);
|
||||
AsymmetricKeyParameter publicParameter;
|
||||
AsymmetricKeyParameter asymmetricKeyParameter;
|
||||
switch (text)
|
||||
{
|
||||
case "RSA":
|
||||
{
|
||||
if (instance.Count != 9)
|
||||
{
|
||||
throw new PemException("malformed sequence in RSA private key");
|
||||
}
|
||||
RsaPrivateKeyStructure instance2 = RsaPrivateKeyStructure.GetInstance(instance);
|
||||
publicParameter = new RsaKeyParameters(isPrivate: false, instance2.Modulus, instance2.PublicExponent);
|
||||
asymmetricKeyParameter = new RsaPrivateCrtKeyParameters(instance2.Modulus, instance2.PublicExponent, instance2.PrivateExponent, instance2.Prime1, instance2.Prime2, instance2.Exponent1, instance2.Exponent2, instance2.Coefficient);
|
||||
break;
|
||||
}
|
||||
case "DSA":
|
||||
{
|
||||
if (instance.Count != 6)
|
||||
{
|
||||
throw new PemException("malformed sequence in DSA private key");
|
||||
}
|
||||
DerInteger derInteger = (DerInteger)instance[1];
|
||||
DerInteger derInteger2 = (DerInteger)instance[2];
|
||||
DerInteger derInteger3 = (DerInteger)instance[3];
|
||||
DerInteger derInteger4 = (DerInteger)instance[4];
|
||||
DerInteger derInteger5 = (DerInteger)instance[5];
|
||||
DsaParameters parameters = new DsaParameters(derInteger.Value, derInteger2.Value, derInteger3.Value);
|
||||
asymmetricKeyParameter = new DsaPrivateKeyParameters(derInteger5.Value, parameters);
|
||||
publicParameter = new DsaPublicKeyParameters(derInteger4.Value, parameters);
|
||||
break;
|
||||
}
|
||||
case "EC":
|
||||
{
|
||||
ECPrivateKeyStructure instance3 = ECPrivateKeyStructure.GetInstance(instance);
|
||||
AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, instance3.GetParameters());
|
||||
PrivateKeyInfo keyInfo = new PrivateKeyInfo(algorithmIdentifier, instance3.ToAsn1Object());
|
||||
asymmetricKeyParameter = PrivateKeyFactory.CreateKey(keyInfo);
|
||||
DerBitString publicKey = instance3.GetPublicKey();
|
||||
if (publicKey != null)
|
||||
{
|
||||
SubjectPublicKeyInfo keyInfo2 = new SubjectPublicKeyInfo(algorithmIdentifier, publicKey.GetBytes());
|
||||
publicParameter = PublicKeyFactory.CreateKey(keyInfo2);
|
||||
}
|
||||
else
|
||||
{
|
||||
publicParameter = ECKeyPairGenerator.GetCorrespondingPublicKey((ECPrivateKeyParameters)asymmetricKeyParameter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ENCRYPTED":
|
||||
{
|
||||
char[] password2 = pFinder.GetPassword();
|
||||
if (password2 == null)
|
||||
{
|
||||
throw new PasswordException("Password is null, but a password is required");
|
||||
}
|
||||
return PrivateKeyFactory.DecryptKey(password2, EncryptedPrivateKeyInfo.GetInstance(instance));
|
||||
}
|
||||
case "":
|
||||
return PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(instance));
|
||||
default:
|
||||
throw new ArgumentException("Unknown key type: " + text, "type");
|
||||
}
|
||||
return new AsymmetricCipherKeyPair(publicParameter, asymmetricKeyParameter);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
throw new PemException("problem creating " + text + " private key: " + ex2.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static X9ECParameters GetCurveParameters(string name)
|
||||
{
|
||||
X9ECParameters byName = CustomNamedCurves.GetByName(name);
|
||||
if (byName == null)
|
||||
{
|
||||
byName = ECNamedCurveTable.GetByName(name);
|
||||
}
|
||||
if (byName == null)
|
||||
{
|
||||
throw new Exception("unknown curve name: " + name);
|
||||
}
|
||||
return byName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace 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()
|
||||
{
|
||||
((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 num = dekAlgName.LastIndexOf('-');
|
||||
if (num >= 0)
|
||||
{
|
||||
baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName.Substring(0, num));
|
||||
mode = (PemMode)Enums.GetEnumValue(typeof(PemMode), dekAlgName.Substring(num + 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)
|
||||
{
|
||||
ParseDekAlgName(dekAlgName, out var baseAlg, out var mode);
|
||||
string text;
|
||||
switch (mode)
|
||||
{
|
||||
case PemMode.CBC:
|
||||
case PemMode.ECB:
|
||||
text = "PKCS5Padding";
|
||||
break;
|
||||
case PemMode.CFB:
|
||||
case PemMode.OFB:
|
||||
text = "NoPadding";
|
||||
break;
|
||||
default:
|
||||
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
|
||||
}
|
||||
byte[] array = iv;
|
||||
string text2;
|
||||
switch (baseAlg)
|
||||
{
|
||||
case PemBaseAlg.AES_128:
|
||||
case PemBaseAlg.AES_192:
|
||||
case PemBaseAlg.AES_256:
|
||||
text2 = "AES";
|
||||
if (array.Length > 8)
|
||||
{
|
||||
array = new byte[8];
|
||||
Array.Copy(iv, 0, array, 0, array.Length);
|
||||
}
|
||||
break;
|
||||
case PemBaseAlg.BF:
|
||||
text2 = "BLOWFISH";
|
||||
break;
|
||||
case PemBaseAlg.DES:
|
||||
text2 = "DES";
|
||||
break;
|
||||
case PemBaseAlg.DES_EDE:
|
||||
case PemBaseAlg.DES_EDE3:
|
||||
text2 = "DESede";
|
||||
break;
|
||||
case PemBaseAlg.RC2:
|
||||
case PemBaseAlg.RC2_40:
|
||||
case PemBaseAlg.RC2_64:
|
||||
text2 = "RC2";
|
||||
break;
|
||||
default:
|
||||
throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
|
||||
}
|
||||
string algorithm = string.Concat(text2, "/", mode, "/", text);
|
||||
IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
|
||||
ICipherParameters parameters = GetCipherParameters(password, baseAlg, array);
|
||||
if (mode != PemMode.ECB)
|
||||
{
|
||||
parameters = new ParametersWithIV(parameters, iv);
|
||||
}
|
||||
cipher.Init(encrypt, parameters);
|
||||
return cipher.DoFinal(bytes);
|
||||
}
|
||||
|
||||
private static ICipherParameters GetCipherParameters(char[] password, PemBaseAlg baseAlg, byte[] salt)
|
||||
{
|
||||
int keySize;
|
||||
string algorithm;
|
||||
switch (baseAlg)
|
||||
{
|
||||
case PemBaseAlg.AES_128:
|
||||
keySize = 128;
|
||||
algorithm = "AES128";
|
||||
break;
|
||||
case PemBaseAlg.AES_192:
|
||||
keySize = 192;
|
||||
algorithm = "AES192";
|
||||
break;
|
||||
case PemBaseAlg.AES_256:
|
||||
keySize = 256;
|
||||
algorithm = "AES256";
|
||||
break;
|
||||
case PemBaseAlg.BF:
|
||||
keySize = 128;
|
||||
algorithm = "BLOWFISH";
|
||||
break;
|
||||
case PemBaseAlg.DES:
|
||||
keySize = 64;
|
||||
algorithm = "DES";
|
||||
break;
|
||||
case PemBaseAlg.DES_EDE:
|
||||
keySize = 128;
|
||||
algorithm = "DESEDE";
|
||||
break;
|
||||
case PemBaseAlg.DES_EDE3:
|
||||
keySize = 192;
|
||||
algorithm = "DESEDE3";
|
||||
break;
|
||||
case PemBaseAlg.RC2:
|
||||
keySize = 128;
|
||||
algorithm = "RC2";
|
||||
break;
|
||||
case PemBaseAlg.RC2_40:
|
||||
keySize = 40;
|
||||
algorithm = "RC2";
|
||||
break;
|
||||
case PemBaseAlg.RC2_64:
|
||||
keySize = 64;
|
||||
algorithm = "RC2";
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
OpenSslPbeParametersGenerator openSslPbeParametersGenerator = new OpenSslPbeParametersGenerator();
|
||||
openSslPbeParametersGenerator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt);
|
||||
return openSslPbeParametersGenerator.GenerateDerivedParameters(algorithm, keySize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
|
||||
namespace Org.BouncyCastle.OpenSsl;
|
||||
|
||||
public class PemWriter : Org.BouncyCastle.Utilities.IO.Pem.PemWriter
|
||||
{
|
||||
public PemWriter(TextWriter writer)
|
||||
: base(writer)
|
||||
{
|
||||
}
|
||||
|
||||
public void WriteObject(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.WriteObject((PemObjectGenerator)new MiscPemGenerator(obj));
|
||||
}
|
||||
catch (PemGenerationException ex)
|
||||
{
|
||||
if (ex.InnerException is IOException)
|
||||
{
|
||||
throw (IOException)ex.InnerException;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteObject(object obj, string algorithm, char[] password, SecureRandom random)
|
||||
{
|
||||
base.WriteObject((PemObjectGenerator)new MiscPemGenerator(obj, algorithm, password, random));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
|
||||
namespace Org.BouncyCastle.OpenSsl;
|
||||
|
||||
public class Pkcs8Generator : PemObjectGenerator
|
||||
{
|
||||
public static readonly string PbeSha1_RC4_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id;
|
||||
|
||||
public static readonly string PbeSha1_RC4_40 = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id;
|
||||
|
||||
public static readonly string PbeSha1_3DES = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id;
|
||||
|
||||
public static readonly string PbeSha1_2DES = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id;
|
||||
|
||||
public static readonly string PbeSha1_RC2_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id;
|
||||
|
||||
public static readonly string PbeSha1_RC2_40 = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id;
|
||||
|
||||
private char[] password;
|
||||
|
||||
private string algorithm;
|
||||
|
||||
private int iterationCount;
|
||||
|
||||
private AsymmetricKeyParameter privKey;
|
||||
|
||||
private SecureRandom random;
|
||||
|
||||
public SecureRandom SecureRandom
|
||||
{
|
||||
set
|
||||
{
|
||||
random = value;
|
||||
}
|
||||
}
|
||||
|
||||
public char[] Password
|
||||
{
|
||||
set
|
||||
{
|
||||
password = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int IterationCount
|
||||
{
|
||||
set
|
||||
{
|
||||
iterationCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Pkcs8Generator(AsymmetricKeyParameter privKey)
|
||||
{
|
||||
this.privKey = privKey;
|
||||
}
|
||||
|
||||
public Pkcs8Generator(AsymmetricKeyParameter privKey, string algorithm)
|
||||
{
|
||||
this.privKey = privKey;
|
||||
this.algorithm = algorithm;
|
||||
iterationCount = 2048;
|
||||
}
|
||||
|
||||
public PemObject Generate()
|
||||
{
|
||||
if (algorithm == null)
|
||||
{
|
||||
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privKey);
|
||||
return new PemObject("PRIVATE KEY", privateKeyInfo.GetEncoded());
|
||||
}
|
||||
byte[] array = new byte[20];
|
||||
if (random == null)
|
||||
{
|
||||
random = new SecureRandom();
|
||||
}
|
||||
random.NextBytes(array);
|
||||
try
|
||||
{
|
||||
EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(algorithm, password, array, iterationCount, privKey);
|
||||
return new PemObject("ENCRYPTED PRIVATE KEY", encryptedPrivateKeyInfo.GetEncoded());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new PemGenerationException("Couldn't encrypt private key", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user