인증서
인증서를 생성하여 Powershell 스크립트에 서명할 수 있습니다. 서명을 사용하는 이유는 보안
입니다. 실제로 dll이나 jar도 마찬가지입니다만, 악의적인 목적으로 동작을 가로채는 것을 막기 위한 것입니다.
서명되지 않은 스크립트를 사용하려면, Windows 보안 조치를 완전히 비활성화해야 하는데, 이는 좋지 않을 수 있다.
이하 우리가 하는 모든 것은 커맨드 프롬프트가 아니라 Powershell을 사용합니다.
인증 배경:
인증서는 인증기관(CA)에 의해 권한을 부여받습니다. CA는 인증서의 유효 여부를 확인합니다. 컴퓨터가 인증서를 사용하려고 할 때 “신뢰할 수 있는” CA의 인증서 유효성을 요청하여 인증서의 유효성을 확인해야 합니다.
비용을 지불하여 공식 CA에 서명된 인증서를 발급받을 수도 있고, 또는 개인 CA를 만들고, 개인 인증서를 만들고, 개인 CA로 인증서에 서명할 수도 있습니다. 우리는 후자의 과정을 이용하려 합니다.
Windows OS는 인증서 저장소에 유효한 CA 정보를 저장합니다. (again, “신뢰할 수 있는 CA 목록”). 저장 공간은
CurrentUser > Trusted Root Certification Authorities > Certificates 입니다.
일본어 OS를 사용하고 있는 제 환경에서는 다음과 같습니다. 신뢰할 수 있는 CA 목록입니다.
인증서를 관리하는 제어판을 실행하는 명령어는 certmgr
입니다.
PS C:\temp\pwshprj> which certmgr
C:\Windows\system32\certmgr.MSC
용어
몇 가지 용어를 짚고 넘어가도록 하죠.
- x509 : 인증서가 가져야할 항목을 정의한 데이타 정의입니다.
- PKI : 공개 키 기반구조(public key infrastructure)라고 번역이 되는데, CA, RA, VA 기관으로 나누어 인증합니다 라는 의미입니다.
- CA = Certification Authority
- RA = Registration Authority
- VA = Validation Authority
- PKCS : 공개 키 암호 표준 “Public Key Cryptography Standards”. ‘RSA Security LLC’ 라는 회사가 발표하는 표준 포맷입니다. 몇가지 종류가 있는데, 7번이 서명을 위한 표준 포맷, 12번이 공개키와 개인키를 함께 저장하는 포맷입니다. 파일 확장자는 .p12 또는 .pfx 를 사용합니다.
- PFX는 Personal Information Exchange 의 약자입니다.
인증서를 저장하는 포맷으로는 다음과 같은 것들이 있습니다.
- .CER - CER 암호화 된 인증서. 복수의 인증서도 가능.
- .DER - DER 암호화 된 인증서.
- .PEM - (Privacy Enhanced Mail) Base64로 인코딩 된 인증서. “—–BEGIN CERTIFICATE—–“와 “—–END CERTIFICATE—–” 가운데에 들어간다.
- .P7B - .p7c 참조.
- .P7C - PKCS#7 서명 자료 구조(자료는 제외), 인증서이거나 CRL(복수도 가능).
- .PFX - .p12 참조.
- .P12 - PKCS#12, 공개 인증서와 암호로 보호되는 개인 키를 가질 수 있다(복수도 가능).
서명은 위조가 되었나 안되었나만을 확인하는 것인데,
GMO 그룹에서 운영하는 https://www.globalsign.com/ 은 마켓쉐어 6위 정도의 실적을 보이고 있습니다. 원래 영국에 있던 회사였는데 GMO그룹이 인수했습니다.
Powershell 인증서 관련 명령어
powershell에서 인증서와 관련된 명령어가 무엇이 있는 지 확인해 보았습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| PS C:\temp\pwshprj> gcm *Certi*
CommandType Name Version Source
----------- ---- ------- ------
Function Get-RDCertificate 2.0.0.0 RemoteDesktop
Function New-RDCertificate 2.0.0.0 RemoteDesktop
Function Set-RDCertificate 2.0.0.0 RemoteDesktop
Cmdlet Add-CertificateEnrollmentPolicyServer 1.0.0.0 PKI
Cmdlet Export-Certificate 1.0.0.0 PKI
Cmdlet Export-PfxCertificate 1.0.0.0 PKI
Cmdlet Get-Certificate 1.0.0.0 PKI
Cmdlet Get-CertificateAutoEnrollmentPolicy 1.0.0.0 PKI
Cmdlet Get-CertificateEnrollmentPolicyServer 1.0.0.0 PKI
Cmdlet Get-CertificateNotificationTask 1.0.0.0 PKI
Cmdlet Get-PfxCertificate 3.0.0.0 Microsoft.PowerShell.Security
Cmdlet Import-Certificate 1.0.0.0 PKI
Cmdlet Import-PfxCertificate 1.0.0.0 PKI
Cmdlet New-CertificateNotificationTask 1.0.0.0 PKI
Cmdlet New-SelfSignedCertificate 1.0.0.0 PKI
Cmdlet Remove-CertificateEnrollmentPolicyServer 1.0.0.0 PKI
Cmdlet Remove-CertificateNotificationTask 1.0.0.0 PKI
Cmdlet Set-CertificateAutoEnrollmentPolicy 1.0.0.0 PKI
Cmdlet Switch-Certificate 1.0.0.0 PKI
Cmdlet Test-Certificate 1.0.0.0 PKI
Application dmcertinst.exe 10.0.14... C:\Windows\system32\dmcertinst.exe
|
이중에 New-SelfSignedCertificate
라고 하는 명령어가 있습니다. 자 이제 이 명령어를 이용하여 스크립트를 서명해 봅시다. 전체 과정은 5과정입니다.
step 1. 코드서명을 위한 인증서 만들기
1
2
3
4
5
6
7
8
| New-SelfSignedCertificate -CertStoreLocation cert:\currentuser\my `
-Subject "CN=Local Code Signing" `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" `
-KeyExportPolicy Exportable `
-KeyUsage DigitalSignature `
-Type CodeSigningCert
|
1
2
3
4
5
6
7
8
| New-SelfSignedCertificate
-Subject "CN=System Error,e=mymail@mail.com" `
-KeyAlgorithm sha256 `
-KeyLength 2018 `
-FriendlyName "My Cert" `
-KeyUsage DigitalSignature `
-KeyUsageProperty Sign `
-Type CodeSigningCert
|
step 2. OS의 인증서 저장소의 개인 인증서 열기
만들어진 인증서는 OS에 저장됩니다. 리눅스라면 파일시스템으로 저장되는데, 경로는 리눅스 타입에 따라 다릅니다.
- “/etc/ssl/certs/ca-certificates.crt”, // Debian/Ubuntu/Gentoo etc.
- “/etc/pki/tls/certs/ca-bundle.crt”, // Fedora/RHEL 6
- “/etc/ssl/ca-bundle.pem”, // OpenSUSE
- “/etc/pki/tls/cacert.pem”, // OpenELEC
- “/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem”, // CentOS/RHEL 7
- “/etc/ssl/cert.pem”, // Alpine Linux
- “/etc/ssl/certs”, // SLES10/SLES11, https://golang.org/issue/12139
- “/system/etc/security/cacerts”, // Android
- “/usr/local/share/certs”, // FreeBSD
- “/etc/pki/tls/certs”, // Fedora/RHEL
- “/etc/openssl/certs”, // NetBSD
- “/var/ssl/certs”, // AIX
윈도우즈는 파일시스켐으로 관리하지는 않고 있습니다.
저장되었는 지 확인합니다. 확인하는 방법은 몇 가지가 있습니다.
- certmgr 에서
개인 > 인증서
에서 확인 할 수 있습니다., GUI 입니다. - cmd에서
certutil -store My
로도 확인할 수 있습니다. - powershell로 확인하기, 파일시스템처럼 접근해서 확인할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| PS Cert:\CurrentUser\My> New-SelfSignedCertificate -CertStoreLocation cert:\currentuser\my `
>> -Subject "CN=Local Code Signing" `
>> -KeyAlgorithm RSA `
>> -KeyLength 2048 `
>> -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" `
>> -KeyExportPolicy Exportable `
>> -KeyUsage DigitalSignature `
>> -Type CodeSigningCert
PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\my
Thumbprint Subject
---------- -------
3F3EF4020A8F2FA478B46BFD4E555251D9CCC953 CN=Local Code Signing
PS Cert:\CurrentUser\My> dir
PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\My
Thumbprint Subject
---------- -------
330E27CC6CD03143762062542EA8D99B12D9B711 CN=localhost
3F3EF4020A8F2FA478B46BFD4E555251D9CCC953 CN=Local Code Signing
|
step 3. 개인 인증서를 신뢰할 수 있는 타입으로 저장하기
개인 > 증명서 에 있는 CN=Local Code Signing
인증서를 다음의 두 장소에 복사해 넣습니다.
- 신뢰하는 루트 인증기관 (영어 “Trusted Root Certification Authorities”)
- 신뢰하는 발행처 (영어 “Trusted Publishers”)
step 4. script 서명하기
서명할 때는 Set-AuthenticodeSignature
명령어를 사용합니다.
$cert = Get-ChildItem cert:\CurrentUser\My -CodeSigning
Set-AuthenticodeSignature .\test.ps1 $cert
또는
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
Set-AuthenticodeSignature .\test.ps1 $cert -HashAlgorithm `
sha256 -TimestampServer "http://timestamp.digicert.com"
실행한 결과는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
| PS Cert:\CurrentUser\My> Get-ChildItem cert:\CurrentUser\My -CodeSigning | fl
Subject : CN=Local Code Signing
Issuer : CN=Local Code Signing
Thumbprint : 3F3EF4020A8F2FA478B46BFD4E555251D9CCC953
FriendlyName :
NotBefore : 2020/09/26 12:39:43
NotAfter : 2021/09/26 12:59:43
Extensions : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid}
PS C:\temp\pwshprj> dir
ディレクトリ: C:\temp\pwshprj
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2020/09/21 8:53 75 README.md
-a---- 2020/09/21 10:00 137 test.ps1
PS C:\temp\pwshprj> cat test.ps1
function myfunction {
param (
[string]$text
)
[int]$test
Write-Host "You wrote: $text ."
}
PS C:\temp\pwshprj> $cert = Get-ChildItem cert:\CurrentUser\My -CodeSigning
PS C:\temp\pwshprj> Set-AuthenticodeSignature .\test.ps1 $cert
ディレクトリ: C:\temp\pwshprj
SignerCertificate Status Path
----------------- ------ ----
3F3EF4020A8F2FA478B46BFD4E555251D9CCC953 Valid test.ps1
PS C:\temp\pwshprj> cat .\test.ps1
function myfunction {
param (
[string]$text
)
[int]$test
Write-Host "You wrote: $text ."
}
# SIG # Begin signature block
# MIIFdgYJKoZIhvcNAQcCoIIFZzCCBWMCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUrvaKRFD1k7RjzD6eorUSZqxB
# OwagggMOMIIDCjCCAfKgAwIBAgIQMF3cntmzua9FjRfu4pf1iTANBgkqhkiG9w0B
# AQUFADAdMRswGQYDVQQDDBJMb2NhbCBDb2RlIFNpZ25pbmcwHhcNMjAwOTI2MDMz
# OTQzWhcNMjEwOTI2MDM1OTQzWjAdMRswGQYDVQQDDBJMb2NhbCBDb2RlIFNpZ25p
# bmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS1QjZt13tSS+AVGw4
# HjBi+tLDfZJ7L0FDCa8RHKpdpF4v/FAa5uayiPs6zgxO1QFOTnhA5o24Duv7Ig6V
# wCSjezJZv9mfH4tcJ5LsRrR0wjbKTs8jNOjRU9P9v6Dv8PJLz8y2tR8ivxJBmnoz
# 3ty7LLEDWnUGdGC+7xr6Zs2D+UdRG1X5SJqw3TLe33WvYHK6r0GCNWymuWjUihHv
# TZzu4Mtf62722qBReP9QCRGhDTwxCSu0rS/LDgIEa6bc23MTjRxf7C3ZI+04zdBS
# iufOtWlPbNu7KUZZyT7jOBcOvhWCuqbaYDOsudFeGpjA+UXgRNkG1N1zRucVlsxC
# yo/RAgMBAAGjRjBEMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcD
# AzAdBgNVHQ4EFgQUmEqtya+uXUWAeG+NLjJ+5OeAwGwwDQYJKoZIhvcNAQEFBQAD
# ggEBAHzPIwDo9Bqc/KmfjfN1Gb+y8CaQ9YkHUS+V8G02jTWMWdskkIy/cLSWIJBq
# IZaNyvTAf3+Orb9fNszdkvo07AUjpUSJyUF6UfMnnRA/tWkp+ulhuTSA19B4SFVQ
# nYwiymetMutpTeXH3HvvzALktVCXb1SmrTEYIj4VISIEyUBLJ0HwgOZ+T6Cq3FMO
# XgGNjI1h8KFKev0zT1qntlPBNYlFQnbpkVz0YNhNyvfEt5SxpIWw/QUPzfXF3HwU
# 35DBwa3VWI4zKJW6/9wa1nLpppBvu+MfDPyBDmRwOQ68S1vsGeodiISu046McNLy
# yR/EvH4HkIAT/alUr4lS5I3Zi/QxggHSMIIBzgIBATAxMB0xGzAZBgNVBAMMEkxv
# Y2FsIENvZGUgU2lnbmluZwIQMF3cntmzua9FjRfu4pf1iTAJBgUrDgMCGgUAoHgw
# GAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGC
# NwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQx
# FgQUUl40/IMyhS8sq7gVVEqV/S6Ib78wDQYJKoZIhvcNAQEBBQAEggEAxgytjnpU
# j2ETO9n6AmgqdkSXIOmvvWVWgDbzJw1uCjd//07U0Fss1TVgxOAosRGy3qhNTROs
# yZub/UUMqnSqYCjRmFytvLRHz2aQW9BE5c2LVY1ZYBiO1uWgx4Azt3I4BprAzLCd
# fiY4rLPWvLLqJbFUUWKccpGymHzwUtzbZaddFu7C1AutSv3ldSDwuDoFlOxvQr9l
# Pbd8eErp5CA20M4lh/U6WJyHlNDhZk43vXznDGbBtt++oM354ktf9cnK7IZMcvqW
# nTTG4U8sjH+6z5vn5YqfRN/xGkrxzEU4v6dYcZLy+AYa75KBL4NYB2KDyEJWfr8a
# W92b29DeXRk+pw==
# SIG # End signature block
PS C:\temp\pwshprj>
|
스크립트 파일이 아닌 경우는 정상적으로 작동하지 않습니다.
1
2
3
4
5
6
7
8
9
10
| PS C:\temp\pwshprj> Set-AuthenticodeSignature .\README.md $cert -HashAlgorithm `
>> sha256 -TimestampServer "http://timestamp.digicert.com"
ディレクトリ: C:\temp\pwshprj
SignerCertificate Status Path
----------------- ------ ----
UnknownError README.md
|
step 6. test
현재의 세션에서만 ExecutionPlicy를 변경하려면 다음의 명령을 사용합니다.
Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope Process
테스트해본 결과는 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| PS C:\temp\pwshprj> Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope Process
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピック (http://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "N"): Y
PS C:\temp\pwshprj> Get-ExecutionPolicy
AllSigned
PS C:\temp\pwshprj> Get-ExecutionPolicy -list
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process AllSigned
CurrentUser Undefined
LocalMachine RemoteSigned
PS C:\temp\pwshprj> . .\test.ps1
PS C:\temp\pwshprj> myfunction hello
0
You wrote: hello .
PS C:\temp\pwshprj>
|
이상으로 스크립트를 서명해 보았습니다.
레퍼런스