2016-06-21 3 views
2

Я пытаюсь устранить неполадку, почему элемент приложения, написанный и скомпилированный в VB6 на машине Vista SP2, отлично работает на этой машине, но не на 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 

окон 10 завершает вызов выделенного вызова CryptVerifySignature и возвращает Err.LastDllError, равный NTE_BAD_SIGNATURE. Машина 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 бит. Excel 2003 на машине Vista, 32-разрядный Excel 2016 на компьютере с Windows 10. Я считаю, что строка, которая не работает в VBA, является той же строкой, которая не работает в скомпилированной программе VB6, где вызов CryptVerifySignature находится в пользовательской DLL. –

ответ

1

После долгих разочарований и бесплодных исследований я в конце концов обнаружил, в чем проблема. По пути я обнаружил, что проблема возникла в другой части кода. Я также обнаружил, что проблема проявилась и в Windows 10 32-разрядной версии - так что не 64-разрядная проблема.

Неправильно заполненный аргумент dwflags для более раннего вызова CryptImportKey, похоже, не мешал вызову CryptVerifySignature, выполняющемуся под Vista 32 бит, хотя вызов CryptImportKey при расследовании не удался. После того как аргумент dwflags CryptImportKey был исправлен, CRYPT_EXPORTABLE или CRYPT_NO_SALT, он преуспел, и последующий вызов CryptVerifySignature сменился всеми альтернативными комбинациями операционных систем/бит, которые я смог проверить.

Извинения и благодарности в равной мере всем тем, кто стремился помочь в этом вопросе. До следующего раза.

0

EDIT - я не вижу ничего плохого с декларированию или звоните

Единственной альтернативой я видел, чтобы изменить байт указателя быть объявлен как 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