Quote Originally Posted by wqweto View Post
Sorry for the late reply but found this in an unclosed IDE and will post this for posterity.

Code:
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function BCryptOpenAlgorithmProvider Lib "bcrypt" (ByRef hAlgorithm As Long, ByVal pszAlgId As Long, ByVal pszImplementation As Long, ByVal dwFlags As Long) As Long
Private Declare Function BCryptCloseAlgorithmProvider Lib "bcrypt" (ByVal hAlgorithm As Long, ByVal dwFlags As Long) As Long
Private Declare Function BCryptDestroyKey Lib "bcrypt" (ByVal hKey As Long) As Long
Private Declare Function BCryptSetProperty Lib "bcrypt" (ByVal hObject As Long, ByVal pszProperty As Long, ByVal pbInput As Long, ByVal cbInput As Long, ByVal dwFlags As Long) As Long
Private Declare Function BCryptGenerateSymmetricKey Lib "bcrypt" (ByVal hAlgorithm As Long, hKey As Long, ByVal pbKeyObject As Long, ByVal cbKeyObject As Long, ByVal pbSecret As Long, ByVal cbSecret As Long, ByVal dwFlags As Long) As Long
Private Declare Function BCryptDecrypt Lib "bcrypt" (ByVal hKey As Long, ByVal pbInput As Long, ByVal cbInput As Long, ByVal pPaddingInfo As Long, ByVal pbIV As Long, ByVal cbIV As Long, ByVal pbOutput As Long, ByVal cbOutput As Long, cbResult As Long, ByVal dwFlags As Long) As Long

Private Type BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
    cbSize              As Long
    dwInfoVersion       As Long
    pbNonce             As Long
    cbNonce             As Long
    pbAuthData          As Long
    cbAuthData          As Long
    pbTag               As Long
    cbTag               As Long
    pbMacContext        As Long
    cbMacContext        As Long
    cbAAD               As Long
    lPad                As Long
    cbData(7)           As Byte
    dwFlags             As Long
    lPad2               As Long
End Type

Private Function pvCryptoAeadAesGcmDecrypt( _
            baKey() As Byte, baIV() As Byte, _
            baBuffer() As Byte, ByVal lPos As Long, ByVal lSize As Long, _
            baTag() As Byte, ByVal lTagPos As Long, ByVal lTagSize As Long, _
            baAad() As Byte, ByVal lAadPos As Long, ByVal lAdSize As Long) As Boolean
    Dim hResult         As Long
    Dim sApiSource      As String
    Dim hAlg            As Long
    Dim hKey            As Long
    Dim uInfo           As BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
    Dim lResult         As Long

    hResult = BCryptOpenAlgorithmProvider(hAlg, StrPtr("AES"), 0, 0)
    If hResult < 0 Then
        sApiSource = "BCryptOpenAlgorithmProvider"
        GoTo QH
    End If
    hResult = BCryptSetProperty(hAlg, StrPtr("ChainingMode"), StrPtr("ChainingModeGCM"), 32, 0)
    If hResult < 0 Then
        GoTo QH
    End If
    hResult = BCryptGenerateSymmetricKey(hAlg, hKey, 0, 0, VarPtr(baKey(0)), UBound(baKey) + 1, 0)
    If hResult < 0 Then
        GoTo QH
    End If
    With uInfo
        .cbSize = LenB(uInfo)
        .dwInfoVersion = 1
        .pbNonce = VarPtr(baIV(0))
        .cbNonce = UBound(baIV) + 1
        If lAdSize > 0 Then
            .pbAuthData = VarPtr(baAad(lAadPos))
            .cbAuthData = lAdSize
        End If
        .pbTag = VarPtr(baTag(lTagPos))
        .cbTag = lTagSize
    End With
    hResult = BCryptDecrypt(hKey, VarPtr(baBuffer(lPos)), lSize, VarPtr(uInfo), 0, 0, VarPtr(baBuffer(lPos)), lSize, lResult, 0)
    If hResult < 0 Then
        GoTo QH
    End If
    Debug.Assert lResult = lSize
    '--- success
    pvCryptoAeadAesGcmDecrypt = True
QH:
    If hKey <> 0 Then
        Call BCryptDestroyKey(hKey)
    End If
    If hAlg <> 0 Then
        Call BCryptCloseAlgorithmProvider(hAlg, 0)
    End If
    If hResult < 0 Then
        Err.Raise hResult
    End If
End Function

