2016-06-21 22 views
2

我一直在試圖解決爲什麼在Vista SP2機器上編寫和編譯VB6應用程序中的元素在該機器上完美工作,但沒有在64位Windows 10機器上。爲了提高調試功能,我在Excel VBA中複製了編碼問題。適用於Vista機器,但不適用於Windows 10機器。VB代碼使用advapi32.dll cryptverifysignature作品在Vista SP2不在Windows 10 64位

中的CryptoAPI電話都宣稱正是如此:

Private Declare Function CryptVerifySignature _ 
Lib "advapi32.dll" _ 
    Alias "CryptVerifySignatureA" (_ 
     ByVal hHash As Long, _ 
     pbSignature As Byte, _ 
     ByVal dwSigLen As Long, _ 
     ByVal hPubKey As Long, _ 
     ByVal sDescription As String, _ 
     ByVal dwFlags As Long _ 
      ) As Long 

是在Windows 10的機器上失敗的部分由上方和下方鐵軌下面的高亮顯示:

Private Function SignValidate(ByRef abData() As Byte, _ 
         ByRef abSigned() As Byte, _ 
         Optional bSigned As Boolean = True) As Long 
Dim hHash As Long 
Dim lngReturnValue As Long 
Dim lngSigLen As Long 
Dim abText() As Byte 
Dim strTxt As String 
Dim lngW As Long 
Dim lngX As Long 
Dim lngY As Long 

Dim abHashVal() As Byte 

SignValidate = -1 
ReDim abText(UBound(abData)) 
abText = abData 

'Create a hash object to sign/validate 
lngReturnValue = CryptCreateHash(hCryptProv, CALG_SHA, 0, 0, hHash) 
If lngReturnValue = 0 Then 
    'Set_locale regionalSymbol 
    Err.Raise Err.LastDllError, , "DLL error code shown above. Could not create a Hash Object (CryptCreateHash API)" 
End If 
'Hash the data 
lngW = UBound(abText) + 1 
lngReturnValue = CryptHashData(hHash, abText(0), lngW, 0) 
If lngReturnValue = 0 Then 
    'Set_locale regionalSymbol 
    Err.Raise Err.LastDllError, , "DLL error code shown above. Could not calculate a Hash Value (CryptHashData API)" 
End If 

If bSigned Then 
    'release old key pair handle 
    If hKeyPair <> 0 Then CryptDestroyKey hKeyPair 
    'get a handle to the signature key pair 
    lngReturnValue = CryptGetUserKey(hCryptProv, AT_SIGNATURE, hKeyPair) 
    If lngReturnValue = 0 Then 
     'Set_locale regionalSymbol 
     Err.Raise Err.LastDllError, , "DLL error code shown above. Could not obtain key pair" 
    End If 
    'Determine the size of the signature 
    lngReturnValue = CryptSignHash(hHash, AT_SIGNATURE, 0, 0, vbNull, lngSigLength) 
    If lngSigLength > 0 Then ReDim abSig(lngSigLength - 1) 
    'Sign the hash object 
    lngReturnValue = CryptSignHash(hHash, AT_SIGNATURE, 0, 0, abSig(0), lngSigLength) 
    If lngReturnValue = 0 Then 
     'Set_locale regionalSymbol 
     Err.Raise Err.LastDllError, , "DLL error code shown above. Could not sign the hash" 
    End If 
    ' the signature is now available 
    ' size returned array to signature length 
    ReDim abSigned(UBound(abSig)) 
    ' return the signature to the calling procedure 
    abSigned = abSig 
    SignValidate = 0 
Else 
    lngSigLength = UBound(abSigned) + 1 
    ReDim abSig(UBound(abSigned)) 
    abSig = abSigned ' load the Signature array 

'======================================================== 
    'this is the line where the actual validation is done 
    lngReturnValue = CryptVerifySignature(hHash, abSig(0), lngSigLength, hKeyPair, 0, 0) 
'======================================================== 
    If lngReturnValue = 0 Then 'some error occurred 
     SignValidate = Err.LastDllError 
    Else 
     SignValidate = 0 
    End If 
End If 
End Function 

在Windows 10機器突出顯示的對CryptVerifySignature的調用失敗,並返回等於NTE_BAD_SIGNATURE的Err.LastDllError。 Vista機器驗證簽名正常。

我花了幾天的時間研究可能發生的事情。一切都無濟於事。任何指針感激地接受

+2

Vista機器是64位的嗎? – dbugger

+0

您可能需要使用條件編譯屬性。如果你有一個64位版本的辦公室,VBA的版本不再是VBA6,而是VBA7。調用API /函數略有不同。從MS看到這篇文章。 https://msdn.microsoft.com/en-us/library/office/ee691831(v=office.14).aspx –

+0

感謝您的回覆。 Vista機器是32位的。 Vista機器上的Excel 2003,Windows 10機器上的32位Excel 2016。我相信在VBA中失敗的那一行是在編譯的VB6程序中失敗的那一行,其中對CryptVerifySignature的調用位於一個自定義DLL中。 –

回答

1

經過多次的挫折和毫無結果的研究,我終於發現問題所在。一路上,我發現問題完全源於代碼的另一部分。我還發現這個問題也表現在Windows 10 32位上 - 所以不是64位的問題。

以前對CryptImportKey的調用錯誤地填充了dwflags參數,但似乎並未阻止在Vista 32位下成功調用CryptVerifySignature,即使調查時對CryptImportKey的調用失敗。一旦CryptImportKey的dwflags參數被更正爲CRYPT_EXPORTABLE或CRYPT_NO_SALT,它就成功了,並且在我能夠測試的所有替代操作系統/位數組合下,對CryptVerifySignature的後續調用成功完成。

道歉和感謝所有尋求幫助的人。直到下一次。

0

編輯 - 我看不出什麼毛病的聲明或致電

我見過的唯一的選擇就是改變字節的指針聲明爲ByVal pSignature Long,然後調用它使用varPtr(abSig(0)

但你的代碼看起來很好 - 我很困惑


您的聲明與Microsoft API聲明不符。不知道這是設計使然,因爲簽名是一個字節的指針

根據文檔

LPBYTE, BYTE will be : * ByRef Byte 

更改此設置(默認參數傳遞BYVAL)

pbSignature As Byte 

對此

ByRef pbSignature As Byte 
+0

謝謝你。我已經明白VB6的默認值(原始問題似乎表現出來了)是ByRef,但我認爲明確無損,所以我將明確所有的聲明,看看會發生什麼。 –

+0

只需將所有默認聲明更改爲ByRef,失敗與以前完全相同。 –

+0

只有pSignature應該是ByRef - 它是唯一的指針。我看到你正在傳遞字節數組的第一個元素 - 我將在上面編輯我的答案以獲得另一個調用建議 – dbmitch

相關問題