299 lines
12 KiB
C#
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
|
|
}
|
|
}
|