Private Function DecodePassword(baBuffer() As Byte, baMasterKey() As Byte) As String
    Dim baIV()          As Byte
    Dim baCipherText()  As Byte
    Dim baEmpty()       As Byte
    
    ReDim baIV(0 To 11) As Byte
    Call CopyMemory(baIV(0), baBuffer(3), UBound(baIV) + 1)
    ReDim baCipherText(0 To UBound(baBuffer) - 15 - 16) As Byte
    Call CopyMemory(baCipherText(0), baBuffer(15), UBound(baCipherText) + 1)
    If Not pvCryptoAeadAesGcmDecrypt(baMasterKey, baIV, baCipherText, 0, UBound(baCipherText) + 1, baBuffer, UBound(baBuffer) - 15, 16, baEmpty, 0, 0) Then
        GoTo QH
    End If
    DecodePassword = StrConv(baCipherText, vbUnicode)
QH:
End Function

Private Sub Form_Load()
    Const PassCrypt = "76313076F0C9F33DA5EEB1F7979B63589D0D01793F3B6289EBE350A4E990A0C6D9160C77A0CA13C4040B60"
    Const MasterKey = "4405A103B2E0B0C6DC3E4EBB3DFAC7F6F3B47993286F3B009B119CEF6BD7985E"
    Const PassDecrypt = "GxFcyBxI2oty"
    Dim bArrPassCrypt() As Byte
    Dim bArrKey() As Byte
    
    Call HexToByte(PassCrypt, bArrPassCrypt)
    Call HexToByte(MasterKey, bArrKey)
    
    Debug.Assert DecodePassword(bArrPassCrypt, bArrKey) = PassDecrypt
End Sub

Public Function HexToByte(HexStr As String, bHex() As Byte) As Boolean
    Dim lLen As Long
    Dim lPntr As Long
    Dim bTmp() As Byte
    If Len(HexStr) > 1 Then
        lLen = Len(HexStr) / 2
        ReDim bHex(lLen - 1)
        For lPntr = 0 To UBound(bHex)
            bHex(lPntr) = Val("&H" & Mid$(HexStr, lPntr * 2 + 1, 2))
        Next lPntr
        HexToByte = True
    Else
        bHex = bTmp
    End If
End Function
The pvCryptoAeadAesGcmDecrypt helper function above is all you need to use BCrypt (so called CNG system API) to implement AES in GCM mode which is a kind of AEAD cipher i.e. it needs a key, a nonce (so called IV) and can include an additional associated data which is not encrypted but becomes part of the message authentication hash (so called MAC) besides the plaintext.

The helper above decrypts in-place i.e. the ciphertext in baBuffer is decrypted to plaintext again in baBuffer but lAdSize can be zero to skip on additional associated data (as in your case).

cheers,
</wqw>
Perfect!!, I had already summarized enough but, you have simplified it much more!!,i just make some changes to personal necessity since my source is a DATA_BLOB so not to dump a byte array pass and use pointers.

Code:
Private Function pvCryptoAeadAesGcmDecrypt(baKey() As Byte, pCryptData As Long, lSize As Long, pIV As Long, pTag As Long, baDecriptText() As Byte) As Boolean
    Dim hAlg            As Long
    Dim hKey            As Long
    Dim uInfo           As BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
    Dim lResult         As Long
    
    ReDim baDecriptText(lSize - 1)
    With uInfo
        .cbSize = Len(uInfo)
        .dwInfoVersion = 1
        .pbNonce = pIV
        .cbNonce = 12
        .pbTag = pTag
        .cbTag = 16
    End With

    If BCryptOpenAlgorithmProvider(hAlg, StrPtr("AES"), 0, 0) = 0& Then
        If BCryptSetProperty(hAlg, StrPtr("ChainingMode"), StrPtr("ChainingModeGCM"), 32, 0) = 0& Then
            If BCryptGenerateSymmetricKey(hAlg, hKey, 0, 0, VarPtr(baKey(0)), UBound(baKey) + 1, 0) = 0& Then
                If BCryptDecrypt(hKey, pCryptData, lSize, VarPtr(uInfo), 0, 0, VarPtr(baDecriptText(0)), lSize, lResult, 0) = 0& Then
                    pvCryptoAeadAesGcmDecrypt = CBool(lResult = lSize)
                End If
                Call BCryptDestroyKey(hKey)
            End If
        End If
        Call BCryptCloseAlgorithmProvider(hAlg, 0)
    End If
End Function
Code:
With BLOBIN
    If .cbData > 0 Then
        ReDim bHeader(2)
        CopyMemory bHeader(0), ByVal .pbData, 3
        
        If (bHeader(0) Or bHeader(1) Or bHeader(2)) = &H77 Then
            If .cbData > 31 Then
                If pvCryptoAeadAesGcmDecrypt(bKey, .pbData + 15, .cbData - 31, .pbData + 3, .pbData + .cbData - 16, bPass) Then
                    PASSWORD = StrConv(bPass, vbUnicode)
                End If
            End If
        Else
            If CryptUnprotectData(BLOBIN, 0&, 0&, 0&, 0&, 8, BLOBOUT) Then
                PASSWORD = ReadBlobString(BLOBOUT)
            End If
        End If
    End If
End With
whatever observations you have, it's always good to listen to learn