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

[VB6/VBA] Scrypt KDF implementation of RFC 7914

$
0
0
This mdScryptKdf.bas implements scrypt password-based key derivation function as described in RFC 7914.

This module depends on mdSha2.bas for its PBKDF2-HMAC-SHA2 implementation (calls CryptoPbkdf2HmacSha2ByteArray).

Code:

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

#Const HasPtrSafe = (VBA7 <> 0)
#Const HasOperators = (TWINBASIC <> 0)

#If HasPtrSafe Then
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
Private Enum LongPtr
    [_]
End Enum
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#End If

Private Type ArrayLong16
    Item(0 To 15)          As Long
End Type

#If Not HasOperators Then
Private LNG_POW2(0 To 31)          As Long

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

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

Private Sub Op32(X As ArrayLong16, ByVal lIdx As Long, ByVal lA As Long, ByVal lB As Long, ByVal lShift As Long)
    X.Item(lIdx) = X.Item(lIdx) Xor RotL32(UAdd32(X.Item(lA), X.Item(lB)), lShift)
End Sub
#End If

#If HasOperators Then
[ IntegerOverflowChecks (False) ]
#End If
Private Sub pvSalsa20Core(B() As Byte)
    Dim B32            As ArrayLong16
    Dim X              As ArrayLong16
    Dim lIdx            As Long
   
    Debug.Assert UBound(B) + 1 >= 64
    Call CopyMemory(B32, B(0), 64)
    X = B32
    For lIdx = 0 To 3
        #If HasOperators Then
            Dim lTemp As Long
            With X
                lTemp = .Item(0) + .Item(12): .Item(4) = .Item(4) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(4) + .Item(0): .Item(8) = .Item(8) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(8) + .Item(4): .Item(12) = .Item(12) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(12) + .Item(8): .Item(0) = .Item(0) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(5) + .Item(1): .Item(9) = .Item(9) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(9) + .Item(5): .Item(13) = .Item(13) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(13) + .Item(9): .Item(1) = .Item(1) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(1) + .Item(13): .Item(5) = .Item(5) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(10) + .Item(6): .Item(14) = .Item(14) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(14) + .Item(10): .Item(2) = .Item(2) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(2) + .Item(14): .Item(6) = .Item(6) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(6) + .Item(2): .Item(10) = .Item(10) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(15) + .Item(11): .Item(3) = .Item(3) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(3) + .Item(15): .Item(7) = .Item(7) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(7) + .Item(3): .Item(11) = .Item(11) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(11) + .Item(7): .Item(15) = .Item(15) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(0) + .Item(3): .Item(1) = .Item(1) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(1) + .Item(0): .Item(2) = .Item(2) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(2) + .Item(1): .Item(3) = .Item(3) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(3) + .Item(2): .Item(0) = .Item(0) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(5) + .Item(4): .Item(6) = .Item(6) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(6) + .Item(5): .Item(7) = .Item(7) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(7) + .Item(6): .Item(4) = .Item(4) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(4) + .Item(7): .Item(5) = .Item(5) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(10) + .Item(9): .Item(11) = .Item(11) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(11) + .Item(10): .Item(8) = .Item(8) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(8) + .Item(11): .Item(9) = .Item(9) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(9) + .Item(8): .Item(10) = .Item(10) Xor (lTemp << 18 Or lTemp >> 14)
                lTemp = .Item(15) + .Item(14): .Item(12) = .Item(12) Xor (lTemp << 7 Or lTemp >> 25)
                lTemp = .Item(12) + .Item(15): .Item(13) = .Item(13) Xor (lTemp << 9 Or lTemp >> 23)
                lTemp = .Item(13) + .Item(12): .Item(14) = .Item(14) Xor (lTemp << 13 Or lTemp >> 19)
                lTemp = .Item(14) + .Item(13): .Item(15) = .Item(15) Xor (lTemp << 18 Or lTemp >> 14)
            End With
        #Else
            '--- Operate on columns
            Op32 X, 4, 0, 12, 7: Op32 X, 8, 4, 0, 9
            Op32 X, 12, 8, 4, 13: Op32 X, 0, 12, 8, 18
            Op32 X, 9, 5, 1, 7: Op32 X, 13, 9, 5, 9
            Op32 X, 1, 13, 9, 13: Op32 X, 5, 1, 13, 18
            Op32 X, 14, 10, 6, 7: Op32 X, 2, 14, 10, 9
            Op32 X, 6, 2, 14, 13: Op32 X, 10, 6, 2, 18
            Op32 X, 3, 15, 11, 7: Op32 X, 7, 3, 15, 9
            Op32 X, 11, 7, 3, 13: Op32 X, 15, 11, 7, 18
            '--- Operate on rows
            Op32 X, 1, 0, 3, 7: Op32 X, 2, 1, 0, 9
            Op32 X, 3, 2, 1, 13: Op32 X, 0, 3, 2, 18
            Op32 X, 6, 5, 4, 7: Op32 X, 7, 6, 5, 9
            Op32 X, 4, 7, 6, 13: Op32 X, 5, 4, 7, 18
            Op32 X, 11, 10, 9, 7: Op32 X, 8, 11, 10, 9
            Op32 X, 9, 8, 11, 13: Op32 X, 10, 9, 8, 18
            Op32 X, 12, 15, 14, 7: Op32 X, 13, 12, 15, 9
            Op32 X, 14, 13, 12, 13: Op32 X, 15, 14, 13, 18
        #End If
    Next
    For lIdx = 0 To 15
        #If HasOperators Then
            B32.Item(lIdx) += X.Item(lIdx)
        #Else
            B32.Item(lIdx) = UAdd32(B32.Item(lIdx), X.Item(lIdx))
        #End If
    Next
    Call CopyMemory(B(0), B32, 64)
