Files
git.stella-ops.org/src/__Libraries/StellaOps.Cryptography.Plugin.OpenSslGost/OpenSslPemLoader.cs
2026-02-01 21:37:40 +02:00

75 lines
2.5 KiB
C#

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
namespace StellaOps.Cryptography.Plugin.OpenSslGost;
internal static class OpenSslPemLoader
{
public static ECPrivateKeyParameters LoadPrivateKey(string path, string? passphrase)
{
using var reader = File.OpenText(path);
var pemReader = string.IsNullOrEmpty(passphrase)
? new PemReader(reader)
: new PemReader(reader, new StaticPasswordFinder(passphrase));
var pemObject = pemReader.ReadObject();
return pemObject switch
{
AsymmetricCipherKeyPair pair when pair.Private is ECPrivateKeyParameters ecPrivate => ecPrivate,
ECPrivateKeyParameters ecPrivate => ecPrivate,
_ => throw new InvalidOperationException($"Unsupported private key content in '{path}'.")
};
}
public static ECPublicKeyParameters LoadPublicKey(ECPrivateKeyParameters privateKey, X509Certificate2? certificate)
{
if (certificate is not null)
{
var bouncyCert = DotNetUtilities.FromX509Certificate(certificate);
var keyParam = bouncyCert.GetPublicKey();
if (keyParam is ECPublicKeyParameters ecPublic)
{
return ecPublic;
}
}
var q = privateKey.Parameters.G.Multiply(privateKey.D).Normalize();
return new ECPublicKeyParameters(q, privateKey.Parameters);
}
public static X509Certificate2? LoadCertificate(string? path, string? passphrase)
{
if (string.IsNullOrWhiteSpace(path))
{
return null;
}
if (string.Equals(Path.GetExtension(path), ".pem", StringComparison.OrdinalIgnoreCase))
{
return X509Certificate2.CreateFromPemFile(path);
}
var password = string.IsNullOrEmpty(passphrase) ? null : passphrase;
return string.IsNullOrEmpty(password)
? X509CertificateLoader.LoadPkcs12FromFile(path, ReadOnlySpan<char>.Empty)
: X509CertificateLoader.LoadPkcs12FromFile(path, password.AsSpan());
}
private sealed class StaticPasswordFinder : IPasswordFinder
{
private readonly char[] password;
public StaticPasswordFinder(string passphrase)
=> password = passphrase.ToCharArray();
public char[] GetPassword() => password;
}
}