powered by simpleCommunicator - 2.0.40     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Что не так в цифровой подписи использующей BCryptSignHash из BCrypt.dll (CNG)
1 сообщений из 1, страница 1 из 1
Что не так в цифровой подписи использующей BCryptSignHash из BCrypt.dll (CNG)
    #39332678
AdamAry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.

Что не так в этой функции VFP_SIGN для цифровой подписи использующей BCryptSignHash из BCrypt.dll (CNG)?:
BCryptOpenAlgorithmProvider отрабатывает нормально, возвращает 0.
BCryptImportKeyPair отрабатывает нормально, возвращает 0.
Проблемы начинаются в BCryptSignHash, он не возвращает в параметр по ссылке @lcSigned значение цифровой подписи, и возвращает не 0.

SET PROCEDURE TO BCryptSign.prg, BCryptHash.prg ADDITIVE
m.lStr = "Man" && The result for SHA1 must be: 8B70BB3A4D458CF297AB7B3A3B07B63B5CA07DE9
*!* m.lStr = "The quick brown fox jumps over the lazy dog" && The result for SHA1 must be: 2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12
m.lStrHashHexBinary = HASH(m.lStr, "SHA1")
? m.lStrHashHexBinary
STRTOFILE(m.lStrHashHexBinary, "ManHashHexBinary.txt")
&& _cliptext = m.lStrHashHexBinary
m.lStrHashANSI = STRCONV(m.lStrHashHexBinary, 16) && 16 converts from hexbinary to ANSI: ‹p»:MEЊт—«{:;¶;\ }й
? m.lStrHashANSI
STRTOFILE(m.lStrHashANSI, "ManHashAnsi.txt")
&& _cliptext = m.lStrHashANSI

CLEAR
m.lpr = ALLTRIM(FILETOSTR("GeneratedLPR.txt")) && PrivateKey in ANSI
SET STEP ON
*!* ?VFP_ENCRYPT_BY_PRIVATE_KEY("Man", m.lpr)
m.lcSignature = VFP_SIGN(m.lStrHashANSI, m.lpr) && m.lpr ~ PrivateKey in ANSI
&& m.lcSignature = VFP_SIGN(m.lStr, m.lpr)
? m.lcSignature


FUNCTION VFP_SIGN
&& LPARAMETERS m.tcData, m.tcPrivateKey && tcPublicKey
* Encrypts data using the RSA algorithm
LPARAMETERS m.tcData, m.tcPrivateKey && tcPublicKey
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the RSA algorithm
LOCAL m.lnAlg
m.lnAlg = 0
IF m.llOK
m.lNatija = BCryptOpenAlgorithmProvider( @lnAlg, ;
STRCONV("RSA",5)+CHR(0), NULL, 0 ) && BCRYPT_SHA1_ALGORITHM
m.llOK = m.lNatija == 0
ENDIF
* Import the public key
LOCAL m.lnKey
m.lnKey = 0
IF m.llOK
m.lNatija = BCryptImportKeyPair( m.lnAlg, 0, ;
STRCONV("RSAPRIVATEBLOB",5)+CHR(0), @lnKey, ; && STRCONV("RSAPUBLICBLOB",5)+CHR(0), @lnKey, ; */
m.tcPrivateKey, LEN(m.tcPrivateKey), 0 )
m.llOK = m.lNatija == 0
ENDIF

