在 Go 中调用 PFXExportCertStoreEx 不返回数据

我在 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。我已经定义了一个包含数据 blob的结构,并希望使用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就是永远 <nil>。


看到它意味着用指针填充,我尝试将它声明为*uintptr和uint32(只是为了看看是否填充了任何东西),但什么也没有。该值始终保持不变(如果我手动将垃圾数据放入其中,则在执行系统调用后垃圾数据仍然存在)。


我是否错误地定义了结构?用 Go 完成这件事的例子很少,但是从我从众多 C 例子中看到的,这应该是有效的。


ibeautiful
浏览 173回答 2
2回答

心有法竹

这是预期的行为。根据这个:https&nbsp;:&nbsp;//msdn.microsoft.com/en-us/library/windows/desktop/aa387313(v=pPFX&nbsp;vs.85)&nbsp;.aspx,该结构需要一个预先分配的缓冲区,大小在cbData字段中,它将随着复制的数据大小而更新。如果调用pbData等于NULL,则仅cbData更新字段以反映输出缓冲区所需的大小。

白板的微信

JimB 的回答肯定是正确的,但我想添加这个以进行后续处理,以防其他人沿着这条路走下去。我必须用来获取 PFX 文件的实际代码CRYPTOAPI_BLOB是:var (&nbsp; &nbsp; crypt32&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; = syscall.NewLazyDLL("crypt32.dll")&nbsp; &nbsp; procPFXExportCertStoreEx = crypt32.NewProc("PFXExportCertStoreEx")&nbsp; &nbsp; procCryptMemAlloc&nbsp; &nbsp; &nbsp; &nbsp; = crypt32.NewProc("CryptMemAlloc")&nbsp; &nbsp; procCryptMemFree&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= crypt32.NewProc("CryptMemFree"))type CRYPTOAPI_BLOB struct {&nbsp; &nbsp; cbData uint32&nbsp; &nbsp; pbData *byte}func (b *CRYPTOAPI_BLOB) ToByteArray() []byte {&nbsp; &nbsp; d := make([]byte, b.cbData)&nbsp; &nbsp; copy(d, (*[1 << 30]byte)(unsafe.Pointer(b.pbData))[:])&nbsp; &nbsp; return d}func PfxExportCertStore(storeHandle syscall.Handle, password string, flags uint32) (returnData []byte, err error) {&nbsp; &nbsp; var pfxBlob CRYPTOAPI_BLOB&nbsp; &nbsp; r1, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,&nbsp; &nbsp; &nbsp; &nbsp; uintptr(storeHandle),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //hStore&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&pfxBlob)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//*pPFX&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword&nbsp; &nbsp; &nbsp; &nbsp; 0,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //*pvPara&nbsp; &nbsp; &nbsp; &nbsp; uintptr(flags), //dwFlags&nbsp; &nbsp; &nbsp; &nbsp; 0)&nbsp; &nbsp; r2, _, _ := syscall.Syscall(procCryptMemAlloc.Addr(), 1, uintptr(unsafe.Pointer(&pfxBlob.cbData)), 0, 0)&nbsp; &nbsp; p := unsafe.Pointer(&r2)&nbsp; &nbsp; q := (*byte)(p)&nbsp; &nbsp; pfxBlob.pbData = q&nbsp; &nbsp; defer syscall.Syscall(procCryptMemFree.Addr(), 1, uintptr(unsafe.Pointer(pfxBlob.pbData)), 0, 0)&nbsp; &nbsp; r3, _, _ := syscall.Syscall6(procPFXExportCertStoreEx.Addr(), 5,&nbsp; &nbsp; &nbsp; &nbsp; uintptr(storeHandle),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //hStore&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&pfxBlob)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//*pPFX&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(password))), //szPassword&nbsp; &nbsp; &nbsp; &nbsp; 0,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //*pvPara&nbsp; &nbsp; &nbsp; &nbsp; uintptr(flags), //dwFlags&nbsp; &nbsp; &nbsp; &nbsp; 0)&nbsp; &nbsp; returnData = pfxBlob.ToByteArray()&nbsp; &nbsp; return}(我已经剥离了错误处理以使其更易于阅读)。第一次调用PFXExportCertStoreEx只返回大小,一旦我们有了大小,我们就可以调用来PFXExportCertStoreEx分配一个缓冲区,然后我们将相同的指针传递给PFXExportCertStoreEx,但这次它有分配的缓冲区,我们得到了完整的 PFX文件返回。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go