PowerBasic CNG加解密编程

#INCLUDE ONCE "BCrypt.inc"

MACRO ALG_ID = DWORD

'//-----------------------------------------------------------------------
'// 生成MD5密码 16位
'//-----------------------------------------------------------------------
FUNCTION MD5_ComputeHash(BYVAL pass AS STRING) AS STRING
    LOCAL i AS LONG
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptHash AS DWORD
    LOCAL lcHashValue AS DWORD
    LOCAL lnHashSize AS DWORD
    LOCAL lnStatus AS LONG
    LOCAL HashLen AS DWORD
    LOCAL p AS BYTE PTR
    LOCAL md5 AS STRING

    '// 获得指定CSP的密钥容器的句柄
    lnStatus = CryptAcquireContext(hCryptProv, BYVAL %NULL, BYVAL %NULL, %PROV_RSA_FULL, %CRYPT_VERIFYCONTEXT)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//创建一个HASH对象, 指定HASH算法
    lnStatus = CryptCreateHash(hCryptProv, %CALG_MD5, 0, 0, hCryptHash)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//将要计算 md5 值的数据提供给这个哈希对象中
    lnStatus = CryptHashData(hCryptHash, BYVAL STRPTR(pass), LEN(pass), 0)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//获取HASH结果的大小
    lnHashSize = LEN(pass)
    lnStatus = CryptGetHashParam(hCryptHash, %HP_HASHSIZE, HashLen, lnHashSize, 0)
    IF(lnStatus<>1 OR HashLen=0) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    p = VARPTR(HashLen)
    HashLen = @p

    'GLOBALMEM ALLOC HashLen TO lcHashValue '分配缓存空间
    DIM buf(HashLen-1) AS BYTE '分配缓存空间
    '//获取HASH结果
    lnStatus = CryptGetHashParam(hCryptHash, %HP_HASHVAL, BYVAL VARPTR(buf(0)), HashLen, 0)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    p = VARPTR(lcHashValue)
    FOR i=0 TO HashLen-1
        md5 = md5 + CHR$(buf(i))
    NEXT i
    ERASE buf()
    'GLOBALMEM FREE lcHashValue TO lcHashValue
    IF(hCryptHash>0) THEN CryptDestroyHash(hCryptHash)
    IF(hCryptProv>0) THEN CryptReleaseContext(hCryptProv, 0)
    FUNCTION = md5
END FUNCTION

'//-----------------------------------------------------------------------
'// 生成SHA1密码 32位 20位
'//-----------------------------------------------------------------------
FUNCTION SHA1_ComputeHash(BYVAL pass AS STRING) AS STRING
    LOCAL i AS LONG
    LOCAL VersionInformation AS OSVERSIONINFOW
    LOCAL CSP_NAME AS STRING
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptHash AS DWORD
    LOCAL lnHashSize AS DWORD
    LOCAL lnStatus AS LONG
    LOCAL HashLen AS DWORD
    LOCAL p AS BYTE PTR
    LOCAL sha1 AS STRING

    GetVersionEx(VersionInformation)
    CSP_NAME = $$MS_ENH_RSA_AES_PROV_XP_W
    IF VersionInformation.dwMajorVersion<>5 THEN
        CSP_NAME = $$MS_ENH_RSA_AES_PROV_W
    END IF

    '// 获得指定CSP的密钥容器的句柄
    lnStatus = CryptAcquireContext(hCryptProv, BYVAL %NULL, MS_ENH_RSA_AES_PROV, %PROV_RSA_AES, %CRYPT_VERIFYCONTEXT)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//创建一个HASH对象, 指定HASH算法
    lnStatus = CryptCreateHash(hCryptProv, %CALG_SHA1, BYVAL %NULL, BYVAL %NULL, hCryptHash)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//计算HASH数据
    lnStatus = CryptHashData(hCryptHash, BYVAL STRPTR(pass), LEN(pass), 0)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF

    '//获取HASH结果的大小
    lnHashSize = LEN(pass)
    lnStatus = CryptGetHashParam(hCryptHash, %HP_HASHSIZE, HashLen, lnHashSize, 0) '获取哈希值缓存大小
    IF(lnStatus<>1 OR HashLen=0) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    p = VARPTR(HashLen)
    HashLen = @p

    DIM buf(HashLen-1) AS BYTE '分配缓存空间
    '//获取HASH结果
    lnStatus = CryptGetHashParam(hCryptHash, %HP_HASHVAL, BYVAL VARPTR(buf(0)), HashLen, 0)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    FOR i=0 TO UBOUND(buf)
        sha1 = sha1 + CHR$(buf(i))
    NEXT i

    ERASE buf()
    IF(hCryptHash>0) THEN CryptDestroyHash(hCryptHash)
    IF(hCryptProv>0) THEN CryptReleaseContext(hCryptProv, 0)
    FUNCTION = sha1
