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:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user