End Sub

Private Sub pvBlockMix(B() As Byte, Y() As Byte, ByVal lR As Long)
    Dim X(0 To 63)      As Byte
    Dim lIdx            As Long
    Dim lJdx            As Long
   
    Debug.Assert UBound(B) + 1 >= 2 * lR * 64
    Debug.Assert UBound(Y) + 1 >= 2 * lR * 64
    Call CopyMemory(X(0), B((2 * lR - 1) * 64), 64)
    For lIdx = 0 To 2 * lR - 1
        For lJdx = 0 To 63
            X(lJdx) = X(lJdx) Xor B(lIdx * 64 + lJdx)
        Next
        pvSalsa20Core X
        Call CopyMemory(Y(lIdx * 64), X(0), 64)
    Next
    For lIdx = 0 To lR - 1
        Call CopyMemory(B((0 + lIdx) * 64), Y((2 * lIdx + 0) * 64), 64)
    Next
    For lIdx = 0 To lR - 1
        Call CopyMemory(B((lR + lIdx) * 64), Y((2 * lIdx + 1) * 64), 64)
    Next
End Sub

Private Function pvIntegerify(X() As Byte, ByVal lR As Long) As Long
    Debug.Assert UBound(X) + 1 >= 2 * lR * 64
    Call CopyMemory(pvIntegerify, X((2 * lR - 1) * 64), 4)
    pvIntegerify = pvIntegerify And &H7FFFFFFF
End Function

Private Sub pvSMix(ByVal lPtr As LongPtr, ByVal lR As Long, ByVal lN As Long, V() As Byte)
    Dim X()            As Byte
    Dim Y()            As Byte
    Dim lIdx            As Long
    Dim lJdx            As Long
    Dim lK              As Long
    Dim lBlockSize      As Long
   
    lBlockSize = 128 * lR
    Debug.Assert UBound(V) + 1 >= lN * lBlockSize
    ReDim X(0 To lBlockSize - 1) As Byte
    ReDim Y(0 To lBlockSize - 1) As Byte
    Call CopyMemory(X(0), ByVal lPtr, lBlockSize)
    For lIdx = 0 To lN - 1
        Call CopyMemory(V(lIdx * lBlockSize), X(0), lBlockSize)
        pvBlockMix X, Y, lR
    Next
    For lIdx = 0 To lN - 1
        lK = pvIntegerify(X, lR) And (lN - 1)
        For lJdx = 0 To lBlockSize - 1
            X(lJdx) = X(lJdx) Xor V(lK * lBlockSize + lJdx)
        Next
        pvBlockMix X, Y, lR
    Next
    Call CopyMemory(ByVal lPtr, X(0), lBlockSize)
End Sub

Public Function CryptoScryptKdfByteArray(baPass() As Byte, baSalt() As Byte, _
            Optional ByVal OutSize As Long, _
            Optional ByVal CpuCost As Long = 16384, _
            Optional ByVal MemoryCost As Long = 8, _
            Optional ByVal Parallel As Long = 1) As Byte()
    Dim lN              As Long: lN = CpuCost
    Dim lR              As Long: lR = MemoryCost
    Dim lP              As Long: lP = Parallel
    Dim B()            As Byte
    Dim V()            As Byte
    Dim lIdx            As Long
   
    Debug.Assert (lN And (lN - 1)) = 0          '-- must be power of 2
    Debug.Assert CDbl(lP) * lR <= 2 ^ 30
    #If Not HasOperators Then
        If LNG_POW2(0) = 0 Then
            LNG_POW2(0) = 1
            For lIdx = 1 To 30
                LNG_POW2(lIdx) = LNG_POW2(lIdx - 1) * 2
            Next
            LNG_POW2(31) = &H80000000
        End If
    #End If
    ReDim V(0 To lN * 128 * lR - 1) As Byte
    B = CryptoPbkdf2HmacSha2ByteArray(256, baPass, baSalt, 1, lP * 128 * lR)
    For lIdx = 0 To lP - 1
        pvSMix VarPtr(B(lIdx * 128 * lR)), lR, lN, V
    Next
    CryptoScryptKdfByteArray = CryptoPbkdf2HmacSha2ByteArray(256, baPass, B, 1, OutSize)
End Function

The only public CryptoScryptKdfByteArray function uses moderately sized optional parameters for CPU and memory cost so these should be increased to be relevant to modern hardware.

cheers,
</wqw>

Viewing all articles
Browse latest Browse all 1529

Trending Articles



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