Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1448

[VB6/VBA] Pure VB6 implementation of SHA-224, SHA-256, HMAC-SHA224 and HMAC-SHA256

$
0
0
Deliberately does not use any API calls so is not the sharpest tool in the shed

Code:

'--- mdSHA2.bas
Option Explicit
DefObj A-Z

Private PowerOf2(0 To 31)  As Long

Private Function LShift(ByVal lX As Long, ByVal lN As Long) As Long
    If lN = 0 Then
        LShift = lX
    Else
        LShift = (lX And (PowerOf2(31 - lN) - 1)) * PowerOf2(lN) Or -((lX And PowerOf2(31 - lN)) <> 0) * &H80000000
    End If
End Function

Private Function RShift(ByVal lX As Long, ByVal lN As Long) As Long
    If lN = 0 Then
        RShift = lX
    Else
        RShift = (lX And &H7FFFFFFF) \ PowerOf2(lN) Or -(lX < 0) * PowerOf2(31 - lN)
    End If
End Function

Private Function RRotate(ByVal lX As Long, ByVal lN As Long) As Long
    '--- RRotate = RShift(X, n) Or LShift(X, 32 - n)
    Debug.Assert lN <> 0
    RRotate = ((lX And &H7FFFFFFF) \ PowerOf2(lN) - (lX < 0) * PowerOf2(31 - lN)) Or _
        ((lX And (PowerOf2(lN - 1) - 1)) * PowerOf2(32 - lN) Or -((lX And PowerOf2(lN - 1)) <> 0) * &H80000000)
End Function

Private Function UAdd(ByVal lX As Long, ByVal lY As Long) As Long
    If (lX Xor lY) > 0 Then
        UAdd = ((lX Xor &H80000000) + lY) Xor &H80000000
    Else
        UAdd = lX + lY
    End If
End Function

Private Function Ch(ByVal lX As Long, ByVal lY As Long, ByVal lZ As Long) As Long
    Ch = (lX And lY) Xor ((Not lX) And lZ)
End Function

Private Function Maj(ByVal lX As Long, ByVal lY As Long, ByVal lZ As Long) As Long
    Maj = (lX And lY) Xor (lX And lZ) Xor (lY And lZ)
End Function

Private Function BigSigma0(ByVal lX As Long) As Long
    BigSigma0 = RRotate(lX, 2) Xor RRotate(lX, 13) Xor RRotate(lX, 22)
End Function

Private Function BigSigma1(ByVal lX As Long) As Long
    BigSigma1 = RRotate(lX, 6) Xor RRotate(lX, 11) Xor RRotate(lX, 25)
End Function

Private Function SmallSigma0(ByVal lX As Long) As Long
    SmallSigma0 = RRotate(lX, 7) Xor RRotate(lX, 18) Xor RShift(lX, 3)
End Function

Private Function SmallSigma1(ByVal lX As Long) As Long
    SmallSigma1 = RRotate(lX, 17) Xor RRotate(lX, 19) Xor RShift(lX, 10)
End Function

Private Sub ToBigEndian(aRetVal() As Long, baBuffer() As Byte, ByVal lPos As Long, ByVal lSize As Long)
    Dim lIdx            As Long
    Dim lOutSize        As Long
    Dim lOutIdx        As Long
    Dim lOffset        As Long
   
    If lSize < 0 Then
        lSize = UBound(baBuffer) + 1
    End If
    lOutSize = ((lSize + 8) \ 64 + 1) * 16
    ReDim aRetVal(0 To lOutSize - 1) As Long
    For lIdx = 0 To lSize - lPos - 1
        lOutIdx = lIdx \ 4
        lOffset = 24 - (lIdx Mod 4) * 8
        aRetVal(lOutIdx) = aRetVal(lOutIdx) Or LShift(baBuffer(lPos + lIdx), lOffset)
    Next
    lOutIdx = lIdx \ 4
    lOffset = 24 - (lIdx Mod 4) * 8
    aRetVal(lOutIdx) = aRetVal(lOutIdx) Or LShift(&H80, lOffset)
    aRetVal(lOutSize - 1) = LShift(lSize, 3)
    aRetVal(lOutSize - 2) = RShift(lSize, 29)
End Sub