*!* * Determine the size of the encrypted data blob (tmp)
*!* LOCAL m.lnSize
*!* IF m.llOK
*!* m.lnSize = 0
*!* m.lNatija = BCryptEncrypt( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
*!* m.tcData, ; && PUCHAR pbInput
*!* LEN(m.tcData), ; && ULONG cbInput
*!* NULL, ; && VOID *pPaddingInfo
*!* NULL, ; && PUCHAR pbIV
*!* 0, ; && ULONG cbIV
*!* NULL, ; && PUCHAR pbOutput
*!* 0, ; && ULONG cbOutput
*!* @lnSize, ; && ULONG *pcbResult
*!* 0x00000002 ) && ULONG dwFlags && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
*!* m.llOK = m.lNatija == 0
*!* IF VARTYPE(m.lNatija)="L"
*!* m.llOK = m.lNatija == .T.
*!* ELSE
*!* m.llOK = m.lNatija == 0
*!* ENDIF
*!* ENDIF
* Determine the size of the signed data blob
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
m.lNatija = BCryptSignHash( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
NULL, ; && lnAlg, ; && NULL, ; && VOID *pPaddingInfo, && must not be NULL if it is "BCRYPT_PAD_PKCS1": SHA-1
m.tcData, ; && PUCHAR pbInput,
LEN(m.tcData), ; && ULONG cbInput,
NULL, ; && PUCHAR pbOutput,
0 , ; && ULONG cbOutput,
@lnSize, ; && ULONG *pcbResult,
0x00000002) && ULONG dwFlags && If key is asym. key: BCRYPT_PAD_NONE, BCRYPT_PAD_OAEP, BCRYPT_PAD_PKCS1; BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
&& m.llOK = m.lNatija == 0
IF VARTYPE(m.lNatija)="L"
m.llOK = m.lNatija == .T.
ELSE
m.llOK = m.lNatija == 0
ENDIF
ENDIF
*!* * Encrypt the data block (tmp)
*!* LOCAL m.lcEncrypted
*!* IF m.llOK
*!* m.lcEncrypted = SPACE(m.lnSize)
*!* m.lNatija = BCryptEncrypt( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
*!* m.tcData, ; && PUCHAR pbInput
*!* LEN(m.tcData), ; && ULONG cbInput
*!* NULL, ; && VOID *pPaddingInfo
*!* NULL, ; && PUCHAR pbIV
*!* 0, ; && ULONG cbIV
*!* @lcEncrypted, ; && PUCHAR pbOutput
*!* LEN(m.lcEncrypted), ; && ULONG cbOutput,
*!* @lnSize, ; && ULONG *pcbResult,
*!* 0x00000002 ) && ULONG dwFlags && If key is asym. key: BCRYPT_PAD_NONE, BCRYPT_PAD_OAEP, BCRYPT_PAD_PKCS1; BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
*!* IF VARTYPE(m.lNatija)="L"
*!* m.llOK = m.lNatija == .T.
*!* ELSE
*!* m.llOK = m.lNatija == 0
*!* ENDIF
*!* ENDIF

* Sign the data block
LOCAL m.lcSigned
IF m.llOK
m.lcSigned = SPACE(m.lnSize)
m.lNatija = BCryptSignHash( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
NULL, ; && @lnAlg, ; && NULL, ; && VOID *pPaddingInfo, && must not be NULL if it is "BCRYPT_PAD_PKCS1": SHA-1
m.tcData, ; && PUCHAR pbInput,
LEN(m.tcData), ; && ULONG cbInput,
@lcSigned, ; && PUCHAR pbOutput,
LEN(m.lcSigned), ; && ULONG cbOutput,
@lnSize, ; && ULONG *pcbResult,
0x00000002) && ULONG dwFlags && If key is asym. key: BCRYPT_PAD_NONE, BCRYPT_PAD_OAEP, BCRYPT_PAD_PKCS1.
IF VARTYPE(m.lNatija)="L"
m.llOK = m.lNatija == .T.
ELSE
m.llOK = m.lNatija == 0
ENDIF
&& http://en.verysource.com/code/1368430_1/bcrypt.h.html
&& BCRYPT_SIGNATURE_OPERATION 0x00000010
&& ?llOK == 0
&& BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
*!* winapi::bcrypt::BCRYPT_PAD_PKCS1
*!* pub const BCRYPT_PAD_PKCS1: ULONG = 0x00000002
ENDIF
* Cleanup
IF m.lnAlg != 0
BCryptCloseAlgorithmProvider( m.lnAlg, 0 )
ENDIF
IF m.lnKey != 0
BCryptDestroyKey( m.lnKey )
ENDIF
IF NOT m.llOK
m.lcSigned = ""
ENDIF

RETURN m.lcSigned
ENDFUNC


&&&& File CNG.prg (декларация функций WinApi):
* API declarations for the CNG API

* This BCryptSignHash had been added by me. Is it right?
DECLARE BCryptSignHash IN BCrypt.DLL ;
Long hKey, String pPaddingInfo, String pbInput, ;
Long cbInput, String @pbOutput, Long cbOutput, ;
Long @pcbResult, Long dwFlags

*******************************************************************
DECLARE Long BCryptOpenAlgorithmProvider IN BCrypt.DLL ;
Long @phAlgorithm, String pszAlgId, ;
String pszImplementation, Long dwFlags

DECLARE Long BCryptGetProperty IN BCrypt.DLL ;
Long hObject, String pszProperty, Long @pbOutput, ;
Long cbOutput, Long @pcbResult, Long dwFlags

DECLARE Long BCryptCreateHash IN BCrypt.dll ;
Long hAlgorithm, Long @phHash, String @pbHashObject, ;
Long cbHashObject, String pbSecret, Long cbSecret, ;
Long dwFlags

DECLARE Long BCryptHashData IN BCrypt.dll ;
Long hHash, String pbInput, Long cbInput, Long dwFlags

DECLARE Long BCryptFinishHash IN BCrypt.DLL ;
Long hHash, String @pbOutput, Long cbOutput, Long ;
dwFlags

DECLARE Long BCryptDestroyHash IN BCrypt.DLL ;
Long hHash

DECLARE Long BCryptCloseAlgorithmProvider IN BCrypt.DLL;
Long hAlgorithm, Long dwFlags

