使用 PowerShell 设置具有特定启用目的的 CA 证书
Setting a CA Certificate, with specific Enabled Purposes, using PowerShell
如何使用 PowerShell 在相关 Windows 证书存储中以编程方式更改证书颁发机构的启用用途?
这可以在 Certificates MMC snap-in
这是否只能使用 P/Invoke 和 CertSetCertificateContextProperty
as per
理想情况下,我想导入一个自定义的受信任的根证书颁发机构,并且仅为客户端身份验证的目的启用它。
使用 CertSetCertificateContextProperty
at it's core. Thank you to Crypt32 的 PowerShell Cmdlet 以及他们在另一个 post 上的回答作为指导。
用法示例:
Set-CertificateEku -StoreLocation 'CurrentUser' -StoreName 'Root' -CertificateThumbprint 'ffffffffffffffffffffffffffffffffffffffff' -Oids @("1.3.6.1.5.5.7.3.2") # Client Authentication
Function Set-CertificateEku {
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
[ValidateSet('CurrentUser', 'LocalMachine')]
$StoreLocation,
[Parameter(Mandatory)]
$StoreName,
[Parameter(Mandatory)]
$CertificateThumbprint,
[Parameter(Mandatory)]
$Oids
)
$StoreLocation = switch($StoreLocation) {
'CurrentUser' {
[System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
}
'LocalMachine' {
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
}
}
try {
$CertificateStore = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation)
$CertificateStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite -bor [System.Security.Cryptography.X509Certificates.OpenFlags]::OpenExistingOnly)
} catch {
Write-Error "Could not Open Certificate Store $StoreName in $StoreLocation"
return $false
}
$Certificates = $CertificateStore.Certificates.Find(
[System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint,
$CertificateThumbprint,
$false
)
if($Certificates.Count -eq 0) {
Write-Error "Could not find Certificate $CertificateThumbprint in $StoreName in $StoreLocation"
return $false
}
$Certificate = $Certificates[0]
$PKICrypt32 = @"
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
uint dwFlags,
IntPtr pvData
);
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CRYPTOAPI_BLOB {
public uint cbData;
public IntPtr pbData;
}
"@
Add-Type -MemberDefinition $PKICrypt32 -Namespace 'PKI' -Name 'Crypt32'
$OIDs = [Security.Cryptography.OidCollection]::new()
foreach($Oid in $Oids) {
[void]$OIDs.Add([Security.Cryptography.Oid]::new($Oid))
}
$EKU = [Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]::new($OIDs, $false)
$pbData = [Runtime.InteropServices.Marshal]::AllocHGlobal($EKU.RawData.Length)
[Runtime.InteropServices.Marshal]::Copy($EKU.RawData, 0, $pbData, $EKU.RawData.Length)
$Blob = New-Object PKI.Crypt32+CRYPTOAPI_BLOB -Property @{
cbData = $EKU.RawData.Length;
pbData = $pbData;
}
$pvData = [Runtime.InteropServices.Marshal]::AllocHGlobal([Runtime.InteropServices.Marshal]::SizeOf([type][PKI.Crypt32+CRYPTOAPI_BLOB]))
[Runtime.InteropServices.Marshal]::StructureToPtr($Blob, $pvData, $false)
$Result = [PKI.Crypt32]::CertSetCertificateContextProperty($Certificate.Handle, 9, 0, $pvData)
[Runtime.InteropServices.Marshal]::FreeHGlobal($pvData)
[Runtime.InteropServices.Marshal]::FreeHGlobal($pbData)
$CertificateStore.Close()
return $Result
}
如何使用 PowerShell 在相关 Windows 证书存储中以编程方式更改证书颁发机构的启用用途?
这可以在 Certificates MMC snap-in
这是否只能使用 P/Invoke 和 CertSetCertificateContextProperty
as per
理想情况下,我想导入一个自定义的受信任的根证书颁发机构,并且仅为客户端身份验证的目的启用它。
使用 CertSetCertificateContextProperty
at it's core. Thank you to Crypt32 的 PowerShell Cmdlet 以及他们在另一个 post 上的回答作为指导。
用法示例:
Set-CertificateEku -StoreLocation 'CurrentUser' -StoreName 'Root' -CertificateThumbprint 'ffffffffffffffffffffffffffffffffffffffff' -Oids @("1.3.6.1.5.5.7.3.2") # Client Authentication
Function Set-CertificateEku {
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
[ValidateSet('CurrentUser', 'LocalMachine')]
$StoreLocation,
[Parameter(Mandatory)]
$StoreName,
[Parameter(Mandatory)]
$CertificateThumbprint,
[Parameter(Mandatory)]
$Oids
)
$StoreLocation = switch($StoreLocation) {
'CurrentUser' {
[System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
}
'LocalMachine' {
[System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
}
}
try {
$CertificateStore = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation)
$CertificateStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite -bor [System.Security.Cryptography.X509Certificates.OpenFlags]::OpenExistingOnly)
} catch {
Write-Error "Could not Open Certificate Store $StoreName in $StoreLocation"
return $false
}
$Certificates = $CertificateStore.Certificates.Find(
[System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint,
$CertificateThumbprint,
$false
)
if($Certificates.Count -eq 0) {
Write-Error "Could not find Certificate $CertificateThumbprint in $StoreName in $StoreLocation"
return $false
}
$Certificate = $Certificates[0]
$PKICrypt32 = @"
[DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CertSetCertificateContextProperty(
IntPtr pCertContext,
uint dwPropId,
uint dwFlags,
IntPtr pvData
);
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CRYPTOAPI_BLOB {
public uint cbData;
public IntPtr pbData;
}
"@
Add-Type -MemberDefinition $PKICrypt32 -Namespace 'PKI' -Name 'Crypt32'
$OIDs = [Security.Cryptography.OidCollection]::new()
foreach($Oid in $Oids) {
[void]$OIDs.Add([Security.Cryptography.Oid]::new($Oid))
}
$EKU = [Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension]::new($OIDs, $false)
$pbData = [Runtime.InteropServices.Marshal]::AllocHGlobal($EKU.RawData.Length)
[Runtime.InteropServices.Marshal]::Copy($EKU.RawData, 0, $pbData, $EKU.RawData.Length)
$Blob = New-Object PKI.Crypt32+CRYPTOAPI_BLOB -Property @{
cbData = $EKU.RawData.Length;
pbData = $pbData;
}
$pvData = [Runtime.InteropServices.Marshal]::AllocHGlobal([Runtime.InteropServices.Marshal]::SizeOf([type][PKI.Crypt32+CRYPTOAPI_BLOB]))
[Runtime.InteropServices.Marshal]::StructureToPtr($Blob, $pvData, $false)
$Result = [PKI.Crypt32]::CertSetCertificateContextProperty($Certificate.Handle, 9, 0, $pvData)
[Runtime.InteropServices.Marshal]::FreeHGlobal($pvData)
[Runtime.InteropServices.Marshal]::FreeHGlobal($pbData)
$CertificateStore.Close()
return $Result
}