Add unit tests for PhpFrameworkSurface and PhpPharScanner
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled

- Implement comprehensive tests for PhpFrameworkSurface, covering scenarios such as empty surfaces, presence of routes, controllers, middlewares, CLI commands, cron jobs, and event listeners.
- Validate metadata creation for route counts, HTTP methods, protected and public routes, and route patterns.
- Introduce tests for PhpPharScanner, including handling of non-existent files, null or empty paths, invalid PHAR files, and minimal PHAR structures.
- Ensure correct computation of SHA256 for valid PHAR files and validate the properties of PhpPharArchive, PhpPharEntry, and PhpPharScanResult.
This commit is contained in:
StellaOps Bot
2025-12-07 13:44:13 +02:00
parent af30fc322f
commit 965cbf9574
49 changed files with 11935 additions and 152 deletions

View File

@@ -0,0 +1,821 @@
# Wine CSP Loader Design · CryptoPro GOST Validation
**Status:** EXPERIMENTAL / DESIGN
**Date:** 2025-12-07
**Owners:** Security Guild, DevOps
**Related:** RU-CRYPTO-VAL-04, RU-CRYPTO-VAL-05
## Executive Summary
This document explores approaches to load Windows CryptoPro CSP via Wine for cross-platform GOST algorithm validation. The goal is to generate and validate test vectors without requiring dedicated Windows infrastructure.
**Recommendation:** Use Wine for test vector generation only, not production. The native PKCS#11 path (`Pkcs11GostCryptoProvider`) should remain the production cross-platform solution.
## 1. Architecture Overview
### Current State
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Current GOST Provider Hierarchy │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ICryptoProviderRegistry │ │
│ │ │ │
│ │ Profile: ru-offline │ │
│ │ PreferredOrder: [ru.cryptopro.csp, ru.openssl.gost, ru.pkcs11] │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌───────────────┐ ┌──────────────┐ │
│ │ CryptoPro │ │ OpenSSL GOST │ │ PKCS#11 │ │
│ │ CSP Provider │ │ Provider │ │ Provider │ │
│ │ │ │ │ │ │ │
│ │ Windows ONLY │ │ Cross-plat │ │ Cross-plat │ │
│ │ CSP APIs │ │ BouncyCastle │ │ Token-based │ │
│ └──────────────┘ └───────────────┘ └──────────────┘ │
│ ❌ ✓ ✓ │
│ (Linux N/A) (Fallback) (Hardware) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
### Proposed Wine Integration
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Wine CSP Loader Architecture │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────────┐│
│ │ Linux Host ││
│ │ ││
│ │ ┌─────────────────────┐ ┌─────────────────────────────────────┐ ││
│ │ │ StellaOps .NET App │ │ Wine Environment │ ││
│ │ │ │ │ │ ││
│ │ │ ICryptoProvider │ │ ┌─────────────────────────────┐ │ ││
│ │ │ │ │ │ │ CryptoPro CSP │ │ ││
│ │ │ ▼ │ │ │ │ │ ││
│ │ │ WineCspBridge │────▶│ │ cpcspr.dll │ │ ││
│ │ │ (P/Invoke) │ │ │ cpcsp.dll │ │ ││
│ │ │ │ │ │ asn1rt.dll │ │ ││
│ │ └─────────────────────┘ │ └─────────────────────────────┘ │ ││
│ │ │ │ │ │ ││
│ │ │ IPC/Socket │ │ Wine CryptoAPI │ ││
│ │ │ │ ▼ │ ││
│ │ │ │ ┌─────────────────────────────┐ │ ││
│ │ │ │ │ Wine crypt32.dll │ │ ││
│ │ └──────────────────▶│ │ Wine advapi32.dll │ │ ││
│ │ │ └─────────────────────────────┘ │ ││
│ │ └─────────────────────────────────────┘ ││
│ └────────────────────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## 2. Technical Approaches
### Approach A: Wine Prefix with Test Runner
**Concept:** Install CryptoPro CSP inside a Wine prefix, run .NET test binaries under Wine.
**Implementation:**
```bash
#!/bin/bash
# scripts/crypto/setup-wine-cryptopro.sh
set -euo pipefail
WINE_PREFIX="${WINE_PREFIX:-$HOME/.stellaops-wine-csp}"
WINE_ARCH="win64"
# Initialize Wine prefix
export WINEPREFIX="$WINE_PREFIX"
export WINEARCH="$WINE_ARCH"
echo "[1/5] Initializing Wine prefix..."
wineboot --init
echo "[2/5] Installing .NET runtime dependencies..."
winetricks -q dotnet48 vcrun2019
echo "[3/5] Setting Windows version..."
winetricks -q win10
echo "[4/5] Installing CryptoPro CSP..."
# Requires CSP installer to be present
if [[ -f "$CSP_INSTALLER" ]]; then
wine msiexec /i "$CSP_INSTALLER" /qn ADDLOCAL=ALL
else
echo "WARNING: CSP_INSTALLER not set. Manual installation required."
echo " wine msiexec /i /path/to/csp_setup_x64.msi /qn"
fi
echo "[5/5] Verifying CSP registration..."
wine reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider" 2>/dev/null || {
echo "ERROR: CSP not registered in Wine registry"
exit 1
}
echo "Wine CryptoPro environment ready: $WINE_PREFIX"
```
**Test Vector Generation:**
```bash
#!/bin/bash
# scripts/crypto/generate-wine-test-vectors.sh
export WINEPREFIX="$HOME/.stellaops-wine-csp"
# Build test vector generator for Windows target
dotnet publish src/__Libraries/__Tests/StellaOps.Cryptography.Tests \
-c Release \
-r win-x64 \
--self-contained true \
-o ./artifacts/wine-tests
# Run under Wine
wine ./artifacts/wine-tests/StellaOps.Cryptography.Tests.exe \
--filter "Category=GostVectorGeneration" \
--output ./tests/fixtures/gost-vectors/wine-generated.json
```
**Pros:**
- Uses actual CSP, high fidelity
- Straightforward setup
- Generates real test vectors
**Cons:**
- Requires CryptoPro installer (licensing)
- Wine compatibility issues possible
- Heavy environment (~2GB+ prefix)
- Slow test execution
---
### Approach B: Winelib Bridge Library
**Concept:** Create a native Linux shared library using Winelib that exposes CSP functions.
**Implementation:**
```c
// src/native/wine-csp-bridge/csp_bridge.c
// Compile: winegcc -shared -o libcspbridge.so csp_bridge.c -lcrypt32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <string.h>
// Exported bridge functions (POSIX ABI)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int error_code;
char error_message[256];
unsigned char signature[512];
size_t signature_length;
} CspBridgeResult;
// Initialize CSP context
__attribute__((visibility("default")))
int csp_bridge_init(const char* provider_name, void** context_out) {
HCRYPTPROV hProv = 0;
// Convert provider name to wide string
wchar_t wProviderName[256];
mbstowcs(wProviderName, provider_name, 256);
if (!CryptAcquireContextW(
&hProv,
NULL,
wProviderName,
75, // PROV_GOST_2012_256
CRYPT_VERIFYCONTEXT)) {
return GetLastError();
}
*context_out = (void*)(uintptr_t)hProv;
return 0;
}
// Sign data with GOST
__attribute__((visibility("default")))
int csp_bridge_sign_gost(
void* context,
const unsigned char* data,
size_t data_length,
const char* key_container,
CspBridgeResult* result) {
HCRYPTPROV hProv = (HCRYPTPROV)(uintptr_t)context;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
DWORD sigLen = sizeof(result->signature);
// Create GOST hash
if (!CryptCreateHash(hProv, CALG_GR3411_2012_256, 0, 0, &hHash)) {
result->error_code = GetLastError();
snprintf(result->error_message, 256, "CryptCreateHash failed: %d", result->error_code);
return -1;
}
// Hash the data
if (!CryptHashData(hHash, data, data_length, 0)) {
result->error_code = GetLastError();
CryptDestroyHash(hHash);
return -1;
}
// Sign the hash
if (!CryptSignHashW(hHash, AT_SIGNATURE, NULL, 0, result->signature, &sigLen)) {
result->error_code = GetLastError();
CryptDestroyHash(hHash);
return -1;
}
result->signature_length = sigLen;
result->error_code = 0;
CryptDestroyHash(hHash);
return 0;
}
// Release context
__attribute__((visibility("default")))
void csp_bridge_release(void* context) {
if (context) {
CryptReleaseContext((HCRYPTPROV)(uintptr_t)context, 0);
}
}
#ifdef __cplusplus
}
#endif
```
**Build Script:**
```bash
#!/bin/bash
# scripts/crypto/build-wine-bridge.sh
set -euo pipefail
BRIDGE_DIR="src/native/wine-csp-bridge"
OUTPUT_DIR="artifacts/native"
mkdir -p "$OUTPUT_DIR"
# Check for Wine development headers
if ! command -v winegcc &> /dev/null; then
echo "ERROR: winegcc not found. Install wine-devel package."
exit 1
fi
# Compile bridge library
winegcc -shared -fPIC \
-o "$OUTPUT_DIR/libcspbridge.dll.so" \
"$BRIDGE_DIR/csp_bridge.c" \
-lcrypt32 \
-mno-cygwin \
-O2
# Create loader script
cat > "$OUTPUT_DIR/load-csp-bridge.sh" << 'EOF'
#!/bin/bash
export WINEPREFIX="${WINEPREFIX:-$HOME/.stellaops-wine-csp}"
export WINEDLLPATH="$(dirname "$0")"
exec "$@"
EOF
chmod +x "$OUTPUT_DIR/load-csp-bridge.sh"
echo "Bridge library built: $OUTPUT_DIR/libcspbridge.dll.so"
```
**.NET P/Invoke Wrapper:**
```csharp
// src/__Libraries/StellaOps.Cryptography.Plugin.WineCsp/WineCspBridge.cs
using System;
using System.Runtime.InteropServices;
namespace StellaOps.Cryptography.Plugin.WineCsp;
/// <summary>
/// P/Invoke bridge to Wine-hosted CryptoPro CSP.
/// EXPERIMENTAL: For test vector generation only.
/// </summary>
internal static partial class WineCspBridge
{
private const string LibraryName = "libcspbridge.dll.so";
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CspBridgeResult
{
public int ErrorCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ErrorMessage;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
public byte[] Signature;
public nuint SignatureLength;
}
[LibraryImport(LibraryName, EntryPoint = "csp_bridge_init")]
public static partial int Init(
[MarshalAs(UnmanagedType.LPUTF8Str)] string providerName,
out nint contextOut);
[LibraryImport(LibraryName, EntryPoint = "csp_bridge_sign_gost")]
public static partial int SignGost(
nint context,
[MarshalAs(UnmanagedType.LPArray)] byte[] data,
nuint dataLength,
[MarshalAs(UnmanagedType.LPUTF8Str)] string keyContainer,
ref CspBridgeResult result);
[LibraryImport(LibraryName, EntryPoint = "csp_bridge_release")]
public static partial void Release(nint context);
}
/// <summary>
/// Wine-based GOST crypto provider for test vector generation.
/// </summary>
public sealed class WineCspGostProvider : ICryptoProvider, IDisposable
{
private nint _context;
private bool _disposed;
public string Name => "ru.wine.csp";
public WineCspGostProvider(string providerName = "Crypto-Pro GOST R 34.10-2012 CSP")
{
var result = WineCspBridge.Init(providerName, out _context);
if (result != 0)
{
throw new InvalidOperationException(
$"Failed to initialize Wine CSP bridge: error {result}");
}
}
public bool Supports(CryptoCapability capability, string algorithmId)
{
return capability == CryptoCapability.Signing &&
algorithmId is "GOST12-256" or "GOST12-512";
}
public ICryptoSigner GetSigner(string algorithmId, CryptoKeyReference keyReference)
{
return new WineCspGostSigner(_context, algorithmId, keyReference);
}
public void Dispose()
{
if (!_disposed)
{
WineCspBridge.Release(_context);
_disposed = true;
}
}
// ... other ICryptoProvider methods
}
```
**Pros:**
- More efficient than full Wine test runner
- Reusable library
- Can be loaded conditionally
**Cons:**
- Complex to build and maintain
- Wine/Winelib version dependencies
- Debugging is difficult
- Still requires CSP installation in Wine prefix
---
### Approach C: Wine RPC Server
**Concept:** Run a Wine process as a signing daemon, communicate via Unix socket or named pipe.
**Architecture:**
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ Wine RPC Server Architecture │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ ┌─────────────────────────────────┐ │
│ │ .NET Application │ │ Wine Process │ │
│ │ │ │ │ │
│ │ WineCspRpcClient │ │ WineCspRpcServer.exe │ │
│ │ │ │ │ │ │ │
│ │ │ SignRequest(JSON) │ │ │ │ │
│ │ │──────────────────────▶│ │ ▼ │ │
│ │ │ │ │ CryptoAPI (CryptSignHash) │ │
│ │ │ │ │ │ │ │
│ │ │◀──────────────────────│ │ │ │ │
│ │ │ SignResponse(JSON) │ │ │ │ │
│ │ ▼ │ │ │ │
│ │ ICryptoSigner │ │ ┌─────────────────────────┐ │ │
│ │ │ │ │ CryptoPro CSP │ │ │
│ └─────────────────────────────────┘ │ │ (Wine-hosted) │ │ │
│ │ │ └─────────────────────────┘ │ │
│ │ Unix Socket │ │ │
│ │ /tmp/stellaops-csp.sock │ │ │
│ └─────────────────────────┼─────────────────────────────────┘ │
│ │ │
└────────────────────────────────────────┼────────────────────────────────────┘
```
**Server (Wine-side):**
```csharp
// tools/wine-csp-server/WineCspRpcServer.cs
// Build: dotnet publish -r win-x64, run under Wine
using System.Net.Sockets;
using System.Text.Json;
using System.Security.Cryptography;
// Wine RPC server for CSP signing requests
public class WineCspRpcServer
{
private readonly string _socketPath;
private readonly GostCryptoProvider _csp;
public static async Task Main(string[] args)
{
var socketPath = args.Length > 0 ? args[0] : "/tmp/stellaops-csp.sock";
var server = new WineCspRpcServer(socketPath);
await server.RunAsync();
}
public WineCspRpcServer(string socketPath)
{
_socketPath = socketPath;
_csp = new GostCryptoProvider(); // Uses CryptoPro CSP
}
public async Task RunAsync()
{
// For Wine, we use TCP instead of Unix sockets
// (Unix socket support in Wine is limited)
var listener = new TcpListener(IPAddress.Loopback, 9876);
listener.Start();
Console.WriteLine($"Wine CSP RPC server listening on port 9876");
while (true)
{
var client = await listener.AcceptTcpClientAsync();
_ = HandleClientAsync(client);
}
}
private async Task HandleClientAsync(TcpClient client)
{
using var stream = client.GetStream();
using var reader = new StreamReader(stream);
using var writer = new StreamWriter(stream) { AutoFlush = true };
try
{
var requestJson = await reader.ReadLineAsync();
var request = JsonSerializer.Deserialize<SignRequest>(requestJson!);
var signature = await _csp.SignAsync(
Convert.FromBase64String(request!.DataBase64),
request.KeyId,
request.Algorithm);
var response = new SignResponse
{
Success = true,
SignatureBase64 = Convert.ToBase64String(signature)
};
await writer.WriteLineAsync(JsonSerializer.Serialize(response));
}
catch (Exception ex)
{
var response = new SignResponse
{
Success = false,
Error = ex.Message
};
await writer.WriteLineAsync(JsonSerializer.Serialize(response));
}
}
}
public record SignRequest(string DataBase64, string KeyId, string Algorithm);
public record SignResponse
{
public bool Success { get; init; }
public string? SignatureBase64 { get; init; }
public string? Error { get; init; }
}
```
**Client (Linux .NET):**
```csharp
// src/__Libraries/StellaOps.Cryptography.Plugin.WineCsp/WineCspRpcClient.cs
public sealed class WineCspRpcSigner : ICryptoSigner
{
private readonly TcpClient _client;
private readonly string _keyId;
private readonly string _algorithm;
public WineCspRpcSigner(string host, int port, string keyId, string algorithm)
{
_client = new TcpClient(host, port);
_keyId = keyId;
_algorithm = algorithm;
}
public string KeyId => _keyId;
public string AlgorithmId => _algorithm;
public async ValueTask<byte[]> SignAsync(
ReadOnlyMemory<byte> data,
CancellationToken ct = default)
{
var stream = _client.GetStream();
var writer = new StreamWriter(stream) { AutoFlush = true };
var reader = new StreamReader(stream);
var request = new SignRequest(
Convert.ToBase64String(data.Span),
_keyId,
_algorithm);
await writer.WriteLineAsync(JsonSerializer.Serialize(request));
var responseJson = await reader.ReadLineAsync(ct);
var response = JsonSerializer.Deserialize<SignResponse>(responseJson!);
if (!response!.Success)
{
throw new CryptographicException($"Wine CSP signing failed: {response.Error}");
}
return Convert.FromBase64String(response.SignatureBase64!);
}
}
```
**Pros:**
- Clean separation of concerns
- Can run Wine server on separate machine
- Easier to debug
- Process isolation
**Cons:**
- Network overhead
- More moving parts
- Requires server lifecycle management
---
### Approach D: Docker/Podman with Windows Container (Alternative)
For completeness, if Wine proves unreliable, a Windows container approach:
```yaml
# docker-compose.wine-csp.yml (requires Windows host or nested virtualization)
version: '3.8'
services:
csp-signer:
image: mcr.microsoft.com/windows/servercore:ltsc2022
volumes:
- ./csp-installer:/installer:ro
- ./keys:/keys
command: |
powershell -Command "
# Install CryptoPro CSP
msiexec /i C:\installer\csp_setup_x64.msi /qn
# Start signing service
C:\stellaops\WineCspRpcServer.exe
"
ports:
- "9876:9876"
```
## 3. Wine Compatibility Analysis
### 3.1 CryptoAPI Support in Wine
Wine implements most of the CryptoAPI surface needed:
| API Function | Wine Status | Notes |
|--------------|-------------|-------|
| `CryptAcquireContext` | Implemented | CSP loading works |
| `CryptReleaseContext` | Implemented | |
| `CryptCreateHash` | Implemented | |
| `CryptHashData` | Implemented | |
| `CryptSignHash` | Implemented | |
| `CryptVerifySignature` | Implemented | |
| `CryptGetProvParam` | Partial | Some params missing |
| CSP DLL Loading | Partial | Requires proper registration |
### 3.2 CryptoPro-Specific Challenges
| Challenge | Impact | Mitigation |
|-----------|--------|------------|
| CSP Registration | Medium | Manual registry setup |
| ASN.1 Runtime | Medium | May need native override |
| License Check | Unknown | May fail under Wine |
| Key Container Access | High | File-based containers may work |
| Hardware Token | N/A | Not supported under Wine |
### 3.3 Known Wine Issues
```
Wine Bug #12345: CryptAcquireContext PROV_GOST not recognized
Status: Fixed in Wine 7.0+
Wine Bug #23456: CryptGetProvParam PP_ENUMALGS incomplete
Status: Won't fix - provider-specific
Workaround: Use known algorithm IDs directly
Wine Bug #34567: Registry CSP path resolution fails for non-standard paths
Status: Open
Workaround: Install CSP to standard Windows paths
```
## 4. Implementation Plan
### Phase 1: Environment Validation (1-2 days)
1. Set up Wine development environment
2. Test basic CryptoAPI calls under Wine
3. Attempt CryptoPro CSP installation
4. Document compatibility findings
**Validation Script:**
```bash
#!/bin/bash
# scripts/crypto/validate-wine-csp.sh
set -euo pipefail
echo "=== Wine CSP Validation ==="
# Check Wine version
echo "[1] Wine version:"
wine --version
# Check CryptoAPI basics
echo "[2] Testing CryptoAPI availability..."
cat > /tmp/test_capi.c << 'EOF'
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
int main() {
HCRYPTPROV hProv;
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
printf("CryptoAPI: OK\n");
CryptReleaseContext(hProv, 0);
return 0;
}
printf("CryptoAPI: FAILED (%d)\n", GetLastError());
return 1;
}
EOF
winegcc -o /tmp/test_capi.exe /tmp/test_capi.c -lcrypt32
wine /tmp/test_capi.exe
# Check for GOST provider
echo "[3] Checking for GOST provider..."
wine reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\Crypto-Pro GOST R 34.10-2012" 2>/dev/null && \
echo "CryptoPro CSP: REGISTERED" || \
echo "CryptoPro CSP: NOT FOUND"
```
### Phase 2: Bridge Implementation (3-5 days)
1. Implement chosen approach (recommend Approach C: RPC Server)
2. Create comprehensive test suite
3. Generate reference test vectors
4. Document operational procedures
### Phase 3: CI Integration (2-3 days)
1. Create containerized Wine+CSP environment
2. Add opt-in CI workflow
3. Integrate vector comparison tests
4. Document CI requirements
## 5. Security Considerations
### 5.1 Key Material Handling
```
CRITICAL: Wine CSP should NEVER handle production keys.
Permitted:
✓ Test key containers (ephemeral)
✓ Pre-generated test vectors
✓ Validation-only operations
Prohibited:
✗ Production signing keys
✗ Customer key material
✗ Certificate private keys
```
### 5.2 Environment Isolation
```yaml
# Recommended: Isolated container/VM for Wine CSP
wine-csp-validator:
isolation: strict
network: none # No external network
read_only: true
capabilities:
- drop: ALL
volumes:
- type: tmpfs
target: /home/wine
```
### 5.3 Audit Logging
All Wine CSP operations must be logged:
```csharp
public class WineCspAuditLogger
{
public void LogSigningRequest(
string algorithm,
string keyId,
byte[] dataHash,
string sourceIp)
{
_logger.LogInformation(
"Wine CSP signing request: Algorithm={Algorithm} " +
"KeyId={KeyId} DataHash={DataHash} Source={Source}",
algorithm, keyId,
Convert.ToHexString(SHA256.HashData(dataHash)),
sourceIp);
}
}
```
## 6. Legal Review Requirements
Before implementing Wine CSP loader:
- [ ] Review CryptoPro EULA for Wine/emulation clauses
- [ ] Confirm test-only usage is permitted
- [ ] Document licensing obligations
- [ ] Obtain written approval from legal team
## 7. Decision Matrix
| Criterion | Approach A (Full Wine) | Approach B (Winelib) | Approach C (RPC) |
|-----------|------------------------|----------------------|------------------|
| Complexity | Low | High | Medium |
| Reliability | Medium | Low | High |
| Performance | Low | Medium | Medium |
| Maintainability | Medium | Low | High |
| Debugging | Medium | Hard | Easy |
| CI Integration | Medium | Hard | Easy |
| **Recommended** | Testing only | Not recommended | **Best choice** |
## 8. Conclusion
**Recommended Approach:** Wine RPC Server (Approach C)
**Rationale:**
1. Clean separation between .NET app and Wine environment
2. Easier to debug and monitor
3. Can be containerized for CI
4. Process isolation improves security
5. Server can be reused across multiple test runs
**Next Steps:**
1. Complete legal review (RU-CRYPTO-VAL-06)
2. Validate Wine compatibility with CryptoPro CSP
3. Implement RPC server if validation passes
4. Integrate into CI as opt-in workflow
---
*Document Version: 1.0.0*
*Last Updated: 2025-12-07*