DECLARE Long BCryptDestroyKey IN BCrypt.DLL ;
Long hKey

DECLARE Long BCryptFinalizeKeyPair IN BCrypt.DLL ;
Long hKey, Long dwFlags

DECLARE Long BCryptGenerateKeyPair IN BCrypt.DLL ;
Long hAlgorithm, Long @phKey, Long dwLength, ;
Long dwFlags

* New picture
DECLARE Long BCryptExportKey IN BCrypt.DLL ;
Long kKey, Long hExportKey, String pszBlobType, ;
String @pbOutput, Long cbOutput, Long @pcbResult, ;
Long dwFlags

DECLARE Long BCryptEncrypt IN BCrypt.DLL ;
Long hKey, String pbInput, Long cbInput, ;
String pPaddingInfo, String @pbIV, Long cbIV, ;
String @pbOutput, Long cbOutput, Long @pcbResult, ;
Long dwFlags

DECLARE Long BCryptImportKeyPair IN BCrypt.DLL ;
Long hAlgorithm, Long hImportKey, String pszBlobType, ;
Long @phKey, String pbInput, Long cbInput, ;
Long dwFlags

DECLARE Long BCryptDecrypt IN BCrypt.DLL ;
Long hKey, String pbInput, Long cbInput, ;
String pPaddingInfo, String @pbIV, Long cbIV, ;
String @pbOutput, Long cbOutput, Long @pcbResult, ;
Long dwFlags



&&&& File BCryptHash.prg (Функция HASH вычисляет SHA1, SHA256, MD5, SHA512 и т.д.)
*
CLEAR
uz = HASH("The quick brown fox jumps over the lazy dog", "SHA1") && SHA1, SHA256, MD5, SHA512
&& The result for SHA1 must be: 2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12
&& The result for SHA256 must be: D7A8FBB3 07D78094 69CA9ABC B0082E4F 8D5651E4 6D3CDB76 2D02D0BF 37C9E592
?[SHA: ] +uz && Converts single-byte characters in cExpression to encoded hexBinary.
_cliptext = uz
*!* FOR i = 1 TO 16
*!* ?STR(i)+[: ]+STRCONV(STRCONV(uz,16), i) && 16 from hexbinary(16) to ANSI and ....
*!* ENDFOR

