*-------- DECLARACIONES API CNGDECLARE LONG BCryptOpenAlgorithmProvider IN BCrypt; LONG @phAlgorithm, ; STRING pszAlgId, ; STRING pszImplementation, ; LONG dwFlags
DECLARE LONG BCryptGenerateKeyPair IN BCrypt; LONG hAlgorithm, ; LONG @phKey, ; LONG dwLength, ; LONG dwFlags
DECLARE LONG BCryptFinalizeKeyPair IN BCrypt; LONG hKey, ; LONG dwFlags
DECLARE LONG BCryptCloseAlgorithmProvider IN BCrypt; LONG hAlgorithm, ; LONG dwFlags
DECLARE LONG BCryptExportKey IN BCrypt; LONG kKey, ; LONG hExportKey, ; STRING pszBlobType, ; STRING @pbOutput, ; LONG cbOutput, ; LONG @pcbResult, ; LONG dwFlags
DECLARE LONG BCryptImportKeyPair IN BCrypt; LONG hAlgorithm,; LONG hImportKey,; STRING pszBlobType,; LONG @phKey,; STRING pbInput,; LONG cbInput,; LONG dwFlags
DECLARE LONG BCryptSignHash IN BCrypt; LONG hKey,; LONG @pPaddingInfo,; STRING pbInput,; LONG cbInput,; STRING @pbOutput,; LONG cbOutput,; LONG @pcbResult,; LONG dwFlags
DECLARE LONG BCryptGetProperty IN BCrypt; LONG hObject,; STRING pszProperty,; LONG @pbOutput,; LONG cbOutput,; LONG @pcbResult,; LONG dwFlags
DECLARE LONG BCryptCreateHash IN BCrypt; LONG hAlgorithm,; LONG @phHash,; STRING @pbHashObject,; LONG cbHashObject,; STRING pbSecret,; LONG cbSecret,; LONG dwFlags
DECLARE LONG BCryptHashData IN BCrypt; LONG hHash,; STRING pbInput,; LONG cbInput,; LONG dwFlags
DECLARE LONG BCryptFinishHash IN BCrypt; LONG hHash,; STRING @pbOutput,; LONG cbOutput,; LONG dwFlags
DECLARE LONG BCryptDestroyHash IN BCrypt; LONG hHash
DECLARE LONG BCryptDestroyKey IN BCrypt; LONG hKey
DECLARE LONG GetProcessHeap IN Kernel32
DECLARE LONG HeapAlloc IN Kernel32; LONG hHeap,; LONG dwFlags,; LONG dwBytes
DECLARE LONG HeapFree IN Kernel32; LONG hHeap,; LONG dwFlags,; LONG lpMem
*------------------------ CONSTANTES #DEFINE PUBLICKEYBLOB 0x6#DEFINE PRIVATEKEYBLOB 0x7#DEFINE BCRYPT_RSA_ALGORITHM STRCONV("RSA" + CHR(0), 5)#DEFINE BCRYPT_PRIVATE_KEY_BLOB STRCONV("PRIVATEBLOB" + CHR(0), 5)#DEFINE LEGACY_RSAPRIVATE_BLOB STRCONV("CAPIPRIVATEBLOB" + CHR(0), 5)#DEFINE BCRYPT_SHA1_ALGORITHM STRCONV("SHA1" + CHR(0), 5)#DEFINE BCRYPT_PAD_PKCS1 0x00000002#DEFINE BCRYPT_PAD_PSS 0x00000008
*--------- MAIN*----- NOTA: Las cadenas de respuestas, el formato original es ASN1, para este ejemplo las presentaremos en Base64.*----- Creamos en par de claves genéricas, RSA de 2049 bits de longitudCLEARSET STEP ONlcTypeKey = "RSA"tnLengthKey = 2048lnKeyPair = GetCngGenerateKeyPair(lcTypeKey, tnLengthKey)*----- Exportamos el Par de Claves, primero la clave Privada y luego la clave publica.lcPrivate = "RSAPRIVATEBLOB"lcPublic = "RSAPUBLICBLOB"cPrivateKey = GetCngExportKeyBCrypt(lnKeyPair, lcPrivate)cPublicKey = GetCngExportKeyBCrypt(lnKeyPair, lcPublic)? "Private Key: " + STRCONV(cPrivateKey,13)? ? "Public Key: " + STRCONV(cPublicKey,13)?cCadenaParaHash = "Este es el texto que deseo crear hash y firmar, aquí va su texto"cAlgoritmoHash = "SHA1"cHashResp = GetDigestValue(cCadenaParaHash, cAlgoritmoHash)? "Hash: " + STRCONV(cHashResp,13)?cSignHash = GetSignHash(cHashResp, lnKeyPair)? "Signature: " + STRCONV(cSignHash,13)?
*--------- REGIÓN DE PROCEDURES*----- Función GetCngGenerateKeyPair, genera un par de claves genéricas RSA de longitud 2048 bitPROCEDURE GetCngGenerateKeyPair() PARAMETERS tcTypeKey AS String, tnLengthKey AS Integer lnKey = 0 lnAlg = 0 nResp = BCryptOpenAlgorithmProvider(@lnAlg, STRCONV(tcTypeKey,5)+CHR(0), NULL, 0) IF nResp==0 nResp = BCryptGenerateKeyPair(lnAlg, @lnKey, tnLengthKey, 0) IF nResp==0 BCryptFinalizeKeyPair(lnKey, 0) ENDIF ENDIF IF lnAlg<>0 BCryptCloseAlgorithmProvider(lnAlg, 0) ENDIF RETURN lnKeyENDPROC
*----- Función GetCngExportKeyBCrypt, exporta un par de claves genérica.PROCEDURE GetCngExportKeyBCrypt() PARAMETERS tnKey AS Long, tcKey AS String hKey = tnKey pszBlobType = STRCONV(tcKey,5)+CHR(0) pcbResult = 0 nResp = BCryptExportKey(hKey, 0, pszBlobType, NULL, 0, @pcbResult, 0) pbOutPut = SPACE(pcbResult) nResp = BCryptExportKey(hKey, 0, pszBlobType, @pbOutPut, LEN(pbOutPut), @pcbResult, 0) RETURN pbOutPutENDPROC
*----- Función GetDigestValue, crear un valor Hash a partir de una cadena de caracteres, usando un algoritmoPROCEDURE GetDigestValue() PARAMETERS tcData AS String, tcHashAlg AS String lnAlg = 0 nRespBCOAP = BCryptOpenAlgorithmProvider(@lnAlg, STRCONV(tcHashAlg,5)+CHR(0), NULL, 0) IF nRespBCOAP<>0 MESSAGEBOX("ERROR AL ABRIR ALGORITMO") RETURN "" ENDIF *----- Determinamos cuántos bytes necesitamos para almacenar el objeto hash lnSizeObj = 0 lnData = 0 nRespNCGP = BCryptGetProperty(lnAlg, STRCONV("ObjectLength",5)+CHR(0), @lnSizeObj, 4, @lnData, 0) IF nRespNCGP<>0 MESSAGEBOX("ERROR AL OBTENER PROPIEDAD DE ENCRIPTACION") RETURN "" ENDIF *----- Determinamos la longitud de valor hash lnSizeHash = 0 nRespNCGP = BCryptGetProperty(lnAlg, STRCONV("HashDigestLength",5)+CHR(0), @lnSizeHash, 4, @lnData, 0) IF nRespNCGP<>0 MESSAGEBOX("ERROR AL OBTENER PROPIEDAD DE ENCRIPTACION") RETURN "" ENDIF *----- Creamos un objeto Hash LOCAL lnHash, lcHashObj lnHash = 0 lcHashObj = SPACE(lnSizeObj) nRespBCCH = BCryptCreateHash(lnAlg, @lnHash, @lcHashObj, lnSizeObj, NULL, 0, 0) IF nRespBCCH<>0 MESSAGEBOX("ERROR AL CREAR OBJETO HASH") RETURN "" ENDIF *----- Para crear el valor hash agregamos datos al objeto hash. Puede repetir este paso según sea necesario nLenData = LEN(tcData) nRespBCHD = BCryptHashData(lnHash, tcData, nLenData, 0) IF nRespBCHD<>0 nRespBCHD = BCryptHashData(lnHash, tcData, nLenData, 0) IF nRespBCHD<>0 =GetMensajeError(nRespBCHD) RETURN "" ENDIF ENDIF *----- Indicamos al objeto hash que hemos terminado. El algoritmo ahora calcula el valor de hash y lo devuelve. lcHash = SPACE(lnSizeHash) =BCryptFinishHash(lnHash, @lcHash, lnSizeHash, 0) IF lnAlg<>0 BCryptCloseAlgorithmProvider(lnAlg, 0) ENDIF IF lnHash<>0 BCryptDestroyHash(lnHash) ENDIF RETURN lcHashENDPROC
*----- Firma una valor Hash usando un par de claves de tipo BCryptPROCEDURE GetSignHash() PARAMETERS tcDataSign AS String, tnParKey AS Integer lcSigned = "" lnAlg = 0 lnRes = BCryptOpenAlgorithmProvider(@lnAlg, BCRYPT_RSA_ALGORITHM, NULL, 0) lnKey = tnParKey lnAlgoString = HeapAlloc(GetProcessHeap(), 0, LEN(BCRYPT_SHA1_ALGORITHM)) IF lnAlgoString <> 0 SYS(2600, lnAlgoString, LEN(BCRYPT_SHA1_ALGORITHM), BCRYPT_SHA1_ALGORITHM) lnSize = 0 lnRes = BCryptSignHash(lnKey, @lnAlgoString, tcDataSign, LEN(tcDataSign), NULL, 0, @lnSize, 8) IF lnRes = 0 *---- Firmamos la cadena de datos lcSigned = SPACE(lnSize) lnRes = BCryptSignHash(lnKey, @lnAlgoString, tcDataSign, LEN(tcDataSign), @lcSigned, lnSize, @lnSize, 8) IF lnRes = 0 *---- EXITO! lcSigned = LEFT(lcSigned, lnSize) ELSE *---- Siga participando lcSigned = "" ENDIF ENDIF HeapFree(GetProcessHeap(), 0, lnAlgoString) BCryptDestroyKey(lnKey) ENDIF BCryptCloseAlgorithmProvider(lnAlg, 0) RETURN lcSignedENDPROC
*------------------------ KernelDECLARE INTEGER GetLastError IN Kernel32
DECLARE LONG FormatMessage IN Kernel32; LONG dwFlags,; STRING @lpSource,; LONG dwMessageId,; LONG dwLanguageId,; STRING @lpBuffer,; LONG nSize,; LONG Arguments
#DEFINE FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
PROCEDURE GetMensajeError(tcNumError) IF VARTYPE(tcNumError)=="N" lnErrorCode = tcNumError ELSE lnErrorCode = GetLastError() ENDIF lpBuffer = SPACE(128) =FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 'WINERROR.H', lnErrorCode, 0, @lpBuffer, 128 , 0) =MESSAGEBOX(lpBuffer, 16, "Error: " + TRANSFORM(lnErrorCode,"@0"))ENDPROC

