Files
SystemX.Web/Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs

299 lines
12 KiB
C#

using Azure;
using DB.VPKI_DataDB;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.Extensions.FileSystemGlobbing.Internal;
using Microsoft.Identity.Client;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Utilities.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using SystemX.Core.DB;
using VPKI.Library.Config;
using VPKI.Library.Config.Model;
using VPKI.Library.Enums;
using VPKI.Library.Model;
using VPKI.Library.Packet;
using VPKI.Library.Services;
namespace VPKI.Web.Api.Services
{
public class VpkiBaseService
{
private readonly IServiceScopeFactory _scopeFactory;
protected string URL_VPKI_BASE = string.Empty;
protected readonly ConfigService<WebApiConfig> _configService;
protected readonly CertificateService _certificateService;
public VpkiBaseService(ConfigService<WebApiConfig> configService, CertificateService certificateService, IServiceScopeFactory scopeFactory)
: base()
{
_configService = configService;
_certificateService = certificateService;
_scopeFactory = scopeFactory;
var api = _configService!.GetConfig()?.Api?.Find(x => x.ApiName?.ToLower() == Consts.VPKI_API_VPKIRA.ToLower());
URL_VPKI_BASE = $"{api?.Address}";
}
#region
public async Task<List<CertificateHistoryModel>> History(DateOnly startDate, DateOnly endDate)
{
List<CertificateHistoryModel> response = new List<CertificateHistoryModel>();
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
if (context != null)
{
using (var transaction = await context.CreateTransactionAsync(System.Data.IsolationLevel.ReadUncommitted))
{
var getList = await context.TTbscsrs.AsNoTracking().Where(x => startDate <= DateOnly.FromDateTime(x.CDateTime.Date)
&& DateOnly.FromDateTime(x.CDateTime.Date) <= endDate).ToListAsync();
response.AddRange(getList.Select(x => new CertificateHistoryModel { TTbscsr = x, TCertificate = null }));
foreach (var r in response)
{
var certificate = await context.TCertificates.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == r!.TTbscsr!.CCuid);
if (certificate != null)
r.TCertificate = certificate;
var verifyResult = await context.TVerifyResults.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == r!.TTbscsr!.CCuid);
if (verifyResult != null)
r.TVerifyResult = verifyResult;
var ocspResult = await context.TOcsps.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == r!.TTbscsr!.CCuid);
if (ocspResult != null)
r.TOcsp = ocspResult;
}
await context.CloseTransactionAsync(transaction);
}
}
}
return response;
}
public async Task<CertificateHistoryModel> History(long ccuid)
{
CertificateHistoryModel response = new CertificateHistoryModel();
using (var scope = _scopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
if (context != null)
{
using (var transaction = await context.CreateTransactionAsync(System.Data.IsolationLevel.ReadUncommitted))
{
var searchData = await context.TTbscsrs.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == ccuid);
if (searchData != null)
{
response.TTbscsr = searchData;
var certificate = await context.TCertificates.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == searchData!.CCuid);
if (certificate != null)
response.TCertificate = certificate;
var verifyResult = await context.TVerifyResults.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == searchData!.CCuid);
if (verifyResult != null)
response.TVerifyResult = verifyResult;
var ocspResult = await context.TOcsps.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == searchData!.CCuid);
if (ocspResult != null)
response.TOcsp = ocspResult;
}
await context.CloseTransactionAsync(transaction);
}
}
}
return response;
}
//SubCA
public virtual string GetSubCA(VpkiType vpkiType, bool isEncoding = true)
{
string result = string.Empty;
var openSslConfig = $"{_configService?.GetConfig()?.Openssl?.SubCAPath}";
string subCaName = FindSubCaName(vpkiType);
var subCA = File.ReadAllText(@$"{openSslConfig}{subCaName}");
if (isEncoding == false)
{
result = subCA;
}
else
{
subCA = subCA.Replace($"{Consts.BEGIN_CERTIFICATE}", "").Replace($"{Consts.END_CERTIFICATE}", "");
subCA = subCA.Replace("\r", "").Replace("\n", "");
var subCaAscii = Encoding.ASCII.GetBytes(subCA).ToList();
if (subCaAscii != null)
{
result = Convert.ToBase64String(subCaAscii.ToArray());
}
}
return subCA;
}
public async Task<string> GetCertificateInfo(long ccuid)
{
string result = string.Empty;
//인증서 Temp에 저장
string tempPath = @$"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}/temp/";
var history = await History(ccuid);
if (Directory.Exists(tempPath) == false)
Directory.CreateDirectory(tempPath);
string pcid = $"{history?.TTbscsr?.CPcid}";
File.WriteAllText($"{tempPath}{pcid}.pem", history?.TCertificate?.CCert);
// 프로세스 설정
string command = $"x509 -in {tempPath}{pcid}.pem -text";
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = @$"{_configService?.GetConfig()?.Openssl?.Path}", // cmd.exe로 명령어 실행
Arguments = $"{command}", // /c는 명령어 실행 후 종료하는 옵션
RedirectStandardOutput = true, // 표준 출력 리디렉션
RedirectStandardError = true, // 표준 오류 리디렉션
UseShellExecute = false, // 셸을 사용하지 않도록 설정
CreateNoWindow = true // 새 창을 열지 않도록 설정,
};
// 프로세스 실행
using (Process? process = Process.Start(startInfo))
{
if (process != null)
{
// 출력 결과를 읽기
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
// 출력 결과 또는 오류 표시
if (!string.IsNullOrEmpty(output))
result = output;
if (!string.IsNullOrEmpty(error))
result += output;
}
}
return result;
}
public async Task<string> Ocsp(long ccuid)
{
string result = string.Empty;
//인증서 Temp에 저장
string tempPath = @$"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}/temp/";
string subCaPath = @$"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}/../SubCA/";
var history = await History(ccuid);
if (Directory.Exists(tempPath) == false)
Directory.CreateDirectory(tempPath);
string pcid = $"{history?.TTbscsr?.CPcid}";
File.WriteAllText($"{tempPath}{pcid}.pem", history?.TCertificate?.CCert);
string certificateInfo = await GetCertificateInfo(ccuid);
string url = GetOcspUrl(certificateInfo);
var vpkiType = (VpkiType)Enum.Parse(typeof(VpkiType), $"{history?.TTbscsr?.CCertType}");
string subCaFile = string.Empty;
var openSslConfig = _configService?.GetConfig()?.Openssl?.SubCA;
var prop = openSslConfig?.GetType()?.GetProperty($"{vpkiType}");
subCaFile = $"{prop?.GetValue(openSslConfig)?.ToString()}";
// 프로세스 설정
string command = $"ocsp -issuer {subCaPath}{subCaFile} -CAfile {subCaPath}hkmcrootca.pem -cert {tempPath}{pcid}.pem -url {url} -text -timeout 3";
Log4net.WriteLine($"{command}", LogType.Debug);
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = @$"{_configService?.GetConfig()?.Openssl?.Path}", // cmd.exe로 명령어 실행
Arguments = $"{command}", // /c는 명령어 실행 후 종료하는 옵션
RedirectStandardOutput = true, // 표준 출력 리디렉션
RedirectStandardError = true, // 표준 오류 리디렉션
UseShellExecute = false, // 셸을 사용하지 않도록 설정
CreateNoWindow = true // 새 창을 열지 않도록 설정,
};
// 프로세스 실행
using (Process? process = Process.Start(startInfo))
{
if (process != null)
{
// 출력 결과를 읽기
string output = process.StandardOutput.ReadToEnd();
string response = process.StandardError.ReadToEnd();
// 출력 결과 또는 오류 표시
if (!string.IsNullOrEmpty(output))
result = output;
if (!string.IsNullOrEmpty(response))
result += response;
}
}
result = result.Replace($"{tempPath}","");
GetOcspStatus(pcid, result);
GetOcspVerify(result);
return result;
}
protected virtual string GetOcspStatus(string pcid, string ocsp)
{
var ocspLines = ocsp.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).ToList();
var statusLine = ocspLines.Find(x => x.Contains($"{pcid}.pem"));
string? status = statusLine?.Split(":")?.Last();
return $"{status}";
}
protected virtual string GetOcspVerify(string ocsp)
{
var ocspLines = ocsp.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).ToList();
var verifyLine = ocspLines.Find(x => x.ToLower().Contains($"response verify"));
string? verify = verifyLine?.Split(" ")?.Last();
return $"{verify}";
}
protected virtual string GetOcspUrl(string certificateInfo)
{
string finder = "OCSP - URI:";
var certificateLines = certificateInfo.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).ToList();
var ocspUrl = certificateLines.Find(x => x.Contains($"{finder}"));
string? url = ocspUrl?.Replace(finder, "");
return $"{url}";
}
protected virtual string FindSubCaName(VpkiType vpkiType)
{
var openSslConfig = _configService?.GetConfig()?.Openssl?.SubCA;
var prop = openSslConfig?.GetType()?.GetProperty($"{vpkiType}");
string subCaFile = $"{prop?.GetValue(openSslConfig)?.ToString()}";
return subCaFile;
}
#endregion
}
}