FUNCTION HASH
* Creates a SHA 256 hash value
LPARAMETERS tcData, tcHashAlg
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the hashing algorithm provider
LOCAL m.lnAlg
m.lnAlg = 0
IF m.llOK
m.llOK= BCryptOpenAlgorithmProvider( ;
@lnAlg, STRCONV(tcHashAlg,5)+CHR(0), NULL, 0 ) == 0 && @lnAlg, STRCONV("SHA256",5)+CHR(0), NULL, 0 ) == 0
ENDIF
* Determine how many bytes we need to store hash object
LOCAL m.lnSizeObj, m.lnData
IF m.llOK
m.lnSizeObj = 0
m.lnData = 0
m.llOK = BCryptGetProperty(m.lnAlg, ;
STRCONV("ObjectLength",5)+CHR(0), @lnSizeObj, ;
4, @lnData, 0 ) == 0
ENDIF
* Determine length of the hash value
LOCAL m.lnSizeHash
IF m.llOK
m.lnSizeHash = 0
m.llOK = BCryptGetProperty( m.lnAlg, ;
STRCONV("HashDigestLength",5)+CHR(0), ;
@lnSizeHash, 4, @lnData, 0 ) == 0
ENDIF
* Create the hash object (ostagiisii yangii suratta', itia', bitta')
LOCAL m.lnHash, m.lcHashObj
m.lnHash = 0
IF m.llOK
m.lcHashObj = SPACE(m.lnSizeObj)
m.llOK = BCryptCreateHash( m.lnAlg, @lnHash, ;
@lcHashObj, m.lnSizeObj, NULL, 0, 0) == 0
ENDIF
* To create the hash value we add data to the hash
* object. You can repeat this step as needed
IF m.llOK
m.llOK=BCryptHashData( ;
m.lnHash, m.tcData, LEN(m.tcData), 0 ) == 0
ENDIF
* Tell the hash object that we are done. The algorithm
* now calculates the hash value and returns it.
LOCAL m.lcHash
IF m.llOK
m.lcHash = SPACE(m.lnSizeHash)
m.llOK = BCryptFinishHash( ;
m.lnHash, @lcHash, m.lnSizeHash, 0 ) == 0
ENDIF
* Cleanup
IF m.lnAlg != 0
BCryptCloseAlgorithmProvider( m.lnAlg, 0 )
ENDIF
IF m.lnHash != 0
BCryptDestroyHash( m.lnHash )
ENDIF
IF NOT m.llOK
lcHash = ""
ENDIF

m.lcHash15 = STRCONV(m.lcHash,15) && HexBinary ~ 16 format
RETURN m.lcHash15 && m.lcHash
ENDFUNC


&&&& File bcryptgenrsa2048bitkeys.prg (генерирует пару открытого и закрытого ключа):
*!* CLEAR
*!* apk = FILETOSTR("apple_private_key.pem")
*!* ?apk
*!* ?LEN(apk)

CLEAR
PUBLIC LPR, LPU && LPR - private key, LPU - public key
?GENERATE_KEYS(@LPR, @LPU)
STRTOFILE(LPR, "GeneratedLPR.txt")
STRTOFILE(LPU, "GeneratedLPU.txt")
_cliptext =LPU
*!* _cliptext = LPR

*!* LPR13 = STRCONV(LPR,13)
*!* LPU13 = STRCONV(LPU,13)
*!* STRTOFILE(LPR13, "GeneratedLPR13.txt")
*!* STRTOFILE(LPU13, "GeneratedLPU13.txt")

LPR15 = STRCONV(LPR,15)
LPU15 = STRCONV(LPU,15)
STRTOFILE(LPR15, "GeneratedLPR15.txt")
STRTOFILE(LPU15, "GeneratedLPU15.txt")

*!* LPR16 = STRCONV(LPR,16)
*!* LPU16 = STRCONV(LPU,16)
*!* STRTOFILE(LPR16, "GeneratedLPR16.txt")
*!* STRTOFILE(LPU16, "GeneratedLPU16.txt")

&& normal i for STRCONV(LPR,i) and STRCONV(LPU,i): 13, 15
&& 13: Converts single-byte characters in cExpression to encoded base64 binary.
&& 15: Converts single-byte characters in cExpression to encoded hexBinary.
&& Last "=" -> 13 (len 720)
&& len 1078 -> 15
*!* FOR i = 13 TO 13
*!* ?[LPR: ] + CHR(13)+CHR(10)+STRCONV(LPR,i)
*!* ?[LPU: ] + CHR(13)+CHR(10)+STRCONV(LPU,i)
*!* ?[ STR(LEN(STRCONV(LPR,i))): ] + STR(LEN(STRCONV(LPR,i)))
*!* ENDFOR

FUNCTION GENERATE_KEYS
* Generates a pair of public and private keys
LPARAMETERS m.rcPrivate, m.rcPublic
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the algorithm
LOCAL m.lnAlg
m.lnAlg = 0
IF m.llOK
m.llOK = BCryptOpenAlgorithmProvider( @lnAlg, ;
STRCONV("RSA",5)+CHR(0), NULL, 0 ) == 0
ENDIF
* Generate the keys.
LOCAL m.lnKey
m.lnKey = 0
IF m.llOK
m.llOK = BCryptGenerateKeyPair( ;
m.lnAlg, @lnKey, 2048, 0 ) == 0
ENDIF
IF m.llOK
llOK = BCryptFinalizeKeyPair( lnKey, 0 ) == 0
ENDIF
* Get the two keys
IF m.llOK
m.rcPrivate = ExportKey( m.lnKey, "RSAPRIVATEBLOB" )
m.rcPublic = ExportKey( m.lnKey, "RSAPUBLICBLOB" )
IF EMPTY(m.rcPrivate) OR EMPTY(m.rcPublic)
m.llOK = .F.
ENDIF
ENDIF
* Cleanup
IF m.lnAlg != 0
BCryptCloseAlgorithmProvider( m.lnAlg, 0 )
ENDIF
IF m.lnKey !=0
BCryptDestroyKey( m.lnKey )
ENDIF

RETURN m.llOK
ENDFUNC

* Returns the key value
PROCEDURE ExportKey( m.tnKey, m.tcKey)
LOCAL m.llOK
m.llOK = .T.
* Determine the size of the key
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
llOK = BCryptExportKey( m.tnKey, 0, ;
STRCONV(m.tcKey,5)+CHR(0), NULL, 0, @lnSize, ;
0 ) == 0
ENDIF
* Request the key
LOCAL m.lcKey
IF m.llOK
lcKey = SPACE(m.lnSize)
llOK = BCryptExportKey( m.tnKey, 0, ;
STRCONV(m.tcKey,5)+CHR(0), @lcKey, LEN(m.lcKey), ;
@lnSize, 0 ) == 0
ENDIF
* Returns key if successful
IF NOT m.llOK
lcKey = ""
ENDIF
RETURN m.lcKey
ENDPROC


&&&& File BCryptSign.prg (Здесь функции для цифровой подписи, также функции для шифрования):

*************************************************************************************************************************
&& BCryptSignHash's example, c++:
&& https://msdn.microsoft.com/en-us/library/windows/desktop/aa376304(v=vs.85).aspx
&& "RSAFULLPRIVATEBLOB"
FUNCTION VFP_SIGN
&& LPARAMETERS m.tcData, m.tcPrivateKey && tcPublicKey
* Encrypts data using the RSA algorithm
LPARAMETERS m.tcData, m.tcPrivateKey && tcPublicKey
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the RSA algorithm
LOCAL m.lnAlg
m.lnAlg = 0
IF m.llOK
m.lNatija = BCryptOpenAlgorithmProvider( @lnAlg, ;
STRCONV("RSA",5)+CHR(0), NULL, 0 ) && BCRYPT_SHA1_ALGORITHM
m.llOK = m.lNatija == 0
ENDIF
* Import the public key
LOCAL m.lnKey
m.lnKey = 0
IF m.llOK
m.lNatija = BCryptImportKeyPair( m.lnAlg, 0, ;
STRCONV("RSAPRIVATEBLOB",5)+CHR(0), @lnKey, ; && STRCONV("RSAPUBLICBLOB",5)+CHR(0), @lnKey, ; */
m.tcPrivateKey, LEN(m.tcPrivateKey), 0 )
m.llOK = m.lNatija == 0
ENDIF

*!* * Determine the size of the encrypted data blob (tmp)
*!* LOCAL m.lnSize
*!* IF m.llOK
*!* m.lnSize = 0
*!* m.lNatija = BCryptEncrypt( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
*!* m.tcData, ; && PUCHAR pbInput
*!* LEN(m.tcData), ; && ULONG cbInput
*!* NULL, ; && VOID *pPaddingInfo
*!* NULL, ; && PUCHAR pbIV
*!* 0, ; && ULONG cbIV
*!* NULL, ; && PUCHAR pbOutput
*!* 0, ; && ULONG cbOutput
*!* @lnSize, ; && ULONG *pcbResult
*!* 0x00000002 ) && ULONG dwFlags && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
*!* m.llOK = m.lNatija == 0
*!* IF VARTYPE(m.lNatija)="L"
*!* m.llOK = m.lNatija == .T.
*!* ELSE
*!* m.llOK = m.lNatija == 0
*!* ENDIF
*!* ENDIF
* Determine the size of the signed data blob
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
m.lNatija = BCryptSignHash( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
NULL, ; && lnAlg, ; && NULL, ; && VOID *pPaddingInfo, && must not be NULL if it is "BCRYPT_PAD_PKCS1": SHA-1
m.tcData, ; && PUCHAR pbInput,
LEN(m.tcData), ; && ULONG cbInput,
NULL, ; && PUCHAR pbOutput,
0 , ; && ULONG cbOutput,
@lnSize, ; && ULONG *pcbResult,
0x00000002) && ULONG dwFlags && If key is asym. key: BCRYPT_PAD_NONE, BCRYPT_PAD_OAEP, BCRYPT_PAD_PKCS1; BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
&& m.llOK = m.lNatija == 0
IF VARTYPE(m.lNatija)="L"
m.llOK = m.lNatija == .T.
ELSE
m.llOK = m.lNatija == 0
ENDIF
ENDIF
*!* * Encrypt the data block (tmp)
*!* LOCAL m.lcEncrypted
*!* IF m.llOK
*!* m.lcEncrypted = SPACE(m.lnSize)
*!* m.lNatija = BCryptEncrypt( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
*!* m.tcData, ; && PUCHAR pbInput
*!* LEN(m.tcData), ; && ULONG cbInput
*!* NULL, ; && VOID *pPaddingInfo
*!* NULL, ; && PUCHAR pbIV
*!* 0, ; && ULONG cbIV
*!* @lcEncrypted, ; && PUCHAR pbOutput
*!* LEN(m.lcEncrypted), ; && ULONG cbOutput,
*!* @lnSize, ; && ULONG *pcbResult,
*!* 0x00000002 ) && ULONG dwFlags && If key is asym. key: BCRYPT_PAD_NONE, BCRYPT_PAD_OAEP, BCRYPT_PAD_PKCS1; BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
*!* IF VARTYPE(m.lNatija)="L"
*!* m.llOK = m.lNatija == .T.
*!* ELSE
*!* m.llOK = m.lNatija == 0
*!* ENDIF
*!* ENDIF

* Sign the data block
LOCAL m.lcSigned
IF m.llOK
m.lcSigned = SPACE(m.lnSize)
m.lNatija = BCryptSignHash( m.lnKey, ; && BCRYPT_KEY_HANDLE hKey
NULL, ; && @lnAlg, ; && NULL, ; && VOID *pPaddingInfo, && must not be NULL if it is "BCRYPT_PAD_PKCS1": SHA-1
m.tcData, ; && PUCHAR pbInput,
LEN(m.tcData), ; && ULONG cbInput,
@lcSigned, ; && PUCHAR pbOutput,
LEN(m.lcSigned), ; && ULONG cbOutput,
@lnSize, ; && ULONG *pcbResult,
0x00000002) && ULONG dwFlags && If key is asym. key: BCRYPT_PAD_NONE, BCRYPT_PAD_OAEP, BCRYPT_PAD_PKCS1.
IF VARTYPE(m.lNatija)="L"
m.llOK = m.lNatija == .T.
ELSE
m.llOK = m.lNatija == 0
ENDIF
&& http://en.verysource.com/code/1368430_1/bcrypt.h.html
&& BCRYPT_SIGNATURE_OPERATION 0x00000010
&& ?llOK == 0
&& BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
*!* winapi::bcrypt::BCRYPT_PAD_PKCS1
*!* pub const BCRYPT_PAD_PKCS1: ULONG = 0x00000002
ENDIF
* Cleanup
IF m.lnAlg != 0
BCryptCloseAlgorithmProvider( m.lnAlg, 0 )
ENDIF
IF m.lnKey != 0
BCryptDestroyKey( m.lnKey )
ENDIF
IF NOT m.llOK
m.lcSigned = ""
ENDIF

RETURN m.lcSigned
ENDFUNC

*************************************************************************************************************************

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&& New function added by me:
FUNCTION VFP_ENCRYPT_BY_PRIVATE_KEY
* Encrypts data using the RSA algorithm
LPARAMETERS m.tcData, m.tcPrivateKey && tcPublicKey
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the RSA algorithm
LOCAL m.lnAlg
m.lnAlg = 0
IF m.llOK
m.llOK = BCryptOpenAlgorithmProvider( @lnAlg, ;
STRCONV("RSA",5)+CHR(0), NULL, 0 ) == 0
ENDIF
* Import the public key
LOCAL m.lnKey
m.lnKey = 0
IF m.llOK
m.llOK = BCryptImportKeyPair( m.lnAlg, 0, ;
STRCONV("RSAPRIVATEBLOB",5)+CHR(0), @lnKey, ; && STRCONV("RSAPUBLICBLOB",5)+CHR(0), @lnKey, ; */
m.tcPrivateKey, LEN(m.tcPrivateKey), 0 ) == 0
ENDIF
* Determine the size of the encrypted data blob
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
llOK = BCryptEncrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, NULL, 0, @lnSize, ;
0x00000002 ) == 0 && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
ENDIF
* Encrypt the data block
LOCAL m.lcEncrypted
IF m.llOK
m.lcEncrypted = SPACE(m.lnSize)
m.lNatija = BCryptEncrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, @lcEncrypted, ;
LEN(m.lcEncrypted), @lnSize, 0x00000002 ) && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
llOK = m.lNatija == 0
ENDIF
* Cleanup
IF m.lnAlg != 0
BCryptCloseAlgorithmProvider( m.lnAlg, 0 )
ENDIF
IF m.lnKey != 0
BCryptDestroyKey( m.lnKey )
ENDIF
IF NOT m.llOK
m.lcEncrypted = ""
ENDIF

