[성현모] VPKI 프로젝트 Import
This commit is contained in:
30
Projects/VPKI/VPKI/.dockerignore
Normal file
30
Projects/VPKI/VPKI/.dockerignore
Normal file
@ -0,0 +1,30 @@
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
!**/.gitignore
|
||||
!.git/HEAD
|
||||
!.git/config
|
||||
!.git/packed-refs
|
||||
!.git/refs/heads/**
|
||||
80
Projects/VPKI/VPKI/Config/VPKI.WebApiConfig.json
Normal file
80
Projects/VPKI/VPKI/Config/VPKI.WebApiConfig.json
Normal file
@ -0,0 +1,80 @@
|
||||
{
|
||||
"Server": {
|
||||
"Address": "https://*",
|
||||
"Port": 8080,
|
||||
"IIS": false
|
||||
},
|
||||
"API": [
|
||||
{
|
||||
"ApiName": "vpkira",
|
||||
"Address": "https://vpkira.hmckmc.co.kr/"
|
||||
//"Address": "https://vpkira-dev.hmckmc.co.kr/"
|
||||
},
|
||||
//{
|
||||
// "ApiName": "ocsp",
|
||||
// "Address": "http://ocsp.hmckmc.co.kr/"
|
||||
// //"Address": "http://d-ocsp.hmckmc.co.kr/"
|
||||
//},
|
||||
//{
|
||||
// "ApiName": "d-crl",
|
||||
// "Address": "http://crl.hmckmc.co.kr/"
|
||||
// //"Address": "http://d-crl.hmckmc.co.kr/"
|
||||
//}
|
||||
],
|
||||
"Auth": {
|
||||
"issuer": "vpki.api",
|
||||
"audience": "vpki",
|
||||
"accessTokenSecret": "t6zdogyrT0U1bYw3gJvMm3JHmj2Iyawr7O2WKE2truX+MK0l/XNGmpU2ofagdUWBN4DxAUv7c8xSYVv/8abL6A==",
|
||||
"accessTokenExpires": 60, //minutes
|
||||
"refreshTokenSecret": "1vVuoGqIqkStFI3QUXHMr0/yO1feLPnhqcfFGjZyk478+4WY7dhrUjCfVeWjmmSZYgb+rtP0X6ec+3iL35Yezw==",
|
||||
"refreshTokenExpires": 1440 //minuts, 60*24 (1day)
|
||||
},
|
||||
"DataBase": [
|
||||
{
|
||||
"IP": "127.0.0.1",
|
||||
"Port": 1433,
|
||||
"DBName": "VPKI_AccountDB",
|
||||
"DBID": 1,
|
||||
"DBContext": "VpkiAccountDbContext",
|
||||
"UserID": "VPKI",
|
||||
"Password": "Kefico!@34"
|
||||
},
|
||||
{
|
||||
"IP": "127.0.0.1",
|
||||
"Port": 1433,
|
||||
"DBName": "VPKI_AccountDB_DEV",
|
||||
"DBID": 2,
|
||||
"DBContext": "VpkiAccountDbContext",
|
||||
"UserID": "VPKI",
|
||||
"Password": "Kefico!@34"
|
||||
},
|
||||
{
|
||||
"IP": "127.0.0.1",
|
||||
"Port": 1433,
|
||||
"DBName": "VPKI_DataDB",
|
||||
"DBID": 1,
|
||||
"DBContext": "VpkiDataDbContext",
|
||||
"UserID": "VPKI",
|
||||
"Password": "Kefico!@34"
|
||||
},
|
||||
{
|
||||
"IP": "127.0.0.1",
|
||||
"Port": 1433,
|
||||
"DBName": "VPKI_DataDB_DEV",
|
||||
"DBID": 2,
|
||||
"DBContext": "VpkiDataDbContext",
|
||||
"UserID": "VPKI",
|
||||
"Password": "Kefico!@34"
|
||||
}
|
||||
],
|
||||
"Openssl": {
|
||||
"Path": "C:/Program Files/OpenSSL-Win64/bin/openssl.exe",
|
||||
"SubCAPath": "../SubCA/",
|
||||
"SubCA": {
|
||||
"prov_v1": "SubCA_P02OEM.pem",
|
||||
"prov_cert": "SubCA_P20OEM.pem",
|
||||
"vehicle_cert": "SubCA_P20VHC.pem"
|
||||
},
|
||||
"RootCA": "hkmcrootca.pem"
|
||||
}
|
||||
}
|
||||
14
Projects/VPKI/VPKI/Config/VPKI.WebClientConfig.json
Normal file
14
Projects/VPKI/VPKI/Config/VPKI.WebClientConfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"Server": {
|
||||
"Address": "https://*",
|
||||
"Port": 8000,
|
||||
"IIS": false
|
||||
},
|
||||
"Api": [
|
||||
{
|
||||
"ApiName": "VPKI.API",
|
||||
"Address": "https://127.0.0.1",
|
||||
"Port": 8080
|
||||
}
|
||||
]
|
||||
}
|
||||
81
Projects/VPKI/VPKI/Config/log4net.config
Normal file
81
Projects/VPKI/VPKI/Config/log4net.config
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<log4net>
|
||||
<root>
|
||||
<level value="ALL"/>
|
||||
<appender-ref ref="Console"/>
|
||||
<appender-ref ref="file"/>
|
||||
<appender-ref ref="fatal_file"/>
|
||||
</root>
|
||||
|
||||
<appender name="Console" type="log4net.Appender.ManagedColoredConsoleAppender">
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="[%date] [%thread] %-6level: %message%newline" />
|
||||
</layout>
|
||||
<mapping>
|
||||
<level value="FATAL" />
|
||||
<foreColor value="White" />
|
||||
<backColor value="Red" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="ERROR" />
|
||||
<foreColor value="Red" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="WARN" />
|
||||
<foreColor value="Yellow" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="INFO" />
|
||||
<foreColor value="Green" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="DEBUG" />
|
||||
<foreColor value="Blue" />
|
||||
</mapping>
|
||||
|
||||
<mapping>
|
||||
<level value="DB" />
|
||||
<foreColor value="DarkMagenta" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="HTTP" />
|
||||
<foreColor value="DarkYellow" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="SOCKET" />
|
||||
<foreColor value="DarkCyan" />
|
||||
</mapping>
|
||||
<mapping>
|
||||
<level value="CONTROLLER" />
|
||||
<foreColor value="DarkGreen" />
|
||||
</mapping>
|
||||
</appender>
|
||||
|
||||
<appender name="file" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="log/" />
|
||||
<datepattern value="yyyy////MM////yyyy-MM-dd'.log'"/>
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
<staticLogFileName value="false" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="[%date] [%thread] %level %logger - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="fatal_file" type="log4net.Appender.RollingFileAppender">
|
||||
<file value="log/" />
|
||||
<datepattern value="yyyy////MM////yyyy-MM-dd'_fatal.log'"/>
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
<staticLogFileName value="false" />
|
||||
<filter type="log4net.Filter.LevelRangeFilter">
|
||||
<param name="LevelMin" value="FATAL" />
|
||||
<param name="LevelMax" value="FATAL" />
|
||||
</filter>
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="[%date] [%thread] %level %logger - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
</log4net>
|
||||
</configuration>
|
||||
16
Projects/VPKI/VPKI/Config/nginx.conf
Normal file
16
Projects/VPKI/VPKI/Config/nginx.conf
Normal file
@ -0,0 +1,16 @@
|
||||
events {
|
||||
worker_connections 1000;
|
||||
}
|
||||
|
||||
http {
|
||||
upstream vpki.web.api {
|
||||
server vpki.web.api:5555;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
location / {
|
||||
proxy_pass https://vpki.web.api/;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Projects/VPKI/VPKI/SubCA/SubCA_P02OEM.pem
Normal file
17
Projects/VPKI/VPKI/SubCA/SubCA_P02OEM.pem
Normal file
@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICszCCAlmgAwIBAgIUHxrrBdc1lvNKymblQjb06G6MSJYwCgYIKoZIzj0EAwI
|
||||
wPjELMAkGA1UEBhMCS1IxDTALBgNVBAoMBEhLTUMxDDAKBgNVBAsMA0VDQzESMB
|
||||
AGA1UEAwwJUm9vdENBMDAxMCAXDTE5MDYxMjA2MTUxNVoYDzIwNzkwNjEyMjM1O
|
||||
TU5WjA8MQswCQYDVQQGEwJLUjENMAsGA1UECgwESEtNQzEMMAoGA1UECwwDRUND
|
||||
MRAwDgYDVQQDDAdDQTAxMDAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB0K
|
||||
uXigZeI7U1McUnjEhYGL4g7zsvyzoNl8SMJ0oPxJgiXka+A37JjK4L/P85bAG7N
|
||||
4C6IYuSem99P0C0vt0K6OCATMwggEvMB8GA1UdIwQYMBaAFLW9YfqauBG22R0cD
|
||||
ywt08OqFD99MB0GA1UdDgQWBBQl67U3b8S3sG1J/ukFKlGcqPpw8DAOBgNVHQ8B
|
||||
Af8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADBBBgNVHR8EOjA4MDagNKAyhjB
|
||||
odHRwOi8vY3JsLmhtY2ttYy5jby5rci9FQ0MvUm9vdC9hcmwvQXJsMURwMS5jcm
|
||||
wwgYUGCCsGAQUFBwEBBHkwdzA7BggrBgEFBQcwAoYvaHR0cDovL2NybC5obWNrb
|
||||
WMuY28ua3IvRUNDL2NlcnQvaGttY3Jvb3RjYS5kZXIwOAYIKwYBBQUHMAGGLGh0
|
||||
dHA6Ly9ydG9jc3AuaG1ja21jLmNvLmtyL0VDQy9PQ1NQL2hrbWNvY3NwMAoGCCq
|
||||
GSM49BAMCA0gAMEUCICfXVV8IhFBXkaOHkg2Wk883y9r3B5rPtDV9JKhUQuBXAi
|
||||
EAug5R/broK+ZjM3vYdU7dndBfMFkOYtCa1NBdq6ie/Fs=
|
||||
-----END CERTIFICATE-----
|
||||
3
Projects/VPKI/VPKI/SubCA/SubCA_P20OEM.pem
Normal file
3
Projects/VPKI/VPKI/SubCA/SubCA_P20OEM.pem
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICvzCCAiCgAwIBAgIUDsyHo4Z9sUNMNqyLEBC1HBmJjDIwCgYIKoZIzj0EAwQwPjELMAkGA1UEBhMCS1IxDTALBgNVBAoMBEhLTUMxDDAKBgNVBAsMA0VDQzESMBAGA1UEAwwJUm9vdENBMDAyMCAXDTIzMDEzMDAyNTAzM1oYDzIwODMwMTMwMTQ1OTU5WjA8MQswCQYDVQQGEwJLUjENMAsGA1UECgwESEtNQzEMMAoGA1UECwwDRUNDMRAwDgYDVQQDDAdDQTAxMDAyMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB0OtZd+xmRyO4zVZxg3sHV+TsDq/eUq10gqDU8UgdWOX2dqS9ELG1atX7jZ/B7GjpkM+iHkfWT2HAdq5UbDo8hq0BnisaBxK5GCE39Qn6RRtuCaBxuxmSdLUUj/2FNun7enFzlL8hsYt3MK4iK4YLI6ibaVUvuegeYRKYai5XscAPgkajgbgwgbUwIgYDVR0jAQH/BBgwFoAURTRfYSTjJP2uBQL8GaTkuNZZ/LAwIAYDVR0OAQH/BBYEFAYMTDbCQgUerEWCQXA17t7r/CDyMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMEkGA1UdHwEB/wQ/MD0wO6A5oDeGNWh0dHA6Ly9jcmwuaG1ja21jLmNvLmtyL0VDQy9Sb290Q0EwMDIvYXJsL0FybDFEcDEuY3JsMAoGCCqGSM49BAMEA4GMADCBiAJCAPW2gWcbrJdhOPbHGiXHHrSBiV8z5BSLzmHFn4jmsmFOrVpACVZTcTXg0odfug9iyI+OjTI2yj8MqdcGpfd3CZu8AkIBazSGl8GqiCi7dJb346Y/1TFLg14R76UVG2EahQIetp4Hj8SZtN8eHcVrXmm+ksL8OKyMh9lc5S2qmTch1ZxY9Bk=
|
||||
-----END CERTIFICATE-----
|
||||
3
Projects/VPKI/VPKI/SubCA/SubCA_P20VHC.pem
Normal file
3
Projects/VPKI/VPKI/SubCA/SubCA_P20VHC.pem
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICvjCCAiCgAwIBAgIUD3/W7mdD8uEvO8tG52SdiVKJgB0wCgYIKoZIzj0EAwQwPjELMAkGA1UEBhMCS1IxDTALBgNVBAoMBEhLTUMxDDAKBgNVBAsMA0VDQzESMBAGA1UEAwwJUm9vdENBMDAyMCAXDTIzMDEzMDAzMjA1NloYDzIwODMwMTMwMTQ1OTU5WjA8MQswCQYDVQQGEwJLUjENMAsGA1UECgwESEtNQzEMMAoGA1UECwwDRUNDMRAwDgYDVQQDDAdDQTAxMDAzMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQA0eDXwzSjBaWTFcjg48QtsHGrcSJ4n++/EB76paBW8hfA1FQ3rGtZ0cVR5NPfS2+2R1sgqJz6LpGvh1LgXCV+DG8B+HpqSE7JjGaLrUhpN0GObyEmQzid4YISEqAcgXonh6l/F7C76QsSOjMQigVAxZUWk0Z7WVGi3zO+5eKAiFoztKSjgbgwgbUwIgYDVR0jAQH/BBgwFoAURTRfYSTjJP2uBQL8GaTkuNZZ/LAwIAYDVR0OAQH/BBYEFI0Kz6ICty/fnhYaFq4ckuNJoHSwMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMEkGA1UdHwEB/wQ/MD0wO6A5oDeGNWh0dHA6Ly9jcmwuaG1ja21jLmNvLmtyL0VDQy9Sb290Q0EwMDIvYXJsL0FybDFEcDEuY3JsMAoGCCqGSM49BAMEA4GLADCBhwJBAZ8WxHdQFXzR5MBbzBKrE0phkHxXNtg8ncDtusaBrCcMFLQYQUSzf1gmxcGHWGGhBEOwBpN5EU9ox7HQ6P0HYv4CQgEYx+Qu5VxjnsNkue8Xl9kaFdZp2wf5drmk67XcV7O4llCnWa/L45PS9CrpLp8qjxAQffjrqumYglJn45+EfYeO2A==
|
||||
-----END CERTIFICATE-----
|
||||
12
Projects/VPKI/VPKI/SubCA/hkmcrootca.pem
Normal file
12
Projects/VPKI/VPKI/SubCA/hkmcrootca.pem
Normal file
@ -0,0 +1,12 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBwTCCAWigAwIBAgIUCeUMZnQywRQfK13l7kWUsltWGOAwCgYIKoZIzj0EAwIw
|
||||
PjELMAkGA1UEBhMCS1IxDTALBgNVBAoMBEhLTUMxDDAKBgNVBAsMA0VDQzESMBAG
|
||||
A1UEAwwJUm9vdENBMDAxMCAXDTE5MDUwOTAwNDEwMFoYDzIxMDkwNTA5MjM1OTU5
|
||||
WjA+MQswCQYDVQQGEwJLUjENMAsGA1UECgwESEtNQzEMMAoGA1UECwwDRUNDMRIw
|
||||
EAYDVQQDDAlSb290Q0EwMDEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR/ROoS
|
||||
YMi4T9nJ+KGujVjnWWxHMy2+8TZ69QcfFqO5Rg0ipl7t9N1BQWj1BqfsYEjzCpQZ
|
||||
9jppik7NeknLgZ9Io0IwQDAdBgNVHQ4EFgQUtb1h+pq4EbbZHRwPLC3Tw6oUP30w
|
||||
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAw
|
||||
RAIgPQ/HKZJI3cuz38yNJTrmlOz5vwB5QfAOU8lwk+7pmCoCIFMk1HQSpARINQH/
|
||||
Pm27xACoQY4OTElHcJ1EKOTOnIDp
|
||||
-----END CERTIFICATE-----
|
||||
@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DB.VPKI_AccountDB;
|
||||
|
||||
public partial class VpkiAccountDbContext : DbContext
|
||||
{
|
||||
public VpkiAccountDbContext()
|
||||
{
|
||||
}
|
||||
|
||||
public VpkiAccountDbContext(DbContextOptions<VpkiAccountDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DbSet<TRefreshToken> TRefreshTokens { get; set; }
|
||||
|
||||
public virtual DbSet<TRole> TRoles { get; set; }
|
||||
|
||||
public virtual DbSet<TUser> TUsers { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
|
||||
=> optionsBuilder.UseSqlServer("server=127.0.0.1; user id=VPKI; password=Kefico!@34; database=VPKI_AccountDB; TrustServerCertificate=true;");
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<TRefreshToken>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CAuid).HasName("PK__tRefresh__FBF0855408955D04");
|
||||
|
||||
entity.ToTable("tRefreshToken");
|
||||
|
||||
entity.Property(e => e.CAuid)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("cAuid");
|
||||
entity.Property(e => e.CRefreshToken)
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnName("cRefreshToken");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TRole>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CAuid).HasName("PK__tRole__FBF0855456FE2E20");
|
||||
|
||||
entity.ToTable("tRole");
|
||||
|
||||
entity.Property(e => e.CAuid)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("cAuid");
|
||||
entity.Property(e => e.CRoleId).HasColumnName("cRoleID");
|
||||
entity.Property(e => e.CRoleName)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cRoleName");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TUser>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CUserId).HasName("PK__tUser__A75DC19A1C6A7C5E");
|
||||
|
||||
entity.ToTable("tUser");
|
||||
|
||||
entity.Property(e => e.CUserId)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("cUserID");
|
||||
entity.Property(e => e.CAuid)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("cAuid");
|
||||
entity.Property(e => e.CCreateDateTime).HasColumnName("cCreateDateTime");
|
||||
entity.Property(e => e.CLastLoginDateTime).HasColumnName("cLastLoginDateTime");
|
||||
entity.Property(e => e.CPasswordHashed)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("cPasswordHashed");
|
||||
entity.Property(e => e.CState).HasColumnName("cState");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_AccountDB;
|
||||
|
||||
public partial class TRefreshToken
|
||||
{
|
||||
public string CAuid { get; set; } = null!;
|
||||
|
||||
public string CRefreshToken { get; set; } = null!;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_AccountDB;
|
||||
|
||||
public partial class TRole
|
||||
{
|
||||
public string CAuid { get; set; } = null!;
|
||||
|
||||
public byte CRoleId { get; set; }
|
||||
|
||||
public string CRoleName { get; set; } = null!;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_AccountDB;
|
||||
|
||||
public partial class TUser
|
||||
{
|
||||
public string CUserId { get; set; } = null!;
|
||||
|
||||
public string CAuid { get; set; } = null!;
|
||||
|
||||
public string CPasswordHashed { get; set; } = null!;
|
||||
|
||||
public byte CState { get; set; }
|
||||
|
||||
public DateTime CCreateDateTime { get; set; }
|
||||
|
||||
public DateTime? CLastLoginDateTime { get; set; }
|
||||
}
|
||||
@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DB.VPKI_DataDB;
|
||||
|
||||
public partial class VpkiDataDbContext : DbContext
|
||||
{
|
||||
public VpkiDataDbContext()
|
||||
{
|
||||
}
|
||||
|
||||
public VpkiDataDbContext(DbContextOptions<VpkiDataDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual DbSet<TCertificate> TCertificates { get; set; }
|
||||
|
||||
public virtual DbSet<TOcsp> TOcsps { get; set; }
|
||||
|
||||
public virtual DbSet<TTbscsr> TTbscsrs { get; set; }
|
||||
|
||||
public virtual DbSet<TVerifyResult> TVerifyResults { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
|
||||
=> optionsBuilder.UseSqlServer("server=127.0.0.1; user id=VPKI; password=Kefico!@34; database=VPKI_DataDB; TrustServerCertificate=true;");
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<TCertificate>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CCuid).HasName("PK__tCertifi__2AA00D94B11718A8");
|
||||
|
||||
entity.ToTable("tCertificate");
|
||||
|
||||
entity.Property(e => e.CCuid)
|
||||
.ValueGeneratedNever()
|
||||
.HasColumnName("cCuid");
|
||||
entity.Property(e => e.CBrandCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cBrandCode");
|
||||
entity.Property(e => e.CCert)
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnName("cCert");
|
||||
entity.Property(e => e.CCsr)
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnName("cCsr");
|
||||
entity.Property(e => e.CCsrsignature)
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnName("cCsrsignature");
|
||||
entity.Property(e => e.CDateTime).HasColumnName("cDateTime");
|
||||
entity.Property(e => e.CIssueCount).HasColumnName("cIssueCount");
|
||||
entity.Property(e => e.CLocalCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cLocalCode");
|
||||
entity.Property(e => e.CMessage)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("cMessage");
|
||||
entity.Property(e => e.CTierCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cTierCode");
|
||||
entity.Property(e => e.CUnitCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cUnitCode");
|
||||
entity.Property(e => e.CVehicleCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cVehicleCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TOcsp>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CCuid).HasName("PK__tOcsp__2AA00D941E2BA200");
|
||||
|
||||
entity.ToTable("tOcsp");
|
||||
|
||||
entity.Property(e => e.CCuid)
|
||||
.ValueGeneratedNever()
|
||||
.HasColumnName("cCuid");
|
||||
entity.Property(e => e.CDateTime).HasColumnName("cDateTime");
|
||||
entity.Property(e => e.COcsp).HasColumnName("cOcsp");
|
||||
entity.Property(e => e.CStatus)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cStatus");
|
||||
entity.Property(e => e.CVerify)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cVerify");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TTbscsr>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CCuid).HasName("PK__tTbscsr__2AA00D94155F4FC3");
|
||||
|
||||
entity.ToTable("tTbscsr");
|
||||
|
||||
entity.Property(e => e.CCuid).HasColumnName("cCuid");
|
||||
entity.Property(e => e.CCertType)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cCertType");
|
||||
entity.Property(e => e.CDateTime).HasColumnName("cDateTime");
|
||||
entity.Property(e => e.CDc)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cDc");
|
||||
entity.Property(e => e.CDn)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("cDn");
|
||||
entity.Property(e => e.CHashedTbscsr)
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnName("cHashedTbscsr");
|
||||
entity.Property(e => e.CIdType)
|
||||
.HasMaxLength(10)
|
||||
.HasColumnName("cIdType");
|
||||
entity.Property(e => e.CIftid)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("cIftid");
|
||||
entity.Property(e => e.CMacaddr)
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("cMacaddr");
|
||||
entity.Property(e => e.COriginTbscsr)
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnName("cOriginTbscsr");
|
||||
entity.Property(e => e.CPcid)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("cPcid");
|
||||
entity.Property(e => e.CPublickey)
|
||||
.HasMaxLength(1024)
|
||||
.HasColumnName("cPublickey");
|
||||
entity.Property(e => e.CSupplierId)
|
||||
.HasMaxLength(10)
|
||||
.HasColumnName("cSupplierId");
|
||||
entity.Property(e => e.CTierCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cTierCode");
|
||||
entity.Property(e => e.CUnitCode)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cUnitCode");
|
||||
entity.Property(e => e.CWmi)
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("cWmi");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TVerifyResult>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.CCuid).HasName("PK__tVerifyR__2AA00D94A7EE4DE6");
|
||||
|
||||
entity.ToTable("tVerifyResult");
|
||||
|
||||
entity.Property(e => e.CCuid)
|
||||
.ValueGeneratedNever()
|
||||
.HasColumnName("cCuid");
|
||||
entity.Property(e => e.CResult)
|
||||
.HasMaxLength(20)
|
||||
.IsFixedLength()
|
||||
.HasColumnName("cResult");
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_DataDB;
|
||||
|
||||
public partial class TCertificate
|
||||
{
|
||||
public long CCuid { get; set; }
|
||||
|
||||
public string CCsrsignature { get; set; } = null!;
|
||||
|
||||
public string CTierCode { get; set; } = null!;
|
||||
|
||||
public string CUnitCode { get; set; } = null!;
|
||||
|
||||
public string CVehicleCode { get; set; } = null!;
|
||||
|
||||
public string CLocalCode { get; set; } = null!;
|
||||
|
||||
public string CBrandCode { get; set; } = null!;
|
||||
|
||||
public string CCsr { get; set; } = null!;
|
||||
|
||||
public string CCert { get; set; } = null!;
|
||||
|
||||
public string CMessage { get; set; } = null!;
|
||||
|
||||
public int CIssueCount { get; set; }
|
||||
|
||||
public DateTime CDateTime { get; set; }
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_DataDB;
|
||||
|
||||
public partial class TOcsp
|
||||
{
|
||||
public long CCuid { get; set; }
|
||||
|
||||
public string CStatus { get; set; } = null!;
|
||||
|
||||
public string CVerify { get; set; } = null!;
|
||||
|
||||
public string? COcsp { get; set; }
|
||||
|
||||
public DateTime CDateTime { get; set; }
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_DataDB;
|
||||
|
||||
public partial class TTbscsr
|
||||
{
|
||||
public long CCuid { get; set; }
|
||||
|
||||
public string CIftid { get; set; } = null!;
|
||||
|
||||
public string CMacaddr { get; set; } = null!;
|
||||
|
||||
public string CWmi { get; set; } = null!;
|
||||
|
||||
public string CIdType { get; set; } = null!;
|
||||
|
||||
public string CSupplierId { get; set; } = null!;
|
||||
|
||||
public string CDc { get; set; } = null!;
|
||||
|
||||
public string CTierCode { get; set; } = null!;
|
||||
|
||||
public string CUnitCode { get; set; } = null!;
|
||||
|
||||
public string CPublickey { get; set; } = null!;
|
||||
|
||||
public string CCertType { get; set; } = null!;
|
||||
|
||||
public string COriginTbscsr { get; set; } = null!;
|
||||
|
||||
public string CHashedTbscsr { get; set; } = null!;
|
||||
|
||||
public string CPcid { get; set; } = null!;
|
||||
|
||||
public string CDn { get; set; } = null!;
|
||||
|
||||
public DateTime CDateTime { get; set; }
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DB.VPKI_DataDB;
|
||||
|
||||
public partial class TVerifyResult
|
||||
{
|
||||
public long CCuid { get; set; }
|
||||
|
||||
public string CResult { get; set; } = null!;
|
||||
}
|
||||
31
Projects/VPKI/VPKI/VPKI.Library.DB/VPKI.Library.DB.csproj
Normal file
31
Projects/VPKI/VPKI/VPKI.Library.DB/VPKI.Library.DB.csproj
Normal file
@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
<NoWarn>1701;1702;1030</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
<NoWarn>1701;1702;1030</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.11">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
21
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Api.cs
Normal file
21
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Api.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Config.Model
|
||||
{
|
||||
public class Api
|
||||
{
|
||||
[JsonPropertyName("ApiName")]
|
||||
public string? ApiName { get; set; }
|
||||
|
||||
[JsonPropertyName("Address")]
|
||||
public string? Address { get; set; }
|
||||
|
||||
[JsonPropertyName("Port")]
|
||||
public int Port { get; set; }
|
||||
}
|
||||
}
|
||||
33
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Auth.cs
Normal file
33
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Auth.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Config.Model
|
||||
{
|
||||
public class Auth
|
||||
{
|
||||
//jwt common
|
||||
[JsonPropertyName("issuer")]
|
||||
public string? issuer { get; set; }
|
||||
|
||||
[JsonPropertyName("audience")]
|
||||
public string? audience { get; set; }
|
||||
|
||||
//access token
|
||||
[JsonPropertyName("accessTokenSecret")]
|
||||
public string? accessTokenSecret { get; set; }
|
||||
|
||||
[JsonPropertyName("accessTokenExpires")]
|
||||
public uint? accessTokenExpires { get; set; }
|
||||
|
||||
//refresh token
|
||||
[JsonPropertyName("refreshTokenSecret")]
|
||||
public string? refreshTokenSecret { get; set; }
|
||||
|
||||
[JsonPropertyName("refreshTokenExpires")]
|
||||
public uint? refreshTokenExpires { get; set; }
|
||||
}
|
||||
}
|
||||
33
Projects/VPKI/VPKI/VPKI.Library/Config/Model/DataBase.cs
Normal file
33
Projects/VPKI/VPKI/VPKI.Library/Config/Model/DataBase.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Config.Model
|
||||
{
|
||||
public class DataBase
|
||||
{
|
||||
[JsonPropertyName("IP")]
|
||||
public string? IP { get; set; }
|
||||
|
||||
[JsonPropertyName("Port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[JsonPropertyName("DBName")]
|
||||
public string? DBName { get; set; }
|
||||
|
||||
[JsonPropertyName("DBID")]
|
||||
public int DBID { get; set; }
|
||||
|
||||
[JsonPropertyName("DBContext")]
|
||||
public string? DBContext { get; set; }
|
||||
|
||||
[JsonPropertyName("UserID")]
|
||||
public string? UserID { get; set; }
|
||||
|
||||
[JsonPropertyName("Password")]
|
||||
public string? Password { get; set; }
|
||||
}
|
||||
}
|
||||
36
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Openssl.cs
Normal file
36
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Openssl.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Config.Model
|
||||
{
|
||||
public class Openssl
|
||||
{
|
||||
[JsonPropertyName("Path")]
|
||||
public string? Path { get; set; }
|
||||
|
||||
[JsonPropertyName("SubCAPath")]
|
||||
public string? SubCAPath { get; set; }
|
||||
|
||||
[JsonPropertyName("SubCA")]
|
||||
public SubCA? SubCA { get; set; }
|
||||
|
||||
[JsonPropertyName("RootCA")]
|
||||
public string? RootCA { get; set; }
|
||||
}
|
||||
|
||||
public class SubCA
|
||||
{
|
||||
[JsonPropertyName("prov_v1")]
|
||||
public string? prov_v1 { get; set; }
|
||||
|
||||
[JsonPropertyName("prov_cert")]
|
||||
public string? prov_cert { get; set; }
|
||||
|
||||
[JsonPropertyName("vehicle_cert")]
|
||||
public string? vehicle_cert { get; set; }
|
||||
}
|
||||
}
|
||||
21
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Server.cs
Normal file
21
Projects/VPKI/VPKI/VPKI.Library/Config/Model/Server.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Config.Model
|
||||
{
|
||||
public class Server
|
||||
{
|
||||
[JsonPropertyName("Address")]
|
||||
public string? Address { get; set; }
|
||||
|
||||
[JsonPropertyName("Port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[JsonPropertyName("IIS")]
|
||||
public bool IIS { get; set; }
|
||||
}
|
||||
}
|
||||
25
Projects/VPKI/VPKI/VPKI.Library/Config/WebApiConfig.cs
Normal file
25
Projects/VPKI/VPKI/VPKI.Library/Config/WebApiConfig.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Config.Model;
|
||||
|
||||
namespace VPKI.Library.Config
|
||||
{
|
||||
public class WebApiConfig : WebCommonConfig
|
||||
{
|
||||
[JsonPropertyName("Api")]
|
||||
public List<Api>? Api { get; set; }
|
||||
|
||||
[JsonPropertyName("Auth")]
|
||||
public Auth? Auth { get; set; }
|
||||
|
||||
[JsonPropertyName("DataBase")]
|
||||
public List<DataBase>? DataBase { get; set; }
|
||||
|
||||
[JsonPropertyName("Openssl")]
|
||||
public Openssl? Openssl { get; set; }
|
||||
}
|
||||
}
|
||||
16
Projects/VPKI/VPKI/VPKI.Library/Config/WebClientConfig.cs
Normal file
16
Projects/VPKI/VPKI/VPKI.Library/Config/WebClientConfig.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Config.Model;
|
||||
|
||||
namespace VPKI.Library.Config
|
||||
{
|
||||
public class WebClientConfig : WebCommonConfig
|
||||
{
|
||||
[JsonPropertyName("Api")]
|
||||
public List<Api>? Api { get; set; }
|
||||
}
|
||||
}
|
||||
16
Projects/VPKI/VPKI/VPKI.Library/Config/WebCommonConfig.cs
Normal file
16
Projects/VPKI/VPKI/VPKI.Library/Config/WebCommonConfig.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Config.Model;
|
||||
|
||||
namespace VPKI.Library.Config
|
||||
{
|
||||
public class WebCommonConfig
|
||||
{
|
||||
[JsonPropertyName("Server")]
|
||||
public Server Server { get; set; } = new();
|
||||
}
|
||||
}
|
||||
22
Projects/VPKI/VPKI/VPKI.Library/Consts/Consts.cs
Normal file
22
Projects/VPKI/VPKI/VPKI.Library/Consts/Consts.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class Consts
|
||||
{
|
||||
//vpki fixex value
|
||||
public static readonly string VPKI_API = "VPKI.API";
|
||||
public static readonly string VPKI_API_VPKIRA = "VPKIRA";
|
||||
|
||||
//certificate fixed value
|
||||
public static readonly string BEGIN_CERTIFICATE_REQUEST = "-----BEGIN CERTIFICATE_REQUEST-----";
|
||||
public static readonly string END_CERTIFICATE_REQUEST = "-----END CERTIFICATE_REQUEST-----";
|
||||
|
||||
public static readonly string BEGIN_CERTIFICATE = $"-----BEGIN CERTIFICATE-----";
|
||||
public static readonly string END_CERTIFICATE = $"-----END CERTIFICATE-----";
|
||||
|
||||
public static readonly string BEGIN_PUBLIC_KEY = $"-----BEGIN PUBLIC KEY-----";
|
||||
public static readonly string END_PUBLIC_KEY = $"-----END PUBLIC KEY-----";
|
||||
}
|
||||
20
Projects/VPKI/VPKI/VPKI.Library/Enums/ECDSAType.cs
Normal file
20
Projects/VPKI/VPKI/VPKI.Library/Enums/ECDSAType.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Enums
|
||||
{
|
||||
public enum ECDSAType
|
||||
{
|
||||
NONEWITHECDSA = 1,
|
||||
SHA256WITHECDSA = 2,
|
||||
}
|
||||
|
||||
public enum CurveName
|
||||
{
|
||||
secp256r1 = 0,
|
||||
secp521r1 = 1,
|
||||
}
|
||||
}
|
||||
32
Projects/VPKI/VPKI/VPKI.Library/Enums/ErrorCode.cs
Normal file
32
Projects/VPKI/VPKI/VPKI.Library/Enums/ErrorCode.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Enums
|
||||
{
|
||||
public enum ERROR_CODE
|
||||
{
|
||||
//기본 에러
|
||||
EC_NONE = 0,
|
||||
EC_OK = 1,
|
||||
|
||||
//DB 관련 에러
|
||||
EC_DEFAULT_ERROR = 1000,
|
||||
EC_DATABASE_ERROR = 1001,
|
||||
|
||||
//유저 관련 에러
|
||||
EC_USER_REGISTER_FAILED = 2000,
|
||||
EC_USER_REGISTER_EXIST = 2001,
|
||||
EC_USER_REGISTER_CONFIRM_PASSWORD_ERROR = 2002,
|
||||
|
||||
EC_USER_LOGIN_FAILED = 2100,
|
||||
EC_USER_LOGIN_NOT_EXIST = 2101,
|
||||
EC_USER_LOGIN_INVALID_PASSWORD = 2102,
|
||||
EC_USER_LOGIN_INAVTIVE = 2103,
|
||||
EC_USER_LOGIN_BLOCKED = 2104,
|
||||
|
||||
EC_USER_LOGOUT_FAILED = 2200
|
||||
}
|
||||
}
|
||||
16
Projects/VPKI/VPKI/VPKI.Library/Enums/StatusCode.cs
Normal file
16
Projects/VPKI/VPKI/VPKI.Library/Enums/StatusCode.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Enums
|
||||
{
|
||||
//VPKI 응답 상태, API 문서 참고
|
||||
public enum Status
|
||||
{
|
||||
none = 0,
|
||||
success = 1,
|
||||
error = 2,
|
||||
}
|
||||
}
|
||||
20
Projects/VPKI/VPKI/VPKI.Library/Enums/UserRole.cs
Normal file
20
Projects/VPKI/VPKI/VPKI.Library/Enums/UserRole.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Enums
|
||||
{
|
||||
//User 권한
|
||||
public enum UserRole : byte
|
||||
{
|
||||
None = 0,
|
||||
Ananymous = 1,
|
||||
|
||||
User = 10,
|
||||
Admin = 11,
|
||||
|
||||
SuperUser = 20,
|
||||
}
|
||||
}
|
||||
15
Projects/VPKI/VPKI/VPKI.Library/Enums/UserState.cs
Normal file
15
Projects/VPKI/VPKI/VPKI.Library/Enums/UserState.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Enums
|
||||
{
|
||||
public enum UserState: byte
|
||||
{
|
||||
Inactive = 0,
|
||||
Active = 1,
|
||||
Block = 2
|
||||
}
|
||||
}
|
||||
23
Projects/VPKI/VPKI/VPKI.Library/Enums/VpkiType.cs
Normal file
23
Projects/VPKI/VPKI/VPKI.Library/Enums/VpkiType.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Enums
|
||||
{
|
||||
public enum VpkiType
|
||||
{
|
||||
prov_v1 = 1,
|
||||
prov_cert = 2,
|
||||
vehicle_cert = 3,
|
||||
|
||||
evcc_cert = 10,
|
||||
}
|
||||
|
||||
public enum VpkiIsoType
|
||||
{
|
||||
ISO15118_02 = 1,
|
||||
ISO15118_20 = 2,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Model;
|
||||
|
||||
public static class LogModelExtend
|
||||
{
|
||||
public static string LogModelToString(this LogModel log, string header = "")
|
||||
{
|
||||
string logString = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(header) == false)
|
||||
{
|
||||
logString += $"{header}::";
|
||||
}
|
||||
|
||||
logString += JsonConvert.SerializeObject(log, Formatting.Indented);
|
||||
logString += Environment.NewLine;
|
||||
|
||||
return logString;
|
||||
}
|
||||
}
|
||||
35
Projects/VPKI/VPKI/VPKI.Library/ExtendClass/ObjectExtend.cs
Normal file
35
Projects/VPKI/VPKI/VPKI.Library/ExtendClass/ObjectExtend.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public static class ObjectExtend
|
||||
{
|
||||
public static string ToJson(this object obj)
|
||||
{
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
result = JsonConvert.SerializeObject(obj, Formatting.Indented);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
result = e.Message.ToString();
|
||||
}
|
||||
result += Environment.NewLine;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static T? DeepCopy<T>(this T obj) where T : class, new()
|
||||
{
|
||||
string originJson = obj.ToJson();
|
||||
T? clone = JsonConvert.DeserializeObject<T>(originJson);
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
20
Projects/VPKI/VPKI/VPKI.Library/ExtendClass/StringExtend.cs
Normal file
20
Projects/VPKI/VPKI/VPKI.Library/ExtendClass/StringExtend.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public static class StringExtend
|
||||
{
|
||||
/// <summary>
|
||||
/// String To SHA256 Hash Base64
|
||||
/// </summary>
|
||||
public static string StringToSHA256Base64(this string str)
|
||||
{
|
||||
var hashedBytes = SHA256.HashData(Encoding.UTF8.GetBytes(str));
|
||||
var hashedString = Convert.ToBase64String(hashedBytes);
|
||||
|
||||
return hashedString;
|
||||
}
|
||||
}
|
||||
34
Projects/VPKI/VPKI/VPKI.Library/Model/Auth/LoginModel.cs
Normal file
34
Projects/VPKI/VPKI/VPKI.Library/Model/Auth/LoginModel.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Enums;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
//로그인 요청 모델
|
||||
public class LoginModel
|
||||
{
|
||||
[Required]
|
||||
public string? UserID { get; set; }
|
||||
|
||||
[Required]
|
||||
public string? Password { get; set; }
|
||||
}
|
||||
|
||||
//로그인 응답 모델
|
||||
public class LoginResponseModel
|
||||
{
|
||||
public string? UserID { get; set; }
|
||||
public UserRole Role { get; set; }
|
||||
public string? RoleName { get; set; }
|
||||
|
||||
public string? AccessToken { get; set; }
|
||||
public long AccessTokenExpired { get; set; }
|
||||
public string? RefreshToken { get; set; }
|
||||
|
||||
public ERROR_CODE? EC { get; set; }
|
||||
}
|
||||
}
|
||||
23
Projects/VPKI/VPKI/VPKI.Library/Model/Auth/LogoutModel.cs
Normal file
23
Projects/VPKI/VPKI/VPKI.Library/Model/Auth/LogoutModel.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Enums;
|
||||
|
||||
namespace VPKI.Library.Model.Auth
|
||||
{
|
||||
public class LogoutModel
|
||||
{
|
||||
[Required]
|
||||
public string? UserID { get; set; }
|
||||
}
|
||||
|
||||
public class LogoutResponseModel
|
||||
{
|
||||
public string? UserID { get; set; }
|
||||
|
||||
public ERROR_CODE? EC { get; set; }
|
||||
}
|
||||
}
|
||||
35
Projects/VPKI/VPKI/VPKI.Library/Model/Auth/RegisterModel.cs
Normal file
35
Projects/VPKI/VPKI/VPKI.Library/Model/Auth/RegisterModel.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Enums;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
//유저 등록 모델
|
||||
public class RegisterModel
|
||||
{
|
||||
[Required]
|
||||
public string UserID { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public string PasswordConfirm { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public UserRole Role { get; set; } = UserRole.User;
|
||||
}
|
||||
|
||||
public class RegisterResponseModel
|
||||
{
|
||||
public string? UserID { get; set; }
|
||||
public UserRole Role { get; set; }
|
||||
public string? RoleName { get; set; }
|
||||
|
||||
public ERROR_CODE? EC { get; set; } = ERROR_CODE.EC_USER_REGISTER_FAILED;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using DB.VPKI_AccountDB;
|
||||
using DB.VPKI_DataDB;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
public class CertificateHistoryModel
|
||||
{
|
||||
public TTbscsr? TTbscsr { get; set; }
|
||||
public TCertificate? TCertificate { get; set; }
|
||||
public TVerifyResult? TVerifyResult { get; set; }
|
||||
public TOcsp? TOcsp { get; set; }
|
||||
}
|
||||
}
|
||||
34
Projects/VPKI/VPKI/VPKI.Library/Model/CsrCompleteModel.cs
Normal file
34
Projects/VPKI/VPKI/VPKI.Library/Model/CsrCompleteModel.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using DB.VPKI_DataDB;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
public class CsrCompleteModel
|
||||
{
|
||||
public byte[]? Tbscsr { get; set; }
|
||||
public byte[]? Signature { get; set; }
|
||||
public Oid? SignatureAlgorithm { get; set; }
|
||||
|
||||
public byte[] CreateCertificateRequest()
|
||||
{
|
||||
// TBSCsr, 서명 알고리즘, 서명 데이터를 결합하여 최종 CSR 포맷을 만든다.
|
||||
var data = Encoding.ASCII.GetBytes($"{SignatureAlgorithm?.Value}");
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
if (Tbscsr != null && Signature != null)
|
||||
{
|
||||
ms.Write(Tbscsr, 0, Tbscsr.Length);
|
||||
ms.Write(Encoding.ASCII.GetBytes($"{SignatureAlgorithm?.Value}"), 0, data.Length);
|
||||
ms.Write(Signature, 0, Signature.Length);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Projects/VPKI/VPKI/VPKI.Library/Model/CsrHashedModel.cs
Normal file
15
Projects/VPKI/VPKI/VPKI.Library/Model/CsrHashedModel.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
public class CsrHashedModel
|
||||
{
|
||||
public string? SignedCsr { get; set; } = string.Empty;
|
||||
public string? EncodedSignedCsr { get; set; } = string.Empty;
|
||||
public bool Verify { get; set; } = false;
|
||||
}
|
||||
}
|
||||
19
Projects/VPKI/VPKI/VPKI.Library/Model/LogModel.cs
Normal file
19
Projects/VPKI/VPKI/VPKI.Library/Model/LogModel.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
public class LogModel
|
||||
{
|
||||
public string? ClientIP { get; set; }
|
||||
public string? Method { get; set; }
|
||||
public string? Action { get; set; }
|
||||
public string? RequestUrl { get; set; }
|
||||
public dynamic? Body { get; set; }
|
||||
}
|
||||
}
|
||||
15
Projects/VPKI/VPKI/VPKI.Library/Model/UserModel.cs
Normal file
15
Projects/VPKI/VPKI/VPKI.Library/Model/UserModel.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using DB.VPKI_AccountDB;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Model
|
||||
{
|
||||
public class UserModel
|
||||
{
|
||||
public TUser? TUser { get; set; }
|
||||
public TRole? TRole { get; set; }
|
||||
}
|
||||
}
|
||||
25
Projects/VPKI/VPKI/VPKI.Library/Packet/CommonPacket.cs
Normal file
25
Projects/VPKI/VPKI/VPKI.Library/Packet/CommonPacket.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Enums;
|
||||
|
||||
namespace VPKI.Library.Packet
|
||||
{
|
||||
public class CommonPacket
|
||||
{
|
||||
}
|
||||
|
||||
//request
|
||||
public class CommonPacketRequest : CommonPacket
|
||||
{
|
||||
}
|
||||
|
||||
//response
|
||||
public class CommonPacketResponse : CommonPacket
|
||||
{
|
||||
public string? status { get; set; } = Status.success.ToString();
|
||||
public string? message { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
38
Projects/VPKI/VPKI/VPKI.Library/Packet/OEMPacket.cs
Normal file
38
Projects/VPKI/VPKI/VPKI.Library/Packet/OEMPacket.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
//VPKI <-> OEM PKI(auto ever srver)
|
||||
namespace VPKI.Library.Packet
|
||||
{
|
||||
#region 인증서 발급/재발급 요청 (ISO15118-2/ISO15118-20)
|
||||
public class Request_CertificateOEM : CommonPacketRequest
|
||||
{
|
||||
public string? csr { get; set; }
|
||||
public string? unitCode { get; set; }
|
||||
public string? tierCode { get; set; }
|
||||
public string? vehicleCode { get; set; }
|
||||
public string? localCode { get; set; }
|
||||
public string? brandCode { get; set; }
|
||||
}
|
||||
|
||||
public class Response_CertificateOEM : CommonPacketResponse
|
||||
{
|
||||
public string? cert { get; set; }
|
||||
public string? resultMessage { get; set; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 인증서 폐기 요청 (ISO15118-2/ISO15118-20)
|
||||
public class Request_CertificateRevokeOEM : CommonPacketRequest
|
||||
{
|
||||
public string dn { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class Response_CertificateRevokeOEM : CommonPacketResponse
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
103
Projects/VPKI/VPKI/VPKI.Library/Packet/VPKIPacket.cs
Normal file
103
Projects/VPKI/VPKI/VPKI.Library/Packet/VPKIPacket.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
//client <-> vPKI(VPKI Server)
|
||||
namespace VPKI.Library.Packet
|
||||
{
|
||||
#region CSR 생성 요청 (ISO15118-2)
|
||||
public class Request_Tbscsr : CommonPacketRequest
|
||||
{
|
||||
public string iftid { get; set; } = string.Empty;
|
||||
public CnInfo cnInfo { get; set; } = new();
|
||||
public CertInfo certInfo { get; set; } = new();
|
||||
public string publickey { get; set; } = string.Empty;
|
||||
|
||||
#region InnerClass
|
||||
public class CnInfo
|
||||
{
|
||||
public string macaddr { get; set; } = string.Empty;
|
||||
public string wmi { get; set; } = string.Empty;
|
||||
public string idType { get; set; } = string.Empty;
|
||||
public string supplierId { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class CertInfo
|
||||
{
|
||||
public string dc { get; set; } = string.Empty;
|
||||
public string tierCode { get; set; } = string.Empty;
|
||||
public string unitCode { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public string certType { get; set; } = string.Empty;
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class Response_Tbscsr : CommonPacketResponse
|
||||
{
|
||||
public Data? data { get; set; }
|
||||
|
||||
#region InnerClass
|
||||
public class Data
|
||||
{
|
||||
public string? hashedtbscsr { get; set; }
|
||||
public string? pcid { get; set; }
|
||||
public string? evccid { get; set; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 인증서 발급 요청 (ISO15118-2/ISO15118-20)
|
||||
public class Request_Certificate : CommonPacketRequest
|
||||
{
|
||||
public string? iftid { get; set; }
|
||||
public string? csrsignature { get; set; }
|
||||
public string? unitCode { get; set; }
|
||||
public string? tierCode { get; set; }
|
||||
public string? vehicleCode { get; set; }
|
||||
public string? localCode { get; set; }
|
||||
public string? brandCode { get; set; }
|
||||
}
|
||||
|
||||
public class Response_Certificate : CommonPacketResponse
|
||||
{
|
||||
public Data? data { get; set; }
|
||||
|
||||
#region InnerClass
|
||||
public class Data
|
||||
{
|
||||
public string? leafcertificate { get; set; }
|
||||
public string? subcacertificate { get; set; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 인증서 검증 결과 전송 (ISO15118-2/ISO15118-20)
|
||||
public class Request_Verifyresult : CommonPacketRequest
|
||||
{
|
||||
public string? iftid { get; set; }
|
||||
public string? pcid { get; set; }
|
||||
public string? result { get; set; }
|
||||
}
|
||||
|
||||
public class Response_Verifyresult : CommonPacketResponse
|
||||
{
|
||||
public Data? data { get; set; }
|
||||
|
||||
#region InnerClass
|
||||
public class Data
|
||||
{
|
||||
public string? iftid { get; set; }
|
||||
public string? pcid{ get; set; }
|
||||
public string? ift_result{ get; set; }
|
||||
public string? server_result{ get; set; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
960
Projects/VPKI/VPKI/VPKI.Library/Services/CertificateService.cs
Normal file
960
Projects/VPKI/VPKI/VPKI.Library/Services/CertificateService.cs
Normal file
@ -0,0 +1,960 @@
|
||||
using Azure.Core;
|
||||
using DB.VPKI_DataDB;
|
||||
using DocumentFormat.OpenXml.Bibliography;
|
||||
using DocumentFormat.OpenXml.Office2016.Excel;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Newtonsoft.Json;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.IsisMtt.Ocsp;
|
||||
using Org.BouncyCastle.Asn1.Nist;
|
||||
using Org.BouncyCastle.Asn1.Ocsp;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using Org.BouncyCastle.Bcpg.OpenPgp;
|
||||
using Org.BouncyCastle.Cms;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Agreement;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Operators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Signers;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Math.EC;
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using Org.BouncyCastle.Pqc.Asn1;
|
||||
using Org.BouncyCastle.Pqc.Crypto;
|
||||
using Org.BouncyCastle.Pqc.Crypto.Lms;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Tls;
|
||||
using Org.BouncyCastle.Utilities.IO.Pem;
|
||||
using Org.BouncyCastle.X509;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Formats.Asn1;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Packet;
|
||||
|
||||
namespace VPKI.Library.Services
|
||||
{
|
||||
public class CertificateService : CommonService
|
||||
{
|
||||
private Dictionary<char, string> WordMap = new Dictionary<char, string>();
|
||||
|
||||
private readonly int PublicKey256Length = 66;
|
||||
private readonly int PublicKey256Offset = 25;
|
||||
|
||||
private readonly int PublickKey512Length = 134;
|
||||
private readonly int PublickKey512Offset = 24;
|
||||
|
||||
public CertificateService()
|
||||
{
|
||||
InitMapTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sha256 base64
|
||||
/// </summary>
|
||||
public string CreateCsr256(string dn, string publicKey)
|
||||
{
|
||||
string csrBase64 = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
using (ECDsa ecdsa = ECDsa.Create(System.Security.Cryptography.ECCurve.NamedCurves.nistP256))
|
||||
{
|
||||
//load public key
|
||||
var publicKeyPem = ConvertToPEM(Convert.FromBase64String(publicKey));
|
||||
Log4net.WriteLine($"Input Public Key (Base64): {publicKey}", LogType.Info);
|
||||
Log4net.WriteLine($"Input Public Key Pem (Base64): {publicKeyPem}", LogType.Debug);
|
||||
|
||||
//create csr
|
||||
X500DistinguishedName subjectName = new X500DistinguishedName(dn);
|
||||
var csrRequest = new System.Security.Cryptography.X509Certificates.CertificateRequest(subjectName, ecdsa, HashAlgorithmName.SHA256);
|
||||
|
||||
byte[] csrBytes = csrRequest.CreateSigningRequest();
|
||||
byte[] publicKeyArr = Convert.FromBase64String(publicKeyPem);
|
||||
|
||||
//input public key
|
||||
int startOffset = 0;
|
||||
for(int i = 2; i < csrBytes.Length - 2 ; i++)
|
||||
{
|
||||
if (csrBytes[i - 2] == 3 && csrBytes[i - 1] == 66 && csrBytes[i] == 0 && csrBytes[i + 1] == 4)
|
||||
{
|
||||
startOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < PublicKey256Length; i++)
|
||||
{
|
||||
csrBytes[i + startOffset] = publicKeyArr[i + PublicKey256Offset];
|
||||
}
|
||||
Asn1Sequence sequence = (Asn1Sequence)Asn1Object.FromByteArray(csrBytes);
|
||||
|
||||
var writer = new AsnWriter(AsnEncodingRules.DER);
|
||||
writer.WriteEncodedValue(sequence[0].GetEncoded());
|
||||
|
||||
//csr origin
|
||||
csrBase64 = Convert.ToBase64String(writer.Encode());
|
||||
|
||||
Log4net.WriteLine($"Origin CSR (Base64): {csrBase64}", LogType.Debug);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
|
||||
return csrBase64;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sha256 base64
|
||||
/// </summary>
|
||||
public string CreateCsr512(string dn, string publicKey)
|
||||
{
|
||||
string csrBase64 = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
using (ECDsa ecdsa = ECDsa.Create(System.Security.Cryptography.ECCurve.NamedCurves.nistP521))
|
||||
{
|
||||
//load public key
|
||||
var publicKeyPem = ConvertToPEM(Convert.FromBase64String(publicKey));
|
||||
Log4net.WriteLine($"Input Public Key (Base64): {publicKey}", LogType.Info);
|
||||
Log4net.WriteLine($"Input Public Key Pem (Base64): {publicKeyPem}", LogType.Debug);
|
||||
|
||||
//create csr
|
||||
X500DistinguishedName subjectName = new X500DistinguishedName(dn);
|
||||
var csrRequest = new System.Security.Cryptography.X509Certificates.CertificateRequest(subjectName, ecdsa, HashAlgorithmName.SHA256);
|
||||
|
||||
byte[] csrBytes = csrRequest.CreateSigningRequest();
|
||||
byte[] publicKeyArr = Convert.FromBase64String(publicKeyPem);
|
||||
|
||||
//input public key
|
||||
int startOffset = 0;
|
||||
for (int i = 2; i < csrBytes.Length - 2; i++)
|
||||
{
|
||||
if (csrBytes[i - 2] == 129 && csrBytes[i - 1] == 134 && csrBytes[i] == 0 && csrBytes[i + 1] == 4)
|
||||
{
|
||||
startOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < PublickKey512Length; i++)
|
||||
{
|
||||
csrBytes[i + startOffset] = publicKeyArr[i + PublickKey512Offset];
|
||||
}
|
||||
|
||||
Asn1Sequence sequence = (Asn1Sequence)Asn1Object.FromByteArray(csrBytes);
|
||||
|
||||
var writer = new AsnWriter(AsnEncodingRules.DER);
|
||||
writer.WriteEncodedValue(sequence[0].GetEncoded());
|
||||
//csr origin
|
||||
csrBase64 = Convert.ToBase64String(writer.Encode());
|
||||
|
||||
Log4net.WriteLine($"Origin CSR (Base64): {csrBase64}", LogType.Debug);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
|
||||
return csrBase64;
|
||||
}
|
||||
|
||||
public AsymmetricKeyParameter LoadPublicKey(string publicKeyPem)
|
||||
{
|
||||
using (StringReader reader = new StringReader(publicKeyPem))
|
||||
{
|
||||
var pemObje = (AsymmetricKeyParameter)new Org.BouncyCastle.OpenSsl.PemReader(reader).ReadObject();
|
||||
return pemObje;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pcid
|
||||
/// </summary>
|
||||
public string CreatePCID(Request_Tbscsr request, VpkiType vpkiType)
|
||||
{
|
||||
string pcid = string.Empty;
|
||||
|
||||
switch(vpkiType)
|
||||
{
|
||||
case VpkiType.prov_v1:
|
||||
pcid = CreatePCIDV1(request);
|
||||
break;
|
||||
case VpkiType.prov_cert:
|
||||
pcid = CreatePCIDV2Prov(request);
|
||||
break;
|
||||
case VpkiType.vehicle_cert:
|
||||
pcid = CreatePCIDV2Vehicle(request);
|
||||
break;
|
||||
}
|
||||
|
||||
return pcid;
|
||||
}
|
||||
|
||||
private string CreatePCIDV1(Request_Tbscsr request)
|
||||
{
|
||||
var wmi = $"{request?.cnInfo?.wmi}";
|
||||
var idType = $"{request?.cnInfo?.idType}";
|
||||
var supplierId = $"{request?.cnInfo?.supplierId}";
|
||||
|
||||
string strMacEnc = EncodeMacAddress($"{request?.cnInfo?.macaddr}");
|
||||
string strCvVal = ConvertNotation(strMacEnc);
|
||||
|
||||
string strIDVal = wmi + idType + supplierId + strCvVal;
|
||||
string strValueString = GeneratePCID(strIDVal);
|
||||
|
||||
return strValueString;
|
||||
}
|
||||
|
||||
private string CreatePCIDV2Prov(Request_Tbscsr request)
|
||||
{
|
||||
var wmi = $"{request?.cnInfo?.wmi}";
|
||||
var idType = $"{request?.cnInfo?.idType}";
|
||||
var supplierId = $"{request?.cnInfo?.supplierId}";
|
||||
|
||||
string strMacEnc = EncodeMacAddress($"{request?.cnInfo?.macaddr}");
|
||||
string strCvVal = ConvertNotation(strMacEnc);
|
||||
|
||||
string strSID = (Convert.ToInt32(supplierId) + 1).ToString();
|
||||
string strIDVal = wmi + idType + strSID + strCvVal;
|
||||
string strValueString = GeneratePCID(strIDVal);
|
||||
|
||||
return strValueString;
|
||||
}
|
||||
private string CreatePCIDV2Vehicle(Request_Tbscsr request)
|
||||
{
|
||||
var wmi = $"{request?.cnInfo?.wmi}";
|
||||
var idType = $"{request?.cnInfo?.idType}";
|
||||
var supplierId = $"{request?.cnInfo?.supplierId}";
|
||||
|
||||
string strMacEnc = EncodeMacAddress($"{request?.cnInfo?.macaddr}");
|
||||
string strCvVal = ConvertNotation(strMacEnc);
|
||||
|
||||
string strIDVal = wmi + idType + supplierId + "00" + strCvVal;
|
||||
string strValueString = GeneratePCID(strIDVal);
|
||||
|
||||
return strValueString;
|
||||
}
|
||||
|
||||
string GetChecksumString(string strInput)
|
||||
{
|
||||
List<long> vnCheckUnit = new List<long>();
|
||||
|
||||
for (int i = 0; i < strInput.Length; i++)
|
||||
{
|
||||
char cVal = strInput.ElementAt(i);
|
||||
int nVal = Convert.ToInt32(cVal.ToString());
|
||||
//Console.WriteLine(nVal);
|
||||
long nFactor = Convert.ToInt64(Math.Pow(2, i));
|
||||
|
||||
vnCheckUnit.Add(nVal * nFactor);
|
||||
}
|
||||
|
||||
long nSum = vnCheckUnit.Sum();
|
||||
|
||||
return nSum.ToString();
|
||||
}
|
||||
|
||||
string GeneratePCID(string strIDVal)
|
||||
{
|
||||
string strValueString = string.Empty;
|
||||
|
||||
foreach (char cVal in strIDVal.ToArray())
|
||||
strValueString += WordMap[cVal];
|
||||
|
||||
int nLengthStr = strValueString.Length;
|
||||
string strChecksumStr = GetChecksumString(strValueString);
|
||||
long nModuloCRC11 = Convert.ToInt64(strChecksumStr) % 11;
|
||||
|
||||
if (nModuloCRC11 == 10)
|
||||
strIDVal = strIDVal + "X";
|
||||
else
|
||||
strIDVal = strIDVal + nModuloCRC11.ToString();
|
||||
|
||||
return strIDVal;
|
||||
}
|
||||
|
||||
string ConvertNotation(string strHexValue)
|
||||
{
|
||||
string strOriginVal = strHexValue;
|
||||
string strNewVal = string.Empty;
|
||||
|
||||
if (strOriginVal.Length % 2 > 0)
|
||||
strOriginVal = "0" + strOriginVal;
|
||||
|
||||
List<string> vstrNewVals = new List<string>();
|
||||
|
||||
for (int i = 0; i < strOriginVal.Length - 1; i = i + 2)
|
||||
{
|
||||
string strHexUnit = strOriginVal.Substring(i, 2);
|
||||
int nVal = int.Parse(strHexUnit, System.Globalization.NumberStyles.HexNumber);
|
||||
string strTHVal = ConvertBase(nVal, 32);
|
||||
|
||||
vstrNewVals.Add(strTHVal);
|
||||
}
|
||||
|
||||
foreach (string strUnit in vstrNewVals)
|
||||
strNewVal += strUnit;
|
||||
|
||||
return strNewVal;
|
||||
}
|
||||
|
||||
private string ConvertBase(int nVal, int nBase)
|
||||
{
|
||||
string strVal = string.Empty;
|
||||
int k = nVal / nBase;
|
||||
int nRest = (nVal % nBase);
|
||||
|
||||
strVal = nRest.ToString() + strVal; // 나머지를 뒤로 이동
|
||||
|
||||
if (k >= nBase)
|
||||
ConvertBase(k, nBase); // 나눌게 있다면? 재귀함수
|
||||
else
|
||||
{
|
||||
if (nRest >= 10 && nRest < nBase)
|
||||
strVal = (Convert.ToChar(55 + nRest)).ToString();
|
||||
|
||||
strVal = k.ToString() + strVal; // 나눌게 없다면 ? 몫}
|
||||
}
|
||||
|
||||
return strVal;
|
||||
}
|
||||
|
||||
public string EncodeMacAddress(string strMacID)
|
||||
{
|
||||
List<byte> vnMacAddr = StringToByteArray(strMacID).ToList();
|
||||
List<byte> vnMacAddrEnc = (from nUnit in vnMacAddr let nEnc = Convert.ToByte(nUnit ^ 0xFF) select nEnc).ToList();
|
||||
|
||||
string strEncMacID = ByteArrayToHexString(vnMacAddrEnc.ToArray());
|
||||
|
||||
return strEncMacID;
|
||||
}
|
||||
|
||||
public string ByteArrayToHexString(byte[] bytearray)
|
||||
{
|
||||
string hex = BitConverter.ToString(bytearray);
|
||||
hex = hex.Replace("-", "");
|
||||
return hex;
|
||||
}
|
||||
|
||||
public byte[] StringToByteArray(string str)
|
||||
{
|
||||
int length = str.Length / 2; // 짝수일 경우만 고려함 --> 홀수의 경우 어떻게 자를지 고민해야 할듯(필요없을 수도)
|
||||
byte[] byteArray = new byte[length];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
string strUnit = str.Substring(i * 2, 2);
|
||||
byteArray[i] = Convert.ToByte(strUnit, 16);
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
void InitMapTable()
|
||||
{
|
||||
WordMap.Add('0', "0");
|
||||
WordMap.Add('1', "1");
|
||||
WordMap.Add('2', "2");
|
||||
WordMap.Add('3', "3");
|
||||
WordMap.Add('4', "4");
|
||||
WordMap.Add('5', "5");
|
||||
WordMap.Add('6', "6");
|
||||
WordMap.Add('7', "7");
|
||||
WordMap.Add('8', "8");
|
||||
WordMap.Add('9', "9");
|
||||
WordMap.Add('A', "10");
|
||||
WordMap.Add('B', "11");
|
||||
WordMap.Add('C', "12");
|
||||
WordMap.Add('D', "13");
|
||||
WordMap.Add('E', "14");
|
||||
WordMap.Add('F', "15");
|
||||
WordMap.Add('G', "16");
|
||||
WordMap.Add('H', "17");
|
||||
WordMap.Add('I', "18");
|
||||
WordMap.Add('J', "19");
|
||||
WordMap.Add('K', "20");
|
||||
WordMap.Add('L', "21");
|
||||
WordMap.Add('M', "22");
|
||||
WordMap.Add('N', "23");
|
||||
WordMap.Add('O', "24");
|
||||
WordMap.Add('P', "25");
|
||||
WordMap.Add('Q', "26");
|
||||
WordMap.Add('R', "27");
|
||||
WordMap.Add('S', "28");
|
||||
WordMap.Add('T', "29");
|
||||
WordMap.Add('U', "30");
|
||||
WordMap.Add('V', "31");
|
||||
WordMap.Add('W', "32");
|
||||
WordMap.Add('X', "33");
|
||||
WordMap.Add('Y', "34");
|
||||
WordMap.Add('Z', "35");
|
||||
}
|
||||
|
||||
#region MacAddress Decode
|
||||
private string DecodeMacAddress(string macAddress)
|
||||
{
|
||||
var decodeByteArray = HexStringToByteArray(macAddress);
|
||||
List<byte> vnMacAddrEnc =
|
||||
(from nUnit in decodeByteArray let nEnc = Convert.ToByte(nUnit ^ 0xFF) select nEnc).ToList();
|
||||
|
||||
string macAddressHexString = ByteArrayToHexString(vnMacAddrEnc.ToArray());
|
||||
|
||||
return macAddressHexString;
|
||||
}
|
||||
|
||||
private byte[] HexStringToByteArray(string str)
|
||||
{
|
||||
int length = str.Length / 2;
|
||||
byte[] byteArray = new byte[length];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
string strUnit = str.Substring(i * 2, 2);
|
||||
byteArray[i] = Convert.ToByte(strUnit, 16);
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BouncyCastle
|
||||
public AsymmetricCipherKeyPair GenerateBouncyCastleKeyPairECDH(string curveName)
|
||||
{
|
||||
ECKeyPairGenerator gen = new ECKeyPairGenerator("ECDSA");
|
||||
SecureRandom rndSecure = new SecureRandom();
|
||||
|
||||
X9ECParameters ecp = SecNamedCurves.GetByName($"{curveName}");
|
||||
ECDomainParameters ecSpec = new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H, ecp.GetSeed());
|
||||
ECKeyGenerationParameters ecgp = new ECKeyGenerationParameters(ecSpec, rndSecure);
|
||||
|
||||
gen.Init(ecgp);
|
||||
|
||||
AsymmetricCipherKeyPair eckp = gen.GenerateKeyPair();
|
||||
ECPublicKeyParameters ecPub = (ECPublicKeyParameters)eckp.Public;
|
||||
ECPrivateKeyParameters ecPri = (ECPrivateKeyParameters)eckp.Private;
|
||||
|
||||
byte[] publicKeyBytes = ecPub.Q.GetEncoded();
|
||||
byte[] privateKey = ecPri.D.ToByteArrayUnsigned();
|
||||
string strValue = GetKeyString(publicKeyBytes.ToList());
|
||||
|
||||
return eckp;
|
||||
}
|
||||
|
||||
public string GetKeyString(List<byte> vnData)
|
||||
{
|
||||
string strResult = string.Empty;
|
||||
|
||||
for (int i = 0; i < vnData.Count; i++)
|
||||
strResult += Convert.ToChar(vnData[i]).ToString();
|
||||
|
||||
int nLen = strResult.Length;
|
||||
|
||||
return strResult;
|
||||
}
|
||||
|
||||
public List<byte> GetKeyArray(string strKey)
|
||||
{
|
||||
List<byte> vstrResult = new List<byte>();
|
||||
|
||||
for (int i = 0; i < strKey.Length; i++)
|
||||
vstrResult.Add(Convert.ToByte(strKey[i]));
|
||||
|
||||
return vstrResult;
|
||||
}
|
||||
|
||||
public List<byte>? GetPublicKeyArrayBC(ECPublicKeyParameters? pubKey)
|
||||
{
|
||||
if (pubKey != null)
|
||||
{
|
||||
byte[] publicKeyBytes = pubKey.Q.GetEncoded();
|
||||
List<byte> vnX = pubKey.Q.AffineXCoord.GetEncoded().ToList();
|
||||
List<byte> vnY = pubKey.Q.AffineYCoord.GetEncoded().ToList();
|
||||
|
||||
return publicKeyBytes.ToList();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<byte>? GetPrivateKeyArrayBC(ECPrivateKeyParameters? ecPri)
|
||||
{
|
||||
if (ecPri != null)
|
||||
{
|
||||
byte[] privateKey = ecPri.D.ToByteArrayUnsigned();
|
||||
|
||||
return privateKey.ToList();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ECPublicKeyParameters? GetPublicKeyBC(AsymmetricCipherKeyPair? keyPair)
|
||||
{
|
||||
if (keyPair != null)
|
||||
{
|
||||
ECPublicKeyParameters ecPub = (ECPublicKeyParameters)keyPair.Public;
|
||||
return ecPub;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ECPrivateKeyParameters? GetPrivateKeyBC(AsymmetricCipherKeyPair? keyPair)
|
||||
{
|
||||
if (keyPair != null)
|
||||
{
|
||||
ECPrivateKeyParameters ecPri = (ECPrivateKeyParameters)keyPair.Private;
|
||||
return ecPri;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public string GetKeyBase64Encrypted(List<byte> keyValue)
|
||||
{
|
||||
List<byte> publicKey = keyValue;
|
||||
string strKey = GetKeyString(publicKey);
|
||||
int nOrgKeyLen = strKey.Length;
|
||||
|
||||
string strEnc64Val = Convert.ToBase64String(publicKey.ToArray());
|
||||
|
||||
return strEnc64Val;
|
||||
}
|
||||
|
||||
public List<byte> GetKeyDecrypted(string strEncKey)
|
||||
{
|
||||
string strResult = string.Empty;
|
||||
List<byte> vnStrDecKey = Convert.FromBase64String(strEncKey).ToList();
|
||||
string strStrDecKey = GetKeyString(vnStrDecKey);
|
||||
|
||||
int nOutLength = 0;
|
||||
List<byte> vnDerDecKey = AsnDecoder.ReadIntegerBytes(vnStrDecKey.ToArray(), AsnEncodingRules.DER, out nOutLength).ToArray().ToList();
|
||||
string strDerDecKey = GetKeyString(vnDerDecKey);
|
||||
|
||||
List<byte> derDecStr = GetKeyArray(strDerDecKey);
|
||||
|
||||
return derDecStr;
|
||||
}
|
||||
|
||||
public CsrHashedModel SignHashed02(string? csr, AsymmetricCipherKeyPair? keyPair)
|
||||
{
|
||||
CsrHashedModel hashedCsr = new CsrHashedModel();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(csr))
|
||||
return hashedCsr;
|
||||
|
||||
List<byte> vnRHashVal = Convert.FromBase64String(csr).ToList();
|
||||
List<byte> vnSignedHash = GetBouncyCastleECDSASignedHashKey(vnRHashVal, GetPrivateKeyBC(keyPair), ECDSAType.SHA256WITHECDSA);
|
||||
List<byte> vnDEREncVal = EncodeDERSignature_02(vnSignedHash);
|
||||
bool bVerfRst = VerifyHashBC(vnSignedHash, vnRHashVal, GetPublicKeyBC(keyPair), ECDSAType.SHA256WITHECDSA);
|
||||
|
||||
hashedCsr.SignedCsr = GetKeyBase64Encrypted(vnSignedHash);
|
||||
hashedCsr.EncodedSignedCsr = GetKeyBase64Encrypted(vnDEREncVal);
|
||||
hashedCsr.Verify = bVerfRst;
|
||||
|
||||
var decoded = DecodeDERSignature_02(vnDEREncVal);
|
||||
|
||||
return hashedCsr;
|
||||
}
|
||||
|
||||
public CsrHashedModel SignHashed20(string? csr, AsymmetricCipherKeyPair? keyPair)
|
||||
{
|
||||
CsrHashedModel hashedCsr = new CsrHashedModel();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(csr))
|
||||
return hashedCsr;
|
||||
|
||||
List<byte> vnRHashVal = Convert.FromBase64String(csr).ToList();
|
||||
List<byte> vnSignedHash = GetBouncyCastleECDSASignedHashKey(vnRHashVal, GetPrivateKeyBC(keyPair), ECDSAType.NONEWITHECDSA);
|
||||
List<byte> vnDEREncVal = EncodeDERSignature_20(vnSignedHash);
|
||||
bool bVerfRst = VerifyHashBC(vnSignedHash, vnRHashVal, GetPublicKeyBC(keyPair), ECDSAType.NONEWITHECDSA);
|
||||
|
||||
hashedCsr.SignedCsr = GetKeyBase64Encrypted(vnSignedHash);
|
||||
hashedCsr.EncodedSignedCsr = GetKeyBase64Encrypted(vnDEREncVal);
|
||||
hashedCsr.Verify = bVerfRst;
|
||||
|
||||
return hashedCsr;
|
||||
}
|
||||
|
||||
public List<byte> GetBouncyCastleECDSASignedHashKey(List<byte> vnRHashVal, ECPrivateKeyParameters? priKey, ECDSAType ecdsaType)
|
||||
{
|
||||
var signer = new ECDsaSigner();
|
||||
|
||||
signer.Init(true, priKey);
|
||||
|
||||
var anSign = signer.GenerateSignature(vnRHashVal.ToArray());
|
||||
byte[] signatureBytes = ConvertSignatureToByteArray(anSign);
|
||||
return signatureBytes.ToList();
|
||||
}
|
||||
|
||||
byte[] ConvertSignatureToByteArray(BigInteger[] signature)
|
||||
{
|
||||
// 서명은 r과 s 값으로 이루어져 있습니다.
|
||||
byte[] rBytes = signature[0].ToByteArrayUnsigned(); // r 값
|
||||
byte[] sBytes = signature[1].ToByteArrayUnsigned(); // s 값
|
||||
|
||||
// r과 s를 DER 형식으로 결합
|
||||
var seq = new DerSequence(new DerInteger(signature[0]), new DerInteger(signature[1]));
|
||||
|
||||
return seq.GetEncoded(); // DER 인코딩된 byte[] 반환
|
||||
}
|
||||
|
||||
public List<byte> EncodeDERSignature_02(List<byte> signature)
|
||||
{
|
||||
List<byte> resultData = new List<byte>();
|
||||
byte[] r = new byte[32];
|
||||
byte[] s = new byte[32];
|
||||
|
||||
int lengthOfR = signature[3];
|
||||
|
||||
int lengthOfS = signature[lengthOfR + 5];
|
||||
|
||||
if (lengthOfR == 33)
|
||||
r = signature.GetRange(5, lengthOfR - 1).ToArray();
|
||||
else if (lengthOfR == 32)
|
||||
r = signature.GetRange(4, lengthOfR).ToArray();
|
||||
else
|
||||
{
|
||||
List<byte> rawData = signature.GetRange(4, lengthOfR);
|
||||
|
||||
for (int nBI = 32 - lengthOfR; nBI < lengthOfR; nBI++)
|
||||
r[nBI] = rawData[nBI - 32 + lengthOfR];
|
||||
}
|
||||
|
||||
if (lengthOfS == 33)
|
||||
s = signature.GetRange(lengthOfR + 7, lengthOfS - 1).ToArray();
|
||||
else if (lengthOfS == 32)
|
||||
s = signature.GetRange(lengthOfR + 6, lengthOfS).ToArray();
|
||||
else
|
||||
{
|
||||
List<byte> rawData = signature.GetRange(lengthOfR + 6, lengthOfS);
|
||||
|
||||
for (int nBI = 32 - lengthOfS; nBI < lengthOfS; nBI++)
|
||||
s[nBI] = rawData[nBI - 32 + lengthOfS];
|
||||
}
|
||||
|
||||
resultData.AddRange(r);
|
||||
resultData.AddRange(s);
|
||||
|
||||
return resultData;
|
||||
}
|
||||
|
||||
public List<byte> DecodeDERSignature_02(List<byte> signature)
|
||||
{
|
||||
List<List<byte>> decodeData = new List<List<byte>>();
|
||||
|
||||
List<byte> r = signature.GetRange(0, 32);
|
||||
List<byte> s = signature.GetRange(32, 32);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
List<byte> caseData = new List<byte>();
|
||||
|
||||
//header 고정값 1자리
|
||||
caseData.Add(48);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
caseData.Add(68);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(32);
|
||||
caseData.AddRange(r);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(32);
|
||||
caseData.AddRange(s);
|
||||
}
|
||||
if (i == 1)
|
||||
{
|
||||
caseData.Add(69);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(32);
|
||||
caseData.AddRange(r);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(33);
|
||||
caseData.Add(0);
|
||||
caseData.AddRange(s);
|
||||
}
|
||||
if (i == 2)
|
||||
{
|
||||
caseData.Add(69);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(33);
|
||||
caseData.Add(0);
|
||||
caseData.AddRange(r);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(32);
|
||||
caseData.AddRange(s);
|
||||
}
|
||||
if (i == 3)
|
||||
{
|
||||
caseData.Add(70);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(33);
|
||||
caseData.Add(0);
|
||||
caseData.AddRange(r);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(33);
|
||||
caseData.Add(0);
|
||||
caseData.AddRange(s);
|
||||
|
||||
|
||||
}
|
||||
decodeData.Add(caseData.ToList());
|
||||
}
|
||||
|
||||
return decodeData.Last();
|
||||
}
|
||||
|
||||
public bool VerifyHashBC(List<byte> signedHash, List<byte> unsignedHash, ECPublicKeyParameters? publicKey, ECDSAType ecdsaType)
|
||||
{
|
||||
ISigner signer = SignerUtilities.GetSigner($"{ecdsaType.ToString()}");
|
||||
List<byte> vnRHashVal = unsignedHash;
|
||||
|
||||
signer.Init(false, publicKey);
|
||||
signer.BlockUpdate(vnRHashVal.ToArray(), 0, vnRHashVal.Count);
|
||||
|
||||
bool bResult = signer.VerifySignature(signedHash.ToArray());
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
public List<byte> GetKeyBase64Decrypted(string strKey)
|
||||
{
|
||||
List<byte> vnKey = Convert.FromBase64String(strKey).ToList();
|
||||
|
||||
return vnKey;
|
||||
}
|
||||
|
||||
public List<byte> EncodeDERSignature_20(List<byte> signature)
|
||||
{
|
||||
List<byte> resultData = new List<byte>();
|
||||
List<byte> r = new List<byte>(66);
|
||||
List<byte> s = new List<byte>(66);
|
||||
|
||||
int lengthOfR = signature[4];
|
||||
int lengthOfS = signature[lengthOfR + 6];
|
||||
|
||||
if (lengthOfR == 66)
|
||||
r.AddRange(signature.GetRange(5, lengthOfR));
|
||||
else if (lengthOfR == 65)
|
||||
{
|
||||
r.Add(00);
|
||||
r.AddRange(signature.GetRange(5, lengthOfR));
|
||||
}
|
||||
|
||||
|
||||
if (lengthOfS == 66)
|
||||
s.AddRange(signature.GetRange(lengthOfR + 7, lengthOfS));
|
||||
else if (lengthOfS == 65)
|
||||
{
|
||||
s.Add(00);
|
||||
s.AddRange(signature.GetRange(lengthOfR + 7, lengthOfS));
|
||||
}
|
||||
|
||||
resultData.AddRange(r);
|
||||
resultData.AddRange(s);
|
||||
|
||||
return resultData;
|
||||
}
|
||||
|
||||
public List<byte> DecodeDERSignature_20(List<byte> signature)
|
||||
{
|
||||
List<List<byte>> decodeData = new List<List<byte>>();
|
||||
|
||||
List<byte> r = signature.GetRange(0, 66);
|
||||
List<byte> s = signature.GetRange(66, 66);
|
||||
|
||||
for(int i = 0 ; i < 4 ; i++)
|
||||
{
|
||||
List<byte> caseData = new List<byte>();
|
||||
|
||||
//header 고정값 2자리
|
||||
caseData.Add(48);
|
||||
caseData.Add(129);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
caseData.Add(134);
|
||||
caseData.Add(2);
|
||||
caseData.Add(65);
|
||||
caseData.AddRange(r.GetRange(1, 65));
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(65);
|
||||
caseData.AddRange(s.GetRange(1, 65));
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
caseData.Add(135);
|
||||
caseData.Add(2);
|
||||
caseData.Add(65);
|
||||
caseData.AddRange(r.GetRange(1,65));
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(66);
|
||||
caseData.AddRange(s);
|
||||
}
|
||||
else if(i == 2)
|
||||
{
|
||||
caseData.Add(135);
|
||||
caseData.Add(2);
|
||||
caseData.Add(66);
|
||||
caseData.AddRange(r);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(65);
|
||||
caseData.AddRange(s.GetRange(1,65));
|
||||
}
|
||||
else if (i == 3)
|
||||
{
|
||||
caseData.Add(136);
|
||||
caseData.Add(2);
|
||||
caseData.Add(66);
|
||||
caseData.AddRange(r);
|
||||
|
||||
caseData.Add(2);
|
||||
caseData.Add(66);
|
||||
caseData.AddRange(s);
|
||||
}
|
||||
|
||||
decodeData.Add(caseData);
|
||||
}
|
||||
|
||||
return decodeData.Last();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CRC16
|
||||
private ushort[] CRCTable =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
//==========================================================================//
|
||||
|
||||
public List<byte> MakeCRC16_CCIT(List<byte> bytes, int ilen)
|
||||
{
|
||||
int icrc = 0xFFFF;
|
||||
|
||||
for (int i = 0; i < ilen; i++)
|
||||
{
|
||||
icrc = (ushort)((icrc << 8) ^ CRCTable[((icrc >> 8) ^ (bytes[i]) & 0xFF)]);
|
||||
}
|
||||
|
||||
List<byte> ret = BitConverter.GetBytes(icrc).ToList();
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public string ConvertToPEM(byte[] rawPublicKey)
|
||||
{
|
||||
if (rawPublicKey.Count() > 65)
|
||||
{
|
||||
// ECDSA 공개키를 X.509 형식으로 변환
|
||||
var ecParameters = new ECParameters
|
||||
{
|
||||
Q = new System.Security.Cryptography.ECPoint
|
||||
{
|
||||
X = rawPublicKey.Skip(1).Take(66).ToArray(), // X 좌표 (66바이트)
|
||||
Y = rawPublicKey.Skip(67).Take(132).ToArray() // Y 좌표 (66바이트)
|
||||
},
|
||||
Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP521
|
||||
};
|
||||
|
||||
using (var ecdsa = ECDsa.Create(ecParameters))
|
||||
{
|
||||
// 공개키를 X.509 형식으로 변환
|
||||
byte[] x509PublicKey = ecdsa.ExportSubjectPublicKeyInfo();
|
||||
|
||||
// PEM 형식으로 변환
|
||||
return Convert.ToBase64String(x509PublicKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ECDSA 공개키를 X.509 형식으로 변환
|
||||
var ecParameters = new ECParameters
|
||||
{
|
||||
Q = new System.Security.Cryptography.ECPoint
|
||||
{
|
||||
X = rawPublicKey.Skip(1).Take(32).ToArray(), // X 좌표 (32바이트)
|
||||
Y = rawPublicKey.Skip(33).Take(32).ToArray() // Y 좌표 (32바이트)
|
||||
},
|
||||
Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP256
|
||||
};
|
||||
|
||||
using (var ecdsa = ECDsa.Create(ecParameters))
|
||||
{
|
||||
// 공개키를 X.509 형식으로 변환
|
||||
byte[] x509PublicKey = ecdsa.ExportSubjectPublicKeyInfo();
|
||||
|
||||
// PEM 형식으로 변환
|
||||
return Convert.ToBase64String(x509PublicKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Projects/VPKI/VPKI/VPKI.Library/Services/CommonService.cs
Normal file
18
Projects/VPKI/VPKI/VPKI.Library/Services/CommonService.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Services
|
||||
{
|
||||
public class CommonService
|
||||
{
|
||||
public CommonService()
|
||||
{
|
||||
}
|
||||
|
||||
}//end class
|
||||
}//end namespace
|
||||
39
Projects/VPKI/VPKI/VPKI.Library/Services/ConfigService.cs
Normal file
39
Projects/VPKI/VPKI/VPKI.Library/Services/ConfigService.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPKI.Library.Config;
|
||||
|
||||
namespace VPKI.Library.Services
|
||||
{
|
||||
public class ConfigService<T> where T : WebCommonConfig
|
||||
{
|
||||
public static T? Config { get; set; }
|
||||
|
||||
public bool OpenConfig(string path)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
try
|
||||
{
|
||||
string clientConfigJson = File.ReadAllText(path);
|
||||
Config = JsonConvert.DeserializeObject<T>(clientConfigJson);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Config Init Error");
|
||||
Console.WriteLine(e.Message);
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public T? GetConfig()
|
||||
{
|
||||
return Config;
|
||||
}
|
||||
}
|
||||
}
|
||||
112
Projects/VPKI/VPKI/VPKI.Library/Services/HttpService.cs
Normal file
112
Projects/VPKI/VPKI/VPKI.Library/Services/HttpService.cs
Normal file
@ -0,0 +1,112 @@
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace VPKI.Library.Services
|
||||
{
|
||||
public class HttpService : CommonService
|
||||
{
|
||||
public HttpService()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PostJsonAsync
|
||||
/// </summary>
|
||||
/// <param name="url">https://127.0.0.1:443</param>
|
||||
/// <param name="timeOutSeconds">Range 5~30 secconds</param>
|
||||
public virtual async Task<RESPONSE?> PostJsonAsync<REQUEST, RESPONSE>(string url, REQUEST request, short timeOutSeconds = 5) where REQUEST : class where RESPONSE : class
|
||||
{
|
||||
RESPONSE? response = default(RESPONSE);
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
int retry = 0;
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
try
|
||||
{
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{url}");
|
||||
|
||||
Log4net.WriteLine($"[POST] Request({guid})::{url}{Environment.NewLine}{request?.ToJson()}", LogType.Warn);
|
||||
|
||||
DateTime requestTime = DateTime.Now;
|
||||
var res = await httpClient.PostAsJsonAsync(url, request);
|
||||
response = await res.Content.ReadFromJsonAsync<RESPONSE>();
|
||||
|
||||
Log4net.WriteLine($"[POST] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}{Environment.NewLine}{response?.ToJson()}", LogType.Warn);
|
||||
break;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
retry += 1;
|
||||
}
|
||||
|
||||
if (retry > 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetJsonAsnyc
|
||||
/// </summary>
|
||||
/// <param name="url">https://127.0.0.1:443</param>
|
||||
/// <param name="timeOutSeconds">Range 5~30 secconds</param>
|
||||
public virtual async Task<RESPONSE?> GetJsonAsync<RESPONSE>(string url, short timeOutSeconds = 10) where RESPONSE : class
|
||||
{
|
||||
RESPONSE? response = default(RESPONSE);
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{url}");
|
||||
|
||||
Log4net.WriteLine($"[GET] Request({guid})::{url}", LogType.Warn);
|
||||
|
||||
DateTime requestTime = DateTime.Now;
|
||||
response = await httpClient.GetFromJsonAsync<RESPONSE>(url);
|
||||
|
||||
Log4net.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogType.Warn);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
protected HttpClientHandler GetClientHandler()
|
||||
{
|
||||
HttpClientHandler clientHandler = new HttpClientHandler();
|
||||
clientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
return clientHandler;
|
||||
}
|
||||
|
||||
protected short SetTimeout(short timeOutSeconds)
|
||||
{
|
||||
short timeoutMin = 5;
|
||||
short timeoutMax = 30;
|
||||
|
||||
timeOutSeconds = Math.Clamp(timeOutSeconds, timeoutMin, timeoutMax);
|
||||
|
||||
return timeOutSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
139
Projects/VPKI/VPKI/VPKI.Library/Static/Document4net.cs
Normal file
139
Projects/VPKI/VPKI/VPKI.Library/Static/Document4net.cs
Normal file
@ -0,0 +1,139 @@
|
||||
using DocumentFormat.OpenXml;
|
||||
using DocumentFormat.OpenXml.Packaging;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPKI.Library.Static
|
||||
{
|
||||
public static class Document4net
|
||||
{
|
||||
public static List<string> ConvertToCsvFile<T>(this IEnumerable<T> data)
|
||||
{
|
||||
string separator = ",";
|
||||
List<string> result = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
Type t = typeof(T);
|
||||
var properties = t.GetProperties();
|
||||
|
||||
//header
|
||||
List<string> headers = GetHeader(properties);
|
||||
result.Add(string.Join(separator, headers.ToArray()));
|
||||
//data
|
||||
|
||||
foreach (var d in data)
|
||||
{
|
||||
var getValues = GetValue(d);
|
||||
string rsultValue = string.Empty;
|
||||
|
||||
foreach (var h in headers)
|
||||
{
|
||||
bool isFindHeader = false;
|
||||
foreach(var v in getValues)
|
||||
{
|
||||
if (v.Header == h)
|
||||
{
|
||||
isFindHeader = true;
|
||||
rsultValue += $"{v.Value}{separator}";//string.Join(separator, v.Value);
|
||||
break;
|
||||
//result.Add(string.Join(separator, getValues.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
if(isFindHeader == false)
|
||||
rsultValue += $"{separator}";
|
||||
}
|
||||
|
||||
result.Add(rsultValue);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log4net.WriteLine("Document4net ExportToCsv Exception",LogType.Error);
|
||||
Log4net.WriteLine(ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<string> GetHeader(PropertyInfo[] propertyInfo)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
|
||||
foreach(var prop in propertyInfo)
|
||||
{
|
||||
if (prop != null)
|
||||
{
|
||||
//객체일때 재귀
|
||||
if (prop.PropertyType!.IsClass == true && prop.PropertyType.Name.ToLower().Contains("string") == false)
|
||||
{
|
||||
result.AddRange(GetHeader(prop.PropertyType.GetProperties()));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add($"{prop.DeclaringType!.Name}.{prop.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<CSV> GetValue<T>(T data)
|
||||
{
|
||||
List<CSV> result = new List<CSV>();
|
||||
|
||||
if(data != null)
|
||||
{
|
||||
foreach (var prop in data.GetType().GetProperties())
|
||||
{
|
||||
//객체일때 재귀
|
||||
if (prop.PropertyType!.IsClass == true && prop.PropertyType.Name.ToLower().Contains("string") == false)
|
||||
{
|
||||
result.AddRange(GetValue(prop.GetValue(data)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prop.PropertyType == typeof(DateTime))
|
||||
{
|
||||
var datetTime = Convert.ToDateTime(prop!.GetValue(data));
|
||||
result.Add(new CSV
|
||||
{
|
||||
Header = $"{prop.DeclaringType!.Name}.{prop.Name}",
|
||||
Value = $"\"{datetTime.ToString("yyyy-MM-dd HH:mm:ss")}\"".Replace("\r", "").Replace("\n", "")
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new CSV
|
||||
{
|
||||
Header = $"{prop.DeclaringType!.Name}.{prop.Name}",
|
||||
Value = $"\"{prop!.GetValue(data)}\"".Replace("\r", "").Replace("\n", "")
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class CSV
|
||||
{
|
||||
public string? Header { get; set; }
|
||||
public string? Value { get; set; }
|
||||
}
|
||||
}
|
||||
45
Projects/VPKI/VPKI/VPKI.Library/VPKI.Library.csproj
Normal file
45
Projects/VPKI/VPKI/VPKI.Library/VPKI.Library.csproj
Normal file
@ -0,0 +1,45 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" />
|
||||
<PackageReference Include="DocumentFormat.OpenXml" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VPKI.Library.DB\VPKI.Library.DB.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="SystemX.Core">
|
||||
<HintPath>..\..\..\DLL\SystemX.Core.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
12
Projects/VPKI/VPKI/VPKI.Web.Api/.config/dotnet-tools.json
Normal file
12
Projects/VPKI/VPKI/VPKI.Web.Api/.config/dotnet-tools.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "8.0.10",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
151
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/AuthController.cs
Normal file
151
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/AuthController.cs
Normal file
@ -0,0 +1,151 @@
|
||||
using Azure;
|
||||
using Azure.Core;
|
||||
using DB.VPKI_AccountDB;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Model.Auth;
|
||||
using VPKI.Library.Services;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
[Tags("Auth")]
|
||||
[Route("api/auth")]
|
||||
[ApiController]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public class AuthController : CommonController
|
||||
{
|
||||
private readonly AuthService _authService;
|
||||
|
||||
public AuthController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor,
|
||||
AuthService authService)
|
||||
: base(serviceProvider, httpContextAccessor)
|
||||
{
|
||||
_authService = authService;
|
||||
}
|
||||
|
||||
[HttpPost("regisger")]
|
||||
public async Task<IResult> Register([FromBody] RegisterModel request)
|
||||
{
|
||||
Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.Debug);
|
||||
|
||||
RegisterResponseModel response = new RegisterResponseModel();
|
||||
|
||||
if (request?.UserID != null && request?.Password != null)
|
||||
{
|
||||
response = await _authService.CreateUser(request);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
public async Task<IResult> Login([FromBody] LoginModel request)
|
||||
{
|
||||
Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.Debug);
|
||||
|
||||
LoginResponseModel response = new LoginResponseModel();
|
||||
response.UserID = request.UserID;
|
||||
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
|
||||
|
||||
if (request.UserID != null && request.Password != null)
|
||||
{
|
||||
response = await _authService.SelectUser(request);
|
||||
|
||||
if (response.EC == ERROR_CODE.EC_OK)
|
||||
{
|
||||
double convertExpires = Convert.ToDouble(_configService?.GetConfig()?.Auth?.accessTokenExpires);
|
||||
|
||||
response.AccessToken = GenerateJwtToken(response);
|
||||
response.AccessTokenExpired = DateTime.UtcNow.AddMinutes(convertExpires).ToUnixTime();
|
||||
|
||||
response.RefreshToken = GenerateJwtToken(response, true);
|
||||
}
|
||||
|
||||
await _authService.UpdateLoginInfo(request, response.RefreshToken);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
[HttpPost("logout")]
|
||||
public async Task<IResult> Logout([FromBody] LogoutModel request)
|
||||
{
|
||||
Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request Auth"), LogType.Debug);
|
||||
|
||||
var response = _authService.LogoutUser(request);
|
||||
await Task.CompletedTask;
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response Auth"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpPost("validate")]
|
||||
public ActionResult<string> Validate([FromBody] string authToken)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
private TokenValidationParameters GetValidationParameters()
|
||||
{
|
||||
return new TokenValidationParameters()
|
||||
{
|
||||
ValidateLifetime = true,
|
||||
ValidateAudience = true,
|
||||
ValidateIssuer = true,
|
||||
ValidIssuer = $"{_configService?.GetConfig()?.Auth?.issuer}",
|
||||
ValidAudience = $"{_configService?.GetConfig()?.Auth?.issuer}",
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes($"{_configService?.GetConfig()?.Auth?.accessTokenSecret}"))
|
||||
};
|
||||
}
|
||||
|
||||
private string GenerateJwtToken(LoginResponseModel loginResponseModel, bool isRefreshToken = false)
|
||||
{
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, $"{loginResponseModel.UserID}"),
|
||||
new Claim(ClaimTypes.Role, $"{loginResponseModel.RoleName}"),
|
||||
};
|
||||
|
||||
string secret = $"{_configService?.GetConfig()?.Auth?.accessTokenSecret}";
|
||||
double convertExpires = Convert.ToDouble(_configService?.GetConfig()?.Auth?.accessTokenExpires);
|
||||
if (isRefreshToken == true)
|
||||
{
|
||||
secret = $"{_configService?.GetConfig()?.Auth?.refreshTokenSecret}";
|
||||
convertExpires = Convert.ToDouble(_configService?.GetConfig()?.Auth?.refreshTokenExpires);
|
||||
}
|
||||
|
||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
|
||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: $"{_configService?.GetConfig()?.Auth?.issuer}",
|
||||
audience: $"{_configService?.GetConfig()?.Auth?.audience}",
|
||||
claims: claims,
|
||||
expires: DateTime.UtcNow.AddMinutes(convertExpires),
|
||||
signingCredentials: creds
|
||||
);
|
||||
|
||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
106
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/CommonController.cs
Normal file
106
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/CommonController.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Newtonsoft.Json;
|
||||
using System.Runtime.CompilerServices;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
public class CommonController
|
||||
{
|
||||
public readonly IServiceProvider _serviceProvider;
|
||||
public readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public readonly ConfigService<WebApiConfig>? _configService;
|
||||
|
||||
protected static Guid guid { get; private set; } = Guid.NewGuid();
|
||||
|
||||
public CommonController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
//provider
|
||||
_serviceProvider = serviceProvider;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
||||
//service
|
||||
_configService = _serviceProvider.GetService<ConfigService<WebApiConfig>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request 클라이언트 IP
|
||||
/// </summary>
|
||||
protected virtual string? GetClientIP()
|
||||
{
|
||||
return _httpContextAccessor?.HttpContext?.Connection?.RemoteIpAddress?.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request 클라이언트 Url
|
||||
/// </summary>
|
||||
protected virtual string? GetRequestUrl()
|
||||
{
|
||||
return _httpContextAccessor?.HttpContext?.Request?.Path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request 클라이언트 method: [GET] or [POST]
|
||||
/// </summary>
|
||||
protected virtual string? GetRequestMethod()
|
||||
{
|
||||
return _httpContextAccessor?.HttpContext?.Request?.Method;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 Action(함수) 이름 가져오기
|
||||
/// </summary>
|
||||
protected virtual string GetMethodName([CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
return callerMemberName;
|
||||
}
|
||||
|
||||
#region System Log
|
||||
//request log
|
||||
protected virtual LogModel GetRequestLog([CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
return new LogModel
|
||||
{
|
||||
ClientIP = $"{GetClientIP()}",
|
||||
Method = $"{GetRequestMethod()}",
|
||||
RequestUrl = $"{GetRequestUrl()}",
|
||||
Action = $"{callerMemberName}",
|
||||
Body = null,
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual LogModel GetRequestLog<T>(T fromBody, [CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
var requestLog = GetRequestLog(callerMemberName);
|
||||
requestLog.Body = fromBody;
|
||||
|
||||
return requestLog;
|
||||
}
|
||||
|
||||
//response log
|
||||
protected virtual LogModel GetResponseLog([CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
return new LogModel
|
||||
{
|
||||
ClientIP = $"{GetClientIP()}",
|
||||
Method = $"{GetRequestMethod()}",
|
||||
RequestUrl = $"{GetRequestUrl()}",
|
||||
Action = $"{callerMemberName}",
|
||||
Body = null,
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual LogModel GetResponseLog<T>(T fromBody, [CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
var responseLog = GetResponseLog(callerMemberName);
|
||||
responseLog.Body = fromBody;
|
||||
|
||||
return responseLog;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
[Route("api/user/[Action]")]
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public class UserController : CommonController
|
||||
{
|
||||
private readonly UserService _userService;
|
||||
|
||||
public UserController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor,
|
||||
UserService userService)
|
||||
: base(serviceProvider, httpContextAccessor)
|
||||
{
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IEnumerable<UserModel>> GetAllUser(string url = "")
|
||||
{
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request Auth"), LogType.Debug);
|
||||
var response = await _userService.GetAllUsers();
|
||||
|
||||
Log4net.WriteLine(GetRequestLog(response).LogModelToString("Response Auth"), LogType.Debug);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<UserModel> UpdateUser(UserModel user)
|
||||
{
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request Auth"), LogType.Debug);
|
||||
var response = await _userService.UpdateUser(user);
|
||||
|
||||
Log4net.WriteLine(GetRequestLog(response).LogModelToString("Response Auth"), LogType.Debug);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
public class VPKIBaseController : CommonController
|
||||
{
|
||||
public VPKIBaseController(IServiceProvider serviceProvider, IHttpContextAccessor _httpContextAccessor)
|
||||
:base(serviceProvider, _httpContextAccessor)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// tbscsr데이터 조회 (ISO15118-2)
|
||||
/// </summary>
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("history")]
|
||||
public async Task<IResult> TbscsrHistory(DateTime startDate, DateTime endDate)
|
||||
{
|
||||
List<CertificateHistoryModel> response = new List<CertificateHistoryModel>();
|
||||
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.Debug);
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate));
|
||||
}
|
||||
|
||||
long min = 0;
|
||||
if(response.Count > 0)
|
||||
{
|
||||
response.Min(x => x!.TTbscsr!.CCuid);
|
||||
}
|
||||
|
||||
Log4net.WriteLine($"Ressponse::Start CCUID:{min}, Count:{response.Count}", LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// tbscsr데이터 조회 (ISO15118-2)
|
||||
/// </summary>
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("history/ccuid")]
|
||||
public async Task<IResult> TbscsrHistoryByCcuid(long ccuid = 0)
|
||||
{
|
||||
CertificateHistoryModel response = new CertificateHistoryModel();
|
||||
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.Debug);
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.History(ccuid);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// prov
|
||||
/// </summary>
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("certificate/GetProv")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> GetProv(VpkiType vpkiType)
|
||||
{
|
||||
string response = string.Empty;
|
||||
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.Debug);
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
response = service.GetSubCA(vpkiType, false);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// certificate info
|
||||
/// </summary>
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("certificate/GetCertificateInfo")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> GetCertificateInfo(long ccuid = 0)
|
||||
{
|
||||
string response = string.Empty;
|
||||
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.Debug);
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.GetCertificateInfo(ccuid);
|
||||
}
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// certificate info
|
||||
/// </summary>
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("certificate/ocsp")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> Ocsp(long ccuid = 0)
|
||||
{
|
||||
string response = string.Empty;
|
||||
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.Debug);
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.Ocsp(ccuid);
|
||||
}
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString("Response"), LogType.Debug);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
143
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIv1_Controller.cs
Normal file
143
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIv1_Controller.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using DB.VPKI_DataDB;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.OpenApi.Validations.Rules;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Packet;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
[Tags("VPKI API v1")]
|
||||
[ApiController()]
|
||||
[Route("api/v1")]
|
||||
public class VPKIv1_Controller : VPKIBaseController
|
||||
{
|
||||
public VPKIv1_Controller(IServiceProvider serviceProvider, IHttpContextAccessor _httpContextAccessor)
|
||||
: base(serviceProvider, _httpContextAccessor)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CSR 생성 요청 (ISO15118-2)
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("tbscsr")]
|
||||
public async Task<IResult> Tbscsr([FromBody] Request_Tbscsr _request)
|
||||
{
|
||||
Response_Tbscsr response = new Response_Tbscsr();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(_request).LogModelToString($"Request ({guid})"), LogType.Info);
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_02Service>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.RequestTbscsr(_request);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"), LogType.Info);
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 발급 요청 (ISO15118-2)
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("certificate")]
|
||||
public async Task<IResult> Certificate([FromBody] Request_Certificate _request)
|
||||
{
|
||||
Response_Certificate response = new Response_Certificate();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(_request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_02Service>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.RequestCertificate(_request);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 검증 결과 전송 (ISO15118-2)
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("verifyresult")]
|
||||
public async Task<IResult> Verifyresult([FromBody] Request_Verifyresult request)
|
||||
{
|
||||
Response_Verifyresult response = new Response_Verifyresult();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_02Service>();
|
||||
if(service != null)
|
||||
{
|
||||
response = await service.RequestVerifyresult(request);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 재발급 (ISO15118-2)
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("reissue")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> Reissue([FromBody] Request_Certificate request)
|
||||
{
|
||||
//Response_Certificate response = new Response_Certificate();
|
||||
//Log4net.WriteLine(GetRequestLog(request).LogModelToString("Request"));
|
||||
|
||||
//var service = _serviceProvider.GetService<ISO15118_02Service>();
|
||||
//if (service != null)
|
||||
//{
|
||||
// response = await service.RequestCertificateReissue(request);
|
||||
//}
|
||||
|
||||
//Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
//return Results.Ok(response);
|
||||
await Task.CompletedTask;
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 폐기 (ISO15118-2)
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Route("revoke")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> Revoke([FromBody] Request_CertificateRevokeOEM request)
|
||||
{
|
||||
//Response_CertificateRevokeOEM response = new Response_CertificateRevokeOEM();
|
||||
|
||||
//Guid guid = Guid.NewGuid();
|
||||
//Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
//var service = _serviceProvider.GetService<ISO15118_02Service>();
|
||||
//if (service != null)
|
||||
//{
|
||||
// response = await service.RequestCertificateRevoke(request);
|
||||
//}
|
||||
|
||||
//Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
//return Results.Ok(response);
|
||||
await Task.CompletedTask;
|
||||
return Results.NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
275
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIv2_Controller.cs
Normal file
275
Projects/VPKI/VPKI/VPKI.Web.Api/Controllers/VPKIv2_Controller.cs
Normal file
@ -0,0 +1,275 @@
|
||||
using Azure;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Packet;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
[ApiController()]
|
||||
[Route("api/v2")]
|
||||
public class VPKIv2_Controller : VPKIBaseController
|
||||
{
|
||||
public VPKIv2_Controller(IServiceProvider serviceProvider, IHttpContextAccessor _httpContextAccessor)
|
||||
: base(serviceProvider, _httpContextAccessor)
|
||||
{
|
||||
}
|
||||
|
||||
#region prov
|
||||
/// <summary>
|
||||
/// CSR 생성 요청 (ISO15118-20) prov
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 prov")]
|
||||
[HttpPost]
|
||||
[Route("prov/tbscsr")]
|
||||
public async Task<IResult> ProvTbscsr([FromBody] Request_Tbscsr _request)
|
||||
{
|
||||
Response_Tbscsr response = new Response_Tbscsr();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(_request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
if(service != null)
|
||||
{
|
||||
response = await service.RequestTbscsr(_request, Library.Enums.VpkiType.prov_cert);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 발급 요청 (ISO15118-20) prov
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 prov")]
|
||||
[HttpPost]
|
||||
[Route("prov/certificate")]
|
||||
public async Task<IResult> ProvCertificate([FromBody] Request_Certificate _request)
|
||||
{
|
||||
Response_Certificate response = new Response_Certificate();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(_request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
if(service != null)
|
||||
{
|
||||
response = await service.RequestCertificate(_request, Library.Enums.VpkiType.prov_cert);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 검증 결과 전송 (ISO15118-20) prov
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 prov")]
|
||||
[HttpPost]
|
||||
[Route("prov/verifyresult")]
|
||||
public async Task<IResult> ProvVerifyresult([FromBody] Request_Verifyresult request)
|
||||
{
|
||||
Response_Verifyresult response = new Response_Verifyresult();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.RequestVerifyresult(request);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 재발급 (ISO15118-20)
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 prov")]
|
||||
[HttpPost]
|
||||
[Route("prov/reissue")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> ProvReissue([FromBody] Request_Certificate request)
|
||||
{
|
||||
//Response_Certificate response = new Response_Certificate();
|
||||
|
||||
//Guid guid = Guid.NewGuid();
|
||||
//Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
//var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
//if (service != null)
|
||||
//{
|
||||
// response = await service.RequestCertificateReissue(request, Library.Enums.VpkiType.prov_cert);
|
||||
//}
|
||||
|
||||
//Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
//return Results.Ok(response);
|
||||
await Task.CompletedTask;
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 폐기 (ISO15118-20)
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 prov")]
|
||||
[HttpPost]
|
||||
[Route("prov/revoke")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> ProvRevoke([FromBody] Request_CertificateRevokeOEM request)
|
||||
{
|
||||
//Response_CertificateRevokeOEM response = new Response_CertificateRevokeOEM();
|
||||
|
||||
//Guid guid = Guid.NewGuid();
|
||||
//Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
//var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
//if (service != null)
|
||||
//{
|
||||
// response = await service.RequestCertificateRevoke(request, Library.Enums.VpkiType.prov_cert);
|
||||
//}
|
||||
|
||||
//Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
//return Results.Ok(response);
|
||||
await Task.CompletedTask;
|
||||
return Results.NotFound();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region vehicle
|
||||
/// <summary>
|
||||
/// CSR 생성 요청 (ISO15118-20) vehicle
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 vehicle")]
|
||||
[HttpPost]
|
||||
[Route("vehicle/tbscsr")]
|
||||
public async Task<IResult> VehicleTbscsr([FromBody] Request_Tbscsr _request)
|
||||
{
|
||||
Response_Tbscsr response = new Response_Tbscsr();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(_request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.RequestTbscsr(_request, Library.Enums.VpkiType.vehicle_cert);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 발급 요청 (ISO15118-20) vehicle
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 vehicle")]
|
||||
[HttpPost]
|
||||
[Route("vehicle/certificate")]
|
||||
public async Task<IResult> VehicleCertificate([FromBody] Request_Certificate _request)
|
||||
{
|
||||
Response_Certificate response = new Response_Certificate();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(_request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.RequestCertificate(_request, Library.Enums.VpkiType.vehicle_cert);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 검증 결과 전송 (ISO15118-20) vehicle
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 vehicle")]
|
||||
[HttpPost]
|
||||
[Route("vehicle/verifyresult")]
|
||||
public async Task<IResult> VehicleVerifyresult([FromBody] Request_Verifyresult request)
|
||||
{
|
||||
Response_Verifyresult response = new Response_Verifyresult();
|
||||
|
||||
Guid guid = Guid.NewGuid();
|
||||
Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.RequestVerifyresult(request);
|
||||
}
|
||||
|
||||
Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 재발급 (ISO15118-20)
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 vehicle")]
|
||||
[HttpPost]
|
||||
[Route("vehicle/reissue")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> VehicleReissue([FromBody] Request_Certificate request)
|
||||
{
|
||||
//Response_Certificate response = new Response_Certificate();
|
||||
|
||||
//Guid guid = Guid.NewGuid();
|
||||
//Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
//var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
//if (service != null)
|
||||
//{
|
||||
// response = await service.RequestCertificateReissue(request, Library.Enums.VpkiType.vehicle_cert);
|
||||
//}
|
||||
|
||||
//Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
//return Results.Ok(response);
|
||||
await Task.CompletedTask;
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 인증서 폐기 (ISO15118-20)
|
||||
/// </summary>
|
||||
[Tags("VPKI API v2 vehicle")]
|
||||
[HttpPost]
|
||||
[Route("vehicle/revoke")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public async Task<IResult> VehicleRevoke([FromBody] Request_CertificateRevokeOEM request)
|
||||
{
|
||||
//Response_CertificateRevokeOEM response = new Response_CertificateRevokeOEM();
|
||||
|
||||
//Guid guid = Guid.NewGuid();
|
||||
//Log4net.WriteLine(GetRequestLog(request).LogModelToString($"Request ({guid})"));
|
||||
|
||||
//var service = _serviceProvider.GetService<ISO15118_20Service>();
|
||||
//if (service != null)
|
||||
//{
|
||||
// response = await service.RequestCertificateRevoke(request, Library.Enums.VpkiType.vehicle_cert);
|
||||
//}
|
||||
|
||||
//Log4net.WriteLine(GetResponseLog(response).LogModelToString($"Response ({guid})"));
|
||||
|
||||
//return Results.Ok(response);
|
||||
await Task.CompletedTask;
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
35
Projects/VPKI/VPKI/VPKI.Web.Api/Dockerfile
Normal file
35
Projects/VPKI/VPKI/VPKI.Web.Api/Dockerfile
Normal file
@ -0,0 +1,35 @@
|
||||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
|
||||
#For more information, please see https://aka.ms/containercompat
|
||||
|
||||
FROM dotnet8 AS base
|
||||
EXPOSE 5555
|
||||
|
||||
WORKDIR /
|
||||
RUN mkdir /Config
|
||||
RUN dotnet dev-certs https --trust
|
||||
COPY ["Config/*", "/Config/"]
|
||||
|
||||
WORKDIR /app
|
||||
FROM dotnet8 AS build
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
|
||||
WORKDIR /src
|
||||
COPY ["VPKI.Web.Api/VPKI.Web.Api.csproj", "VPKI.Web.Api/"]
|
||||
COPY ["VPKI.Library.DB/VPKI.Library.DB.csproj", "VPKI.Library.DB/"]
|
||||
COPY ["VPKI.Library/VPKI.Library.csproj", "VPKI.Library/"]
|
||||
RUN dotnet restore "./VPKI.Web.Api/VPKI.Web.Api.csproj"
|
||||
|
||||
COPY . .
|
||||
WORKDIR "/src/VPKI.Web.Api"
|
||||
RUN dotnet build "./VPKI.Web.Api.csproj" -c %BUILD_CONFIGURATION% -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
RUN dotnet publish "./VPKI.Web.Api.csproj" -c %BUILD_CONFIGURATION% -o /app/publish /p:UseAppHost=false
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "VPKI.Web.Api.dll"]
|
||||
138
Projects/VPKI/VPKI/VPKI.Web.Api/Program.cs
Normal file
138
Projects/VPKI/VPKI/VPKI.Web.Api/Program.cs
Normal file
@ -0,0 +1,138 @@
|
||||
using DB.VPKI_AccountDB;
|
||||
using DB.VPKI_DataDB;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.Identity.Client;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Security.Cryptography.Xml;
|
||||
using System.Text;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Services;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
|
||||
string configDir = @"../Config";
|
||||
|
||||
//raed log4net config
|
||||
if (Log4net.IsConfigLoad == true)
|
||||
{
|
||||
Log4net.WriteLine("Log4net Init Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine("Log4net Init Failed", LogType.Error);
|
||||
}
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
|
||||
//singleton
|
||||
builder.Services.AddSingleton<ConfigService<WebApiConfig>>();
|
||||
builder.Services.AddSingleton<CertificateService>();
|
||||
|
||||
//scoped
|
||||
builder.Services.AddScoped<VpkiBaseService>();
|
||||
builder.Services.AddScoped<ISO15118_02Service>();
|
||||
builder.Services.AddScoped<ISO15118_20Service>();
|
||||
builder.Services.AddScoped<AuthService>();
|
||||
builder.Services.AddScoped<UserService>();
|
||||
|
||||
//dbContext
|
||||
builder.Services.AddDbContext<VpkiAccountDbContext>();
|
||||
builder.Services.AddDbContext<VpkiDataDbContext>();
|
||||
|
||||
//config preload
|
||||
ConfigService<WebApiConfig> preloadConfig = new ConfigService<WebApiConfig>();
|
||||
if (preloadConfig.OpenConfig($@"{configDir}/VPKI.WebApiConfig.json") == true)
|
||||
{
|
||||
var config = preloadConfig.GetConfig();
|
||||
|
||||
//auth
|
||||
builder.Services
|
||||
.AddAuthentication(option =>
|
||||
{
|
||||
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ClockSkew = TimeSpan.Zero,
|
||||
ValidIssuer = $"{config?.Auth?.issuer}",
|
||||
ValidAudience = $"{config?.Auth?.audience}",
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes($"{config?.Auth?.accessTokenSecret}"))
|
||||
};
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Config Preload Load Error.");
|
||||
return;
|
||||
}
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
//read api config and set
|
||||
string serverUrl = string.Empty;
|
||||
var configService = app.Services.GetService<ConfigService<WebApiConfig>>();
|
||||
bool isIIS = false;
|
||||
if (configService?.OpenConfig($@"{configDir}/VPKI.WebApiConfig.json") == true)
|
||||
{
|
||||
Log4net.WriteLine("WebApi Config Success.");
|
||||
var apiConfig = ConfigService<WebApiConfig>.Config;
|
||||
if(apiConfig != null)
|
||||
{
|
||||
serverUrl = $"{apiConfig?.Server?.Address}:{apiConfig?.Server?.Port}";
|
||||
isIIS = apiConfig!.Server.IIS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine("WebApi Config Error.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
Log4net.WriteLine($"IsDevelopment:{app.Environment.IsDevelopment()}");
|
||||
Log4net.WriteLine($"Swagger Url: {serverUrl}/swagger");
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(option => {
|
||||
option.DefaultModelsExpandDepth(-1);
|
||||
});
|
||||
}
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseHttpsRedirection();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
if (isIIS == true)
|
||||
{
|
||||
app.Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine($"Operation Url: {serverUrl}");
|
||||
app.Run($"{serverUrl}");
|
||||
}
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
{
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5013"
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "https://localhost:7296;http://localhost:5013"
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Container (Dockerfile)": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_HTTP_PORTS": "5555"
|
||||
},
|
||||
"publishAllPorts": true,
|
||||
"useSSL": true
|
||||
}
|
||||
},
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:48976",
|
||||
"sslPort": 44335
|
||||
}
|
||||
}
|
||||
}
|
||||
265
Projects/VPKI/VPKI/VPKI.Web.Api/Services/AuthService.cs
Normal file
265
Projects/VPKI/VPKI/VPKI.Web.Api/Services/AuthService.cs
Normal file
@ -0,0 +1,265 @@
|
||||
using Azure;
|
||||
using DB.VPKI_AccountDB;
|
||||
using DocumentFormat.OpenXml.Presentation;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Data;
|
||||
using SystemX.Core.DB;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Model.Auth;
|
||||
using VPKI.Library.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Services
|
||||
{
|
||||
public class AuthService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly ConfigService<WebApiConfig>? _configService;
|
||||
|
||||
private readonly Library.Config.Model.DataBase? _accountDB;
|
||||
|
||||
private static List<LoginResponseModel> Session = new List<LoginResponseModel>();
|
||||
|
||||
public AuthService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, ConfigService<WebApiConfig> configSerice)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_configService = configSerice;
|
||||
_scopeFactory = scopeFactory;
|
||||
_accountDB = _configService?.GetConfig()?.DataBase?.Find(x=>x.DBContext == "VpkiAccountDbContext");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// create new user
|
||||
/// </summary>
|
||||
public async Task<RegisterResponseModel> CreateUser(RegisterModel registerModel)
|
||||
{
|
||||
//response
|
||||
RegisterResponseModel response = new RegisterResponseModel();
|
||||
response.EC = ERROR_CODE.EC_USER_REGISTER_FAILED;
|
||||
response.UserID = registerModel.UserID;
|
||||
response.Role = registerModel.Role;
|
||||
response.RoleName = registerModel.Role.ToString();
|
||||
|
||||
//context
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiAccountDbContext>();
|
||||
if (context is not null)
|
||||
{
|
||||
var user = await context.TUsers.AsNoTracking().Where(x => x.CUserId.ToLower() == registerModel.UserID.ToLower()).ToListAsync();
|
||||
if (user?.Count <= 0)
|
||||
{
|
||||
string auid = Guid.NewGuid().ToString();
|
||||
//user
|
||||
TUser newUser = new TUser
|
||||
{
|
||||
CAuid = auid,
|
||||
CUserId = registerModel.UserID,
|
||||
CPasswordHashed = registerModel.Password,
|
||||
CCreateDateTime = DateTime.Now,
|
||||
CLastLoginDateTime = new DateTime()
|
||||
};
|
||||
//role
|
||||
TRole newUserRole = new TRole
|
||||
{
|
||||
CAuid = auid,
|
||||
CRoleId = Convert.ToByte(registerModel.Role),
|
||||
CRoleName = registerModel.Role.ToString()
|
||||
};
|
||||
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
await context.AddAsync(newUser);
|
||||
await context.AddAsync(newUserRole);
|
||||
|
||||
var result = await context.CloseTransactionAsync(transaction);
|
||||
if (result == true)
|
||||
{
|
||||
response.EC = ERROR_CODE.EC_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// select user(login)
|
||||
/// </summary>
|
||||
public async Task<LoginResponseModel> SelectUser(LoginModel loginModel)
|
||||
{
|
||||
//response
|
||||
LoginResponseModel response = new LoginResponseModel();
|
||||
response.EC = ERROR_CODE.EC_USER_LOGIN_FAILED;
|
||||
response.UserID = loginModel.UserID;
|
||||
|
||||
//var session = Session.Find(x => x.UserID?.ToLower() == loginModel.UserID?.ToLower());
|
||||
//if (session?.AccessTokenExpired < DateTime.Now.ToUnixTime())
|
||||
//{
|
||||
// Session.Remove(session);
|
||||
//}
|
||||
|
||||
//기존 로그인 체크
|
||||
// if (Session.Exists(x => x.UserID == $"{loginModel.UserID?.ToLower()}") == false)
|
||||
{
|
||||
if (loginModel != null)
|
||||
{
|
||||
//context
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiAccountDbContext>();
|
||||
if (context is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted))
|
||||
{
|
||||
//select user
|
||||
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
|
||||
if (selectUser is not null)
|
||||
{
|
||||
if (selectUser.CPasswordHashed == loginModel?.Password)
|
||||
{
|
||||
//select role
|
||||
var selectRole = await context.TRoles.FindAsync(selectUser.CAuid);
|
||||
if (selectRole != null)
|
||||
{
|
||||
response.Role = (UserRole)Enum.Parse(typeof(UserRole), selectRole.CRoleId.ToString());
|
||||
response.RoleName = selectRole.CRoleName;
|
||||
}
|
||||
|
||||
// Session.Add(response);
|
||||
|
||||
if (selectUser.CState == (byte)UserState.Active)
|
||||
{
|
||||
response.EC = ERROR_CODE.EC_OK;
|
||||
}
|
||||
else if (selectUser.CState == (byte)UserState.Inactive)
|
||||
{
|
||||
response.EC = ERROR_CODE.EC_USER_LOGIN_INAVTIVE;
|
||||
}
|
||||
else if (selectUser.CState == (byte)UserState.Block)
|
||||
{
|
||||
response.EC = ERROR_CODE.EC_USER_LOGIN_BLOCKED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.EC = ERROR_CODE.EC_USER_LOGIN_INVALID_PASSWORD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.EC = ERROR_CODE.EC_USER_LOGIN_NOT_EXIST;
|
||||
Log4net.WriteLine($"{response.EC}", LogType.Error);
|
||||
}
|
||||
await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine($"Select User Transaction Error", LogType.Error);
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateLoginInfo(LoginModel loginModel, string? RefreshToken = "")
|
||||
{
|
||||
bool result = false;
|
||||
bool transactionResult = true;
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiAccountDbContext>();
|
||||
if (context is not null)
|
||||
{
|
||||
var selectUser = await context.TUsers.AsNoTracking().FirstOrDefaultAsync(x => x.CUserId.ToLower() == loginModel!.UserID!.ToLower());
|
||||
if (selectUser is not null)
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
//user info
|
||||
selectUser.CLastLoginDateTime = DateTime.Now;
|
||||
context.Update(selectUser);
|
||||
|
||||
//refresh token
|
||||
var findRefreshToken = await context.TRefreshTokens.AsNoTracking().FirstOrDefaultAsync(x => x.CAuid == selectUser.CAuid);
|
||||
//null이면(없으면) add
|
||||
if (findRefreshToken == null)
|
||||
{
|
||||
await context.AddAsync(new TRefreshToken
|
||||
{
|
||||
CAuid = selectUser.CAuid,
|
||||
CRefreshToken = $"{RefreshToken}"
|
||||
});
|
||||
}
|
||||
//있으면 update
|
||||
else
|
||||
{
|
||||
findRefreshToken.CRefreshToken = $"{RefreshToken}";
|
||||
context.Update(findRefreshToken);
|
||||
}
|
||||
|
||||
//commit
|
||||
Log4net.WriteLine(findRefreshToken?.ToJson(), LogType.Debug);
|
||||
|
||||
result = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log4net.WriteLine(ex);
|
||||
}
|
||||
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine($"Not Exist User {loginModel.UserID}", LogType.Error);
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
Log4net.WriteLine($"Transaction Error", LogType.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine($"Transaction Success", LogType.DB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public LogoutResponseModel LogoutUser(LogoutModel logoutModel)
|
||||
{
|
||||
LogoutResponseModel response = new LogoutResponseModel();
|
||||
response.UserID = logoutModel.UserID;
|
||||
response.EC = ERROR_CODE.EC_USER_LOGOUT_FAILED;
|
||||
|
||||
var session = Session.Find(x => x.UserID?.ToLower() == logoutModel?.UserID?.ToLower());
|
||||
if (session != null)
|
||||
{
|
||||
Session.Remove(session);
|
||||
response.EC = ERROR_CODE.EC_OK;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
373
Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_02Service.cs
Normal file
373
Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_02Service.cs
Normal file
@ -0,0 +1,373 @@
|
||||
using DB.VPKI_DataDB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using SystemX.Core.DB;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Packet;
|
||||
using VPKI.Library.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Services
|
||||
{
|
||||
public class ISO15118_02Service : VpkiBaseService
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
|
||||
private readonly string URL_V1_CERTIFICATE_ISSUE = "api/v1/{1}/issue";
|
||||
|
||||
public ISO15118_02Service(ConfigService<WebApiConfig> configSerice, CertificateService certificateService, IServiceScopeFactory scopeFactory)
|
||||
:base(configSerice, certificateService, scopeFactory)
|
||||
{
|
||||
_scopeFactory = scopeFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// tbscsr
|
||||
/// </summary>
|
||||
public async Task<Response_Tbscsr> RequestTbscsr(Request_Tbscsr request, VpkiType vpkiType = VpkiType.prov_v1)
|
||||
{
|
||||
Response_Tbscsr response = new Response_Tbscsr();
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
string pcid = _certificateService.CreatePCID(request, VpkiType.prov_v1);
|
||||
string dn = $"cn={pcid},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}";
|
||||
|
||||
string csrOrigin = _certificateService.CreateCsr256(dn, request.publickey);
|
||||
string tbaCsrHashed = string.Empty;
|
||||
|
||||
//sha 256
|
||||
using (SHA256 sha256 = SHA256.Create())
|
||||
{
|
||||
byte[] hashed = sha256.ComputeHash(Convert.FromBase64String(csrOrigin));
|
||||
tbaCsrHashed = Convert.ToBase64String(hashed);
|
||||
Log4net.WriteLine($"Hashed CSR (Base64): {tbaCsrHashed}", LogType.Info);
|
||||
}
|
||||
|
||||
//csr error
|
||||
if (string.IsNullOrEmpty(csrOrigin) == true)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "create csr error";
|
||||
}
|
||||
//pcid error
|
||||
else if (string.IsNullOrEmpty(pcid) == true)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "create pcid error";
|
||||
}
|
||||
//success
|
||||
else
|
||||
{
|
||||
var tbscsr = new TTbscsr
|
||||
{
|
||||
CIftid = $"{request?.iftid}",
|
||||
CMacaddr = $"{request?.cnInfo?.macaddr}",
|
||||
CWmi = $"{request?.cnInfo?.wmi}",
|
||||
CIdType = $"{request?.cnInfo?.idType}",
|
||||
CSupplierId = $"{request?.cnInfo?.supplierId}",
|
||||
CDc = $"{request?.certInfo?.dc}",
|
||||
CTierCode = $"{request?.certInfo?.tierCode}",
|
||||
CUnitCode = $"{request?.certInfo?.unitCode}",
|
||||
CPublickey = $"{request?.publickey}",
|
||||
CCertType = "prov_v1",
|
||||
|
||||
COriginTbscsr = csrOrigin,
|
||||
CHashedTbscsr = tbaCsrHashed,
|
||||
CPcid = pcid,
|
||||
CDn = $"{dn}",
|
||||
|
||||
CDateTime = DateTime.Now
|
||||
};
|
||||
|
||||
//db context
|
||||
bool transactionResult = true;
|
||||
bool isExist = false;
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
//pcid 중복 체크, 있으면 에러
|
||||
if (await context.TTbscsrs.AsNoTracking().FirstOrDefaultAsync(x => x.CPcid == tbscsr.CPcid) != null)
|
||||
{
|
||||
isExist = true;
|
||||
}
|
||||
//success
|
||||
else
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
await context.AddAsync(tbscsr);
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "ISO15118-02 Tbscsr database error";
|
||||
}
|
||||
|
||||
if (isExist == true)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = $"pcid aleady exist";
|
||||
}
|
||||
}
|
||||
|
||||
response.data = new Response_Tbscsr.Data
|
||||
{
|
||||
hashedtbscsr = $"{tbaCsrHashed}",
|
||||
pcid = $"{pcid}",
|
||||
evccid = $"{pcid}",
|
||||
};
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// certificate
|
||||
/// </summary>
|
||||
public async Task<Response_Certificate> RequestCertificate(Request_Certificate request)
|
||||
{
|
||||
Response_Certificate response = new Response_Certificate();
|
||||
|
||||
Request_CertificateOEM requestOem = new Request_CertificateOEM();
|
||||
Response_CertificateOEM? responseOem = new Response_CertificateOEM();
|
||||
|
||||
bool isVerify = false;
|
||||
bool transactionResult = true;
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
if (context != null)
|
||||
{
|
||||
string cCertType = "prov_v1";
|
||||
|
||||
TTbscsr tbscsr = new TTbscsr();
|
||||
foreach (var csr in await context.TTbscsrs.AsNoTracking().Where(x => x.CCertType == cCertType).OrderByDescending(x => x.CCuid).ToListAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
using (ECDsa ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256))
|
||||
{
|
||||
var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}";
|
||||
ecdsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(publicKeyPem), out _);
|
||||
|
||||
var hachedTbsCsr = Convert.FromBase64String(csr.CHashedTbscsr);
|
||||
isVerify = ecdsa.VerifyHash(hachedTbsCsr, Convert.FromBase64String($"{request.csrsignature}"));
|
||||
}
|
||||
|
||||
if (isVerify == true)
|
||||
{
|
||||
tbscsr = csr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (isVerify == true)
|
||||
{
|
||||
var decode = _certificateService.DecodeDERSignature_02(Convert.FromBase64String($"{request.csrsignature}").ToList());
|
||||
Log4net.WriteLine($"Decode Csrsignature: {Convert.ToBase64String(decode.ToArray())}", LogType.Debug);
|
||||
|
||||
CertificationRequestInfo certificationRequestInfo = CertificationRequestInfo.GetInstance(Convert.FromBase64String($"{tbscsr.COriginTbscsr}"));
|
||||
CertificationRequest certificationRequest = new CertificationRequest(
|
||||
certificationRequestInfo,
|
||||
new AlgorithmIdentifier(X9ObjectIdentifiers.ECDsaWithSha256),
|
||||
new DerBitString(decode.ToArray()));
|
||||
Pkcs10CertificationRequest pKCS10CertificationRequest = new Pkcs10CertificationRequest(certificationRequest.GetEncoded());
|
||||
|
||||
byte[] completeCsr = pKCS10CertificationRequest.GetEncoded();
|
||||
|
||||
requestOem = new Request_CertificateOEM
|
||||
{
|
||||
csr = $"{Consts.BEGIN_CERTIFICATE_REQUEST}{Convert.ToBase64String(completeCsr)}{Consts.END_CERTIFICATE_REQUEST}",
|
||||
unitCode = request.unitCode,
|
||||
tierCode = request.tierCode,
|
||||
vehicleCode = request.vehicleCode,
|
||||
localCode = request.localCode,
|
||||
brandCode = request.brandCode
|
||||
};
|
||||
|
||||
string url = $"{URL_VPKI_BASE}{URL_V1_CERTIFICATE_ISSUE}";
|
||||
url = url.Replace("{1}", "prov");
|
||||
|
||||
responseOem = await PostJsonAsync<Request_CertificateOEM, Response_CertificateOEM>($"{url}", requestOem);
|
||||
|
||||
response.status = responseOem?.status;
|
||||
response.message = $"{responseOem?.resultMessage}";
|
||||
|
||||
//db처리
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
if (await context.TCertificates.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == tbscsr.CCuid) != null)
|
||||
{
|
||||
var certificate = new TCertificate
|
||||
{
|
||||
CCuid = tbscsr.CCuid,
|
||||
CCsrsignature = $"{request.csrsignature}",
|
||||
CCsr = $"{requestOem?.csr}",
|
||||
CTierCode = $"{requestOem?.tierCode}",
|
||||
CUnitCode = $"{requestOem?.unitCode}",
|
||||
CVehicleCode = $"{requestOem?.vehicleCode}",
|
||||
CLocalCode = $"{requestOem?.localCode}",
|
||||
CBrandCode = $"{requestOem?.brandCode}",
|
||||
CCert = $"{responseOem?.cert}",
|
||||
CMessage = $"{responseOem?.resultMessage}",
|
||||
CIssueCount = 1,
|
||||
|
||||
CDateTime = DateTime.Now
|
||||
};
|
||||
await context.AddAsync(certificate);
|
||||
}
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
|
||||
//ocsp
|
||||
var ocsp = await Ocsp(tbscsr.CCuid);
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
if (await context.TOcsps.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == tbscsr.CCuid) != null)
|
||||
{
|
||||
var certificate = new TOcsp
|
||||
{
|
||||
CCuid = tbscsr.CCuid,
|
||||
CStatus = GetOcspStatus(tbscsr.CPcid, ocsp),
|
||||
CVerify = GetOcspVerify(ocsp),
|
||||
COcsp = $"{ocsp}",
|
||||
CDateTime = DateTime.Now
|
||||
};
|
||||
await context.AddAsync(certificate);
|
||||
}
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
//verify failed
|
||||
else
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message += "verify fialed";
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message += "database error";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string cert = $"{responseOem?.cert}";
|
||||
cert = cert.Replace($"{Consts.BEGIN_CERTIFICATE}","").Replace($"{Consts.END_CERTIFICATE}", "");
|
||||
cert = cert.Replace($"\r","").Replace($"\n", "");
|
||||
response.data = new Response_Certificate.Data
|
||||
{
|
||||
leafcertificate = $"{cert}",
|
||||
subcacertificate = $"{GetSubCA(VpkiType.prov_v1)}"
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// verifyresult
|
||||
/// </summary>
|
||||
public async Task<Response_Verifyresult> RequestVerifyresult(Request_Verifyresult request)
|
||||
{
|
||||
Response_Verifyresult response = new Response_Verifyresult();
|
||||
|
||||
bool transactionResult = true;
|
||||
string serverResult = "success";
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
if (context != null)
|
||||
{
|
||||
var tbscsr = await context.TTbscsrs.AsNoTracking().FirstOrDefaultAsync(x => x.CIftid == request.iftid && x.CPcid == request.pcid);
|
||||
if (tbscsr != null)
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
var findVerifyResult = await context.TVerifyResults.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == tbscsr.CCuid);
|
||||
if (findVerifyResult == null)
|
||||
{
|
||||
var verifyResult = new TVerifyResult
|
||||
{
|
||||
CCuid = tbscsr.CCuid,
|
||||
CResult = $"{request.result}"
|
||||
};
|
||||
await context.AddAsync(verifyResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
findVerifyResult.CResult = $"{request.result}";
|
||||
context.Update(findVerifyResult);
|
||||
}
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message += "database error";
|
||||
}
|
||||
|
||||
//server_result
|
||||
var certificate = await context.TCertificates.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == tbscsr.CCuid);
|
||||
if (certificate != null)
|
||||
{
|
||||
//인증서 없다
|
||||
if (string.IsNullOrEmpty(certificate.CCert) == true)
|
||||
{
|
||||
serverResult = "empty";
|
||||
}
|
||||
//폐기된 인증서
|
||||
else if (certificate.CIssueCount < 0)
|
||||
{
|
||||
serverResult = "revoked";
|
||||
}
|
||||
}
|
||||
}
|
||||
//일치하는 데이터 없으면
|
||||
else
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "Not matched ift and pcid";
|
||||
serverResult = "error";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.data = new Response_Verifyresult.Data
|
||||
{
|
||||
iftid = $"{request.iftid}",
|
||||
pcid = $"{request.pcid}",
|
||||
ift_result = $"{request.result}",
|
||||
server_result=$"{serverResult}"
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
364
Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_20Service.cs
Normal file
364
Projects/VPKI/VPKI/VPKI.Web.Api/Services/ISO15118_20Service.cs
Normal file
@ -0,0 +1,364 @@
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Pkcs;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Packet;
|
||||
using VPKI.Library.Services;
|
||||
using Org.BouncyCastle.Asn1.Pkcs;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using DB.VPKI_DataDB;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SystemX.Core.DB;
|
||||
|
||||
namespace VPKI.Web.Api.Services
|
||||
{
|
||||
public class ISO15118_20Service : VpkiBaseService
|
||||
{
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
|
||||
private readonly string URL_V2_CERTIFICATE_ISSUE = "api/v2/{1}/issue";
|
||||
|
||||
public ISO15118_20Service(ConfigService<WebApiConfig> configService, CertificateService certificateService, IServiceScopeFactory scopeFactory)
|
||||
: base(configService, certificateService, scopeFactory)
|
||||
{
|
||||
_scopeFactory = scopeFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// tbscsr
|
||||
/// </summary>
|
||||
public async Task<Response_Tbscsr> RequestTbscsr(Request_Tbscsr request, VpkiType vpkiType)
|
||||
{
|
||||
Response_Tbscsr response = new Response_Tbscsr();
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
if (request.certType?.Contains(VpkiType.evcc_cert.ToString()) == true)
|
||||
{
|
||||
request.certType = VpkiType.vehicle_cert.ToString();
|
||||
}
|
||||
|
||||
string pcid = _certificateService.CreatePCID(request, VpkiType.prov_v1);
|
||||
string dn = $"cn={_certificateService.CreatePCID(request, VpkiType.prov_cert)},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}";
|
||||
if (request.certType == VpkiType.vehicle_cert.ToString() || request.certType == VpkiType.evcc_cert.ToString())
|
||||
dn = $"cn={_certificateService.CreatePCID(request, VpkiType.vehicle_cert)},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}";
|
||||
|
||||
string csrOrigin = _certificateService.CreateCsr512(dn, request.publickey);
|
||||
string tbaCsrHashed = string.Empty;
|
||||
|
||||
//sha 512
|
||||
using (SHA512 sha512 = SHA512.Create())
|
||||
{
|
||||
byte[] hashed = sha512.ComputeHash(Convert.FromBase64String(csrOrigin));
|
||||
tbaCsrHashed = Convert.ToBase64String(hashed);
|
||||
Log4net.WriteLine($"Hashed CSR (Base64): {tbaCsrHashed}", LogType.Debug);
|
||||
}
|
||||
|
||||
//csr error
|
||||
if (string.IsNullOrEmpty(csrOrigin) == true)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "create csr error";
|
||||
}
|
||||
//pcid error
|
||||
else if (string.IsNullOrEmpty(pcid) == true)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "create pcid error";
|
||||
}
|
||||
//success
|
||||
else
|
||||
{
|
||||
var tbscsr = new TTbscsr
|
||||
{
|
||||
CIftid = $"{request?.iftid}",
|
||||
CMacaddr = $"{request?.cnInfo?.macaddr}",
|
||||
CWmi = $"{request?.cnInfo?.wmi}",
|
||||
CIdType = $"{request?.cnInfo?.idType}",
|
||||
CSupplierId = $"{request?.cnInfo?.supplierId}",
|
||||
CDc = $"{request?.certInfo?.dc}",
|
||||
CTierCode = $"{request?.certInfo?.tierCode}",
|
||||
CUnitCode = $"{request?.certInfo?.unitCode}",
|
||||
CPublickey = $"{request?.publickey}",
|
||||
CCertType = $"{request?.certType}",
|
||||
|
||||
COriginTbscsr = csrOrigin,
|
||||
CHashedTbscsr = tbaCsrHashed,
|
||||
CPcid = pcid,
|
||||
CDn = $"{dn}",
|
||||
|
||||
CDateTime = DateTime.Now
|
||||
};
|
||||
|
||||
//db context
|
||||
bool transactionResult = true;
|
||||
bool isExist = false;
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
if (context != null)
|
||||
{
|
||||
//pcid 중복 체크, 있으면 업데이트
|
||||
if (await context.TTbscsrs.AsNoTracking().FirstOrDefaultAsync(x => x.CPcid == tbscsr.CPcid) != null)
|
||||
{
|
||||
isExist = true;
|
||||
}
|
||||
//success
|
||||
else
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
await context.AddAsync(tbscsr);
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "ISO15118-20 Tbscsr database error";
|
||||
}
|
||||
|
||||
if (isExist == true)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = $"pcid aleady exist";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.data = new Response_Tbscsr.Data
|
||||
{
|
||||
hashedtbscsr = $"{tbaCsrHashed}",
|
||||
pcid = $"{pcid}",
|
||||
evccid = $"{pcid}"
|
||||
};
|
||||
}
|
||||
Log4net.WriteLine(response.ToJson(), response!.status!.Contains("error") ? LogType.Error : LogType.Info);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// certificate
|
||||
/// </summary>
|
||||
public async Task<Response_Certificate> RequestCertificate(Request_Certificate request, VpkiType vpkiType)
|
||||
{
|
||||
if (vpkiType == VpkiType.evcc_cert)
|
||||
vpkiType = VpkiType.vehicle_cert;
|
||||
|
||||
Response_Certificate response = new Response_Certificate();
|
||||
|
||||
Request_CertificateOEM requestOem = new Request_CertificateOEM();
|
||||
Response_CertificateOEM? responseOem = new Response_CertificateOEM();
|
||||
|
||||
bool isVerify = false;
|
||||
bool transactionResult = true;
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
if (context != null)
|
||||
{
|
||||
string cCertType = vpkiType.ToString();
|
||||
|
||||
TTbscsr tbscsr = new TTbscsr();
|
||||
foreach (var csr in await context.TTbscsrs.AsNoTracking().Where(x => x.CCertType == cCertType).OrderByDescending(x => x.CCuid).ToListAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
using (ECDsa ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP521))
|
||||
{
|
||||
var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}";
|
||||
ecdsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(publicKeyPem), out _);
|
||||
|
||||
var hachedTbsCsr = Convert.FromBase64String(csr.CHashedTbscsr);
|
||||
isVerify = ecdsa.VerifyHash(hachedTbsCsr, Convert.FromBase64String($"{request.csrsignature}"));
|
||||
}
|
||||
|
||||
if (isVerify == true)
|
||||
{
|
||||
tbscsr = csr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if (isVerify == true)
|
||||
{
|
||||
var decode = _certificateService.DecodeDERSignature_20(Convert.FromBase64String($"{request.csrsignature}").ToList());
|
||||
Log4net.WriteLine($"Decode Csrsignature: {Convert.ToBase64String(decode.ToArray())}", LogType.Debug);
|
||||
|
||||
CertificationRequestInfo certificationRequestInfo = CertificationRequestInfo.GetInstance(Convert.FromBase64String($"{tbscsr.COriginTbscsr}"));
|
||||
CertificationRequest certificationRequest = new CertificationRequest(
|
||||
certificationRequestInfo,
|
||||
new AlgorithmIdentifier(X9ObjectIdentifiers.ECDsaWithSha512),
|
||||
new DerBitString(decode.ToArray()));
|
||||
Pkcs10CertificationRequest pKCS10CertificationRequest = new Pkcs10CertificationRequest(certificationRequest.GetEncoded());
|
||||
|
||||
byte[] completeCsr = pKCS10CertificationRequest.GetEncoded();//csr.CreateCertificateRequest();
|
||||
|
||||
requestOem = new Request_CertificateOEM
|
||||
{
|
||||
csr = $"{Consts.BEGIN_CERTIFICATE_REQUEST}{Convert.ToBase64String(completeCsr)}{Consts.END_CERTIFICATE_REQUEST}",
|
||||
unitCode = request.unitCode,
|
||||
tierCode = request.tierCode,
|
||||
vehicleCode = request.vehicleCode,
|
||||
localCode = request.localCode,
|
||||
brandCode = request.brandCode
|
||||
};
|
||||
|
||||
string url = $"{URL_VPKI_BASE}{URL_V2_CERTIFICATE_ISSUE}";
|
||||
url = url.Replace("{1}", $"{vpkiType.ToString().Split("_").FirstOrDefault()}");
|
||||
|
||||
responseOem = await PostJsonAsync<Request_CertificateOEM, Response_CertificateOEM>(url, requestOem);
|
||||
|
||||
response.status = responseOem?.status;
|
||||
response.message = $"{responseOem?.resultMessage}";
|
||||
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
if (await context.TCertificates.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == tbscsr.CCuid) != null)
|
||||
{
|
||||
var certificate = new TCertificate
|
||||
{
|
||||
CCuid = tbscsr.CCuid,
|
||||
CCsrsignature = $"{request.csrsignature}",
|
||||
CCsr = requestOem.csr,
|
||||
CTierCode = $"{requestOem?.tierCode}",
|
||||
CUnitCode = $"{requestOem?.unitCode}",
|
||||
CVehicleCode = $"{requestOem?.vehicleCode}",
|
||||
CLocalCode = $"{requestOem?.localCode}",
|
||||
CBrandCode = $"{requestOem?.brandCode}",
|
||||
CCert = $"{responseOem?.cert}",
|
||||
CMessage = $"{responseOem?.resultMessage}",
|
||||
CIssueCount = 1,
|
||||
|
||||
CDateTime = DateTime.Now
|
||||
};
|
||||
await context.AddAsync(certificate);
|
||||
}
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
//verify failed
|
||||
else
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message += "verify fialed";
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message += "database error";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string cert = $"{responseOem?.cert}";
|
||||
cert = cert.Replace($"{Consts.BEGIN_CERTIFICATE}", "").Replace($"{Consts.END_CERTIFICATE}", "");
|
||||
cert = cert.Replace($"\r", "").Replace($"\n", "");
|
||||
response.data = new Response_Certificate.Data
|
||||
{
|
||||
leafcertificate = $"{cert}",
|
||||
subcacertificate = $"{GetSubCA(vpkiType)}"
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// verifytresult
|
||||
/// </summary>
|
||||
public async Task<Response_Verifyresult> RequestVerifyresult(Request_Verifyresult request)
|
||||
{
|
||||
Response_Verifyresult response = new Response_Verifyresult();
|
||||
|
||||
bool transactionResult = true;
|
||||
string serverResult = "success";
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
if (context != null)
|
||||
{
|
||||
var tbscsr = await context.TTbscsrs.AsNoTracking().FirstOrDefaultAsync(x => x.CIftid == request.iftid && x.CPcid == request.pcid);
|
||||
if (tbscsr != null)
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
var findVerifyResult = await context.TVerifyResults.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == tbscsr.CCuid);
|
||||
if (findVerifyResult == null)
|
||||
{
|
||||
var verifyResult = new TVerifyResult
|
||||
{
|
||||
CCuid = tbscsr.CCuid,
|
||||
CResult = $"{request.result}"
|
||||
};
|
||||
await context.AddAsync(verifyResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
findVerifyResult.CResult = $"{request.result}";
|
||||
context.Update(findVerifyResult);
|
||||
}
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message += "database error";
|
||||
}
|
||||
|
||||
//server_result
|
||||
var certificate = context.TCertificates.ToList().Find(x => x.CCuid == tbscsr.CCuid);
|
||||
if (certificate != null)
|
||||
{
|
||||
//인증서 없다
|
||||
if (string.IsNullOrEmpty(certificate.CCert) == true)
|
||||
{
|
||||
serverResult = "empty";
|
||||
}
|
||||
//폐기된 인증서
|
||||
else if (certificate.CIssueCount < 0)
|
||||
{
|
||||
serverResult = "revoked";
|
||||
}
|
||||
}
|
||||
}
|
||||
//일치하는 데이터 없으면
|
||||
else
|
||||
{
|
||||
response.status = Status.error.ToString();
|
||||
response.message = "Not matched ift and pcid";
|
||||
serverResult = "error";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.data = new Response_Verifyresult.Data
|
||||
{
|
||||
iftid = $"{request.iftid}",
|
||||
pcid = $"{request.pcid}",
|
||||
ift_result = $"{request.result}",
|
||||
server_result = $"{serverResult}"
|
||||
};
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
95
Projects/VPKI/VPKI/VPKI.Web.Api/Services/UserService.cs
Normal file
95
Projects/VPKI/VPKI/VPKI.Web.Api/Services/UserService.cs
Normal file
@ -0,0 +1,95 @@
|
||||
using Azure;
|
||||
using DB.VPKI_AccountDB;
|
||||
using DB.VPKI_DataDB;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Org.BouncyCastle.Pqc.Crypto.Lms;
|
||||
using System;
|
||||
using System.Data;
|
||||
using SystemX.Core.DB;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Services
|
||||
{
|
||||
public class UserService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
|
||||
private readonly ConfigService<WebApiConfig>? _configService;
|
||||
|
||||
private readonly Library.Config.Model.DataBase? _accountDB;
|
||||
|
||||
public UserService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory,
|
||||
ConfigService<WebApiConfig> configSerice)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_scopeFactory = scopeFactory;
|
||||
_configService = configSerice;
|
||||
|
||||
_accountDB = _configService?.GetConfig()?.DataBase?.Find(x => x.DBContext == "VpkiAccountDbContext");
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<UserModel>> GetAllUsers()
|
||||
{
|
||||
List<UserModel> Users = new List<UserModel>();
|
||||
|
||||
//context
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiAccountDbContext>();
|
||||
if (context is not null)
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted))
|
||||
{
|
||||
Users = await context.TUsers.AsNoTracking().Join(context.TRoles.AsNoTracking(), x => x.CAuid, y => y.CAuid,
|
||||
(x, y) => new UserModel { TUser = x, TRole = y }).ToListAsync();
|
||||
|
||||
await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Users;
|
||||
}
|
||||
|
||||
public async Task<UserModel> UpdateUser(UserModel user)
|
||||
{
|
||||
bool transactionResult = false;
|
||||
|
||||
//context
|
||||
if(user.TUser != null && user.TRole != null)
|
||||
{
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiAccountDbContext>();
|
||||
if (context is not null)
|
||||
{
|
||||
using (var transaction = await context.CreateTransactionAsync())
|
||||
{
|
||||
context.Update(user.TUser);
|
||||
context.Update(user.TRole);
|
||||
transactionResult = await context.CloseTransactionAsync(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
//db error
|
||||
if (transactionResult == false)
|
||||
{
|
||||
Log4net.WriteLine($"Transaction Error::", LogType.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine($"Transaction Success", LogType.DB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
298
Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs
Normal file
298
Projects/VPKI/VPKI/VPKI.Web.Api/Services/VpkiBaseService.cs
Normal file
@ -0,0 +1,298 @@
|
||||
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 : HttpService
|
||||
{
|
||||
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.Info);
|
||||
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
|
||||
}
|
||||
}
|
||||
62
Projects/VPKI/VPKI/VPKI.Web.Api/VPKI.Web.Api.csproj
Normal file
62
Projects/VPKI/VPKI/VPKI.Web.Api/VPKI.Web.Api.csproj
Normal file
@ -0,0 +1,62 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>a5eca56b-f522-474b-8bf2-451ed90325f3</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Windows</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="temp\**" />
|
||||
<Content Remove="temp\**" />
|
||||
<EmbeddedResource Remove="temp\**" />
|
||||
<None Remove="temp\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.15">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.2.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VPKI.Library.DB\VPKI.Library.DB.csproj" />
|
||||
<ProjectReference Include="..\VPKI.Library\VPKI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="SystemX.Core">
|
||||
<HintPath>..\..\..\DLL\SystemX.Core.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="xcopy /E /I /Y "$(ProjectDir)/../SubCA" "$(OutDir)/../SubCA"
xcopy /E /I /Y "$(ProjectDir)/../Config" "$(OutDir)/../Config"" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
Projects/VPKI/VPKI/VPKI.Web.Api/appsettings.json
Normal file
9
Projects/VPKI/VPKI/VPKI.Web.Api/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
12
Projects/VPKI/VPKI/VPKI.Web.Client/.config/dotnet-tools.json
Normal file
12
Projects/VPKI/VPKI/VPKI.Web.Client/.config/dotnet-tools.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "8.0.10",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Projects/VPKI/VPKI/VPKI.Web.Client/Components/App.razor
Normal file
25
Projects/VPKI/VPKI/VPKI.Web.Client/Components/App.razor
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>VPKI Operation</title>
|
||||
<base href="/" />
|
||||
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="app.css" />
|
||||
<link rel="stylesheet" href="VPKI.Web.Client.styles.css" />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<HeadOutlet />
|
||||
|
||||
<RadzenTheme Theme="software-dark" @rendermode="new InteractiveServerRenderMode(prerender: false)" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
|
||||
<script src="js/scripts.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -0,0 +1,22 @@
|
||||
@page "/loading/{Message?}"
|
||||
|
||||
<div style="text-align: center;">
|
||||
<div class="lds-ring">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="message">
|
||||
@Message
|
||||
</div>
|
||||
</div>
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Message { get; set; }
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
.message {
|
||||
/* change color here */
|
||||
color: #f8b26a;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lds-ring {
|
||||
/* change color here */
|
||||
color: #f8b26a;
|
||||
}
|
||||
|
||||
.lds-ring,
|
||||
.lds-ring div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.lds-ring {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.lds-ring div {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 8px;
|
||||
border: 8px solid currentColor;
|
||||
border-radius: 50%;
|
||||
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
border-color: currentColor transparent transparent transparent;
|
||||
}
|
||||
|
||||
.lds-ring div:nth-child(1) {
|
||||
animation-delay: -0.45s;
|
||||
}
|
||||
|
||||
.lds-ring div:nth-child(2) {
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
|
||||
.lds-ring div:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
}
|
||||
|
||||
@keyframes lds-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
@using System.Security.Claims
|
||||
@using VPKI.Library.Model.Auth
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject AuthenticationStateProvider AuthStateProvider
|
||||
@inject ApiService ApiService
|
||||
|
||||
<div class="d-flex justify-content-between w-100 px-4">
|
||||
<div>
|
||||
<RadzenLabel Style="font-size:20px;" Text="VPKI Operation" />
|
||||
</div>
|
||||
<div>
|
||||
<AuthorizeView>
|
||||
<Authorized>
|
||||
<RadzenLabel Style="font-size: 15px; margin-right: 10px;" Text="@($"Session Time {TimeSpan.FromMilliseconds(LostLoginTime * 1000)}")" />
|
||||
<RadzenLabel Style="font-size: 15px;" Text="@($"{@context.User.Identity?.Name}")"/>
|
||||
<RadzenLabel Style="font-size: 15px; margin-right: 8px;" Text="@($"({Role})")" />
|
||||
<RadzenLabel Style="cursor:pointer; font-size: 15px;" @onclick="@OnClickLogout" Text="Logout"></RadzenLabel>
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<RadzenLabel Style="cursor:pointer; font-size: 15px;" @onclick="@OnClickLogin" Text="Login"></RadzenLabel>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code{
|
||||
private string Role = string.Empty;
|
||||
private long LostLoginTime = 0;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
Task.Run(async() =>
|
||||
{
|
||||
var state = await((ExtendAuthenticationStatProvicer)AuthStateProvider).GetAuthenticationStateAsync();
|
||||
if (state?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
Role = $"{state?.User?.Claims.Where(x => x.Type == ClaimTypes.Role)?.First().Value}";
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
});
|
||||
|
||||
//자동 로그아웃
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var state = await ((ExtendAuthenticationStatProvicer)AuthStateProvider).GetAuthenticationStateAsync();
|
||||
if (state?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
//expired
|
||||
var expired = await ((ExtendAuthenticationStatProvicer)AuthStateProvider).GetExpiredTimeAsync();
|
||||
LostLoginTime = expired - DateTime.Now.ToUnixTime();
|
||||
if (LostLoginTime < 0)
|
||||
{
|
||||
await ((ExtendAuthenticationStatProvicer)AuthStateProvider).MakeUserLogout();
|
||||
NavigationManager.NavigateTo("/login");
|
||||
}
|
||||
}
|
||||
await Task.Delay(1000);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task OnClickLogout()
|
||||
{
|
||||
var state = await ((ExtendAuthenticationStatProvicer)AuthStateProvider).GetAuthenticationStateAsync();
|
||||
|
||||
LogoutModel logoutModel = new LogoutModel
|
||||
{
|
||||
UserID = state?.User?.Identity?.Name
|
||||
};
|
||||
|
||||
await((ExtendAuthenticationStatProvicer)AuthStateProvider).MakeUserLogout();
|
||||
var res = await ApiService.PostJsonAsyncBearer<LogoutModel, LogoutResponseModel>("/api/auth/logout", logoutModel);
|
||||
NavigationManager.NavigateTo("/login");
|
||||
}
|
||||
|
||||
private async Task OnClickLogin()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
//await ((ExtendAuthenticationStatProvicer)AuthStateProvider).MakeUserLogout();
|
||||
NavigationManager.NavigateTo("/login");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@inherits LayoutComponentBase
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<RadzenLayout>
|
||||
<RadzenHeader>
|
||||
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0">
|
||||
<RadzenSidebarToggle Click="@(() => sidebar1Expanded = !sidebar1Expanded)" />
|
||||
<HeaderBar />
|
||||
</RadzenStack>
|
||||
</RadzenHeader>
|
||||
<RadzenSidebar @bind-Expanded="@sidebar1Expanded">
|
||||
<RadzenPanelMenu>
|
||||
<RadzenPanelMenuItem Text="Home" Icon="home" Path="/" />
|
||||
<RadzenPanelMenuItem Text="VPKI.API" Icon="compare_arrows" Path="/vpki/api" />
|
||||
<RadzenPanelMenuItem Text="VPKI.Manager" Icon="description" Path="/vpki/manager" />
|
||||
<RadzenPanelMenuItem Text="Users" Icon="account_box" Path="/user" />
|
||||
</RadzenPanelMenu>
|
||||
</RadzenSidebar>
|
||||
<RadzenBody>
|
||||
<div class="rz-p-4">
|
||||
@Body
|
||||
</div>
|
||||
</RadzenBody>
|
||||
<RadzenFooter>
|
||||
<div>
|
||||
<RadzenLabel Text="@("Copyright © 2024, SystemX Inc. All rights reserved.")"></RadzenLabel>
|
||||
</div>
|
||||
</RadzenFooter>
|
||||
</RadzenLayout>
|
||||
|
||||
<RadzenComponents @rendermode="InteractiveServer" />
|
||||
|
||||
@code {
|
||||
bool sidebar1Expanded = true;
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row.auth ::deep a:first-child {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
@ -0,0 +1,213 @@
|
||||
@using System.Security.Cryptography
|
||||
@using System.Text
|
||||
@using Org.BouncyCastle.Crypto
|
||||
@using Org.BouncyCastle.Crypto.Generators
|
||||
@using Org.BouncyCastle.Crypto.Parameters
|
||||
@using Org.BouncyCastle.OpenSsl
|
||||
@using Org.BouncyCastle.Security
|
||||
@using VPKI.Library.Packet
|
||||
|
||||
@inject CertificateService CertificateService
|
||||
@inject ApiService ApiService
|
||||
@inject VpkiDialogService DialogService
|
||||
|
||||
<RadzenFieldset Text="Certificate">
|
||||
<div style="display:flex">
|
||||
<!--generator-->
|
||||
<RadzenFieldset Style="width: 100%; margin-right: 20px;" Text="Certificate Generator">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenButton Style="width:100%;" Text="@($"Signed Hash ({StrISO})")" Click="OnClickSignedHash"></RadzenButton>
|
||||
|
||||
<div style="margin-top: 10px;">
|
||||
<RadzenTextArea Style="width:100%; height: 130px;" @bind-Value=@StringCsrHashed>
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Device ID"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@CertificateContainer.RequestCertificate.iftid"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Tier Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@CertificateContainer.RequestCertificate.tierCode"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Unit Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@CertificateContainer.RequestCertificate.unitCode"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Vehicle Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@CertificateContainer.RequestCertificate.vehicleCode"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Local Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@CertificateContainer.RequestCertificate.localCode"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Brand Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@CertificateContainer.RequestCertificate.brandCode"></RadzenTextBox>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
<!--TX RX-->
|
||||
<RadzenFieldset Style="width:100%;" Text="Call API">
|
||||
<div>
|
||||
<RadzenButton Style="width:100%; margin-bottom: 0.5rem;" Text="@($"Generate Request {StrISO}")" Click="@OnClickGenerateCertificate"></RadzenButton>
|
||||
<RadzenButton Style="width:100%;" Text="@($"Send Request")" Click="@OnClickSendCertificate"></RadzenButton>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<RadzenLabel Text="Request"></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height: 180px;" @bind-Value=@CertificateContainer.StrRequest>
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenLabel Text="Response"></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height: 180px;" @bind-Value="@CertificateContainer.StrResponse">
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired]
|
||||
public CertificateContainer CertificateContainer { get; set; } = new CertificateContainer();
|
||||
[Parameter]
|
||||
public EventCallback<CertificateContainer> CertificateContainerChanged { get; set; }
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public string ServerAddress { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public TbscsrContainer TbscsrContainer { get; set; } = new TbscsrContainer();
|
||||
|
||||
//ISO
|
||||
private string StrISO = string.Empty;
|
||||
|
||||
private string StringCsrHashed = string.Empty;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
StrISO = $"{TbscsrContainer.ISOType.ToString().Replace("_", "-")}";
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
string ecdsa = "";
|
||||
if (TbscsrContainer.VpkiType == VpkiType.prov_v1)
|
||||
{
|
||||
ecdsa = ECDSAType.SHA256WITHECDSA.ToString();
|
||||
}
|
||||
else if (TbscsrContainer.VpkiType == VpkiType.prov_cert || TbscsrContainer.VpkiType == VpkiType.vehicle_cert)
|
||||
{
|
||||
ecdsa = ECDSAType.NONEWITHECDSA.ToString();
|
||||
}
|
||||
|
||||
CreateCsrHash(ecdsa);
|
||||
}
|
||||
|
||||
private void OnClickSignedHash()
|
||||
{
|
||||
SignedHash();
|
||||
}
|
||||
|
||||
private void SignedHash()
|
||||
{
|
||||
if (TbscsrContainer.KeyPair != null && TbscsrContainer.ResponseTbscsr.data != null)
|
||||
{
|
||||
var publicKey = (ECPublicKeyParameters)TbscsrContainer.KeyPair.Public;
|
||||
|
||||
string ecdsa = "";
|
||||
if (TbscsrContainer.VpkiType == VpkiType.prov_v1)
|
||||
{
|
||||
ecdsa = ECDSAType.SHA256WITHECDSA.ToString();
|
||||
var pKey = TbscsrContainer.PublicKey;
|
||||
CertificateContainer.CsrHashed = CertificateService.SignHashed02(TbscsrContainer.ResponseTbscsr.data.hashedtbscsr, TbscsrContainer.KeyPair);
|
||||
}
|
||||
else if (TbscsrContainer.VpkiType == VpkiType.prov_cert || TbscsrContainer.VpkiType == VpkiType.vehicle_cert)
|
||||
{
|
||||
ecdsa = ECDSAType.NONEWITHECDSA.ToString();
|
||||
CertificateContainer.CsrHashed = CertificateService.SignHashed20(TbscsrContainer.ResponseTbscsr.data.hashedtbscsr, TbscsrContainer.KeyPair);
|
||||
}
|
||||
|
||||
CreateCsrHash(ecdsa);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCsrHashed += "Request tbscsr first";
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateCsrHash(string ecdsa)
|
||||
{
|
||||
if(string.IsNullOrEmpty(CertificateContainer.CsrHashed.SignedCsr) == false)
|
||||
{
|
||||
StringCsrHashed = $"{StrISO} Signed {ecdsa}:{Environment.NewLine}";
|
||||
StringCsrHashed += $"{CertificateContainer.CsrHashed.SignedCsr}{Environment.NewLine}";
|
||||
StringCsrHashed += $"{Environment.NewLine}";
|
||||
|
||||
StringCsrHashed += $"{StrISO} Signed {ecdsa}(DER ENCODED):{Environment.NewLine}";
|
||||
StringCsrHashed += $"{CertificateContainer.CsrHashed.EncodedSignedCsr}{Environment.NewLine}";
|
||||
StringCsrHashed += $"{Environment.NewLine}";
|
||||
|
||||
StringCsrHashed += $"Verify:{CertificateContainer.CsrHashed.Verify}{Environment.NewLine}";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClickGenerateCertificate()
|
||||
{
|
||||
CertificateContainer.RequestCertificate.csrsignature = CertificateContainer.CsrHashed.EncodedSignedCsr;
|
||||
if (TbscsrContainer.VpkiType == VpkiType.prov_cert || TbscsrContainer.VpkiType == VpkiType.vehicle_cert)
|
||||
{
|
||||
CertificateContainer.RequestCertificate.csrsignature = CertificateContainer.CsrHashed.EncodedSignedCsr;
|
||||
}
|
||||
|
||||
CertificateContainer.StrRequest = $"{CertificateContainer.RequestCertificate.ToJson()}";
|
||||
}
|
||||
|
||||
private async Task OnClickSendCertificate()
|
||||
{
|
||||
DialogService.OpenIndicator();
|
||||
|
||||
try
|
||||
{
|
||||
var request = JsonConvert.DeserializeObject<Request_Certificate>(CertificateContainer.StrRequest);
|
||||
if (request != null)
|
||||
{
|
||||
string url = $"api/v1/certificate";
|
||||
if (TbscsrContainer.VpkiType == VpkiType.prov_cert)
|
||||
{
|
||||
url = $"api/v2/prov/certificate";
|
||||
}
|
||||
else if (TbscsrContainer.VpkiType == VpkiType.vehicle_cert)
|
||||
{
|
||||
url = $"api/v2/vehicle/certificate";
|
||||
}
|
||||
|
||||
var Response = await ApiService.PostJsonAsync<Request_Certificate, Response_Certificate>($"https://{ServerAddress}/{url}", request);
|
||||
if (Response != null)
|
||||
{
|
||||
CertificateContainer.ResponseCertificate = Response;
|
||||
CertificateContainer.StrResponse = $"{Response.ToJson()}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TbscsrContainer.StrResponse = "Request Context Error";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log4net.WriteLine(ex);
|
||||
TbscsrContainer.StrResponse = $"Request Context Error{Environment.NewLine}{ex.Message}";
|
||||
}
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,218 @@
|
||||
@using Org.BouncyCastle.Crypto
|
||||
@using Org.BouncyCastle.Crypto.Parameters
|
||||
@using VPKI.Library.Packet
|
||||
|
||||
@inject CertificateService CertificateService
|
||||
@inject ApiService ApiService
|
||||
@inject VpkiDialogService DialogService
|
||||
|
||||
<RadzenFieldset Text="TBSCSR">
|
||||
<div style="display:flex">
|
||||
<!--csr generate-->
|
||||
<RadzenFieldset Style="width:100%; margin-right: 20px;" Text="Key Generate">
|
||||
@if (TbscsrContainer?.RequestTbscsr != null)
|
||||
{
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="IFT ID"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.iftid"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Priefix Value"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.cnInfo.idType"></RadzenTextBox>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.cnInfo.supplierId"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="MAC Address"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.cnInfo.macaddr"></RadzenTextBox>
|
||||
<RadzenButton Text="Random" Click="@OnClickRandomMacaddresss"></RadzenButton>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="WMI"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.cnInfo.wmi"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Domain Component"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.certInfo.dc"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Tier Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.certInfo.tierCode"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Unit Code"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@TbscsrContainer.RequestTbscsr.certInfo.unitCode"></RadzenTextBox>
|
||||
</div>
|
||||
|
||||
<!--Generate Key-->
|
||||
<div style="margin-top: 20px; margin-bottom:10px;">
|
||||
<RadzenButton Style="width:100%;" Text="@($"Generate for {StrISO}")" Click="@OnClickGenerateKey"></RadzenButton>
|
||||
</div>
|
||||
<div style="margin-top: 20px; margin-bottom:10px;">
|
||||
<RadzenTextArea Style="width:100%; height: 130px;" @bind-Value="@KeyPairString">
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
}
|
||||
</RadzenFieldset>
|
||||
|
||||
<!--Tx Rx-->
|
||||
<RadzenFieldset Style="width: 100%;" Text="Call API">
|
||||
<div>
|
||||
<RadzenButton Style="width:100%; margin-bottom: 0.5rem;" Text="@($"Generate Request {StrISO}")" Click="@OnClickGenerateTbscsr"></RadzenButton>
|
||||
<RadzenButton Style="width:100%;" Text="@($"Send Request")" Click="@OnClickSendTbscsr"></RadzenButton>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<RadzenLabel Text="Request"></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height: 180px;" @bind-Value=@TbscsrContainer.StrRequest>
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenLabel Text="Response"></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height: 180px;" @bind-Value=TbscsrContainer.StrResponse>
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired]
|
||||
public TbscsrContainer TbscsrContainer { get; set; } = new TbscsrContainer();
|
||||
[Parameter]
|
||||
public EventCallback<TbscsrContainer> TbscsrContainerChanged { get; set; }
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public string ServerAddress { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<TbscsrContainer> TbscsrCallback { get; set; }
|
||||
|
||||
//ISO
|
||||
private string StrISO = string.Empty;
|
||||
|
||||
//Key
|
||||
private string KeyPairString = string.Empty;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (string.IsNullOrEmpty(TbscsrContainer.RequestTbscsr.cnInfo.macaddr) == true)
|
||||
{
|
||||
TbscsrContainer.RequestTbscsr.cnInfo.macaddr = CreateRandomMacAddress();
|
||||
}
|
||||
|
||||
StrISO = $"{TbscsrContainer.ISOType.ToString().Replace("_", "-")}";
|
||||
|
||||
SetKeyPairString();
|
||||
}
|
||||
|
||||
//mac address
|
||||
private void OnClickRandomMacaddresss()
|
||||
{
|
||||
var randomMac = CreateRandomMacAddress();
|
||||
TbscsrContainer.RequestTbscsr.cnInfo.macaddr = randomMac;
|
||||
}
|
||||
|
||||
private string CreateRandomMacAddress()
|
||||
{
|
||||
Random rand = new Random();
|
||||
byte[] buffer = new byte[6];
|
||||
rand.NextBytes(buffer);
|
||||
return string.Join("", buffer.Select(x => x.ToString("X2")));
|
||||
}
|
||||
|
||||
//generate key
|
||||
private void OnClickGenerateKey()
|
||||
{
|
||||
GenerateKey();
|
||||
}
|
||||
|
||||
private void GenerateKey()
|
||||
{
|
||||
if (TbscsrContainer.ISOType == VpkiIsoType.ISO15118_02)
|
||||
{
|
||||
TbscsrContainer.KeyPair = CertificateService.GenerateBouncyCastleKeyPairECDH($"{CurveName.secp256r1}");
|
||||
var pKey = TbscsrContainer.PublicKey;
|
||||
}
|
||||
else if (TbscsrContainer.ISOType == VpkiIsoType.ISO15118_20)
|
||||
{
|
||||
TbscsrContainer.KeyPair = CertificateService.GenerateBouncyCastleKeyPairECDH($"{CurveName.secp521r1}");
|
||||
}
|
||||
|
||||
//public key
|
||||
var vnPubKey = CertificateService.GetPublicKeyArrayBC(CertificateService.GetPublicKeyBC(TbscsrContainer.KeyPair));
|
||||
if (vnPubKey != null)
|
||||
TbscsrContainer.PublicKey = CertificateService.GetKeyBase64Encrypted(vnPubKey);
|
||||
|
||||
//private key
|
||||
var vnPriKey = CertificateService.GetPrivateKeyArrayBC(CertificateService.GetPrivateKeyBC(TbscsrContainer.KeyPair));
|
||||
if (vnPriKey != null)
|
||||
TbscsrContainer.PrivateKey = CertificateService.GetKeyBase64Encrypted(vnPriKey);
|
||||
|
||||
List<byte> vnPubKeyRcv = CertificateService.GetKeyBase64Decrypted(TbscsrContainer.PublicKey);
|
||||
|
||||
var publicKey = (ECPublicKeyParameters)TbscsrContainer.KeyPair.Public;
|
||||
|
||||
SetKeyPairString();
|
||||
}
|
||||
|
||||
private void SetKeyPairString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(TbscsrContainer.PublicKey) == false && string.IsNullOrEmpty(TbscsrContainer.PrivateKey) == false)
|
||||
{
|
||||
KeyPairString = $"{StrISO} Public Key ({TbscsrContainer.PublicKey.Length} Bytes): {Environment.NewLine}{TbscsrContainer.PublicKey}{Environment.NewLine}{Environment.NewLine}Private Key ({TbscsrContainer.PrivateKey.Length} Bytes): {Environment.NewLine}{TbscsrContainer.PrivateKey}";
|
||||
}
|
||||
}
|
||||
|
||||
//request tbscsr
|
||||
private void OnClickGenerateTbscsr()
|
||||
{
|
||||
TbscsrContainer.RequestTbscsr.publickey = TbscsrContainer.PublicKey;
|
||||
TbscsrContainer.StrRequest = $"{TbscsrContainer.RequestTbscsr.ToJson()}";
|
||||
}
|
||||
|
||||
private async Task OnClickSendTbscsr()
|
||||
{
|
||||
DialogService.OpenIndicator();
|
||||
|
||||
try
|
||||
{
|
||||
var request = JsonConvert.DeserializeObject<Request_Tbscsr>(TbscsrContainer.StrRequest);
|
||||
if (request != null)
|
||||
{
|
||||
string url = $"api/v1/tbscsr";
|
||||
if (TbscsrContainer.VpkiType == VpkiType.prov_cert)
|
||||
{
|
||||
url = $"api/v2/prov/tbscsr";
|
||||
}
|
||||
else if (TbscsrContainer.VpkiType == VpkiType.vehicle_cert)
|
||||
{
|
||||
url = $"api/v2/vehicle/tbscsr";
|
||||
}
|
||||
|
||||
var Response = await ApiService.PostJsonAsync<Request_Tbscsr, Response_Tbscsr>($"https://{ServerAddress}/{url}", request);
|
||||
if (Response != null)
|
||||
{
|
||||
TbscsrContainer.ResponseTbscsr = Response;
|
||||
TbscsrContainer.StrResponse = $"{Response.ToJson()}";
|
||||
|
||||
await TbscsrCallback.InvokeAsync(TbscsrContainer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TbscsrContainer.StrResponse = "Request Context Error";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log4net.WriteLine(ex);
|
||||
TbscsrContainer.StrResponse = $"Request Context Error{Environment.NewLine}{ex.Message}";
|
||||
}
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
@using VPKI.Library.Packet
|
||||
|
||||
@inject CertificateService CertificateService
|
||||
@inject ApiService ApiService
|
||||
@inject VpkiDialogService DialogService
|
||||
|
||||
<RadzenFieldset Text="VerifyResult">
|
||||
<div style="display:flex">
|
||||
<RadzenFieldset Style="width: 100%; margin-right: 20px;" Text="Request VerifyResult">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="IFT ID"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@VerifyResultContainer.RequestVerifyresult.iftid"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="PCID"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@VerifyResultContainer.RequestVerifyresult.pcid"></RadzenTextBox>
|
||||
</div>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="RESULT"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@VerifyResultContainer.RequestVerifyresult.result"></RadzenTextBox>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
<RadzenFieldset Style="width:100%;" Text="Call API">
|
||||
<div>
|
||||
<RadzenButton Style="width:100%; margin-bottom: 0.5rem;" Text="@($"Generate Request {StrISO}")" Click="@OnClickGenerateVerifyResult"></RadzenButton>
|
||||
<RadzenButton Style="width:100%;" Text="Send Request" Click="@OnClickSendVerifyResult"></RadzenButton>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<RadzenLabel Text="Request"></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height: 180px;" @bind-Value=@VerifyResultContainer.StrRequest>
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenLabel Text="Response"></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height: 180px;" @bind-Value="@VerifyResultContainer.StrResponse">
|
||||
</RadzenTextArea>
|
||||
</div>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired]
|
||||
public VerifyResultContainer VerifyResultContainer { get; set; } = new VerifyResultContainer();
|
||||
[Parameter]
|
||||
public EventCallback<VerifyResultContainer> VerifyResultContainerChanged { get; set; }
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public string ServerAddress { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public TbscsrContainer TbscsrContainer { get; set; } = new TbscsrContainer();
|
||||
|
||||
//ISO
|
||||
private string StrISO = string.Empty;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
StrISO = $"{TbscsrContainer.ISOType.ToString().Replace("_", "-")}";
|
||||
}
|
||||
|
||||
private void OnClickGenerateVerifyResult()
|
||||
{
|
||||
VerifyResultContainer.StrRequest = $"{VerifyResultContainer.RequestVerifyresult.ToJson()}";
|
||||
}
|
||||
|
||||
private async Task OnClickSendVerifyResult()
|
||||
{
|
||||
DialogService.OpenIndicator();
|
||||
try
|
||||
{
|
||||
var request = JsonConvert.DeserializeObject<Request_Verifyresult>(VerifyResultContainer.StrRequest);
|
||||
if (request != null)
|
||||
{
|
||||
string url = $"api/v1/verifyresult";
|
||||
if (TbscsrContainer.VpkiType == VpkiType.prov_cert)
|
||||
{
|
||||
url = $"api/v2/prov/verifyresult";
|
||||
}
|
||||
else if (TbscsrContainer.VpkiType == VpkiType.vehicle_cert)
|
||||
{
|
||||
url = $"api/v2/vehicle/verifyresult";
|
||||
}
|
||||
|
||||
var Response = await ApiService.PostJsonAsync<Request_Verifyresult, Response_Verifyresult>($"https://{ServerAddress}/{url}", request);
|
||||
if (Response != null)
|
||||
{
|
||||
VerifyResultContainer.ResponseVerifyresult = Response;
|
||||
VerifyResultContainer.StrResponse = $"{Response.ToJson()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log4net.WriteLine(ex);
|
||||
VerifyResultContainer.StrResponse = $"Request Context Error{Environment.NewLine}{ex.Message}";
|
||||
}
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
@page "/Error"
|
||||
@using System.Diagnostics
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
@page "/"
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<AuthorizeView>
|
||||
<h1>Hello, @context.User.Identity?.Name!</h1>
|
||||
</AuthorizeView>
|
||||
|
||||
Welcome to your new app.
|
||||
@ -0,0 +1,68 @@
|
||||
@page "/login"
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ApiService ApiService
|
||||
@inject AuthenticationStateProvider AuthStateProvider
|
||||
@inject VpkiDialogService DialogService
|
||||
@inject IJSRuntime JS
|
||||
@inject NotificationService NotiService
|
||||
|
||||
<AuthorizeView Context="ContextAuth">
|
||||
<NotAuthorized>
|
||||
<div class="p-5">
|
||||
<EditForm Model="@LoginModel" FormName="Login" OnValidSubmit="HandleLogin" Context="ContextLogin">
|
||||
<DataAnnotationsValidator />
|
||||
<div class="form-group">
|
||||
<label for="username">UserID</label>
|
||||
<InputText id="username" class="form-control" @bind-Value="@LoginModel.UserID"></InputText>
|
||||
</div>
|
||||
<br />
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<InputText id="password" class="form-control" type="password" @bind-Value="@LoginModel.Password"></InputText>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-3">Login</button>
|
||||
</EditForm>
|
||||
<RadzenLabel Style="color: red; margin-top: 5px;">@ErrorCode</RadzenLabel>
|
||||
</div>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
|
||||
@code {
|
||||
private LoginModel LoginModel = new LoginModel();
|
||||
private string ErrorCode = string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var auth = await((ExtendAuthenticationStatProvicer)AuthStateProvider).GetAuthenticationStateAsync();
|
||||
if(auth?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleLogin()
|
||||
{
|
||||
DialogService.OpenIndicator("Login");
|
||||
|
||||
//password hash
|
||||
LoginModel.Password = $"{LoginModel.Password?.StringToSHA256Base64()}";
|
||||
ErrorCode = string.Empty;
|
||||
|
||||
var res = await ApiService.PostJsonAsyncBearer<LoginModel, LoginResponseModel>($"/api/auth/login", LoginModel);
|
||||
if (res?.AccessToken != null)
|
||||
{
|
||||
await ((ExtendAuthenticationStatProvicer)AuthStateProvider).MakeUserAsAuthenticated(res);
|
||||
NavigationManager.NavigateTo("/", true);
|
||||
NotiService.Notify(NotificationSeverity.Success, "Login", "Login Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
LoginModel.Password = string.Empty;
|
||||
ErrorCode = $"{res?.EC.ToString()}";
|
||||
NotiService.Notify(NotificationSeverity.Error, "Login", "Login Failed");
|
||||
}
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
@page "/register"
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ApiService ApiService
|
||||
@inject AuthenticationStateProvider AuthStateProvider
|
||||
|
||||
<AuthorizeView Context="ContextAuth">
|
||||
<NotAuthorized>
|
||||
@if (string.IsNullOrEmpty(RegisterUserID) == false)
|
||||
{
|
||||
<h5>Register Success!</h5>
|
||||
<h5>@($"UserID: {RegisterUserID}")</h5>
|
||||
<br />
|
||||
<RadzenButton Click="@OnClickGotoLogin">Go to Login</RadzenButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="p-5">
|
||||
<EditForm Model="@RegisterModel" FormName="Register" OnValidSubmit="HandleRegister" Context="ContextRegister">
|
||||
<DataAnnotationsValidator />
|
||||
<div class="form-group">
|
||||
<label for="username">UserID</label>
|
||||
<InputText id="username" class="form-control" @bind-Value="@RegisterModel.UserID"></InputText>
|
||||
</div>
|
||||
<br />
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<InputText id="password" class="form-control" type="password" @bind-Value="@RegisterModel.Password"></InputText>
|
||||
</div>
|
||||
<br />
|
||||
<div class="form-group">
|
||||
<label for="password">Password Confirm</label>
|
||||
<InputText id="password" class="form-control" type="password" @bind-Value="@RegisterModel.PasswordConfirm"></InputText>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-3">Register</button>
|
||||
</EditForm>
|
||||
<RadzenLabel Style="color: red; margin-top: 5px;">@ErrorCode</RadzenLabel>
|
||||
</div>
|
||||
}
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
|
||||
@code {
|
||||
private RegisterModel RegisterModel = new RegisterModel();
|
||||
private string ErrorCode = string.Empty;
|
||||
private string RegisterUserID = string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
RegisterUserID = string.Empty;
|
||||
var auth = await ((ExtendAuthenticationStatProvicer)AuthStateProvider).GetAuthenticationStateAsync();
|
||||
if (auth?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
NavigationManager.NavigateTo("/");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleRegister()
|
||||
{
|
||||
ErrorCode = string.Empty;
|
||||
if (RegisterModel.Password != RegisterModel.PasswordConfirm)
|
||||
{
|
||||
ErrorCode = ERROR_CODE.EC_USER_REGISTER_CONFIRM_PASSWORD_ERROR.ToString();
|
||||
return;
|
||||
}
|
||||
|
||||
//password hash
|
||||
RegisterModel.Password = $"{RegisterModel.Password?.StringToSHA256Base64()}";
|
||||
RegisterModel.PasswordConfirm = $"{RegisterModel.PasswordConfirm?.StringToSHA256Base64()}";
|
||||
var res = await ApiService.PostJsonAsyncBearer<RegisterModel, RegisterResponseModel>($"/api/auth/regisger", RegisterModel);
|
||||
if (res != null)
|
||||
{
|
||||
if (res.EC == ERROR_CODE.EC_OK)
|
||||
{
|
||||
RegisterUserID = $"{res.UserID}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClickGotoLogin()
|
||||
{
|
||||
NavigationManager.NavigateTo("/login");
|
||||
}
|
||||
}
|
||||
123
Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/User.razor
Normal file
123
Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/User.razor
Normal file
@ -0,0 +1,123 @@
|
||||
@page "/user"
|
||||
|
||||
@inject ApiService ApiService
|
||||
@inject VpkiDialogService DialogService
|
||||
@inject IJSRuntime JS
|
||||
@inject NotificationService NotiService
|
||||
|
||||
<AuthorizeView Roles="@($"{UserRole.SuperUser.ToString()}")">
|
||||
<Authorized>
|
||||
<!--DataGrid-->
|
||||
@if (data?.Count > 0)
|
||||
{
|
||||
<RadzenDataGrid @ref="@grid" Data="@data" TItem="UserModel" EditMode="DataGridEditMode.Single">
|
||||
<Columns>
|
||||
<RadzenDataGridColumn Title="UserID" Property="UserModel.TUser.CUserId" />
|
||||
<RadzenDataGridColumn Title="Role" Property="UserModel.TRole.CRoleName">
|
||||
<Template Context="user">
|
||||
@{
|
||||
string? state = $"auth-{user.TRole.CRoleName.ToLower()}";
|
||||
}
|
||||
<label class="@state">@($"{(UserRole)Enum.Parse(typeof(UserRole), user.TRole.CRoleId.ToString())}")</label>
|
||||
</Template>
|
||||
<EditTemplate Context="user">
|
||||
@{
|
||||
var roleList = Enum.GetValues(typeof(UserRole)).Cast<UserRole>().Where(x => 10 <= (byte)x);
|
||||
<RadzenDropDown Data="@roleList" @bind-Value="@user.TRole.CRoleId">
|
||||
<Template Context="role">
|
||||
@($"{Enum.GetName(typeof(UserRole), role)}")
|
||||
</Template>
|
||||
</RadzenDropDown>
|
||||
}
|
||||
</EditTemplate>
|
||||
</RadzenDataGridColumn>
|
||||
<RadzenDataGridColumn Title="CreateDateTime" Property="UserModel.TUser.CCreateDateTime" />
|
||||
<RadzenDataGridColumn Title="LastLoginDateTime" Property="UserModel.TUser.CLastLoginDateTime" />
|
||||
<RadzenDataGridColumn Title="State" Property="UserModel.TUser.CState">
|
||||
<Template Context="user">
|
||||
@{
|
||||
string? state = $"user-{Enum.GetName(typeof(UserState), user.TUser.CState).ToLower()}";
|
||||
}
|
||||
<label class="@state">@($"{(UserState)Enum.Parse(typeof(UserState), user.TUser.CState.ToString())} ({user.TUser.CState})")</label>
|
||||
</Template>
|
||||
<EditTemplate Context="user">
|
||||
@{
|
||||
var stateList = Enum.GetValues(typeof(UserState)).Cast<UserState>();
|
||||
<RadzenDropDown Data="@stateList" @bind-Value="@user.TUser.CState">
|
||||
<Template Context="state">
|
||||
@($"{Enum.GetName(typeof(UserState), state)} ({Convert.ToByte(state)})")
|
||||
</Template>
|
||||
</RadzenDropDown>
|
||||
}
|
||||
</EditTemplate>
|
||||
</RadzenDataGridColumn>
|
||||
<!--edit-->
|
||||
<RadzenDataGridColumn Title="Edit" TextAlign="TextAlign.Center">
|
||||
<Template Context="user">
|
||||
@if (user.TRole.CAuid.ToLower() != UserRole.SuperUser.ToString().ToLower())
|
||||
{
|
||||
<RadzenButton Text="Edit" Style="background: #7E57C2;" Click="@(()=>OnClickUserEdit(user))" Disabled="@isEditing" />
|
||||
}
|
||||
</Template>
|
||||
<EditTemplate Context="user">
|
||||
<RadzenButton Text="Apply" Style="color:black;" ButtonStyle="ButtonStyle.Warning" Click="@(()=>OnClickUserEditApply(user))"></RadzenButton>
|
||||
<RadzenButton Text="Cancel" Style="color:black;" ButtonStyle="ButtonStyle.Danger" Click="@(()=>OnClickUserEditCancel(user))"></RadzenButton>
|
||||
</EditTemplate>
|
||||
</RadzenDataGridColumn>
|
||||
</Columns>
|
||||
</RadzenDataGrid>
|
||||
}
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<RadzenLabel Text="Not Authorized"></RadzenLabel>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
|
||||
@code {
|
||||
List<UserModel> data = new List<UserModel>();
|
||||
RadzenDataGrid<UserModel>? grid;
|
||||
bool isEditing = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await GetAllUsers();
|
||||
}
|
||||
|
||||
private async Task OnClickUserEdit(UserModel user)
|
||||
{
|
||||
isEditing = true;
|
||||
await grid?.EditRow(user);
|
||||
}
|
||||
|
||||
private async Task OnClickUserEditApply(UserModel user)
|
||||
{
|
||||
bool confirm = await DialogService.Confirm("Edit User", "Apply Edit User?");
|
||||
if(confirm == true)
|
||||
{
|
||||
user.TRole.CRoleName = $"{Enum.GetName(typeof(UserRole), user.TRole.CRoleId)}";
|
||||
var retunUser = await ApiService.PostJsonAsyncBearer<UserModel, UserModel>("/api/user/UpdateUser", user);
|
||||
if (retunUser != null)
|
||||
{
|
||||
await GetAllUsers();
|
||||
NotiService.Notify(NotificationSeverity.Success, "Edit User",$"Edit '{user.TUser.CUserId}' Update Success");
|
||||
}
|
||||
}
|
||||
|
||||
isEditing = false;
|
||||
}
|
||||
|
||||
private async Task OnClickUserEditCancel(UserModel user)
|
||||
{
|
||||
await GetAllUsers();
|
||||
isEditing = false;
|
||||
}
|
||||
|
||||
private async Task GetAllUsers()
|
||||
{
|
||||
var response = await ApiService.GetJsonAsyncBearer<List<UserModel>>("/api/user/GetAllUser");
|
||||
if (response != null)
|
||||
{
|
||||
data = response.OrderBy(x=>x.TUser.CCreateDateTime).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
.user-inactive{
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
.user-active {
|
||||
color: lime;
|
||||
}
|
||||
|
||||
.user-block{
|
||||
color: #f9777f;
|
||||
}
|
||||
|
||||
.auth-superuser {
|
||||
color: #FF5722;
|
||||
}
|
||||
|
||||
.auth-admin {
|
||||
color: #FFEB3B;
|
||||
}
|
||||
|
||||
.auth-user {
|
||||
color: #03A9F4;
|
||||
}
|
||||
@ -0,0 +1,232 @@
|
||||
@page "/Vpki/Api"
|
||||
@using Newtonsoft.Json
|
||||
@using Org.BouncyCastle.Crypto
|
||||
@using VPKI.Library.Packet
|
||||
@using VPKI.Library.Services
|
||||
|
||||
@inject CertificateService csrSrvice;
|
||||
@inject ApiService ApiService;
|
||||
|
||||
<h3>VPKI API</h3>
|
||||
<AuthorizeView Roles="@($"{UserRole.Admin.ToString()},{UserRole.SuperUser.ToString()}")">
|
||||
<Authorized>
|
||||
<RadzenFieldset Style="margin-bottom: 10px;" Text="Server Info">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Server Address"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@ServerAddress"></RadzenTextBox>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
<RadzenTabs>
|
||||
<Tabs>
|
||||
@foreach (var vpkiType in Enum.GetValues(typeof(VpkiType)))
|
||||
{
|
||||
if (DicTbscsrContainer.TryGetValue((VpkiType)vpkiType, out var outTbscsr) == true &&
|
||||
DicCertificateContainer.TryGetValue((VpkiType)vpkiType, out var outCertificate) == true &&
|
||||
DicVerifyResultContainer.TryGetValue((VpkiType)vpkiType, out var outVeryfiResult) == true)
|
||||
{
|
||||
<RadzenTabsItem Text="@vpkiType.ToString()">
|
||||
<div @key=@vpkiType>
|
||||
<!--CSR-->
|
||||
<VPKIApiTbscsr @bind-TbscsrContainer=@outTbscsr ServerAddress="@ServerAddress"
|
||||
TbscsrCallback="@TbscsrCallback"/>
|
||||
<br />
|
||||
|
||||
<!--certificate-->
|
||||
<VPKIApiCertificate @bind-CertificateContainer=@outCertificate ServerAddress="@ServerAddress" TbscsrContainer="@outTbscsr" />
|
||||
<br />
|
||||
|
||||
<!--certificate-->
|
||||
<VPKIApiVerifyResult @bind-VerifyResultContainer=@outVeryfiResult ServerAddress="@ServerAddress" TbscsrContainer="@outTbscsr" />
|
||||
</div>
|
||||
</RadzenTabsItem>
|
||||
}
|
||||
}
|
||||
</Tabs>
|
||||
</RadzenTabs>
|
||||
<br />
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<RadzenLabel Text="Not Authorized"></RadzenLabel>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
@code {
|
||||
private string ServerAddress = "127.0.0.1:8080";
|
||||
|
||||
Dictionary<VpkiType, TbscsrContainer> DicTbscsrContainer = new Dictionary<VpkiType, TbscsrContainer>();
|
||||
Dictionary<VpkiType, CertificateContainer> DicCertificateContainer = new Dictionary<VpkiType, CertificateContainer>();
|
||||
Dictionary<VpkiType, VerifyResultContainer> DicVerifyResultContainer = new Dictionary<VpkiType, VerifyResultContainer>();
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
SetDefaultValue();
|
||||
}
|
||||
|
||||
private void SetDefaultValue()
|
||||
{
|
||||
//tbscsr
|
||||
DicTbscsrContainer.Add(VpkiType.prov_v1, new TbscsrContainer
|
||||
{
|
||||
RequestTbscsr = new Request_Tbscsr
|
||||
{
|
||||
iftid = "ift_1",
|
||||
certInfo = new Request_Tbscsr.CertInfo
|
||||
{
|
||||
tierCode = "P002",
|
||||
unitCode = "C001",
|
||||
dc = "OEM"
|
||||
},
|
||||
cnInfo = new Request_Tbscsr.CnInfo
|
||||
{
|
||||
idType = "P",
|
||||
supplierId = "2",
|
||||
wmi = "KM8",
|
||||
macaddr = ""
|
||||
}
|
||||
},
|
||||
VpkiType = VpkiType.prov_v1,
|
||||
ISOType = VpkiIsoType.ISO15118_02
|
||||
});
|
||||
|
||||
DicTbscsrContainer.Add(VpkiType.prov_cert, new TbscsrContainer
|
||||
{
|
||||
RequestTbscsr = new Request_Tbscsr
|
||||
{
|
||||
iftid = "ift_2",
|
||||
certInfo = new Request_Tbscsr.CertInfo
|
||||
{
|
||||
tierCode = "P002",
|
||||
unitCode = "C001",
|
||||
dc = "OEM20"
|
||||
},
|
||||
cnInfo = new Request_Tbscsr.CnInfo
|
||||
{
|
||||
idType = "P",
|
||||
supplierId = "2",
|
||||
wmi = "KM7",
|
||||
macaddr = ""
|
||||
},
|
||||
certType = $"{VpkiType.prov_cert}"
|
||||
},
|
||||
VpkiType = VpkiType.prov_cert,
|
||||
ISOType = VpkiIsoType.ISO15118_20
|
||||
});
|
||||
|
||||
DicTbscsrContainer.Add(VpkiType.vehicle_cert, new TbscsrContainer
|
||||
{
|
||||
RequestTbscsr = new Request_Tbscsr
|
||||
{
|
||||
iftid = "ift_3",
|
||||
certInfo = new Request_Tbscsr.CertInfo
|
||||
{
|
||||
tierCode = "P002",
|
||||
unitCode = "C001",
|
||||
dc = "EV"
|
||||
},
|
||||
cnInfo = new Request_Tbscsr.CnInfo
|
||||
{
|
||||
idType = "V",
|
||||
supplierId = "2",
|
||||
wmi = "KM7",
|
||||
macaddr = ""
|
||||
},
|
||||
certType = $"{VpkiType.vehicle_cert}"
|
||||
},
|
||||
VpkiType = VpkiType.vehicle_cert,
|
||||
ISOType = VpkiIsoType.ISO15118_20
|
||||
});
|
||||
|
||||
//certificate
|
||||
DicCertificateContainer.Add(VpkiType.prov_v1, new CertificateContainer
|
||||
{
|
||||
RequestCertificate = new Request_Certificate
|
||||
{
|
||||
iftid = "ift_1",
|
||||
csrsignature = string.Empty,
|
||||
tierCode = "P002",
|
||||
unitCode = "C001",
|
||||
vehicleCode = "MV EV",
|
||||
localCode = "EU",
|
||||
brandCode = "KMC"
|
||||
}
|
||||
});
|
||||
|
||||
DicCertificateContainer.Add(VpkiType.prov_cert, new CertificateContainer
|
||||
{
|
||||
RequestCertificate = new Request_Certificate
|
||||
{
|
||||
iftid = "ift_2",
|
||||
csrsignature = string.Empty,
|
||||
tierCode = "P002",
|
||||
unitCode = "C001",
|
||||
vehicleCode = "MV EV",
|
||||
localCode = "EU",
|
||||
brandCode = "KMC"
|
||||
}
|
||||
});
|
||||
|
||||
DicCertificateContainer.Add(VpkiType.vehicle_cert, new CertificateContainer
|
||||
{
|
||||
RequestCertificate = new Request_Certificate
|
||||
{
|
||||
iftid = "ift_3",
|
||||
csrsignature = string.Empty,
|
||||
tierCode = "P002",
|
||||
unitCode = "C001",
|
||||
vehicleCode = "MV EV",
|
||||
localCode = "EU",
|
||||
brandCode = "KMC"
|
||||
}
|
||||
});
|
||||
|
||||
DicVerifyResultContainer.Add(VpkiType.prov_v1, new VerifyResultContainer
|
||||
{
|
||||
RequestVerifyresult = new Request_Verifyresult
|
||||
{
|
||||
iftid = "ift_1",
|
||||
pcid = "",
|
||||
result = "success"
|
||||
}
|
||||
});
|
||||
|
||||
DicVerifyResultContainer.Add(VpkiType.prov_cert, new VerifyResultContainer
|
||||
{
|
||||
RequestVerifyresult = new Request_Verifyresult
|
||||
{
|
||||
iftid = "ift_2",
|
||||
pcid = "",
|
||||
result = "success"
|
||||
}
|
||||
});
|
||||
|
||||
DicVerifyResultContainer.Add(VpkiType.vehicle_cert, new VerifyResultContainer
|
||||
{
|
||||
RequestVerifyresult = new Request_Verifyresult
|
||||
{
|
||||
iftid = "ift_3",
|
||||
pcid = "",
|
||||
result = "success"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task TbscsrCallback(TbscsrContainer args)
|
||||
{
|
||||
if (DicCertificateContainer.TryGetValue(args.VpkiType, out var outCertificate) == true)
|
||||
{
|
||||
outCertificate.RequestCertificate.iftid = args.RequestTbscsr.iftid;
|
||||
outCertificate.RequestCertificate.tierCode = args.RequestTbscsr.certInfo.tierCode;
|
||||
outCertificate.RequestCertificate.unitCode = args.RequestTbscsr.certInfo.unitCode;
|
||||
|
||||
outCertificate.RequestCertificate.csrsignature = args.ResponseTbscsr.data.hashedtbscsr;
|
||||
}
|
||||
|
||||
if (DicVerifyResultContainer.TryGetValue(args.VpkiType, out var outVerifyResult) == true)
|
||||
{
|
||||
outVerifyResult.RequestVerifyresult.iftid = args.RequestTbscsr.iftid;
|
||||
outVerifyResult.RequestVerifyresult.pcid = args.ResponseTbscsr.data.pcid;
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,520 @@
|
||||
@page "/vpki/manager"
|
||||
@using DB.VPKI_DataDB
|
||||
@using System.Text
|
||||
@using VPKI.Library.Packet
|
||||
@using VPKI.Library.Static
|
||||
|
||||
@inject ApiService ApiService
|
||||
@inject VpkiDialogService DialogService
|
||||
@inject IJSRuntime JS
|
||||
@inject NotificationService NotiService
|
||||
@inject TooltipService TooltipService
|
||||
|
||||
<h3>VPKI MANAGER</h3>
|
||||
|
||||
<AuthorizeView Roles="@($"{UserRole.Admin.ToString()},{UserRole.SuperUser.ToString()}")">
|
||||
<Authorized Context="AuthContext">
|
||||
<RadzenFieldset Style="margin-bottom: 10px;" Text="Server Info">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<RadzenLabel Style="width: 130px;" Text="Server Address"></RadzenLabel>
|
||||
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@ServerAddress"></RadzenTextBox>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
|
||||
<RadzenFieldset Style="margin-bottom: 10px;" Text="View Options">
|
||||
<div style="margin-bottom: 10px;">
|
||||
<!--date-->
|
||||
<RadzenLabel Style="margin-right: 5px;" Text="Date"></RadzenLabel>
|
||||
<RadzenDatePicker Style="margin-right: 5px;" @bind-Value="@SearchStartDate" DateFormat="yyyy/MM/dd" />
|
||||
|
||||
<RadzenLabel Style="margin-right: 5px;" Text="~"></RadzenLabel>
|
||||
<RadzenDatePicker Style="margin-right: 10px;" @bind-Value="@SearchEndDate" DateFormat="yyyy/MM/dd" />
|
||||
|
||||
<RadzenButton Style="margin-right: 30px;" Click="@(()=>Search(0))">Search</RadzenButton>
|
||||
|
||||
<!--vew Count-->
|
||||
<RadzenLabel Style="margin-right: 5px;" Text="ViewCount (20~100)"></RadzenLabel>
|
||||
<RadzenNumeric @bind-Value=@ViewCount Min=20 Max=100></RadzenNumeric>
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
<br />
|
||||
<!--count-->
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 0.7rem;">
|
||||
<div style="display: flex; align-items:center;">
|
||||
<RadzenLabel Style="color:#BA68C8; font-weight: 600; font-size: 1.1rem; margin-right: 1.2rem;" Text=@($"Total Count: {history.Count}")></RadzenLabel>
|
||||
<RadzenLabel Style="color:#64B5F6; font-weight: 600; font-size: 1.1rem;" Text=@($"Filter Count: {grid.View.Count()}")></RadzenLabel>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenButton Style="background: #7E57C2; margin-right: 0.5rem;" Text="Export CSV(Full Data)" Click="@(()=>OnClickExportCSV(false))"></RadzenButton>
|
||||
<RadzenButton Style="background: #1976D2;" Text="Export CSV(Filter Data)" Click="@(()=>OnClickExportCSV(true))"></RadzenButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RadzenDataGrid @ref="@grid" Data="@history" TItem="CertificateHistoryModel" AllowFiltering FilterMode="FilterMode.Simple"
|
||||
AllowPaging PageNumbersCount="10" PageSize="@ViewCount" PagerHorizontalAlign="HorizontalAlign.Center" AllowSorting RowExpand="@((args)=>OnExpand(args))"
|
||||
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" Filter="@OnChangeFilter" FilterCleared="@OnChangeFilter">
|
||||
<Columns>
|
||||
|
||||
<!--index or no-->
|
||||
@* <RadzenDataGridColumn Title="No">
|
||||
<Template>
|
||||
@(history.IndexOf(context)+1)
|
||||
</Template>
|
||||
</RadzenDataGridColumn> *@
|
||||
|
||||
<!--data-->
|
||||
@foreach (var prop in typeof(TTbscsr).GetProperties())
|
||||
{
|
||||
if (prop.Name.ToLower().Contains("hashedtbscsr") || prop.Name.ToLower().Contains("publickey") || prop.Name.ToLower().Contains("origintbscsr")
|
||||
|| prop.Name.ToLower().Contains("csrsignature") || prop.Name.ToLower().Contains("datetime") || prop.Name.ToLower().Contains("cdn"))
|
||||
continue;
|
||||
|
||||
string propName = $"{prop.Name}";
|
||||
<RadzenDataGridColumn Title="@propName" Property=@($"TTbscsr.{propName}") />
|
||||
}
|
||||
<!--date time-->
|
||||
<RadzenDataGridColumn Width="9rem" Title="CDATETIME">
|
||||
<Template>
|
||||
@{
|
||||
<div style="font-size: 0.8rem;">
|
||||
<RadzenLabel Text="Tbscsr DateTime"></RadzenLabel>
|
||||
<br />
|
||||
<RadzenLabel Text="@context?.TTbscsr?.CDateTime.ToString("yyyy-MM-dd HH:mm:ss")"></RadzenLabel>
|
||||
<br />
|
||||
<RadzenLabel Text="Certificate DateTime"></RadzenLabel>
|
||||
<br />
|
||||
<RadzenLabel Text="@context?.TCertificate?.CDateTime.ToString("yyyy-MM-dd HH:mm:ss")"></RadzenLabel>
|
||||
</div>
|
||||
}
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
|
||||
<!--Reissue, Revoke-->
|
||||
@* <RadzenDataGridColumn Title="Reissue">
|
||||
<Template>
|
||||
@{
|
||||
bool canReissue = string.IsNullOrEmpty($"{context.TCertificate?.CCsr}");
|
||||
|
||||
<RadzenButton Style="width:100%; color:black;" Text="Reissue" Disabled=@canReissue
|
||||
ButtonStyle="ButtonStyle.Warning" Click="@(()=>OnClickReissue(context))"></RadzenButton>
|
||||
}
|
||||
</Template>
|
||||
</RadzenDataGridColumn> *@
|
||||
@* <RadzenDataGridColumn Title="Revoke">
|
||||
<Template>
|
||||
@{
|
||||
bool canRevoke = true;
|
||||
canRevoke = !(context.TCertificate?.CIssueCount > 0);
|
||||
}
|
||||
<RadzenButton Style="width:100%; color: black;" Text="Revoke" Disabled=@canRevoke
|
||||
ButtonStyle="ButtonStyle.Danger" Click="@(()=>OnClickRevoke(context))"></RadzenButton>
|
||||
</Template>
|
||||
</RadzenDataGridColumn> *@
|
||||
</Columns>
|
||||
<Template>
|
||||
<!--tbscsr-->
|
||||
<div style="display:flex; align-items: center; margin-bottom: 0.2rem;">
|
||||
<RadzenLabel Text="Tbscsr" Style="margin-right: 0.5rem;"></RadzenLabel>
|
||||
<RadzenIcon Icon="description" Style="cursor: pointer;" MouseEnter="@(args => TooltipService.Open(args, "Copy"))" @onclick="@(()=>OnClickCopy(context?.TTbscsr?.ToJson()))"></RadzenIcon>
|
||||
</div>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context?.TTbscsr?.ToJson()" ReadOnly></RadzenTextArea>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<!--certificate-->
|
||||
<RadzenLabel Text="TCertificate"></RadzenLabel>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context?.TCertificate?.ToJson()" ReadOnly></RadzenTextArea>
|
||||
</div>
|
||||
@{
|
||||
bool canDownload = string.IsNullOrEmpty($"{context.TCertificate?.CCert}");
|
||||
}
|
||||
<RadzenButton Style="background: #7E57C2;" Text="Certificate Download" Click="@(()=>OnClickExportCertificate(context))" Disabled="@canDownload"></RadzenButton>
|
||||
<RadzenButton Style="background: #1976D2;" Text="SubCA Certificate Download" Click="@(()=>OnClickExportSubCACertificate(context))" Disabled="@canDownload"></RadzenButton>
|
||||
<br />
|
||||
<br />
|
||||
<!--verify result-->
|
||||
<RadzenLabel Text="TVerifyResult"></RadzenLabel>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context?.TVerifyResult?.ToJson()" ReadOnly></RadzenTextArea>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
@if (context.TTbscsr.CCertType == VpkiType.prov_v1.ToString())
|
||||
{
|
||||
<!--certificate info-->
|
||||
<RadzenLabel Text="TOcsp"></RadzenLabel>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context.TOcsp?.ToJson()" ReadOnly></RadzenTextArea>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<!--ocsp-->
|
||||
<RadzenLabel Text="OCSP"></RadzenLabel>
|
||||
<div>
|
||||
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context.TOcsp?.COcsp" ReadOnly></RadzenTextArea>
|
||||
</div>
|
||||
<RadzenButton Style="background: #7E57C2;" Text="OCSP Download" Click="@(()=>OnClickOcspDownload(context))"></RadzenButton>
|
||||
}
|
||||
</Template>
|
||||
</RadzenDataGrid>
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<RadzenLabel Text="Not Authorized"></RadzenLabel>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
|
||||
@code {
|
||||
private string ServerAddress = "127.0.0.1:8080";
|
||||
|
||||
private DateOnly SearchStartDate = DateOnly.FromDateTime(DateTime.Now.AddDays(-7));
|
||||
private DateOnly SearchEndDate = DateOnly.FromDateTime(DateTime.Now);
|
||||
|
||||
private string FilterIft = string.Empty;
|
||||
private string FilterWMI = string.Empty;
|
||||
private string FilterDC = string.Empty;
|
||||
private string FilterCertType = string.Empty;
|
||||
|
||||
private int ViewCount = 20;
|
||||
|
||||
List<CertificateHistoryModel> history = new List<CertificateHistoryModel>();
|
||||
RadzenDataGrid<CertificateHistoryModel> grid = new();
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
//await Search(0);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task Search(int startCcuid)
|
||||
{
|
||||
DialogService.OpenIndicator("Search History");
|
||||
|
||||
string requestUrl = $"https://{ServerAddress}/history?";
|
||||
|
||||
//Default filter
|
||||
requestUrl += $"startDate={SearchStartDate}&";
|
||||
requestUrl += $"endDate={SearchEndDate}&";
|
||||
requestUrl += $"startCcuid={startCcuid}&";
|
||||
|
||||
//optional filter
|
||||
if (string.IsNullOrEmpty(FilterIft) == false)
|
||||
{
|
||||
requestUrl += $"ift={FilterIft}&";
|
||||
}
|
||||
if (string.IsNullOrEmpty(FilterWMI) == false)
|
||||
{
|
||||
requestUrl += $"wmi={FilterWMI}&";
|
||||
}
|
||||
if (string.IsNullOrEmpty(FilterDC) == false)
|
||||
{
|
||||
requestUrl += $"dc={FilterDC}&";
|
||||
}
|
||||
if (string.IsNullOrEmpty(FilterCertType) == false)
|
||||
{
|
||||
requestUrl += $"certType={FilterCertType}&";
|
||||
}
|
||||
|
||||
history?.Clear();
|
||||
var result = await ApiService.GetJsonAsync<List<CertificateHistoryModel>>(requestUrl);
|
||||
if (result != null)
|
||||
{
|
||||
history.AddRange(result);
|
||||
history.Reverse();
|
||||
}
|
||||
grid?.Reload();
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
private async Task OnClickReissue(CertificateHistoryModel args)
|
||||
{
|
||||
var confirmRsult = await DialogService.Confirm("Reissue", "Are you sure certificate reissue?");
|
||||
if (confirmRsult == false)
|
||||
return;
|
||||
|
||||
DialogService.OpenIndicator("Reissue");
|
||||
|
||||
Request_Certificate requestReissue = new Request_Certificate
|
||||
{
|
||||
iftid = args.TTbscsr.CIftid,
|
||||
csrsignature = args.TCertificate.CCsrsignature,
|
||||
tierCode = args.TCertificate.CTierCode,
|
||||
unitCode = args.TCertificate.CUnitCode,
|
||||
vehicleCode = args.TCertificate.CVehicleCode,
|
||||
localCode = args.TCertificate.CLocalCode,
|
||||
brandCode = args.TCertificate.CBrandCode
|
||||
};
|
||||
|
||||
string api = string.Empty;
|
||||
if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_v1.ToString())
|
||||
{
|
||||
api = "api/v1/reissue";
|
||||
}
|
||||
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_cert.ToString())
|
||||
{
|
||||
api = "api/v2/prov/reissue";
|
||||
}
|
||||
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.vehicle_cert.ToString())
|
||||
{
|
||||
api = "api/v2/vehicle/reissue";
|
||||
}
|
||||
|
||||
var result = await ApiService.PostJsonAsync<Request_Certificate, Response_Certificate>($"https://{ServerAddress}/{api}", requestReissue);
|
||||
if (result != null)
|
||||
{
|
||||
string requestUrl = $"https://{ServerAddress}/history/ccuid?ccuid={args.TTbscsr.CCuid}";
|
||||
var updateResult = await ApiService.GetJsonAsync<CertificateHistoryModel>(requestUrl);
|
||||
if (updateResult != null)
|
||||
{
|
||||
args.TTbscsr = updateResult.TTbscsr;
|
||||
args.TCertificate = updateResult.TCertificate;
|
||||
args.TVerifyResult = updateResult.TVerifyResult;
|
||||
args.TOcsp = updateResult.TOcsp;
|
||||
}
|
||||
NotiService.Notify(NotificationSeverity.Success, "Reissue", "Reissue Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(NotificationSeverity.Error, "Reissue", "Reissue Failed");
|
||||
}
|
||||
|
||||
await grid?.CollapseAll();
|
||||
await grid?.Reload();
|
||||
|
||||
StateHasChanged();
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
private async Task OnClickRevoke(CertificateHistoryModel args)
|
||||
{
|
||||
var confirmRsult = await DialogService.Confirm("Revoke", "Are you sure certificate revoke?");
|
||||
if (confirmRsult == false)
|
||||
return;
|
||||
|
||||
DialogService.OpenIndicator("Revoke");
|
||||
Request_CertificateRevokeOEM requestRevoke = new Request_CertificateRevokeOEM
|
||||
{
|
||||
dn = args.TTbscsr.CDn
|
||||
};
|
||||
|
||||
string api = string.Empty;
|
||||
if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_v1.ToString())
|
||||
{
|
||||
api = "api/v1/revoke";
|
||||
}
|
||||
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_cert.ToString())
|
||||
{
|
||||
api = "api/v2/prov/revoke";
|
||||
}
|
||||
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.vehicle_cert.ToString())
|
||||
{
|
||||
api = "api/v2/vehicle/revoke";
|
||||
}
|
||||
|
||||
var result = await ApiService.PostJsonAsync<Request_CertificateRevokeOEM, Response_CertificateRevokeOEM>($"https://{ServerAddress}/{api}", requestRevoke);
|
||||
if (result != null)
|
||||
{
|
||||
string requestUrl = $"https://{ServerAddress}/history/ccuid?ccuid={args.TTbscsr.CCuid}";
|
||||
var updateResult = await ApiService.GetJsonAsync<CertificateHistoryModel>(requestUrl);
|
||||
if (updateResult != null)
|
||||
{
|
||||
args.TTbscsr = updateResult.TTbscsr;
|
||||
args.TCertificate = updateResult.TCertificate;
|
||||
args.TVerifyResult = updateResult.TVerifyResult;
|
||||
args.TOcsp = updateResult.TOcsp;
|
||||
}
|
||||
NotiService.Notify(NotificationSeverity.Success, "Revoke", "Revoke Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(NotificationSeverity.Error, "Revoke", "Revoke Failed");
|
||||
}
|
||||
|
||||
await grid?.CollapseAll();
|
||||
await grid?.Reload();
|
||||
StateHasChanged();
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
async Task OnClickExportCSV(bool isFilter = false)
|
||||
{
|
||||
DialogService.OpenIndicator("Export to CSV");
|
||||
List<string> exportData = new List<string>();
|
||||
|
||||
if (isFilter == true)
|
||||
{
|
||||
//필터링된 데이터만
|
||||
exportData.AddRange(grid.View.ToList().ConvertToCsvFile());
|
||||
}
|
||||
else
|
||||
{
|
||||
//전체 데이터
|
||||
exportData.AddRange(history.ConvertToCsvFile());
|
||||
}
|
||||
|
||||
if (exportData?.Count > 0)
|
||||
{
|
||||
string fileName = $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv";
|
||||
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileCSV", fileName, exportData.ToJson());
|
||||
if (exportResult == true)
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Success,
|
||||
Summary = "Success",
|
||||
Detail = "CSV Export Success"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Error,
|
||||
Summary = "Failed",
|
||||
Detail = "CSV Export Failed",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
void OnChangeFilter()
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async Task OnClickExportCertificate(CertificateHistoryModel? certificate)
|
||||
{
|
||||
DialogService.OpenIndicator("Export to Prov Certificate");
|
||||
|
||||
if (certificate != null)
|
||||
{
|
||||
string fileName = $"{certificate?.TTbscsr?.CPcid}.pem";
|
||||
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileStr", fileName, certificate?.TCertificate?.CCert);
|
||||
if (exportResult == true)
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Success,
|
||||
Summary = "Success",
|
||||
Detail = "Certificate Export Success"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Error,
|
||||
Summary = "Failed",
|
||||
Detail = "Certificate Export Failed",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
async Task OnClickExportSubCACertificate(CertificateHistoryModel? certificate)
|
||||
{
|
||||
DialogService.OpenIndicator("Export to Prov Certificate");
|
||||
|
||||
if (certificate != null)
|
||||
{
|
||||
string requestUrl = $"https://{ServerAddress}/certificate/GetProv?vpkiType={certificate.TTbscsr.CCertType}";
|
||||
var response = await ApiService.GetJsonAsync<string>(requestUrl);
|
||||
|
||||
string fileName = $"SubCA.pem";
|
||||
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileStr", fileName, response);
|
||||
if (exportResult == true)
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Success,
|
||||
Summary = "Success",
|
||||
Detail = "SubCA Certificate Export Success"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Error,
|
||||
Summary = "Failed",
|
||||
Detail = "SubCA Certificate Export Failed",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
async Task OnClickOcspDownload(CertificateHistoryModel? certificate)
|
||||
{
|
||||
DialogService.OpenIndicator("Export to Prov Certificate");
|
||||
|
||||
if (certificate != null)
|
||||
{
|
||||
string fileName = $"OCSP_{certificate.TTbscsr.CPcid}.txt";
|
||||
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileStr", fileName, certificate.TOcsp.COcsp);
|
||||
if (exportResult == true)
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Success,
|
||||
Summary = "Success",
|
||||
Detail = "OCSP Export Success"
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Error,
|
||||
Summary = "Failed",
|
||||
Detail = "OCSP Certificate Export Failed",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
private async Task OnExpand(CertificateHistoryModel history)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task OnClickCopy(string? text)
|
||||
{
|
||||
await CopyToClipboard(text);
|
||||
}
|
||||
|
||||
private async Task CopyToClipboard(string? text)
|
||||
{
|
||||
bool result = await JS.InvokeAsync<bool>("copyTextToClipboard", text);
|
||||
if (result == true)
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Success,
|
||||
Summary = "Success",
|
||||
Detail = "Copy To Clipboard Success."
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
{
|
||||
Severity = NotificationSeverity.Error,
|
||||
Summary = "Failed",
|
||||
Detail = "Copy To Clipboard Failed.",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
<Router AppAssembly="typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
24
Projects/VPKI/VPKI/VPKI.Web.Client/Components/_Imports.razor
Normal file
24
Projects/VPKI/VPKI/VPKI.Web.Client/Components/_Imports.razor
Normal file
@ -0,0 +1,24 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@using Newtonsoft.Json
|
||||
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
|
||||
@using VPKI.Library.Model
|
||||
@using VPKI.Library.Enums
|
||||
@using VPKI.Library.Services
|
||||
@using VPKI.Web.Client
|
||||
@using VPKI.Web.Client.Components
|
||||
@using VPKI.Web.Client.Services
|
||||
@using VPKI.Web.Client.Model
|
||||
@using VPKI.Web.Client.Components.Module
|
||||
@ -0,0 +1,15 @@
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Packet;
|
||||
|
||||
namespace VPKI.Web.Client.Model
|
||||
{
|
||||
public class CertificateContainer
|
||||
{
|
||||
public Request_Certificate RequestCertificate { get; set; } = new();
|
||||
public Response_Certificate ResponseCertificate { get; set; } = new();
|
||||
public CsrHashedModel CsrHashed { get; set; } = new();
|
||||
|
||||
public string StrRequest { get; set; } = string.Empty;
|
||||
public string StrResponse { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
23
Projects/VPKI/VPKI/VPKI.Web.Client/Model/TbscsrContainer.cs
Normal file
23
Projects/VPKI/VPKI/VPKI.Web.Client/Model/TbscsrContainer.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Packet;
|
||||
|
||||
namespace VPKI.Web.Client.Model
|
||||
{
|
||||
public class TbscsrContainer
|
||||
{
|
||||
public Request_Tbscsr RequestTbscsr { get; set; } = new();
|
||||
|
||||
public Response_Tbscsr ResponseTbscsr { get; set; } = new();
|
||||
|
||||
public VpkiType VpkiType { get; set; }
|
||||
public VpkiIsoType ISOType { get; set; }
|
||||
|
||||
public AsymmetricCipherKeyPair? KeyPair { get; set; }
|
||||
public string PublicKey { get; set; } = string.Empty;
|
||||
public string PrivateKey { get; set; } = string.Empty;
|
||||
|
||||
public string StrRequest { get; set; } = string.Empty;
|
||||
public string StrResponse { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using VPKI.Library.Packet;
|
||||
|
||||
namespace VPKI.Web.Client.Model
|
||||
{
|
||||
public class VerifyResultContainer
|
||||
{
|
||||
public Request_Verifyresult RequestVerifyresult { get; set; } = new();
|
||||
public Response_Verifyresult ResponseVerifyresult { get; set; } = new();
|
||||
|
||||
public string StrRequest { get; set; } = string.Empty;
|
||||
public string StrResponse { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
89
Projects/VPKI/VPKI/VPKI.Web.Client/Program.cs
Normal file
89
Projects/VPKI/VPKI/VPKI.Web.Client/Program.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.Identity.Client;
|
||||
using Radzen;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Services;
|
||||
using VPKI.Web.Client.Components;
|
||||
using VPKI.Web.Client.Services;
|
||||
|
||||
string configDir = @"../Config";
|
||||
|
||||
if (Log4net.IsConfigLoad == true)
|
||||
{
|
||||
Log4net.WriteLine("Log4net Init Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine("Log4net Init Failed", LogType.Error);
|
||||
}
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddRadzenComponents();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
|
||||
//singleton
|
||||
builder.Services.AddSingleton<ConfigService<WebClientConfig>>();
|
||||
|
||||
builder.Services.AddAuthentication();
|
||||
builder.Services.AddCascadingAuthenticationState();
|
||||
builder.Services.AddScoped<AuthenticationStateProvider, ExtendAuthenticationStatProvicer>();
|
||||
|
||||
builder.Services.AddOutputCache();
|
||||
|
||||
//scope
|
||||
builder.Services.AddScoped<ApiService>();
|
||||
builder.Services.AddScoped<CertificateService>();
|
||||
builder.Services.AddScoped<VpkiDialogService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
//read client config and set
|
||||
string serverUrl = string.Empty;
|
||||
var configService = app.Services.GetService<ConfigService<WebClientConfig>>();
|
||||
bool isIIS = false;
|
||||
if (configService?.OpenConfig($@"{configDir}/VPKI.WebClientConfig.json") == true)
|
||||
{
|
||||
Log4net.WriteLine("WebClient Config Success.");
|
||||
var clientConfig = ConfigService<WebClientConfig>.Config;
|
||||
serverUrl = $"{clientConfig?.Server?.Address}:{clientConfig?.Server?.Port}";
|
||||
isIIS = clientConfig!.Server.IIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine("WebClient Config Error.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
Log4net.WriteLine($"IsDevelopment:{app.Environment.IsDevelopment()}");
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
|
||||
if (isIIS == true)
|
||||
{
|
||||
app.Run();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine($"Operation Url: {serverUrl}");
|
||||
app.Run($"{serverUrl}");
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:9092",
|
||||
"sslPort": 44389
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5231",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7139;http://localhost:5231",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Projects/VPKI/VPKI/VPKI.Web.Client/Services/ApiService.cs
Normal file
98
Projects/VPKI/VPKI/VPKI.Web.Client/Services/ApiService.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using Azure;
|
||||
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using VPKI.Library.Config;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Services;
|
||||
|
||||
namespace VPKI.Web.Client.Services
|
||||
{
|
||||
public class ApiService : HttpService
|
||||
{
|
||||
private readonly ProtectedLocalStorage _localStorage;
|
||||
private readonly ConfigService<WebClientConfig> _configService;
|
||||
|
||||
private readonly string SESSION_STATE = "sessionState";
|
||||
|
||||
public ApiService(ConfigService<WebClientConfig> configService,
|
||||
ProtectedLocalStorage localStorage)
|
||||
:base()
|
||||
{
|
||||
_localStorage = localStorage;
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public async Task<RESPONSE?> PostJsonAsyncBearer<REQUEST, RESPONSE>(string url, REQUEST request, short timeOutSeconds = 5) where REQUEST : class where RESPONSE : class
|
||||
{
|
||||
RESPONSE? response = default(RESPONSE);
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
var apiConfig = _configService?.GetConfig()?.Api?.Find(x => x.ApiName?.ToLower() == Consts.VPKI_API.ToLower());
|
||||
string apiUrl = $"{apiConfig.Address}:{apiConfig.Port}";
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
try
|
||||
{
|
||||
//bearer token set
|
||||
var sessionModel = (await _localStorage.GetAsync<LoginResponseModel>(SESSION_STATE)).Value;
|
||||
var token = sessionModel?.AccessToken;
|
||||
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $"{token}");
|
||||
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{apiUrl}{url}");
|
||||
|
||||
Log4net.WriteLine($"[POST] Request({guid})::{url}{Environment.NewLine}{request?.ToJson()}", LogType.Warn);
|
||||
|
||||
var res = await httpClient.PostAsJsonAsync(url, request);
|
||||
response = await res.Content.ReadFromJsonAsync<RESPONSE>();
|
||||
|
||||
Log4net.WriteLine($"[POST] Rseponse({guid})::{url}{Environment.NewLine}{response?.ToJson()}", LogType.Warn);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<RESPONSE?> GetJsonAsyncBearer<RESPONSE>(string url, short timeOutSeconds = 5) where RESPONSE : class
|
||||
{
|
||||
RESPONSE? response = default(RESPONSE);
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
var apiConfig = _configService?.GetConfig()?.Api?.Find(x => x.ApiName?.ToLower() == Consts.VPKI_API.ToLower());
|
||||
string apiUrl = $"{apiConfig.Address}:{apiConfig.Port}";
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
try
|
||||
{
|
||||
//bearer token set
|
||||
var sessionModel = (await _localStorage.GetAsync<LoginResponseModel>(SESSION_STATE)).Value;
|
||||
var token = sessionModel?.AccessToken;
|
||||
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $"{token}");
|
||||
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{apiUrl}{url}");
|
||||
|
||||
Log4net.WriteLine($"[GET] Request({guid})::{url}{Environment.NewLine}", LogType.Warn);
|
||||
|
||||
var res = await httpClient.GetAsync(url);
|
||||
response = await res.Content.ReadFromJsonAsync<RESPONSE>();
|
||||
|
||||
Log4net.WriteLine($"[GET] Rseponse({guid})::{url}{Environment.NewLine}{response?.ToJson()}", LogType.Warn);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Claims;
|
||||
using VPKI.Library.Model;
|
||||
|
||||
namespace VPKI.Web.Client.Services
|
||||
{
|
||||
public class ExtendAuthenticationStatProvicer(ProtectedLocalStorage localStorage) : AuthenticationStateProvider
|
||||
{
|
||||
public async override Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
var sessionModel = (await localStorage.GetAsync<LoginResponseModel>("sessionState")).Value;
|
||||
ClaimsIdentity identity = new ClaimsIdentity();
|
||||
if(sessionModel?.AccessToken != null)
|
||||
{
|
||||
identity = sessionModel == null ? new ClaimsIdentity() : GetClaimsIdentity(sessionModel.AccessToken);
|
||||
var user = new ClaimsPrincipal(identity);
|
||||
return new AuthenticationState(user);
|
||||
}
|
||||
|
||||
return new AuthenticationState(new ClaimsPrincipal(identity));
|
||||
}
|
||||
|
||||
public async Task<string> GetAccessToken()
|
||||
{
|
||||
var sessionModel = (await localStorage.GetAsync<LoginResponseModel>("sessionState")).Value;
|
||||
return $"{sessionModel?.AccessToken}";
|
||||
}
|
||||
|
||||
public async Task<long> GetExpiredTimeAsync()
|
||||
{
|
||||
var sessionModel = (await localStorage.GetAsync<LoginResponseModel>("sessionState")).Value;
|
||||
ClaimsIdentity identity = new ClaimsIdentity();
|
||||
if (sessionModel?.AccessToken != null)
|
||||
{
|
||||
return sessionModel.AccessTokenExpired;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public async Task MakeUserAsAuthenticated(LoginResponseModel model)
|
||||
{
|
||||
string accessToken = string.Empty;
|
||||
|
||||
if (model?.AccessToken != null)
|
||||
{
|
||||
accessToken = model.AccessToken;
|
||||
await localStorage.SetAsync("sessionState", model);
|
||||
var identity = GetClaimsIdentity(accessToken);
|
||||
var user = new ClaimsPrincipal(identity);
|
||||
|
||||
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task MakeUserLogout()
|
||||
{
|
||||
await localStorage.DeleteAsync("sessionState");
|
||||
var identity = new ClaimsIdentity();
|
||||
var user = new ClaimsPrincipal(identity);
|
||||
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
|
||||
}
|
||||
|
||||
private ClaimsIdentity GetClaimsIdentity(string token)
|
||||
{
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var jwtToken = handler.ReadJwtToken(token);
|
||||
var claims = jwtToken.Claims;
|
||||
return new ClaimsIdentity(claims,"jwt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Radzen;
|
||||
using VPKI.Web.Client.Components.Dialog;
|
||||
|
||||
namespace VPKI.Web.Client.Services
|
||||
{
|
||||
public class VpkiDialogService
|
||||
{
|
||||
public DialogService _dialogService;
|
||||
|
||||
public VpkiDialogService(DialogService dialogService)
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
}
|
||||
|
||||
public async Task<bool> Confirm(string title, string message)
|
||||
{
|
||||
bool result = false;
|
||||
result = await _dialogService.Confirm(message, title, new ConfirmOptions
|
||||
{
|
||||
OkButtonText = "OK",
|
||||
CancelButtonText = "Cancel",
|
||||
})??false;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void OpenIndicator(string message = "")
|
||||
{
|
||||
_dialogService.Open<Loading>("",
|
||||
new Dictionary<string, object>() { { "Message", message } },
|
||||
new DialogOptions
|
||||
{
|
||||
ShowClose = false,
|
||||
ShowTitle =false,
|
||||
Style = "box-shadow: none; background: transparent; min-width:0; min-height:0; width:auto;"
|
||||
});
|
||||
}
|
||||
|
||||
public void CloseIndicator()
|
||||
{
|
||||
_dialogService.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user