Add support for ГОСТ Р 34.10 digital signatures

- Implemented the GostKeyValue class for handling public key parameters in ГОСТ Р 34.10 digital signatures.
- Created the GostSignedXml class to manage XML signatures using ГОСТ 34.10, including methods for computing and checking signatures.
- Developed the GostSignedXmlImpl class to encapsulate the signature computation logic and public key retrieval.
- Added specific key value classes for ГОСТ Р 34.10-2001, ГОСТ Р 34.10-2012/256, and ГОСТ Р 34.10-2012/512 to support different signature algorithms.
- Ensured compatibility with existing XML signature standards while integrating ГОСТ cryptography.
This commit is contained in:
master
2025-11-09 21:59:57 +02:00
parent 75c2bcafce
commit cef4cb2c5a
486 changed files with 32952 additions and 801 deletions

View File

@@ -0,0 +1,73 @@
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
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;
}
}