RETURN m.lcEncrypted
ENDFUNC

FUNCTION VFP_DECRYPT_BY_PUBLIC_KEY
* To decrypt data you need the private key
* Decrypts RSA encrypted data using the private key
LPARAMETERS m.tcData, m.tcPublicKey && tcPrivateKey
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the RSA algorithm
LOCAL m.lnAlg
m.lnKey = 0
IF m.llOK
m.llOK = BCryptImportKeyPair( m.lnAlg, 0, ;
STRCONV("RSAPUBLICBLOB",5)+CHR(0), @lnKey, ; && STRCONV("RSAPRIVATEBLOB",5)+CHR(0), @lnKey, ; */
m.tcPublicKey, LEN(m.tcPublicKey), 0 ) == 0
ENDIF
* Determine the size of the decrypted data block
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
m.llOK = BCryptDecrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, NULL, 0, @lnSize, ;
0x00000002 ) == 0 && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
ENDIF
* Decrypt the data block
LOCAL m.lcPlainText
IF m.llOK
m.lcPlainText = SPACE(m.lnSize)
m.llOK = BCryptDecrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, @lcPlainText, ;
LEN(m.lcPlainText), @lnSize, 0x00000002 ) == 0 && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
ENDIF

ENDFUNC


&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
FUNCTION VFP_ENCRYPT_BY_PUBLIC_KEY
* Encrypts data using the RSA algorithm
LPARAMETERS m.tcData, m.tcPublicKey
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the RSA algorithm
LOCAL m.lnAlg
m.lnAlg = 0
IF m.llOK
m.llOK = BCryptOpenAlgorithmProvider( @lnAlg, ;
STRCONV("RSA",5)+CHR(0), NULL, 0 ) == 0
ENDIF
* Import the public key
LOCAL m.lnKey
m.lnKey = 0
IF m.llOK
m.llOK = BCryptImportKeyPair( m.lnAlg, 0, ;
STRCONV("RSAPUBLICBLOB",5)+CHR(0), @lnKey, ;
m.tcPublicKey, LEN(m.tcPublicKey), 0 ) == 0
ENDIF
* Determine the size of the encrypted data blob
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
llOK = BCryptEncrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, NULL, 0, @lnSize, ;
0x00000002 ) == 0 && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
ENDIF
* Encrypt the data block
LOCAL m.lcEncrypted
IF m.llOK
m.lcEncrypted = SPACE(m.lnSize)
llOK = BCryptEncrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, @lcEncrypted, ;
LEN(m.lcEncrypted), @lnSize, 0x00000002 ) == 0
ENDIF
* Cleanup
IF m.lnAlg != 0
BCryptCloseAlgorithmProvider( m.lnAlg, 0 )
ENDIF
IF m.lnKey != 0
BCryptDestroyKey( m.lnKey )
ENDIF
IF NOT m.llOK
m.lcEncrypted = ""
ENDIF

