在 Go 中调用 PFXExportCertStoreEx 没有 return 数据
Calling PFXExportCertStoreEx in Go does not return data
我正在 Windows 使用 Go 1.6 并尝试将证书容器导出到 PFX(这里的最终目标是从证书存储访问可导出的私钥)。
我打开了一个记忆库,并在存储库中插入了一个证书:
var storedCertCtx *syscall.CertContext
storeHandle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0)
err = syscall.CertAddCertificateContextToStore(storeHandle, certenum, syscall.CERT_STORE_ADD_ALWAYS, &storedCertCtx)
现在我想生成那个商店的 PFX。我定义了一个包含 data blob and want to use PFXExportCertStoreEx 的结构以获取商店的 PFX:
var (
crypt32 = syscall.NewLazyDLL("crypt32.dll")
procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")
)
type CRYPTOAPI_BLOB struct {
DataSize uint32
Data *byte
}
var pfxBlob CRYPTOAPI_BLOB
err = PfxExportCertStore(storeHandle, &pfxBlob, syscall.StringToUTF16Ptr("MyPassword"), 0, 0)
syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("password"))), //szPassword
0, //*pvPara
0, //dwFlags
0)
这一半有效。
DataSize
填充了看起来合适的值(即,如果我向商店添加更多证书,它会变得更大),但是 Data
是 always <nil>
.
因为它是用指针填充的,所以我尝试将其声明为 *uintptr
和 uint32
(只是为了看看 anything 是否得到人口稠密),但什么也没有。该值始终保持不变(如果我手动将垃圾数据放在那里,垃圾数据会在系统调用执行后保留)。
我是否错误地定义了结构?在 Go 中完成此操作的示例很少,但从我从众多 C 示例中可以看出,应该 可以工作。
这是预期的行为。
根据这个:https://msdn.microsoft.com/en-us/library/windows/desktop/aa387313(v=vs.85).aspx,pPFX
结构需要一个预分配的缓冲区,其大小在 cbData
字段中,它将随着数据复制进来。
如果使用 pbData
等于 NULL
进行调用,则只有 cbData
字段会更新以反映输出缓冲区所需的大小。
JimB 的回答肯定是正确的,但我想添加此内容以进行跟进,以防其他人走这条路。我必须使用的将 PFX 文件放入 CRYPTOAPI_BLOB
的实际代码是:
var (
crypt32 = syscall.NewLazyDLL("crypt32.dll")
procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")
procCryptMemAlloc = crypt32.NewProc("CryptMemAlloc")
procCryptMemFree = crypt32.NewProc("CryptMemFree")
)
type CRYPTOAPI_BLOB struct {
cbData uint32
pbData *byte
}
func (b *CRYPTOAPI_BLOB) ToByteArray() []byte {
d := make([]byte, b.cbData)
copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])
return d
}
func PfxExportCertStore(storeHandle syscall.Handle, password string, flags uint32) (returnData []byte, err error) {
var pfxBlob CRYPTOAPI_BLOB
r1, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword
0, //*pvPara
uintptr(flags), //dwFlags
0)
r2, _, _ := syscall.Syscall(procCryptMemAlloc.Addr(), 1, uintptr(unsafe.Pointer(&pfxBlob.cbData)), 0, 0)
p := unsafe.Pointer(&r2)
q := (*byte)(p)
pfxBlob.pbData = q
defer syscall.Syscall(procCryptMemFree.Addr(), 1, uintptr(unsafe.Pointer(pfxBlob.pbData)), 0, 0)
r3, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword
0, //*pvPara
uintptr(flags), //dwFlags
0)
returnData = pfxBlob.ToByteArray()
return
}
(我删除了错误处理以使其更易于阅读)。第一次调用 PFXExportCertStoreEx
只是 returns 大小,一旦我们有了大小,我们就可以调用 PFXExportCertStoreEx
来分配缓冲区,然后我们将相同的指针传递给 PFXExportCertStoreEx
,但这次它有分配的缓冲区,我们得到返回的完整 PFX 文件。
我正在 Windows 使用 Go 1.6 并尝试将证书容器导出到 PFX(这里的最终目标是从证书存储访问可导出的私钥)。
我打开了一个记忆库,并在存储库中插入了一个证书:
var storedCertCtx *syscall.CertContext
storeHandle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0)
err = syscall.CertAddCertificateContextToStore(storeHandle, certenum, syscall.CERT_STORE_ADD_ALWAYS, &storedCertCtx)
现在我想生成那个商店的 PFX。我定义了一个包含 data blob and want to use PFXExportCertStoreEx 的结构以获取商店的 PFX:
var (
crypt32 = syscall.NewLazyDLL("crypt32.dll")
procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")
)
type CRYPTOAPI_BLOB struct {
DataSize uint32
Data *byte
}
var pfxBlob CRYPTOAPI_BLOB
err = PfxExportCertStore(storeHandle, &pfxBlob, syscall.StringToUTF16Ptr("MyPassword"), 0, 0)
syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("password"))), //szPassword
0, //*pvPara
0, //dwFlags
0)
这一半有效。
DataSize
填充了看起来合适的值(即,如果我向商店添加更多证书,它会变得更大),但是 Data
是 always <nil>
.
因为它是用指针填充的,所以我尝试将其声明为 *uintptr
和 uint32
(只是为了看看 anything 是否得到人口稠密),但什么也没有。该值始终保持不变(如果我手动将垃圾数据放在那里,垃圾数据会在系统调用执行后保留)。
我是否错误地定义了结构?在 Go 中完成此操作的示例很少,但从我从众多 C 示例中可以看出,应该 可以工作。
这是预期的行为。
根据这个:https://msdn.microsoft.com/en-us/library/windows/desktop/aa387313(v=vs.85).aspx,pPFX
结构需要一个预分配的缓冲区,其大小在 cbData
字段中,它将随着数据复制进来。
如果使用 pbData
等于 NULL
进行调用,则只有 cbData
字段会更新以反映输出缓冲区所需的大小。
JimB 的回答肯定是正确的,但我想添加此内容以进行跟进,以防其他人走这条路。我必须使用的将 PFX 文件放入 CRYPTOAPI_BLOB
的实际代码是:
var (
crypt32 = syscall.NewLazyDLL("crypt32.dll")
procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")
procCryptMemAlloc = crypt32.NewProc("CryptMemAlloc")
procCryptMemFree = crypt32.NewProc("CryptMemFree")
)
type CRYPTOAPI_BLOB struct {
cbData uint32
pbData *byte
}
func (b *CRYPTOAPI_BLOB) ToByteArray() []byte {
d := make([]byte, b.cbData)
copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])
return d
}
func PfxExportCertStore(storeHandle syscall.Handle, password string, flags uint32) (returnData []byte, err error) {
var pfxBlob CRYPTOAPI_BLOB
r1, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword
0, //*pvPara
uintptr(flags), //dwFlags
0)
r2, _, _ := syscall.Syscall(procCryptMemAlloc.Addr(), 1, uintptr(unsafe.Pointer(&pfxBlob.cbData)), 0, 0)
p := unsafe.Pointer(&r2)
q := (*byte)(p)
pfxBlob.pbData = q
defer syscall.Syscall(procCryptMemFree.Addr(), 1, uintptr(unsafe.Pointer(pfxBlob.pbData)), 0, 0)
r3, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,
uintptr(storeHandle), //hStore
uintptr(unsafe.Pointer(&pfxBlob)), //*pPFX
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword
0, //*pvPara
uintptr(flags), //dwFlags
0)
returnData = pfxBlob.ToByteArray()
return
}
(我删除了错误处理以使其更易于阅读)。第一次调用 PFXExportCertStoreEx
只是 returns 大小,一旦我们有了大小,我们就可以调用 PFXExportCertStoreEx
来分配缓冲区,然后我们将相同的指针传递给 PFXExportCertStoreEx
,但这次它有分配的缓冲区,我们得到返回的完整 PFX 文件。