init commit

This commit is contained in:
2025-10-09 09:57:24 +09:00
commit 4d551bd74f
6636 changed files with 1218703 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
namespace Org.BouncyCastle.OpenSsl;
public interface IPasswordFinder
{
char[] GetPassword();
}

View File

@@ -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);
}
}
}

View File

@@ -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)
{
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}
}