Private Sub FromBigEndian(baRetVal() As Byte, aInput() As Long, ByVal lPos As Long, ByVal lSize As Long)
    Dim lIdx            As Long
    Dim lWord          As Long
   
    If lSize < 0 Then
        lSize = UBound(aInput) + 1
    End If
    ReDim baRetVal(0 To lSize * 4 - 1) As Byte
    For lIdx = 0 To lSize - lPos - 1
        lWord = aInput(lPos + lIdx)
        baRetVal(4 * lIdx + 0) = RShift(lWord, 24) And &HFF&
        baRetVal(4 * lIdx + 1) = (lWord And &HFF0000) \ &H10000 And &HFF&
        baRetVal(4 * lIdx + 2) = (lWord And &HFF00) \ &H100& And &HFF&
        baRetVal(4 * lIdx + 3) = lWord And &HFF&
    Next
End Sub

Private Sub SHA2(baOutput() As Byte, ByVal lOutPos As Long, ByVal lOutSize As Long, baInput() As Byte, ByVal lPos As Long, ByVal lSize As Long, H() As Long)
    Static K(0 To 63)  As Long
    Dim M()            As Long
    Dim W(0 To 63)      As Long
    Dim lA              As Long
    Dim lB              As Long
    Dim lC              As Long
    Dim lD              As Long
    Dim lE              As Long
    Dim lF              As Long
    Dim lG              As Long
    Dim lH              As Long
    Dim lT1            As Long
    Dim lT2            As Long
    Dim lIdx            As Long
    Dim lJdx            As Long
    Dim vElem          As Variant
   
    If PowerOf2(0) = 0 Then
        For lIdx = 0 To 30
            PowerOf2(lIdx) = 2& ^ lIdx
        Next
        PowerOf2(31) = &H80000000
        '--- K: first 32 bits of the fractional parts of the cube roots of the first 64 primes
        For Each vElem In Split("428A2F98 71374491 B5C0FBCF E9B5DBA5 3956C25B 59F111F1 923F82A4 AB1C5ED5 D807AA98 12835B01 243185BE 550C7DC3 72BE5D74 80DEB1FE 9BDC06A7 C19BF174 E49B69C1 EFBE4786 FC19DC6 240CA1CC 2DE92C6F 4A7484AA 5CB0A9DC 76F988DA 983E5152 A831C66D B00327C8 BF597FC7 C6E00BF3 D5A79147 6CA6351 14292967 27B70A85 2E1B2138 4D2C6DFC 53380D13 650A7354 766A0ABB 81C2C92E 92722C85 A2BFE8A1 A81A664B C24B8B70 C76C51A3 D192E819 D6990624 F40E3585 106AA070 19A4C116 1E376C08 2748774C 34B0BCB5 391C0CB3 4ED8AA4A 5B9CCA4F 682E6FF3 748F82EE 78A5636F 84C87814 8CC70208 90BEFFFA A4506CEB BEF9A3F7 C67178F2")
            K(lJdx) = "&H" & vElem
            lJdx = lJdx + 1
        Next
    End If
    ToBigEndian M, baInput, lPos, lSize
    For lIdx = 0 To UBound(M) Step 16
        lA = H(0)
        lB = H(1)
        lC = H(2)
        lD = H(3)
        lE = H(4)
        lF = H(5)
        lG = H(6)
        lH = H(7)
        For lJdx = 0 To 63
            If lJdx < 16 Then
                W(lJdx) = M(lJdx + lIdx)
            Else
                W(lJdx) = UAdd(UAdd(UAdd(SmallSigma1(W(lJdx - 2)), W(lJdx - 7)), SmallSigma0(W(lJdx - 15))), W(lJdx - 16))
            End If
            lT1 = UAdd(UAdd(UAdd(UAdd(lH, BigSigma1(lE)), Ch(lE, lF, lG)), K(lJdx)), W(lJdx))
            lT2 = UAdd(BigSigma0(lA), Maj(lA, lB, lC))
            lH = lG
            lG = lF
            lF = lE
            lE = UAdd(lD, lT1)
            lD = lC
            lC = lB
            lB = lA
            lA = UAdd(lT1, lT2)
        Next
        H(0) = UAdd(lA, H(0))
        H(1) = UAdd(lB, H(1))
        H(2) = UAdd(lC, H(2))
        H(3) = UAdd(lD, H(3))
        H(4) = UAdd(lE, H(4))
        H(5) = UAdd(lF, H(5))
        H(6) = UAdd(lG, H(6))
        H(7) = UAdd(lH, H(7))
    Next
    FromBigEndian baOutput, H, lOutPos, lOutSize
