2016-06-21 23 views
2

Ich habe versucht, zu beheben, warum ein Element einer Anwendung in VB6 auf einem Vista SP2-Computer geschrieben und kompiliert funktioniert perfekt auf diesem Computer aber nicht auf einem 64-Bit-Windows 10-Computer. Um die Debugging-Fähigkeiten zu verbessern, replizierte ich die Problemcodierung in Excel VBA. Funktioniert auf dem Vista-Computer, aber nicht auf dem Windows 10-Computer.VB-Code mit advapi32.dll cryptverifysignature funktioniert auf Vista SP2 nicht unter Windows 10 64-bit

Die Crypto-Anrufe werden alle thusly erklärt:

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 

Der Teil, der auf der Windows 10-Maschine versagt wird von Bahngleisen oben und unten in der folgenden hervorgehoben:

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 

Der Windows- 10 Maschine schlägt auf dem markierten Aufruf von CryptVerifySignature fehl und gibt ein Err.LastDllError gleich NTE_BAD_SIGNATURE zurück. Der Vista-Computer validiert die Signaturbuße.

Ich habe Tage damit verbracht zu recherchieren, was hier passiert. Alles vergebens. Alle Hinweise erhalten dankbar

+2

Ist die Vista-Maschine 64-Bit? – dbugger

+0

Möglicherweise müssen Sie Attribute für die bedingte Kompilierung verwenden. Wenn Sie eine 64-Bit-Version von Office haben, ist die Version von VBA nicht mehr VBA6, sondern VBA7. Aufrufende APIs/Funktionen unterscheiden sich geringfügig. Siehe diesen Artikel von MS. https://msdn.microsoft.com/en-us/library/office/ee691831(v=office.14).aspx –

+0

Vielen Dank für Ihre Antworten. Die Vista-Maschine ist 32 Bit. Excel 2003 auf Vista Maschine, 32-Bit Excel 2016 auf Windows 10 Maschine. Ich glaube, dass die Zeile, die in VBA fehlschlägt, dieselbe Zeile ist, die in dem kompilierten VB6-Programm fehlschlägt, in dem sich der Aufruf von CryptVerifySignature in einer benutzerdefinierten DLL befindet. –

Antwort

1

Nach vielen Frustrationen und fruchtlosen Nachforschungen habe ich schließlich entdeckt, was das Problem war. Auf dem Weg entdeckte ich, dass das Problem in einem anderen Teil des Codes insgesamt entstanden ist. Ich entdeckte auch, dass sich das Problem auch auf Windows 10 32 Bit manifestierte - also kein 64-Bit-Problem.

Ein falsch gefülltes dwflags-Argument zu einem früheren Aufruf von CryptImportKey schien den Aufruf von CryptVerifySignature unter Vista 32-Bit nicht zu verhindern, obwohl der Aufruf von CryptImportKey bei der Untersuchung fehlgeschlagen war. Sobald das dwflags-Argument von CryptImportKey auf CRYPT_EXPORTABLE oder CRYPT_NO_SALT korrigiert wurde, war es erfolgreich und der nachfolgende Aufruf von CryptVerifySignature war unter allen alternativen Kombinationen von Betriebssystem und Bitanzahl erfolgreich, die ich testen konnte.

Entschuldigung und Dank an alle, die in dieser Angelegenheit helfen wollten. Bis zum nächsten Mal.

0

EDIT - ich nichts falsch mit Ihrem declare sehen können oder rufen Sie

Die einzige Alternative, die ich gesehen habe, ist Byte-Zeiger zu ändern deklariert werden als ByVal pSignature Long und dann Aufruf es mit varPtr(abSig(0)

Aber Ihr Code sieht gut aus - ich bin verwirrt


Ihre Deklaration stimmt nicht mit der Microsoft-API-Deklaration überein. Nicht sicher, ob das durch Design ist, weil Signature ein Byte-Zeiger

Nach docs ist

LPBYTE, BYTE will be : * ByRef Byte 

Ändern Sie diese (durch Standardargumente sind vergangen ByVal)

pbSignature As Byte 

Zu diesem

ByRef pbSignature As Byte 
+0

Danke dafür. Ich hatte verstanden, dass der Standard für VB6 (wo sich das ursprüngliche Problem zu manifestieren scheint) ByRef war, aber ich denke, es ist kein Schaden, explizit zu sein, also werde ich alle Deklarationen explizit machen und sehen, was passiert. –

+0

Nur alle Standarddeklarationen in ByRef geändert und der Fehler ist genau der gleiche wie zuvor. –

+0

Nur pSignature sollte ByRef sein - es ist der einzige Zeiger. Ich sehe, dass Sie das erste Element der Byte-Array übergeben - ich werde meine Antwort oben für einen anderen Anruf Vorschlag bearbeiten – dbmitch