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,128 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Concelier.WebService.Diagnostics;
|
||||
|
||||
namespace StellaOps.Concelier.WebService.Services;
|
||||
|
||||
internal interface IAdvisoryAiTelemetry
|
||||
{
|
||||
void TrackChunkResult(AdvisoryAiChunkRequestTelemetry telemetry);
|
||||
|
||||
void TrackChunkFailure(string? tenant, string advisoryKey, string failureReason, string result);
|
||||
}
|
||||
|
||||
internal sealed class AdvisoryAiTelemetry : IAdvisoryAiTelemetry
|
||||
{
|
||||
private readonly ILogger<AdvisoryAiTelemetry> _logger;
|
||||
|
||||
public AdvisoryAiTelemetry(ILogger<AdvisoryAiTelemetry> logger)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public void TrackChunkResult(AdvisoryAiChunkRequestTelemetry telemetry)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(telemetry);
|
||||
|
||||
var tenant = NormalizeTenant(telemetry.Tenant);
|
||||
var result = NormalizeResult(telemetry.Result);
|
||||
|
||||
AdvisoryAiMetrics.ChunkRequestCounter.Add(1,
|
||||
AdvisoryAiMetrics.BuildChunkRequestTags(tenant, result, telemetry.Truncated, telemetry.CacheHit));
|
||||
|
||||
if (telemetry.CacheHit)
|
||||
{
|
||||
AdvisoryAiMetrics.ChunkCacheHitCounter.Add(1,
|
||||
AdvisoryAiMetrics.BuildCacheTags(tenant, "hit"));
|
||||
}
|
||||
|
||||
if (!telemetry.CacheHit && telemetry.GuardrailCounts.Count > 0)
|
||||
{
|
||||
foreach (var kvp in telemetry.GuardrailCounts)
|
||||
{
|
||||
AdvisoryAiMetrics.GuardrailBlockCounter.Add(kvp.Value,
|
||||
AdvisoryAiMetrics.BuildGuardrailTags(tenant, GetReasonTag(kvp.Key), telemetry.CacheHit));
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Advisory chunk guardrails blocked {BlockCount} segments for tenant {Tenant} and key {Key}. Details: {Summary}",
|
||||
telemetry.TotalGuardrailBlocks,
|
||||
tenant,
|
||||
telemetry.AdvisoryKey,
|
||||
FormatGuardrailSummary(telemetry.GuardrailCounts));
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Advisory chunk request for tenant {Tenant} key {Key} returned {Chunks} chunks across {Sources} sources (truncated: {Truncated}, cacheHit: {CacheHit}, durationMs: {Duration}).",
|
||||
tenant,
|
||||
telemetry.AdvisoryKey,
|
||||
telemetry.ChunkCount,
|
||||
telemetry.ObservationCount,
|
||||
telemetry.Truncated,
|
||||
telemetry.CacheHit,
|
||||
telemetry.Duration.TotalMilliseconds.ToString("F2", CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public void TrackChunkFailure(string? tenant, string advisoryKey, string failureReason, string result)
|
||||
{
|
||||
var normalizedTenant = NormalizeTenant(tenant);
|
||||
var normalizedResult = NormalizeResult(result);
|
||||
|
||||
AdvisoryAiMetrics.ChunkRequestCounter.Add(1,
|
||||
AdvisoryAiMetrics.BuildChunkRequestTags(normalizedTenant, normalizedResult, truncated: false, cacheHit: false));
|
||||
|
||||
_logger.LogWarning(
|
||||
"Advisory chunk request for tenant {Tenant} key {Key} failed ({Result}): {Reason}",
|
||||
normalizedTenant,
|
||||
advisoryKey,
|
||||
normalizedResult,
|
||||
failureReason);
|
||||
}
|
||||
|
||||
private static string NormalizeTenant(string? tenant)
|
||||
=> string.IsNullOrWhiteSpace(tenant) ? "unknown" : tenant;
|
||||
|
||||
private static string NormalizeResult(string? result)
|
||||
=> string.IsNullOrWhiteSpace(result) ? "unknown" : result;
|
||||
|
||||
private static string GetReasonTag(AdvisoryChunkGuardrailReason reason)
|
||||
=> reason switch
|
||||
{
|
||||
AdvisoryChunkGuardrailReason.NormalizationFailed => "normalization_failed",
|
||||
AdvisoryChunkGuardrailReason.BelowMinimumLength => "below_minimum_length",
|
||||
AdvisoryChunkGuardrailReason.MissingAlphabeticCharacters => "missing_alpha_characters",
|
||||
_ => reason.ToString().ToLowerInvariant()
|
||||
};
|
||||
|
||||
private static string FormatGuardrailSummary(IReadOnlyDictionary<AdvisoryChunkGuardrailReason, int> counts)
|
||||
{
|
||||
if (counts.Count == 0)
|
||||
{
|
||||
return "none";
|
||||
}
|
||||
|
||||
var parts = counts
|
||||
.OrderBy(static kvp => kvp.Key)
|
||||
.Select(kvp => $"{GetReasonTag(kvp.Key)}={kvp.Value}");
|
||||
return string.Join(",", parts);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record AdvisoryAiChunkRequestTelemetry(
|
||||
string? Tenant,
|
||||
string AdvisoryKey,
|
||||
string Result,
|
||||
bool Truncated,
|
||||
bool CacheHit,
|
||||
int ObservationCount,
|
||||
int ChunkCount,
|
||||
TimeSpan Duration,
|
||||
IReadOnlyDictionary<AdvisoryChunkGuardrailReason, int> GuardrailCounts)
|
||||
{
|
||||
public int TotalGuardrailBlocks => GuardrailCounts.Count == 0
|
||||
? 0
|
||||
: GuardrailCounts.Values.Sum();
|
||||
}
|
||||
Reference in New Issue
Block a user