RETURN m.lcEncrypted
ENDFUNC

FUNCTION VFP_DECRYPT_BY_PRIVATE_KEY
* To decrypt data you need the private key
* Decrypts RSA encrypted data using the private key
LPARAMETERS m.tcData, m.tcPrivateKey
* Initialize API
LOCAL m.llOK
m.llOK = .T.
DO CNG.prg
* Get a handle to the RSA algorithm
LOCAL m.lnAlg
m.lnKey = 0
IF m.llOK
m.llOK = BCryptImportKeyPair( m.lnAlg, 0, ;
STRCONV("RSAPRIVATEBLOB",5)+CHR(0), @lnKey, ;
m.tcPrivateKey, LEN(m.tcPrivateKey), 0 ) == 0
ENDIF
* Determine the size of the decrypted data block
LOCAL m.lnSize
IF m.llOK
m.lnSize = 0
m.llOK = BCryptDecrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, NULL, 0, @lnSize, ;
0x00000002 ) == 0 && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
ENDIF
* Decrypt the data block
LOCAL m.lcPlainText
IF m.llOK
m.lcPlainText = SPACE(m.lnSize)
m.llOK = BCryptDecrypt( m.lnKey, m.tcData, ;
LEN(m.tcData), NULL, NULL, 0, @lcPlainText, ;
LEN(m.lcPlainText), @lnSize, 0x00000002 ) == 0 && BCRYPT_PAD_PKCS1 ~ 0x00000002 (RSASSA-PKCS1-v1_5)
ENDIF

