Cách ký PowerShell Script bằng Code Signing Certificate
Cập nhật lần cuối: 27/08/2026
Hướng dẫn cách ký PowerShell Script bằng Code Signing Certificate, sử dụng chữ ký số để xác thực nguồn gốc và đảm bảo nội dung script không bị thay đổi sau khi ký.
Ký PowerShell Script là gì?
PowerShell Script là các tập lệnh có phần mở rộng .ps1, được sử dụng để tự động hóa nhiều tác vụ trên Windows như quản trị hệ thống, triển khai phần mềm, xử lý file, quản lý người dùng và vận hành hạ tầng.
Do PowerShell Script có thể thực hiện nhiều thao tác trực tiếp trên hệ thống, Windows cung cấp cơ chế Code Signing để xác minh nguồn gốc và tính toàn vẹn của Script.
Ký PowerShell Script là quá trình sử dụng Digital Certificate và Private Key để tạo chữ ký Authenticode cho file .ps1.
PowerShell cung cấp cmdlet Set-AuthenticodeSignature để thực hiện việc ký Script và Get-AuthenticodeSignature để kiểm tra chữ ký.
PowerShell Script không được ký bằng SignTool theo cách thông thường như EXE, DLL hoặc MSI. PowerShell sử dụng cơ chế Authenticode riêng và cung cấp các cmdlet như Set-AuthenticodeSignature để ký file PS1.
Xem thêm: SignTool là gì?
Vì sao cần ký PowerShell Script?
PowerShell Script có thể thực hiện các thao tác quan trọng trên hệ thống. Nếu Script bị thay đổi hoặc bị thay thế bằng một phiên bản khác, người dùng có thể vô tình chạy mã không phải do nhà phát triển hoặc quản trị viên tạo ra.
Digital Signature giúp cung cấp cơ chế để kiểm tra:
- Danh tính của nhà phát hành Script.
- Tính toàn vẹn của Script.
- Certificate được sử dụng để ký.
- Certificate Chain.
- Timestamp nếu chữ ký có Timestamp.
Việc ký Script cũng có thể được sử dụng kết hợp với PowerShell Execution Policy để kiểm soát việc thực thi các Script chưa được ký.
PowerShell sử dụng loại chữ ký nào?
PowerShell sử dụng cơ chế Authenticode để ký Script.
Quá trình này khác với việc ký một file EXE hoặc DLL bằng SignTool.
| Đối tượng | Công cụ / cơ chế thường dùng |
|---|---|
| EXE | SignTool / Authenticode |
| DLL | SignTool / Authenticode |
| MSI | SignTool / Authenticode |
| CAB | SignTool / Authenticode |
| PowerShell Script | Set-AuthenticodeSignature / Authenticode |
Do đó, khi ký file .ps1, không sử dụng lệnh signtool sign như cách ký EXE hoặc MSI mà sử dụng cơ chế ký Script của PowerShell.
Chuẩn bị trước khi ký PowerShell Script
Trước khi thực hiện Code Signing, cần chuẩn bị PowerShell, Code Signing Certificate và Private Key.
1. Chuẩn bị PowerShell Script
Giả sử Script cần ký có đường dẫn:
C:\Scripts\Backup.ps1
Script phải được hoàn tất trước khi ký.
Nếu thay đổi nội dung Script sau khi ký, chữ ký có thể không còn hợp lệ và cần ký lại.
2. Chuẩn bị Code Signing Certificate
Certificate dùng để ký PowerShell Script cần có Private Key tương ứng và mục đích sử dụng phù hợp cho Code Signing.
Certificate có thể được lưu trữ trong:
- Windows Certificate Store.
- USB Token.
- Hardware Security Module (HSM).
- Các giải pháp Remote Signing hoặc Cloud Signing phù hợp.
Khác với ví dụ sử dụng PFX trực tiếp trong SignTool, Set-AuthenticodeSignature thường lấy Certificate từ Windows Certificate Store.
Kiểm tra Code Signing Certificate trong Windows
Trước tiên, có thể liệt kê các Certificate có mục đích Code Signing trong Current User Certificate Store:
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
Lệnh này giúp tìm các Certificate có thể sử dụng để ký PowerShell Script.
Có thể lưu Certificate vào một biến để sử dụng trong các lệnh tiếp theo:
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Sau đó kiểm tra Certificate:
$cert | Format-List Subject, Issuer, Thumbprint, NotBefore, NotAfter
Các thông tin trên giúp xác định đúng Certificate trước khi thực hiện ký.
Ký PowerShell Script bằng Set-AuthenticodeSignature
Cmdlet chính được PowerShell cung cấp để ký Script là:
Set-AuthenticodeSignature
Giả sử Certificate được lưu trong biến $cert, có thể ký Script bằng:
Set-AuthenticodeSignature -FilePath "C:\Scripts\Backup.ps1" -Certificate $cert
Trong đó:
- -FilePath: đường dẫn tới PowerShell Script cần ký.
- -Certificate: Certificate được sử dụng để tạo chữ ký.
Sau khi lệnh hoàn tất, PowerShell sẽ thêm chữ ký Authenticode vào Script.
Ký PowerShell Script và thêm Timestamp
Timestamp giúp ghi nhận thời điểm chữ ký được tạo. Khi Certificate được sử dụng để ký Script hết hạn sau này, Timestamp có thể giúp xác minh rằng chữ ký đã được tạo trong thời gian Certificate còn hiệu lực.
PowerShell hỗ trợ Timestamp thông qua tham số -TimestampServer.
Ví dụ:
Set-AuthenticodeSignature `
-FilePath "C:\Scripts\Backup.ps1" `
-Certificate $cert `
-TimestampServer "https://timestamp.digicert.com"
Trong đó:
- -FilePath: file PS1 cần ký.
- -Certificate: Code Signing Certificate.
- -TimestampServer: Timestamp Server được sử dụng để tạo Timestamp cho chữ ký.
URL Timestamp thực tế có thể thay đổi tùy Certificate Authority hoặc dịch vụ Timestamp mà tổ chức sử dụng.
Xem thêm: Timestamp là gì?
Ký Script bằng Certificate cụ thể
Trong trường hợp máy tính có nhiều Code Signing Certificate, không nên chọn Certificate một cách ngẫu nhiên.
Có thể tìm Certificate theo Subject:
$cert = Get-ChildItem Cert:\CurrentUser\My |
Where-Object {
$_.Subject -like "*Example Company*"
} |
Select-Object -First 1
Sau đó sử dụng Certificate để ký:
Set-AuthenticodeSignature `
-FilePath "C:\Scripts\Backup.ps1" `
-Certificate $cert
Có thể kiểm tra Thumbprint trước khi ký:
$cert | Format-List Subject, Thumbprint, NotAfter
Điều này giúp tránh việc sử dụng nhầm Certificate khi hệ thống có nhiều Certificate khác nhau.
Kiểm tra chữ ký PowerShell Script
Sau khi ký, sử dụng Get-AuthenticodeSignature để kiểm tra chữ ký.
Get-AuthenticodeSignature "C:\Scripts\Backup.ps1"
Kết quả thường cung cấp các thông tin như:
- Status.
- StatusMessage.
- SignerCertificate.
- TimeStamperCertificate.
Ví dụ có thể hiển thị thông tin chi tiết hơn:
$signature = Get-AuthenticodeSignature "C:\Scripts\Backup.ps1"
$signature | Format-List *
Nếu chữ ký hợp lệ, thuộc tính Status thường cho biết trạng thái Valid.
1. Kiểm tra Certificate của người ký
$signature = Get-AuthenticodeSignature "C:\Scripts\Backup.ps1"
$signature.SignerCertificate |
Format-List Subject, Issuer, Thumbprint, NotBefore, NotAfter
Cách này giúp xác định Certificate nào đã được sử dụng để ký Script.
2. Kiểm tra Timestamp Certificate
$signature.TimeStamperCertificate |
Format-List Subject, Issuer, Thumbprint, NotBefore, NotAfter
Nếu Script có Timestamp, thông tin Timestamp Certificate có thể được hiển thị thông qua thuộc tính tương ứng.
PowerShell Execution Policy và Script đã ký
Execution Policy là cơ chế của PowerShell dùng để kiểm soát điều kiện thực thi Script.
Có thể kiểm tra Execution Policy hiện tại bằng:
Get-ExecutionPolicy
Để xem chính sách ở tất cả các Scope:
Get-ExecutionPolicy -List
Một số Execution Policy thường gặp:
| Execution Policy | Ý nghĩa |
|---|---|
| Restricted | Không cho phép chạy PowerShell Script |
| AllSigned | Yêu cầu Script được ký bởi một Publisher được tin cậy |
| RemoteSigned | Script tải từ Internet thường phải có chữ ký hợp lệ |
| Unrestricted | Cho phép Script chạy với ít hạn chế hơn |
| Bypass | Không áp dụng các kiểm tra Execution Policy thông thường |
Trong môi trường doanh nghiệp, AllSigned có thể được sử dụng khi muốn yêu cầu Script phải có chữ ký số.
Thiết lập Execution Policy AllSigned
Có thể thiết lập Execution Policy cho Current User:
Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope CurrentUser
Kiểm tra lại:
Get-ExecutionPolicy -List
Sau khi sử dụng AllSigned, PowerShell sẽ yêu cầu Script phải có chữ ký phù hợp trước khi thực thi.
Execution Policy không phải là một cơ chế bảo mật tuyệt đối. Đây là một tính năng giúp kiểm soát việc thực thi Script và có thể bị giới hạn hoặc thay đổi bởi các cơ chế quản trị hệ thống khác.
PowerShell có tin tưởng mọi Certificate dùng để ký Script không?
Không.
Script có chữ ký số không đồng nghĩa với việc Certificate của người ký được hệ thống tin cậy.
PowerShell và Windows có thể kiểm tra Certificate Chain để xác định Certificate có được phát hành bởi CA đáng tin cậy hay không.
Mô hình xác minh:
PowerShell Script
│
▼
Digital Signature
│
▼
Signer Certificate
│
▼
Intermediate CA
│
▼
Root CA
│
▼
Trusted Root Store
│
▼
Certificate Trusted?
Nếu Certificate hoặc Certificate Chain không được tin cậy, Script có thể không được xác minh như mong muốn.
Ký Script bằng Certificate tự ký (Self-Signed Certificate)
Trong môi trường phát triển hoặc kiểm thử nội bộ, có thể tạo Self-Signed Certificate để thử nghiệm việc ký PowerShell Script.
Ví dụ:
$cert = New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject "CN=PowerShell Test Signing" `
-CertStoreLocation "Cert:\CurrentUser\My"
Sau đó sử dụng Certificate để ký:
Set-AuthenticodeSignature `
-FilePath "C:\Scripts\Backup.ps1" `
-Certificate $cert
Kiểm tra:
Get-AuthenticodeSignature "C:\Scripts\Backup.ps1"
Certificate tự ký phù hợp cho môi trường Test hoặc Development, nhưng không nên sử dụng như một phương án thay thế cho Certificate được CA công khai tin cậy khi phát hành Script cho người dùng bên ngoài.
Ký PowerShell Script bằng USB Token hoặc HSM
Code Signing Certificate dùng để ký PowerShell Script có thể được bảo vệ bằng USB Token hoặc HSM.
Mô hình tổng quát:
PowerShell
│
▼
Code Signing Certificate
│
▼
Windows Certificate Store
│
▼
CSP / KSP
│
▼
USB Token / HSM
│
▼
Private Key
│
▼
Digital Signature
│
▼
Signed PS1
Trong mô hình này, Private Key được giữ trong thiết bị bảo mật thay vì được lưu trực tiếp dưới dạng file Private Key trên máy tính.
Cấu hình cụ thể phụ thuộc vào Token, HSM, CSP/KSP và middleware của nhà cung cấp.
Xem thêm: HSM là gì?
PowerShell Script đã ký có thể chỉnh sửa không?
Không nên chỉnh sửa nội dung Script sau khi ký.
Chữ ký được tạo dựa trên nội dung của Script tại thời điểm ký. Nếu nội dung Script thay đổi, giá trị hash được sử dụng để xác minh chữ ký cũng có thể thay đổi.
Quy trình đúng nên là:
Write Script
│
▼
Test Script
│
▼
Finalize Script
│
▼
Sign Script
│
▼
Verify Signature
│
▼
Release
Nếu cần sửa Script, nên thực hiện thay đổi trước rồi ký lại phiên bản mới.
Ký PowerShell Script trong CI/CD
PowerShell Code Signing có thể được tích hợp vào quy trình CI/CD để tự động ký Script trước khi phát hành.
Một quy trình cơ bản:
Source Code
│
▼
Build / Generate PS1
│
▼
Automated Test
│
▼
Select Code Signing Certificate
│
▼
Set-AuthenticodeSignature
│
├── SHA-256
└── Timestamp
│
▼
Get-AuthenticodeSignature
│
▼
Release Artifact
Trong môi trường CI/CD, Private Key không nên được lưu trực tiếp trong source code hoặc repository.
Có thể sử dụng Secret Management, HSM hoặc Remote Signing tùy yêu cầu bảo mật của hệ thống.
Ví dụ hoàn chỉnh ký và kiểm tra PowerShell Script
Giả sử:
- Script: C:\Scripts\Backup.ps1
- Code Signing Certificate nằm trong Current User Certificate Store.
- Certificate có mục đích Code Signing.
Tìm Certificate:
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert |
Select-Object -First 1
Kiểm tra Certificate:
$cert | Format-List Subject, Issuer, Thumbprint, NotAfter
Ký Script:
Set-AuthenticodeSignature `
-FilePath "C:\Scripts\Backup.ps1" `
-Certificate $cert `
-TimestampServer "https://timestamp.digicert.com"
Kiểm tra chữ ký:
Get-AuthenticodeSignature "C:\Scripts\Backup.ps1"
Hiển thị đầy đủ thông tin:
Get-AuthenticodeSignature "C:\Scripts\Backup.ps1" |
Format-List *
Đây là quy trình cơ bản để ký và xác minh một PowerShell Script.
Các lỗi thường gặp khi ký PowerShell Script
1. Không tìm thấy Code Signing Certificate
Nếu lệnh:
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
không trả về Certificate, có thể Certificate chưa được cài đặt đúng hoặc không có Enhanced Key Usage phù hợp cho Code Signing.
Cần kiểm tra:
- Certificate Store.
- Certificate Chain.
- Enhanced Key Usage.
- Private Key.
- Thời hạn Certificate.
2. Chữ ký có trạng thái UnknownError
Có thể sử dụng:
Get-AuthenticodeSignature "C:\Scripts\Backup.ps1" |
Format-List *
để xem thêm thông tin về Signature Status.
Nguyên nhân có thể liên quan đến Certificate Chain, Timestamp, Trust Store hoặc nội dung Script.
3. Script đã ký nhưng PowerShell vẫn không cho chạy
Cần kiểm tra Execution Policy:
Get-ExecutionPolicy -List
Ngoài Execution Policy, cần kiểm tra Certificate của người ký có được hệ thống tin cậy hay không.
4. Script bị đánh dấu là tải từ Internet
File được tải từ Internet có thể mang Mark of the Web (MOTW), khiến PowerShell áp dụng thêm các cơ chế kiểm tra.
Có thể kiểm tra Alternate Data Stream:
Get-Item "C:\Scripts\Backup.ps1" -Stream *
Trong môi trường kiểm thử, có thể xử lý Mark of the Web bằng:
Unblock-File "C:\Scripts\Backup.ps1"
Việc sử dụng Unblock-File cần được thực hiện theo chính sách bảo mật của hệ thống, không nên dùng để bỏ qua các cơ chế bảo vệ đối với Script không rõ nguồn gốc.
5. Timestamp Server không hoạt động
Nếu Timestamp Server không thể truy cập, quá trình ký có thể không hoàn thành.
Cần kiểm tra:
- DNS.
- Internet Connectivity.
- Firewall.
- Proxy.
- Timestamp Server.
Những hiểu lầm phổ biến về PowerShell Code Signing
1. Chỉ cần đổi Execution Policy là Script sẽ được ký
Không.
Execution Policy chỉ kiểm soát điều kiện thực thi Script. Nó không tạo Digital Signature.
2. Script có chữ ký là chắc chắn an toàn
Không.
Digital Signature giúp xác minh nguồn gốc và tính toàn vẹn của Script, nhưng không chứng minh nội dung Script không chứa mã độc hoặc hành vi nguy hiểm.
3. Có thể sử dụng SignTool để ký file PS1
Không nên áp dụng theo cách ký EXE hoặc MSI.
PowerShell có cơ chế Authenticode riêng và cung cấp Set-AuthenticodeSignature để ký Script.
4. Script đã ký có thể sửa thoải mái
Không.
Nếu nội dung Script thay đổi sau khi ký, chữ ký có thể không còn hợp lệ. Script cần được ký lại sau khi hoàn tất thay đổi.
5. Certificate hết hạn thì mọi Script đã ký đều mất chữ ký
Không nhất thiết.
Nếu chữ ký có Timestamp hợp lệ, hệ thống có thể sử dụng Timestamp để xác định chữ ký được tạo trong thời gian Certificate còn hiệu lực.
Những lưu ý khi ký PowerShell Script
- Hoàn tất và kiểm thử Script trước khi ký.
- Sử dụng Code Signing Certificate phù hợp.
- Ưu tiên SHA-256 cho chữ ký mới.
- Sử dụng Timestamp khi phát hành Script.
- Không chỉnh sửa nội dung Script sau khi ký.
- Luôn kiểm tra bằng Get-AuthenticodeSignature.
- Kiểm tra Certificate Chain và Trust Store.
- Bảo vệ Private Key bằng USB Token, HSM hoặc giải pháp Signing phù hợp.
- Không xem Digital Signature là bằng chứng cho việc Script an toàn tuyệt đối.
- Kết hợp Code Signing với Execution Policy và các cơ chế bảo mật khác của Windows.
Xem thêm: Code Signing Certificate là gì?
Kết luận
Ký PowerShell Script là quá trình sử dụng Authenticode để xác minh nguồn gốc và tính toàn vẹn của file PS1. Khác với EXE, DLL hoặc MSI, PowerShell cung cấp cơ chế ký riêng thông qua Set-AuthenticodeSignature và kiểm tra bằng Get-AuthenticodeSignature.
Quy trình cơ bản gồm chuẩn bị Code Signing Certificate, lấy Certificate từ Windows Certificate Store, sử dụng Set-AuthenticodeSignature để ký Script, thêm Timestamp và kiểm tra lại chữ ký trước khi phát hành.
Đối với môi trường doanh nghiệp, Code Signing có thể kết hợp với Execution Policy như AllSigned để kiểm soát Script được phép thực thi. Tuy nhiên, Digital Signature chỉ xác minh nguồn gốc và tính toàn vẹn của Script, không đảm bảo nội dung Script an toàn.
Bạn vẫn chưa biết nên chọn…?
Đừng lo lắng, đội ngũ chuyên gia của chúng tôi luôn sẵn sàng lắng nghe nhu cầu và tư vấn giải pháp bảo mật phù hợp nhất cho website và doanh nghiệp của bạn. Hãy liên hệ ngay để được hỗ trợ nhanh chóng, chính xác và hiệu quả.