|
Что не так в цифровой подписи использующей BCryptSignHash из BCrypt.dll (CNG)
|
|||
---|---|---|---|
#18+
Всем привет. Что не так в этой функции 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 ... |
|||
:
Нравится:
Не нравится:
|
|||
24.10.2016, 12:56 |
|
|
start [/forum/topic.php?fid=41&fpage=16&tid=1582042]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
35ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
42ms |
get tp. blocked users: |
2ms |
others: | 279ms |
total: | 406ms |
0 / 0 |