ENDFUNC

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
*!* FUNCTION VFP_SHA1(m.str) && works
*!* ** 0. && SHA1
*!* DECLARE A_SHAInit IN advapi32.dll String @
*!* DECLARE A_SHAUpdate IN advapi32.dll String @, String @, Integer
*!* DECLARE A_SHAFinal IN advapi32.dll String @, String @

*!* m.sha_ctx = REPLICATE(CHR(0),168)
*!* m.sha_dig = REPLICATE(CHR(0),20)

*!* && m.str = "Your string"
*!* A_SHAInit(@m.sha_ctx)
*!* A_SHAUpdate(@m.sha_ctx, @m.str, LEN(m.str))
*!* A_SHAFinal(@m.sha_ctx, @m.sha_dig)

*!* result = ""
*!* *!* FOR i = 1 TO 20
*!* *!* result = result + LOWER(RIGHT(TRANSFORM(ASC(SUBSTR(m.sha_dig, i, 1)), "@0"),2))
*!* *!* NEXT

*!* && The entirre final FOR .. NEXT loop could be replaced with
*!* *!* result=STRCONV(m.sha_dig,15)
*!* *!* or
*!* result=LOWER(STRCONV(m.sha_dig,15))
*!* *!* ?result
*!* *!* MESSAGEBOX(result)
*!* *!* MESSAGEBOX(LEN(result))
*!* RETURN result
*!* ENDFUNC

&& Поскольку подписываемые документы — переменного (и как правило достаточно большого) объёма,
&& в схемах ЭП зачастую подпись ставится не на сам документ, а на его хэш.
&& Для вычисления хэша используются криптографические хэш-функции,
&& что гарантирует выявление изменений документа при проверке подписи.
&& Хэш-функции не являются частью алгоритма ЭП,
&& поэтому в схеме может быть использована любая надёжная хэш-функция.