END FUNCTION


'//-----------------------------------------------------------------------
'// 生成SHA256密码 32位
'//-----------------------------------------------------------------------
FUNCTION SHA256_ComputeHash(BYVAL pass AS STRING) AS STRING
    LOCAL i AS LONG
    LOCAL VersionInformation AS OSVERSIONINFOW
    LOCAL CSP_NAME AS STRING
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptHash AS DWORD
    LOCAL lnHashSize AS DWORD
    LOCAL lnStatus AS LONG
    LOCAL HashLen AS DWORD
    LOCAL p AS BYTE PTR
    LOCAL sha256 AS STRING

    GetVersionEx(VersionInformation)
    CSP_NAME = $$MS_ENH_RSA_AES_PROV_XP_W
    IF VersionInformation.dwMajorVersion<>5 THEN
        CSP_NAME = $$MS_ENH_RSA_AES_PROV_W
    END IF

    '// 获得指定CSP的密钥容器的句柄
    lnStatus = CryptAcquireContext(hCryptProv, BYVAL %NULL, MS_ENH_RSA_AES_PROV, %PROV_RSA_AES, %CRYPT_VERIFYCONTEXT)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//创建一个HASH对象, 指定HASH算法
    lnStatus = CryptCreateHash(hCryptProv, %CALG_SHA_256, BYVAL %NULL, BYVAL %NULL, hCryptHash)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//计算HASH数据
    lnStatus = CryptHashData(hCryptHash, BYVAL STRPTR(pass), LEN(pass), 0)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF

    '//获取HASH结果的大小
    lnHashSize = LEN(pass)
    lnStatus = CryptGetHashParam(hCryptHash, %HP_HASHSIZE, HashLen, lnHashSize, 0) '获取哈希值缓存大小
    IF(lnStatus<>1 OR HashLen=0) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    p = VARPTR(HashLen)
    HashLen = @p

    DIM buf(HashLen-1) AS BYTE '分配缓存空间
    '//获取HASH结果
    lnStatus = CryptGetHashParam(hCryptHash, %HP_HASHVAL, BYVAL VARPTR(buf(0)), HashLen, 0)
    IF(lnStatus<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    FOR i=0 TO UBOUND(buf)
        sha256 = sha256 + CHR$(buf(i))
    NEXT i

    ERASE buf()
    IF(hCryptHash>0) THEN CryptDestroyHash(hCryptHash)
    IF(hCryptProv>0) THEN CryptReleaseContext(hCryptProv, 0)
    FUNCTION = sha256
END FUNCTION

'//-----------------------------------------------------------------------
'// 生成AES密码 32位
'//-----------------------------------------------------------------------
FUNCTION AES_ComputeHash(BYVAL buf AS STRING, BYVAL pass AS STRING, BYVAL Algid AS ALG_ID) AS STRING
    LOCAL i AS LONG
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptHash AS DWORD
    LOCAL hCryptKey AS DWORD
    LOCAL bRet AS LONG
    LOCAL pData AS BYTE PTR
    LOCAL aes AS STRING
    LOCAL dwDataLength, dwBufferLength, dwKeyLength AS DWORD

    '// 获得指定CSP的密钥容器的句柄
    bRet = CryptAcquireContext(hCryptProv, BYVAL %NULL, BYVAL %NULL, %PROV_RSA_AES, %CRYPT_VERIFYCONTEXT)
    IF(bRet<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF

    '//创建一个HASH对象, 指定HASH算法
    bRet = CryptCreateHash(hCryptProv, %CALG_MD5, BYVAL %NULL, 0, hCryptHash)
    IF(bRet<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF
    '//计算HASH数据
    bRet = CryptHashData(hCryptHash, BYVAL STRPTR(pass), LEN(pass), 0)
    IF(bRet<>1) THEN
       FUNCTION = ""
       EXIT FUNCTION
    END IF

    '//生成加密hCryptKey
    SELECT CASE Algid
        CASE %CALG_AES_128
            bRet = CryptDeriveKey(hCryptProv, %CALG_AES_128, hCryptHash, %CRYPT_EXPORTABLE, hCryptKey)      '16 * 8
            IF bRet>0 THEN MSGBOX "128"

        CASE %CALG_AES_192
            bRet = CryptDeriveKey(hCryptProv, %CALG_AES_192, hCryptHash, %CRYPT_EXPORTABLE, hCryptKey)      '24 * 8
            IF bRet>0 THEN MSGBOX "192"

        CASE %CALG_AES_256
            bRet = CryptDeriveKey(hCryptProv, %CALG_AES_256, hCryptHash, %CRYPT_EXPORTABLE, hCryptKey)      '32 * 8
            IF bRet>0 THEN MSGBOX "256"

    END SELECT

    pData = STRPTR(buf)
    dwDataLength = LEN(buf)+1
    dwBufferLength = %MAX_PATH

    bRet = CryptEncrypt(hCryptKey, BYVAL %NULL, %TRUE, 0, pData, dwDataLength, dwBufferLength)
    'bRet = CryptDecrypt(hCryptKey, BYVAL %NULL, %TRUE, 0, pData, BYREF dwDataLength)
    FOR i=0 TO dwDataLength-1
        aes = aes + CHR$(@pData[i])
    NEXT i

    IF(hCryptKey>0) THEN CryptDestroyKey(hCryptKey)
    IF(hCryptHash>0) THEN CryptDestroyHash(hCryptHash)
    IF(hCryptProv>0) THEN CryptReleaseContext(hCryptProv, 0)
    FUNCTION = aes
END FUNCTION

'//-----------------------------------------------------------------------
'// 生成CNG_MD5密码 16位
'//-----------------------------------------------------------------------
FUNCTION CNG_MD5_ComputeHash(BYVAL PassWord AS STRING) AS STRING
    LOCAL i AS LONG
    LOCAL bRet AS LONG
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptHash AS DWORD
    LOCAL cbHashObject AS DWORD
    LOCAL cbHash AS DWORD
    LOCAL cbData AS DWORD
    LOCAL pbHashObject AS BYTE PTR
    LOCAL pbHash AS BYTE PTR
    LOCAL Md5Key AS STRING

    hCryptProv = %NULL
    hCryptHash = %NULL

    cbHash = 0
    cbHashObject = %NULL
    cbData = 0

    bRet = BCryptOpenAlgorithmProvider(hCryptProv, $$BCRYPT_MD5_ALGORITHM, BYVAL %NULL, 0)  '加载MD5算法
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    bRet = BCryptGetProperty(hCryptProv, $$BCRYPT_OBJECT_LENGTH, BYREF cbHashObject, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbHashObject = HeapAlloc(GetProcessHeap(), 0, cbHashObject)
    IF pbHashObject = %NULL THEN
        GOTO Cleanup
    END IF

    bRet = BCryptCreateHash(hCryptProv, hCryptHash, pbHashObject, cbHashObject, BYVAL %NULL, 0, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    bRet = BCryptGetProperty(hCryptProv, $$BCRYPT_HASH_LENGTH, BYREF cbHash, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbHash = HeapAlloc(GetProcessHeap(), 0, cbHash)
    IF pbHash = %NULL THEN
        GOTO Cleanup
    END IF

    LOCAL pbInput AS BYTE PTR
    pbInput = STRPTR(PassWord)
    bRet = BCryptHashData(hCryptHash, pbInput, LEN(PassWord), 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    '将加密的MD5密码存放至pbHash地址,cbHash缓存区为大小
    bRet = BCryptFinishHash(hCryptHash, pbHash, cbHash, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    FOR i=0 TO cbHash-1
        Md5Key = Md5Key + CHR$(@pbHash[i])
    NEXT i

    Cleanup:

    IF(pbHashObject) THEN HeapFree(GetProcessHeap(), 0, pbHashObject)
    IF(pbHash) THEN HeapFree(GetProcessHeap(), 0, pbHash)

    IF(hCryptHash)  THEN BCryptDestroyHash(hCryptHash)
    IF(hCryptProv) THEN BCryptCloseAlgorithmProvider(hCryptProv,0)

    FUNCTION = Md5Key
END FUNCTION

'//------------------------------------------------------------------------------------------
'// s = "FXCM-USDDemo02 - FXCM Australia Pty. Limited"
'// Md5Key = CNG_MD5_ComputeHash("g4hpfwm")
'// s1 = CNG_AES_ComputeEncrypt(s,  Md5Key, CryptKey, CNG_AES_128)
'// s2 = CNG_AES_ComputeDecrypt(s1, Md5Key, CryptKey, CNG_AES_128)
'//------------------------------------------------------------------------------------------
'// 明文加密
'// bu_data 数据源
'// Private_Key长度必须为16字节
'// Public_Key指定公匙长度: 16,24,32字节
'// Algid 为指定加密方式: CNG_AES_128位, CNG_AES_192位, CNG_AES_256位 除以8等于对应字节数
'//------------------------------------------------------------------------------------------
FUNCTION CNG_AES_ComputeEncrypt(BYVAL buf_data AS STRING, BYVAL Private_Key AS STRING, BYVAL Public_Key AS STRING, BYVAL Algid AS DWORD) AS STRING
    LOCAL i AS LONG
    LOCAL bRet AS LONG
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptKey AS DWORD        '密匙句柄
    LOCAL cbKeySize AS DWORD        '公匙长度
    LOCAL pbKeyObject AS BYTE PTR   '存放公匙地址指针
    LOCAL cbBlockSize AS DWORD      '区块大小
    LOCAL pbBlockObject AS BYTE PTR '区块指针
    LOCAL cbPlainText AS DWORD      '明文长度
    LOCAL pbPlainText AS BYTE PTR   '明文指针
    LOCAL cbCipherText AS DWORD     '密文长度
    LOCAL pbCipherText AS BYTE PTR  '密文指针
    LOCAL pbSecret AS BYTE PTR      '公钥算法地址
    LOCAL cbSecret AS DWORD         'AES算法类型大小 16,24,32
    LOCAL cbData AS DWORD
    LOCAL cbc_mode AS WSTRING
    LOCAL aes AS STRING
    LOCAL Md5Key AS STRING

    'Md5Key = CNG_MD5_ComputeHash(Private_Key) '用户密码生成的MD5  Private_Key
    'dim PrivateKey(len(Md5Key)-1)    as byte at strptr(Md5Key)
    'dim PublicKey(len(Public_Key)-1) as byte at strptr(Public_Key)

    hCryptProv = %NULL
    hCryptKey  = %NULL

    pbBlockObject = %NULL
    pbKeyObject   = %NULL
    pbPlainText   = %NULL
    pbCipherText  = %NULL
    pbCipherText  = %NUll

    cbBlockSize  = 0
    cbKeySize    = 0
    cbPlainText  = 0
    cbCipherText = 0

    cbData = 0

    IF LEN(Private_Key) <> 16 AND (Algid <> 128 OR Algid <> 192 OR Algid <> 256) THEN
       GOTO Cleanup
    END IF

    bRet = BCryptOpenAlgorithmProvider(hCryptProv, $$BCRYPT_AES_ALGORITHM, BYVAL %NULL, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    bRet = BCryptGetProperty(hCryptProv, $$BCRYPT_OBJECT_LENGTH, BYREF cbKeySize, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbKeyObject = HeapAlloc(GetProcessHeap(), 0, cbKeySize)
    IF pbKeyObject = %NULL THEN
        GOTO Cleanup
    END IF

    bRet = BCryptGetProperty(hCryptProv, $$BCRYPT_BLOCK_LENGTH, BYREF cbBlockSize, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbBlockObject = HeapAlloc(GetProcessHeap(), 0, cbBlockSize)
    IF pbBlockObject = %NULL THEN
        GOTO Cleanup
    END IF

    IF cbBlockSize <> LEN(Private_Key) THEN  '16 byte
        GOTO Cleanup
    END IF
    MEMORY COPY STRPTR(Private_Key), pbBlockObject, LEN(Private_Key)   '私匙

    cbc_mode = $$BCRYPT_CHAIN_MODE_CBC
    bRet = BCryptSetProperty(hCryptProv, $$BCRYPT_CHAINING_MODE , BYVAL STRPTR(cbc_mode), LEN(cbc_mode), 0) '%BCRYPT_PUBLIC_KEY_FLAG
    IF BCRYPT_SUCCESS(bRet) = %false THEN                                                                   '%BCRYPT_PRIVATE_KEY_FLAG
        GOTO Cleanup
    END IF

    cbSecret = Algid/8
    pbSecret = HeapAlloc(GetProcessHeap(), 0, cbSecret)
    IF pbSecret = %NULL THEN
        GOTO Cleanup
    END IF
    ZeroMemory(pbSecret, cbSecret)
    MEMORY COPY STRPTR(Public_Key), pbSecret, LEN(Public_Key)   '公匙复制到分配空间

    bRet = BCryptGenerateSymmetricKey(hCryptProv, hCryptKey, pbKeyObject, cbKeySize, pbSecret, cbSecret, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    '计算系统用于存放转换后公匙的结构大小
    bRet = BCryptExportKey(hCryptKey, BYVAL %NULL, $$BCRYPT_OPAQUE_KEY_BLOB, BYVAL %NULL, 0, BYREF cbBlockSize, 0)  'cbBlockSize = 560字节
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF
    '上面的pbBlockObject中存放加密是私匙
    pbBlockObject = HeapAlloc(GetProcessHeap(), 0, cbBlockSize)
    IF pbBlockObject = %NULL THEN
        GOTO Cleanup
    END IF

    '将加密后的密匙导出至Block块中,并返回指向Block的地址   560字节
    bRet = BCryptExportKey(hCryptKey, BYVAL %NULL, $$BCRYPT_OPAQUE_KEY_BLOB, pbBlockObject, cbBlockSize, BYREF cbBlockSize, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    '// 验证密匙长度,不符合规范则退出
    bRet = BCryptGetProperty(hCryptKey, $$BCRYPT_KEY_LENGTH, BYREF cbKeySize, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    IF cbKeySize <> Algid THEN
        GOTO Cleanup
    END IF

    cbPlainText = LEN(buf_data)
    pbPlainText = HeapAlloc(GetProcessHeap(), 0, cbPlainText)
    IF pbBlockObject = %NULL THEN
        GOTO Cleanup
    END IF
    MEMORY COPY STRPTR(buf_data), pbPlainText, cbPlainText   '明文数据

    '************************************************************************************************************
    'OPEN "mt4_data.cer" FOR BINARY AS #1
    '    FOR i=0 TO cbBlockSize-1
    '        PUT #1,, @pbBlockObject[i]
    '    NEXT i
    'CLOSE #1
    ' pbBlockObject = 这里存放着加密后的私匙 , 不释放这个空间的话,后面可以通过 BCryptImportKey 导出 hCryptKey
    ' cbBlockSize   = 560 byte
    '*************************************************************************************************************

    '计算出密文所需的缓存区大小
    bRet = BCryptEncrypt(hCryptKey, pbPlainText, cbPlainText, BYVAL %NULL, pbBlockObject, cbBlockSize, BYVAL %NULL, 0, BYREF cbCipherText, %BCRYPT_BLOCK_PADDING)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbCipherText = HeapAlloc(GetProcessHeap(), 0, cbCipherText)
    IF pbCipherText = %NULL THEN
        GOTO Cleanup
    END IF

    bRet = BCryptEncrypt(hCryptKey, pbPlainText, cbPlainText, BYVAL %NULL, pbBlockObject, cbBlockSize, pbCipherText, cbCipherText, BYREF cbData, %BCRYPT_BLOCK_PADDING)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    FOR i=0 TO cbData-1
        aes = aes + CHR$(@pbCipherText[i])
    NEXT i

    Cleanup:

    cbBlockSize  = 0
    cbKeySize    = 0
    cbPlainText  = 0
    cbCipherText = 0
    cbSecret     = 0

    IF(pbKeyObject)   THEN HeapFree(GetProcessHeap(), 0, pbKeyObject)
    IF(pbBlockObject) THEN HeapFree(GetProcessHeap(), 0, pbBlockObject)
    IF(pbPlainText)   THEN HeapFree(GetProcessHeap(), 0, pbPlainText)
    IF(pbCipherText)  THEN HeapFree(GetProcessHeap(), 0, pbCipherText)
    IF(pbSecret)      THEN HeapFree(GetProcessHeap(), 0, pbSecret)

    IF(hCryptKey)  THEN BCryptDestroyKey(hCryptKey)
    IF(hCryptProv) THEN BCryptCloseAlgorithmProvider(hCryptProv,0)

    FUNCTION = aes
END FUNCTION

'//------------------------------------------------------------------------------------------
'// 密文解密
'// bu_data 数据源
'// Private_Key长度必须为16字节
'// Public_Key指定公匙长度: 16,24,32字节
'// Algid 为指定加密方式: CNG_AES_128位, CNG_AES_192位, CNG_AES_256位 除以8等于对应字节数
'//------------------------------------------------------------------------------------------
FUNCTION CNG_AES_ComputeDecrypt(BYVAL buf_data AS STRING, BYVAL Private_Key AS STRING, BYVAL Public_Key AS STRING, BYVAL Algid AS DWORD) AS STRING
    LOCAL i AS LONG
    LOCAL bRet AS LONG
    LOCAL hCryptProv AS DWORD
    LOCAL hCryptKey AS DWORD        '密匙句柄
    LOCAL cbKeySize AS DWORD        '公匙长度
    LOCAL pbKeyObject AS BYTE PTR   '存放公匙地址指针
    LOCAL cbBlockSize AS DWORD      '区块大小
    LOCAL pbBlockObject AS BYTE PTR '区块指针
    LOCAL cbPlainText AS DWORD      '明文长度
    LOCAL pbPlainText AS BYTE PTR   '明文指针
    LOCAL cbCipherText AS DWORD     '密文长度
    LOCAL pbCipherText AS BYTE PTR  '密文指针
    LOCAL pbSecret AS BYTE PTR
    LOCAL cbSecret AS DWORD
    LOCAL cbData AS DWORD
    LOCAL aes AS STRING
    LOCAL Md5Key AS STRING
    LOCAL cbc_mode AS WSTRING

    'Md5Key = CNG_MD5_ComputeHash(PassWord) '用户密码生成的MD5  Private_Key
    'dim PrivateKey(len(Md5Key)-1)    as byte at strptr(Md5Key)
    'dim PublicKey(len(Public_Key)-1) as byte at strptr(Public_Key)

    hCryptProv = %NULL
    hCryptKey  = %NULL

    pbBlockObject = %NULL
    pbKeyObject   = %NULL
    pbPlainText   = %NULL
    pbCipherText  = %NULL
    pbCipherText  = %NUll

    cbBlockSize  = 0
    cbKeySize    = 0
    cbPlainText  = 0
    cbCipherText = 0

    cbData = 0

    IF LEN(Private_Key) <> 16 AND (Algid <> 128 OR Algid <> 192 OR Algid <> 256) THEN
       GOTO Cleanup
    END IF

    bRet = BCryptOpenAlgorithmProvider(hCryptProv, $$BCRYPT_AES_ALGORITHM, BYVAL %NULL, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    bRet = BCryptGetProperty(hCryptProv, $$BCRYPT_OBJECT_LENGTH, BYREF cbKeySize, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbKeyObject = HeapAlloc(GetProcessHeap(), 0, cbKeySize)
    IF pbKeyObject = %NULL THEN
        GOTO Cleanup
    END IF

    bRet = BCryptGetProperty(hCryptProv, $$BCRYPT_BLOCK_LENGTH, BYREF cbBlockSize, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbBlockObject = HeapAlloc(GetProcessHeap(), 0, cbBlockSize)
    IF pbBlockObject = %NULL THEN
        GOTO Cleanup
    END IF

    IF cbBlockSize <> LEN(Private_Key) THEN
        GOTO Cleanup
    END IF
    MEMORY COPY STRPTR(Private_Key), pbBlockObject, cbBlockSize   '私匙

    cbc_mode = $$BCRYPT_CHAIN_MODE_CBC
    bRet = BCryptSetProperty(hCryptProv, BYREF $$BCRYPT_CHAINING_MODE, BYVAL STRPTR(cbc_mode), LEN(cbc_mode), 0) '%BCRYPT_PUBLIC_KEY_FLAG
    IF BCRYPT_SUCCESS(bRet) = %false THEN                                                                        '%BCRYPT_PRIVATE_KEY_FLAG
        GOTO Cleanup
    END IF

    cbSecret = Algid/8
    pbSecret = HeapAlloc(GetProcessHeap(), 0, cbSecret)
    IF pbSecret = %NULL THEN
        GOTO Cleanup
    END IF
    ZeroMemory(pbSecret, cbSecret)
    MEMORY COPY STRPTR(Public_Key), pbSecret, LEN(Public_Key)   '公匙复制到分配空间

    bRet = BCryptGenerateSymmetricKey(hCryptProv, hCryptKey, pbKeyObject, cbKeySize, pbSecret, cbSecret, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    '计算系统用于存放转换后公匙的结构大小
    bRet = BCryptExportKey(hCryptKey, BYVAL %NULL, $$BCRYPT_OPAQUE_KEY_BLOB, BYVAL %NULL, 0, BYREF cbBlockSize, 0)  'cbBlockSize = 560字节
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbBlockObject = HeapAlloc(GetProcessHeap(), 0, cbBlockSize)
    IF pbBlockObject = %NULL THEN
        GOTO Cleanup
    END IF

    '将加密后的密匙导出至Block块中,并返回指向Block的地址   560字节
    '表示导出的是对称密钥,密钥用hPubKey指定的公钥加密
    bRet = BCryptExportKey(hCryptKey, BYVAL %NULL, $$BCRYPT_OPAQUE_KEY_BLOB, pbBlockObject, cbBlockSize, BYREF cbBlockSize, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    '// 验证密匙长度,不符合规范则退出
    bRet = BCryptGetProperty(hCryptKey, $$BCRYPT_KEY_LENGTH, BYREF cbKeySize, 4, BYREF cbData, 0)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    IF cbKeySize <> Algid THEN
        GOTO Cleanup
    END IF

    cbCipherText = LEN(buf_data)
    pbCipherText = HeapAlloc(GetProcessHeap(), 0, cbCipherText)
    IF pbBlockObject = %NULL THEN
        GOTO Cleanup
    END IF
    MEMORY COPY STRPTR(buf_data), pbCipherText, cbCipherText   '密文数据

    bRet = BCryptDecrypt(hCryptKey, pbCipherText, cbCipherText, BYVAL %NULL, pbBlockObject, cbBlockSize, BYVAL %NULL, 0, BYREF cbPlainText, %BCRYPT_BLOCK_PADDING)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    pbPlainText = HeapAlloc(GetProcessHeap(), 0, cbPlainText)
    IF pbPlainText = %NULL THEN
        GOTO Cleanup
    END IF
    MEMORY COPY STRPTR(buf_data), pbPlainText, cbCipherText   '密文数据

    bRet = BCryptDecrypt(hCryptKey, pbCipherText, cbCipherText, BYVAL %NULL, pbBlockObject, cbBlockSize, pbPlainText, cbPlainText, BYREF cbData, %BCRYPT_BLOCK_PADDING)
    IF BCRYPT_SUCCESS(bRet) = %false THEN
        GOTO Cleanup
    END IF

    FOR i=0 TO cbData-1
        aes = aes + CHR$(@pbPlainText[i])
    NEXT i

    Cleanup:

    cbBlockSize  = 0
    cbKeySize    = 0
    cbPlainText  = 0
    cbCipherText = 0
    cbSecret     = 0

    IF(pbKeyObject)   THEN HeapFree(GetProcessHeap(), 0, pbKeyObject)
    IF(pbBlockObject) THEN HeapFree(GetProcessHeap(), 0, pbBlockObject)
    IF(pbPlainText)   THEN HeapFree(GetProcessHeap(), 0, pbPlainText)
    IF(pbCipherText)  THEN HeapFree(GetProcessHeap(), 0, pbCipherText)
    IF(pbSecret)      THEN HeapFree(GetProcessHeap(), 0, pbSecret)

    IF(hCryptKey)  THEN BCryptDestroyKey(hCryptKey)
    IF(hCryptProv) THEN BCryptCloseAlgorithmProvider(hCryptProv,0)

    FUNCTION = aes
END FUNCTION

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值