75 lines
2.5 KiB
C#
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;
|
|
}
|
|
}
|