&&&& И наконец sign.prg где пытаемся подписать слово "Man":
SET PROCEDURE TO BCryptSign.prg, BCryptHash.prg ADDITIVE
m.lStr = "Man" && The result for SHA1 must be: 8B70BB3A4D458CF297AB7B3A3B07B63B5CA07DE9
*!* m.lStr = "The quick brown fox jumps over the lazy dog" && The result for SHA1 must be: 2FD4E1C67A2D28FCED849EE1BB76E7391B93EB12
m.lStrHashHexBinary = HASH(m.lStr, "SHA1")
? m.lStrHashHexBinary
STRTOFILE(m.lStrHashHexBinary, "ManHashHexBinary.txt")
&& _cliptext = m.lStrHashHexBinary
m.lStrHashANSI = STRCONV(m.lStrHashHexBinary, 16) && 16 converts from hexbinary to ANSI: ‹p»:MEЊт—«{:;¶;\ }й
? m.lStrHashANSI
STRTOFILE(m.lStrHashANSI, "ManHashAnsi.txt")
&& _cliptext = m.lStrHashANSI

CLEAR
m.lpr = ALLTRIM(FILETOSTR("GeneratedLPR.txt")) && PrivateKey in ANSI
SET STEP ON
*!* ?VFP_ENCRYPT_BY_PRIVATE_KEY("Man", m.lpr)
m.lcSignature = VFP_SIGN(m.lStrHashANSI, m.lpr) && m.lpr ~ PrivateKey in ANSI
&& m.lcSignature = VFP_SIGN(m.lStr, m.lpr)
? m.lcSignature


&&&& Вот сгенерированный закрытый ключ в формате ANSI, GeneratedLPR.txt:
RSA2 Ђ Ђ З\ж=•"GЕИхu7Сr)§­
»Єќъѓ¶д%ҐъЖи,p_dкП ·z nВпѕr§В֑䓘лИ‹‹т”®ЩЊ,(Њўы\У†=іЙќуыЇ@LфЮАQxыµ–С릕Чо№Cѕм
 ’¤зЈ µтФП ЊИ ҐҐ`iк¤°ТЌё}Rаpy9аa˜·цп^jv¬3Ха{ж–Уwўз\Џ•ќђ0SK^+§tMnЭ ¤‹ЎєЦкчрХЎ;P¦p¤T9ли·h«fRўРFя¶k*‡R ‹4eЎiј„Ќwsm$›9‚Д‡;Ы_’еy‡JЫЇЄ
©‡|п­e‡щm…wEУ‘>оM ОЕЪ$Їlзь-юD]±л¤н/э™[vШ[в;№/¶ЮОго/Xя2UыHыгъ|o`ЇљОg‚*J!лГэ+§еЪeДЦq®·¶XЦЬ7€Њя–®¶щ|еБ\°r‡€тq]"лы$»aSМќ¬"x«эX · VХDл?›§к2мQНдJВWA˜ЫeFДkГЈ­ЧgMp]щiБН@\Fа‘%l _“0°°Бўѓ™$ЇpЉyґЅUлкG°Ж9Ц:~щ;˜еU>CЎЉµ}«[сOOмцn}xVљ…&G‚FИЊЩ }


&&&& Вот сгенерированный закрытый ключ в формате ANSI, GeneratedLPR15.txt в 16ти ричном формате (HexBinary):
525341320008000003000000000100008000000080000000010001C75CE63D11952247C5C8F57537D17229A7AD050DBBAA9DFA83B6E425A5FAC603E82C705F64EACFA0B77A09056EC2EFBE72A7C2D691E4149398EBC8048B8BF294AED91D8C2C288CA2FBEE868B5CD311863DB3C99DF3FBAF404CF4DEC05178FBB596D1EBA695D7EEB943BEEC0AA092A4E7A309B5F2D4CF098CC8A0A514A56069EAA4B0D28DB87D52E0707939E0619811B7F6EF5E6A76AC33D5E01E7BE6960ED377A21DE75C8F959D129030534B5E062BA7744D6EDDA0A48BA1BAD6EAF7F0D5A13B0F50A61270A45439EBE8B768AB6652A2D046FFB60B6B0F2A8752008B3465A169BC13848D77736D249B3982C4873BDB5F92E579874ADBAFAA0DA9877CEFAD6587F96D857745D37F121017913EEE4D0B09CEC5DA24AF6CE70FFC2DFE445DB1EBA4ED2FFD995B7617D85BE23BB918032FB6DECEE3EE0F1C2F58FF17320855FB0848FBE3FA7C6F0360AF9A04CE026782072A4A21EBC3FD2BA7E5DA65C4D671AEB7B658D6DC3788038CFF96AEB6F97CE5C15CB0728788F21F71085D22EBFB24BB6153CC9DAC2278ABFD5809B7A056D544EB3F9BA7EA32EC51CDE44A1EC205574198DB6546C46BC3A3AD0F08D7674D705DF90B6918C1CD405C461AE091256CA0195F933017B0B0C1A2839924181915AF04701A8A79B4BD55EBEA470BB0C639D63A7EF93B98E5553E43A18AB57DAB5BF14F4FECF66E7D78569A8526478246C88CD9A07D
...
Рейтинг: 0 / 0
1 сообщений из 1, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Что не так в цифровой подписи использующей BCryptSignHash из BCrypt.dll (CNG)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]