End Sub

Public Sub CryptoSHA224(baRetVal() As Byte, baBuffer() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1)
    Dim H(0 To 7)      As Long

    H(0) = &HC1059ED8
    H(1) = &H367CD507
    H(2) = &H3070DD17
    H(3) = &HF70E5939
    H(4) = &HFFC00B31
    H(5) = &H68581511
    H(6) = &H64F98FA7
    H(7) = &HBEFA4FA4
    SHA2 baRetVal, 0, 7, baBuffer, Pos, Size, H
End Sub

Public Sub CryptoSHA256(baRetVal() As Byte, baBuffer() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1)
    Dim H(0 To 7)      As Long

    H(0) = &H6A09E667
    H(1) = &HBB67AE85
    H(2) = &H3C6EF372
    H(3) = &HA54FF53A
    H(4) = &H510E527F
    H(5) = &H9B05688C
    H(6) = &H1F83D9AB
    H(7) = &H5BE0CD19
    SHA2 baRetVal, 0, 8, baBuffer, Pos, Size, H
End Sub

Private Sub HMAC(baRetVal() As Byte, ByVal lHashSize As Long, baKey() As Byte, baBuffer() As Byte, ByVal lPos As Long, ByVal lSize As Long)
    Const BLOCK_SIZE    As Long = 64
    Const INNER_PAD    As Long = &H36
    Const OUTER_PAD    As Long = &H5C
    Dim lIdx            As Long
    Dim baPass()        As Byte
    Dim baPad()        As Byte
    Dim baHash()        As Byte
   
    If UBound(baKey) < BLOCK_SIZE Then
        baPass = baKey
    ElseIf lHashSize = 256 Then
        CryptoSHA256 baPass, baKey
    Else
        CryptoSHA224 baPass, baKey
    End If
    If lSize < 0 Then
        lSize = UBound(baBuffer) + 1
    End If
    ReDim baPad(0 To lSize + BLOCK_SIZE - 1) As Byte
    For lIdx = 0 To UBound(baPass)
        baPad(lIdx) = baPass(lIdx) Xor INNER_PAD
    Next
    For lIdx = lIdx To BLOCK_SIZE - 1
        baPad(lIdx) = INNER_PAD
    Next
    For lIdx = 0 To lSize - lPos - 1
        baPad(BLOCK_SIZE + lIdx) = baBuffer(lPos + lIdx)
    Next
    If lHashSize = 256 Then
        CryptoSHA256 baHash, baPad
    Else
        CryptoSHA224 baHash, baPad
    End If
    lSize = UBound(baHash) + 1
    ReDim baPad(0 To lSize + BLOCK_SIZE - 1) As Byte
    For lIdx = 0 To UBound(baPass)
        baPad(lIdx) = baPass(lIdx) Xor OUTER_PAD
    Next
    For lIdx = lIdx To BLOCK_SIZE - 1
        baPad(lIdx) = OUTER_PAD
    Next
    For lIdx = 0 To lSize - 1
        baPad(BLOCK_SIZE + lIdx) = baHash(lIdx)
    Next
    If lHashSize = 256 Then
        CryptoSHA256 baRetVal, baPad
    Else
        CryptoSHA224 baRetVal, baPad
    End If
End Sub

Public Sub CryptoHMAC224(baRetVal() As Byte, baKey() As Byte, baBuffer() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1)
    HMAC baRetVal, 224, baKey, baBuffer, Pos, Size
End Sub

Public Sub CryptoHMAC256(baRetVal() As Byte, baKey() As Byte, baBuffer() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1)
    HMAC baRetVal, 256, baKey, baBuffer, Pos, Size
End Sub

CryptoHMAC224 and CryptoHMAC256 functions tested with hmac_sha224_test.json and hmac_sha256_test.json from Project Wycheproof test vectors.

cheers,
</wqw>

Viewing all articles
Browse latest Browse all 1448

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>