*------------ REGION DE DECLARACIONES API*------------ CRYPTO API CSP (Cryptographic Service Providers)*------------ Crypt32.DLLDECLARE LONG CertCreateCertificateContext IN Crypt32; LONG dwCertEncodingType,; STRING pbCertEncoded,; LONG cbCertEncoded
DECLARE LONG CryptBinaryToString IN Crypt32; STRING pbBinary, ; LONG cbBinary, ; LONG dwFlags,; STRING @pszString, ; LONG @pcchString
DECLARE LONG CryptStringToBinaryA IN Crypt32; STRING @pszString, ; LONG cchString, ; LONG dwFlags,; STRING @pbBinary, ; LONG @pcbBinary,; LONG @pdwSkip, ; LONG @pdwFlags
DECLARE LONG CryptStringToBinaryW IN Crypt32; STRING @pszString, ; LONG cchString, ; LONG dwFlags,; STRING @pbBinary, ; LONG @pcbBinary,; LONG pdwSkip, ; LONG pdwFlags DECLARE LONG CryptEncodeObject IN Crypt32; LONG dwCertEncodingType,; STRING lpszStructType,; STRING pvStructInfo,; STRING @pbEncoded,; LONG @pcbEncoded
DECLARE LONG CryptEncodeObjectEx IN Crypt32; LONG dwCertEncodingType,; STRING lpszStructType,; STRING pvStructInfo,; LONG dwFlags,; STRING pEncodePara,; STRING @pvEncoded,; LONG @pcbEncoded
DECLARE LONG CryptDecodeObject IN Crypt32; LONG dwCertEncodingType,; STRING lpszStructType,; STRING pbEncoded,; LONG cbEncoded,; LONG dwFlags,; STRING @pvStructInfo,; LONG @pcbStructInfo
DECLARE LONG CryptDecodeObjectEx IN Crypt32; LONG dwCertEncodingType,; LONG lpszStructType,; STRING pbEncoded,; LONG cbEncoded,; LONG dwFlags,; STRING pDecodePara,; STRING @pvStructInfo,; LONG @pcbStructInfo
DECLARE LONG CryptAcquireCertificatePrivateKey IN Crypt32; LONG pCert,; LONG dwFlags,; LONG pvParameters,; LONG @phCryptProvOrNCryptKey,; LONG @pdwKeySpec,; LONG @pfCallerFreeProvOrNCryptKey
DECLARE LONG CertGetPublicKeyLength IN Crypt32; LONG dwCertEncodingType,; STRING @pPublicKey
*------- CRYPTO API CNG (Cryptography Next Generation)*------- BCrypt.DLLDECLARE LONG BCryptOpenAlgorithmProvider IN BCrypt; LONG @phAlgorithm, ; STRING pszAlgId, ; STRING pszImplementation, ; LONG dwFlags
DECLARE LONG BCryptImportKeyPair IN BCrypt; LONG hAlgorithm, ; LONG hImportKey, ; STRING pszBlobType, ; LONG @phKey, ; STRING pbInput, ; LONG cbInput, ; LONG dwFlags
DECLARE LONG BCryptCloseAlgorithmProvider IN BCrypt; LONG hAlgorithm, ; LONG dwFlags
DECLARE LONG BCryptDestroyKey IN BCrypt; LONG hKey
*------------ APIS de procesos del SO*------------ Kernel32.DLLDECLARE LONG GetLastError IN Kernel32
DECLARE LONG FormatMessage IN Kernel32; LONG dwFlags, ; STRING @lpSource, ; LONG dwMessageId, ; LONG dwLanguageId, ; STRING @lpBuffer, ; LONG nSize, ; LONG Arguments
DECLARE LONG GetProcessHeap IN Kernel32
DECLARE LONG HeapAlloc IN Kernel32; LONG hHeap,; LONG dwFlags,; LONG dwBytes
DECLARE LONG HeapFree IN Kernel32; LONG hHeap,; LONG dwFlags,; LONG lpMem
*------------ REGION DE CONSTANTES#DEFINE X509_ASN_ENCODING 1 #DEFINE PKCS_7_ASN_ENCODING 0x00010000#DEFINE FORMAT_MESSAGE_FROM_SYSTEM 0x00001000#DEFINE CRYPT_STRING_ANY 0x00000007#DEFINE CRYPT_STRING_BASE64HEADER 0x00000000#DEFINE CRYPT_STRING_BASE64 0x00000001#DEFINE CRYPT_STRING_BINARY 0x00000002
*------------ REGION MAIN*----- Firmar con archivo Key (pem, cer)*!* lcFileKey = GETFILE("KEY")*!* IF EMPTY(lcFileKey)*!* RETURN 0*!* ENDIF*!* cStringKey = ALLTRIM(FILETOSTR(lcFileKey))*!* IF EMPTY(cStringKey)*!* MESSAGEBOX("El archivo esta vacio", 16, _SCREEN.Caption)*!* RETURN 0*!* ENDIF*----- Firmar con cadena PrivateKeyTEXT TO cStringKey ADDITIVE NOSHOWMIICXAIBAAKBgQCf6YAJOSBYPve1jpYDzq+w++8YVoATI/YCi/RKZaQk+l2ZfoUQg0qrYrfkzeoOa/qd5VLjTTvHEgwXnlDXMfo+vSgxosUxDOZXMTBqJGOViv5K2QBvk8A1wi4k8tuo/7OWya29HvcfavUk3YXaV2YFe8V6ssaZjNcVWmDdjqNkXwIDAQABAoGALrd+ijNAOcebglT3ioE1XpUbUpbir7TPyAqvAZUUESF7er41jY9tnwgmBRgLCs+M1dgLERCdKBkjozrDDzswifFQmq6PrmYrBkFFqCoLJwepSYdWnK1gbZ/d43rR2sXzSGZngscx0CxO7KZ7xUkwENGd3+lKXV7J6/vgzJ4XnkECQQDTP6zWKT7YDckkWe04hbhHyBuNOW068NgUUvoZdBewerR74MJx6nz28Tp+DeNvc0EveiQxsEnbV8u+NRkX5y0xAkEAwcnEAGBn5kJd6SpU0ALA9XEpUv7tHTAGQYgCRbfTT59hhOq6I22AivjOCNG9c6E7EB2kcPVGuCpYUhy7XBIGjwJAK5lavKCqncDKoLwGn8HJdNcyCIWvq5iFoDw37gTt1ricg2yx9PzmabkDz3xiUmBBNeFJkw/FToXiQRGIakyGIQJAJIemPPPvYgZssYFbT4LVYO8d/Rk1FWVyKHQ9CWtnmADRXz7oK7l+m7PfEuaGsf9YpOcRkoGJ/TluQLxNzUNQnQJBAImwr/yYFenIx3HQ6UX/fCt6qpGDv0VfOLyR64MNeegxo7DhNxHbFkIGzk4lKhMKcHKDrawZbdJtS9ie2geSwVQ=ENDTEXT
SET STEP ONlpParKey = GetImportPrivateKeyToCng(cStringKey)IF lpParKey<>0 ? "Exito!, puntero para firmar: " + TRANSFORM(lpParKey) BCryptDestroyKey(lpParKey)ELSE ? "No se pudo importar el par de claves"ENDIF
*------------ REGION DE PROCEDURES*/// Recibe una cadena de claves publico/privada (KEY) de intercambio*/// Si tiene exito devuelve un puntero al par de claves importadas, listo para firmar o verificar un firmadoPROCEDURE GetImportPrivateKeyToCng(tcStringKey AS String) *----- Decodificamos la cadena pcbBinary=0 pdwSkip=0 pdwFlags=0 nResp = CryptStringToBinaryA(@tcStringKey , LEN(tcStringKey ), CRYPT_STRING_ANY, NULL, @pcbBinary, @pdwSkip, @pdwFlags) DO CASE CASE pdwFlags=0 lcPrivKey=STREXTRACT(tcStringKey , "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----") IF EMPTY(lcPrivKey) lcPrivKey=STREXTRACT(tcStringKey , "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----END ENCRYPTED PRIVATE KEY-----") ENDIF pbBinary=STRCONV(lcPrivKey,14) pcbBinary=LEN(pbBinary) CASE pdwFlags=1 nResp = CryptStringToBinaryA(@tcStringKey , LEN(tcStringKey ), CRYPT_STRING_BASE64, NULL, @pcbBinary, 0, 0) pbBinary = REPLICATE(CHR(0), pcbBinary) nResp = CryptStringToBinaryA(@tcStringKey , LEN(tcStringKey ), CRYPT_STRING_BASE64, @pbBinary, @pcbBinary, 0, 0) CASE pdwFlags=2 nResp = CryptStringToBinaryW(@tcStringKey , LEN(tcStringKey ), CRYPT_STRING_BINARY, NULL, @pcbBinary, 0, 0) pbBinary = REPLICATE(CHR(0), pcbBinary) nResp = CryptStringToBinaryW(@tcStringKey , LEN(tcStringKey ), CRYPT_STRING_BINARY, @pbBinary, @pcbBinary, 0, 0) ENDCASE *----- Decodificamos la cadena ASN1 dwCertEncodingType = BITOR(PKCS_7_ASN_ENCODING, X509_ASN_ENCODING) lpszStructType = 43 pbEncoded = pbBinary && lcPrivKey cbEncoded = pcbBinary && LEN(lcPrivKey) cbKeyBlob = 0 nResp=CryptDecodeObjectEx(dwCertEncodingType, @lpszStructType , pbEncoded, cbEncoded, 0, NULL, NULL, @cbKeyBlob) IF cbKeyBlob=0 GetMessageError() RETURN 0 ENDIF pbKeyBlob = SPACE(cbKeyBlob) nResp=CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded, 0, NULL, @pbKeyBlob, @cbKeyBlob) *----- Abrimos un proveedor de algoritmo pszAlgId = STRCONV("RSA" + CHR(0), 5) lnAlg = 0 lnRes = BCryptOpenAlgorithmProvider(@lnAlg, pszAlgId, NULL, 0) IF lnRes <> 0 MESSAGEBOX("No se pudo apertura el proveedor de algoritmo", 16, _SCREEN.Caption) RETURN 0 ENDIF *------ Importamos el par de claves para CNG, probamos con varios formatos (todos los conocidos hasta ahora) pszBlobType01V = STRCONV("PRIVATEBLOB" + CHR(0), 5) pszBlobType01B = STRCONV("PUBLICBLOB" + CHR(0), 5) pszBlobType02V = STRCONV("DHPRIVATEBLOB" + CHR(0), 5) pszBlobType02B = STRCONV("DHPUBLICBLOB" + CHR(0), 5) pszBlobType03V = STRCONV("DSAPRIVATEBLOB" + CHR(0), 5) pszBlobType03B = STRCONV("DSAPUBLICBLOB" + CHR(0), 5) pszBlobType04V = STRCONV("ECCPRIVATEBLOB" + CHR(0), 5) pszBlobType04B = STRCONV("ECCPUBLICBLOB" + CHR(0), 5) pszBlobType05V = STRCONV("RSAPRIVATEBLOB" + CHR(0), 5) pszBlobType05B = STRCONV("RSAPUBLICBLOB" + CHR(0), 5) pszBlobType06V = STRCONV("CAPIPRIVATEBLOB" + CHR(0), 5) pszBlobType06B = STRCONV("CAPIPUBLICBLOB" + CHR(0), 5) pszBlobType07V = STRCONV("CAPIDHPRIVATEBLOB" + CHR(0), 5) pszBlobType07B = STRCONV("CAPIDHPUBLICBLOB" + CHR(0), 5) pszBlobType08V = STRCONV("CAPIDSAPRIVATEBLOB" + CHR(0), 5) pszBlobType08B = STRCONV("CAPIDSAPUBLICBLOB" + CHR(0), 5) pszBlobType09V = STRCONV("V2CAPIDSAPRIVATEBLOB" + CHR(0), 5) pszBlobType09B = STRCONV("V2CAPIDSAPUBLICBLOB" + CHR(0), 5)
lnKey = 0 DO CASE CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType01V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType01V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType01B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType01B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType02V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType02V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType02B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType02B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType03V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType03V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType03B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType03B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType04V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType04B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType04B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType04B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType05V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType05V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType05B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType05B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType06V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType06V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType06B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType06B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType07V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType07V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType07B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType07B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType08V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType08V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType08B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType08B CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType09V, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType09V CASE BCryptImportKeyPair(lnAlg, 0, pszBlobType09B, @lnKey, pbKeyBlob, cbKeyBlob, 0)==0 ? pszBlobType09B OTHERWISE MESSAGEBOX("No se pudo importar el par de claves." +CHR(13)+ "revise que el archivo key tenga el formato correcto", 16, _SCREEN.Caption) ENDCASE BCryptCloseAlgorithmProvider(lnAlg, 0) RETURN lnKeyENDPROC
*----- Presenta el ultimo error del sistema.PROCEDURE GetMessageError(tnNumError AS Long) IF VARTYPE(tnNumError)=="N" lnErrorCode = tnNumError ELSE lnErrorCode = GetLastError() ENDIF lpBuffer = SPACE(128) =FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 'WINERROR.H', lnErrorCode, 0, @lpBuffer, 128 , 0) =MESSAGEBOX(lpBuffer, 16, "Error: " + TRANSFORM(lnErrorCode,"@0"))ENDPROC