Powershell 查看智能卡上的所有证书
我正在尝试创建一个脚本,以从任何给定的智能卡(当时在SC读卡器中)删除除最新证书以外的所有证书。这是我希望能够分发给最终用户的东西,因此它应该是自给自足的。我的第一个问题是读卡上的证书。我不想影响智能卡以外的任何证书,因此我寻找直接从智能卡读取的解决方案,我发现了以下gem: 它很旧,但看起来应该能满足我的需要。总体而言,它似乎确实有效,但当我上线时,PowerShell ISE崩溃:Powershell 查看智能卡上的所有证书,powershell,x509certificate,Powershell,X509certificate,我正在尝试创建一个脚本,以从任何给定的智能卡(当时在SC读卡器中)删除除最新证书以外的所有证书。这是我希望能够分发给最终用户的东西,因此它应该是自给自足的。我的第一个问题是读卡上的证书。我不想影响智能卡以外的任何证书,因此我寻找直接从智能卡读取的解决方案,我发现了以下gem: 它很旧,但看起来应该能满足我的需要。总体而言,它似乎确实有效,但当我上线时,PowerShell ISE崩溃: $store=new object System.Security.Cryptography.X509Cer
$store=new object System.Security.Cryptography.X509Certificates.X509Store($hwStore)
通过将($hwStore)
从该行中排除,我可以创建一个默认为“我的”存储的通用存储,而不会出现问题,但指定该存储会使我的PowerShell ISE可靠崩溃
这是该站点的函数,我遇到的问题在底部附近
函数获取SCUserStore{
[string]$providerName=“Microsoft基本智能卡加密提供程序”
#从advapi32.dll导入CrytoAPI
$signature=@”
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool CryptGetProvParam(
IntPtr hProv,
uint dwParam,
字节[]表示数据,
参考uint pdwProvDataLen,
uint(dwFlags);
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部布尔加密密钥(
IntPtr hKey);
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部布尔加密上下文(
参考IntPtr hProv,
字符串pszContainer,
字符串pszProvider,
uint类型,
(长旗),;
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool CryptGetUserKey(
IntPtr hProv,
uint dwKeySpec,
参考IntPtr phUserKey);
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool CryptGetKeyParam(
IntPtr hKey,
uint dwParam,
字节[]pbData,
参考uint pdwDataLen,
uint(dwFlags);
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部布尔CryptReleaseContext(
IntPtr hProv,
uint(dwFlags);
"@
$CryptoAPI=Add Type-member$signature-name advapiUtils-Namespace CryptoAPI-passthru
#为CryptoAPI设置一些常量
$AT_密钥交换=1
$AT_签名=2
$PROV_RSA_FULL=1
$KP_证书=26
$PP_=2
$PP_集装箱=6
$PP\u用户\u证书存储=42
$CRYPT_FIRST=1
$CRYPT_NEXT=2
$CRYPT\u VERIFYCONTEXT=0xF0000000
[System.IntPtr]$hProvParent=0
$contextRet=$CryptoAPI::CryptAcquireContext([ref]$hprovParent、$null、$providerName、$PROV_RSA_FULL、$CRYPT_VERIFYCONTEXT)
[Uint32]$pdwProvDataLen=0
[字节[]]$pbProvData=$null
$GetProvParamRet=$CryptoAPI::CryptoGetProvParam($hprovParent,$PP_容器,$pbProvData,[ref]$pdwProvDataLen,0)
如果($pdwProvDataLen-gt 0)
{
$ProvData=新对象字节[]$pdwProvDataLen
$GetKeyParamRet=$CryptoAPI::CryptoGetProvParam($hprovParent,$PP_容器,$ProvData,[ref]$pdwProvDataLen,0)
}
$enc=新对象System.Text.UTF8Encoding($null)
$keyContainer=$enc.GetString($ProvData)
写入主机“默认用户密钥容器:$keyContainer”
[Uint32]$pdwProvDataLen=0
[字节[]]$pbProvData=$null
$GetProvParamRet=$CryptoAPI::CryptoGetProvParam($hprovParent、$PP_USER_CERTSTORE、$pbProvData,[ref]$pdwProvDataLen,0)
如果($pdwProvDataLen-gt 0)
{
$ProvData=新对象字节[]$pdwProvDataLen
$GetKeyParamRet=$CryptoAPI::CryptoGetProvParam($hprovParent、$PP_USER_CERTSTORE、$ProvData,[ref]$pdwProvDataLen,0)
[uint32]$provdataInt=[System.BitConverter]::ToUInt32($provdata,0)
[System.IntPtr]$hwStore=$provdataInt
}
$store=新对象系统。安全性。加密。X509Certificates.X509Store($hwStore)
#释放智能卡
$ReleaseContextRet=$CryptoAPI::CryptoReleaseContext($hprovParent,0)
返回$store
}
我对p/Invoke没有任何经验(我想我说得对),所以我不确定如何对以这种方式导入的东西派生的命令进行故障排除
编辑:由certutil-scinfo-silent
列出的提供程序包括:
Microsoft基本智能卡加密提供程序
Microsoft智能卡密钥存储提供商
我在下面的脚本中尝试了这两种方法,最终结果相同。第二个给了我� 当脚本告诉我默认的用户密钥容器是什么时,我感觉它不正确
正如Vesper所建议的那样,我也尝试过x86版本的PowerShell。应用程序不会崩溃,并且会返回一个包含智能卡证书的有效存储。现在的问题是,我无法将其发送给用户,因为希望他们能够导航到x86版本的PowerShell,然后使用它运行脚本就像希望我的狗给我做华夫饼干一样。。。我想这是可能发生的,但很可能会出什么问题,我最终还是得自己去做
Edit2:好的,我想我将强制脚本的这一部分在x86模式下运行。我将发布一个带有更新代码的答案并接受它。如果@Vesper发布了一个关于64/32位的答案(希望有更多信息),我会接受他的答案,这样他就可以得到信任,因为他的评论是引导我找到解决方案的原因。因此,主要问题实际上是您正在将x86 DLL链接到x64 Powershell进程。您可以检查您的Powershell进程是否为x64(通过查询
(获取进程-Id$PID).StartInfo.EnvironmentVariables[“PROCESSOR_ARCHITECTURE”]
),如果检测到x64 Powershell,请手动启动Powershell(x8)
$Arch = (Get-Process -Id $PID).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"];
$Arch
if ($arch -eq "AMD64") {
$here=$myinvocation.mycommand.definition
"$here launched as $arch!"
start-process C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoNewWindow -ArgumentList $here -wait
return
}
"now running under x86"
function Get-SCUserStore {
[CmdletBinding()]
param(
[string]$providerName ="Microsoft Base Smart Card Crypto Provider"
)
# import CrytoAPI from advapi32.dll
$signature = @"
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetProvParam(
IntPtr hProv,
uint dwParam,
byte[] pbProvData,
ref uint pdwProvDataLen,
uint dwFlags);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptDestroyKey(
IntPtr hKey);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptAcquireContext(
ref IntPtr hProv,
string pszContainer,
string pszProvider,
uint dwProvType,
long dwFlags);
[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetUserKey(
IntPtr hProv,
uint dwKeySpec,
ref IntPtr phUserKey);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptGetKeyParam(
IntPtr hKey,
uint dwParam,
byte[] pbData,
ref uint pdwDataLen,
uint dwFlags);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool CryptReleaseContext(
IntPtr hProv,
uint dwFlags);
"@
$CryptoAPI = Add-Type -member $signature -name advapiUtils -Namespace CryptoAPI -passthru
# set some constants for CryptoAPI
$AT_KEYEXCHANGE = 1
$AT_SIGNATURE = 2
$PROV_RSA_FULL = 1
$KP_CERTIFICATE = 26
$PP_ENUMCONTAINERS = 2
$PP_CONTAINER = 6
$PP_USER_CERTSTORE = 42
$CRYPT_FIRST = 1
$CRYPT_NEXT = 2
$CRYPT_VERIFYCONTEXT = 0xF0000000
[System.IntPtr]$hProvParent=0
if([Environment]::Is64BitProcess) {
[Uint64]$pdwProvDataLen = 0
} else {
[Uint32]$pdwProvDataLen = 0
}
$contextRet = $CryptoAPI::CryptAcquireContext([ref]$hprovParent,$null,$providerName,$PROV_RSA_FULL,$CRYPT_VERIFYCONTEXT)
[byte[]]$pbProvData = $null
$GetProvParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_CONTAINER,$pbProvData,[ref]$pdwProvDataLen,0)
if($pdwProvDataLen -gt 0)
{
$ProvData = new-Object byte[] $pdwProvDataLen
$GetKeyParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_CONTAINER,$ProvData,[ref]$pdwProvDataLen,0)
}
$enc = new-object System.Text.UTF8Encoding($null)
$keyContainer = $enc.GetString($ProvData)
Write-Verbose ("The Default User Key Container:{0}" -f $keyContainer)
if([Environment]::Is64BitProcess) {
[Uint64]$pdwProvDataLen = 0
} else {
[Uint32]$pdwProvDataLen = 0
}
[byte[]]$pbProvData = $null
$GetProvParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_USER_CERTSTORE,$pbProvData,[ref]$pdwProvDataLen,0)
if($pdwProvDataLen -gt 0)
{
$ProvData = new-Object byte[] $pdwProvDataLen
$GetKeyParamRet = $CryptoAPI::CryptGetProvParam($hprovParent,$PP_USER_CERTSTORE,$ProvData,[ref]$pdwProvDataLen,0)
if([Environment]::Is64BitProcess) {
[UInt64]$provdataInt = [System.BitConverter]::ToUInt64($provdata,0)
[System.IntPtr]$hwStore = [Long]$provdataInt
} else {
[UInt32]$provdataInt = [System.BitConverter]::ToUInt32($provdata,0)
[System.IntPtr]$hwStore = $provdataInt
}
}
$store = new-object System.Security.Cryptography.X509Certificates.X509Store($hwStore)
# release smart card
$ReleaseContextRet = $CryptoAPI::CryptReleaseContext($hprovParent,0)
return $store
}
write-host ((get-WmiObject win32_PnPSignedDriver|where{$_.deviceID -like "*smartcard*"}).devicename) "reports the following certificates;"
# returns System.Security.Cryptography.X509Certificates.X509Store object representing PP_USER_CERTSTORE on Smart Card
$SCcertStore = Get-SCuserSTore
# enumerate certificates
$SCcertStore.certificates
<#
.SYNOPSIS
Script to convert code coverage report into xml format that can then be published by external tools.
.DESCRIPTION
Covering code coverage staistics as part of quality improvement initiatives .
https://stackoverflow.com/questions/30215324/vstest-code-coverage-report-in-jenkins
#>
Param(
[String] $InputCoveragePath =@("..\GeneratedFiles\Docs\Reports"),
[String] $OutputCoverageFileExtension =@(".coveragexml"),
[String] $CoverageAnalysisAssembly =@("Microsoft.VisualStudio.Coverage.Analysis.dll"),
[String[]] $ExecutablePaths =@(""),
[String[]] $SymbolPaths =@("")
)
$ScriptLocation = Split-Path $script:MyInvocation.MyCommand.Path -Parent
Write-Host $ScriptLocation
<#
if(!(Test-Path "$OutputCoverageFile")){
Write-Host "Creating empty coveragle file $OutputCoverageFile"
New-Item "$OutputCoverageFile" -ItemType "file"
}
#>
$RunAs32Bit = {
Param(
[String] $InputCoveragePath =@("..\GeneratedFiles\Docs\Reports"),
[String] $OutputCoverageFileExtension =@(".coveragexml"),
[String] $CoverageAnalysisAssembly =@("Microsoft.VisualStudio.Coverage.Analysis.dll"),
[String[]] $ExecutablePaths =@(""),
[String[]] $SymbolPaths =@(""),
[String] $ScriptLocation =@(".")
)
Write-Host "[CoverageConverter][Begin]: Coverage conversion started..."
Write-Host "[CoverageConverter][InputCoveragePath]: $InputCoveragePath"
Write-Host "[CoverageConverter][OutputCoverageFileExtension]: $OutputCoverageFileExtension"
Write-Host "[CoverageConverter][CoverageAnalysisAssembly]: $CoverageAnalysisAssembly"
Write-Host "[CoverageConverter][ExecutablePaths]: $ExecutablePaths"
Write-Host "[CoverageConverter][SymbolPaths]: $SymbolPaths"
Write-Host "[CoverageConverter][ScriptLocation]: $ScriptLocation"
Import-Module -Force -Name (Join-Path "$ScriptLocation" "Utilities.psm1")
Add-Type -path "$CoverageAnalysisAssembly"
$Result = 0
if($InputCoveragePath -and (Test-Path "$InputCoveragePath") )
{
[string[]] $coverageFiles = $(Get-ChildItem -Path $InputCoveragePath -Recurse -Include *coverage)
@($coverageFiles) | ForEach-Object {
$coverageFile = $_
$coverageFileOut = (Join-Path -Path $(Split-Path $_ -Parent) -ChildPath ($(Get-Item $_).BaseName + "$OutputCoverageFileExtension"))
Write-Host "If all OK the xml will be written to: $coverageFileOut"
$info = [Microsoft.VisualStudio.Coverage.Analysis.CoverageInfo]::CreateFromFile($coverageFile, $ExecutablePaths, $SymbolPaths);
if($info){
$data = $info.BuildDataSet()
$data.WriteXml($coverageFileOut)
}
}
}
else
{
Write-Host "Please specify a valid input coverage file."
$Result = 1
}
Write-Host "[CoverageConverter][End]: Coverage conversion completed with result $Result"
return $Result
}
#Run the code in 32bit mode if PowerShell isn't already running in 32bit mode
If($env:PROCESSOR_ARCHITECTURE -ne "x86"){
Write-Warning "Non-32bit architecture detected, processing original request in separate 32bit process."
$Job = Start-Job $RunAs32Bit -RunAs32 -ArgumentList ($InputCoveragePath, $OutputCoverageFileExtension, $CoverageAnalysisAssembly, $ExecutablePaths, $SymbolPaths, $ScriptLocation)
$Result = $Job | Wait-Job | Receive-Job
}Else{
$Result = Invoke-Command -ScriptBlock $RunAs32Bit -ArgumentList ($InputCoveragePath, $OutputCoverageFileExtension, $CoverageAnalysisAssembly, $ExecutablePaths, $SymbolPaths, $ScriptLocation)
}