Skip to content

Instantly share code, notes, and snippets.

@wqweto
Last active December 18, 2022 18:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wqweto/b2ea66bc4831ddc5da414a86f26d2a86 to your computer and use it in GitHub Desktop.
Save wqweto/b2ea66bc4831ddc5da414a86f26d2a86 to your computer and use it in GitHub Desktop.
[VBA/VB6] SipHash cryptographically secure keyed hash function
'--- mdHalfSiphash.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)
Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As LongPtr, ByVal cchWideChar As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
Private Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcW" (ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal Msg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) 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 Long)
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcW" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
Private Const LNG_BLOCKSZ As Long = 4
Private Const LNG_KEYSZ As Long = 8
Private Const LNG_POW2_4 As Long = 2 ^ 4
Private Const LNG_POW2_5 As Long = 2 ^ 5
Private Const LNG_POW2_6 As Long = 2 ^ 6
Private Const LNG_POW2_7 As Long = 2 ^ 7
Private Const LNG_POW2_8 As Long = 2 ^ 8
Private Const LNG_POW2_12 As Long = 2 ^ 12
Private Const LNG_POW2_13 As Long = 2 ^ 13
Private Const LNG_POW2_15 As Long = 2 ^ 15
Private Const LNG_POW2_16 As Long = 2 ^ 16
Private Const LNG_POW2_18 As Long = 2 ^ 18
Private Const LNG_POW2_19 As Long = 2 ^ 19
Private Const LNG_POW2_23 As Long = 2 ^ 23
Private Const LNG_POW2_24 As Long = 2 ^ 24
Private Const LNG_POW2_25 As Long = 2 ^ 25
Private Const LNG_POW2_26 As Long = 2 ^ 26
Private Const LNG_POW2_27 As Long = 2 ^ 27
Private Const LNG_POW2_31 As Long = &H80000000
Private Type ArrayLong128
Item(0 To 127) As Long
End Type
Public Type CryptoHalfSiphashContext
V0 As Long
V1 As Long
V2 As Long
V3 As Long
Partial(0 To LNG_BLOCKSZ - 1) As Byte
NPartial As Long
NInput As Currency
UpdateIters As Long
FinalizeIters As Long
OutSize As Long
End Type
#If Not HasOperators Then
Private Sub pvCompress(uCtx As CryptoHalfSiphashContext, ByVal lRounds As Long)
With uCtx
Do While lRounds > 0
' .V0 = UAdd32(.V0, .V1)
' .V1 = RotL32(.V1, 5) Xor .V0
' .V2 = UAdd32(.V2, .V3)
' .V3 = RotL32(.V3, 8) Xor .V2
' .V0 = RotL32(.V0, 16)
If (.V0 Xor .V1) >= 0 Then
.V0 = ((.V0 Xor &H80000000) + .V1) Xor &H80000000
Else
.V0 = .V0 + .V1
End If
.V1 = ((.V1 And (LNG_POW2_26 - 1)) * LNG_POW2_5 Or -((.V1 And LNG_POW2_26) <> 0) * LNG_POW2_31) Or _
((.V1 And (LNG_POW2_31 Xor -1)) \ LNG_POW2_27 Or -(.V1 < 0) * LNG_POW2_4) Xor .V0
If (.V2 Xor .V3) >= 0 Then
.V2 = ((.V2 Xor &H80000000) + .V3) Xor &H80000000
Else
.V2 = .V2 + .V3
End If
.V3 = ((.V3 And (LNG_POW2_23 - 1)) * LNG_POW2_8 Or -((.V3 And LNG_POW2_23) <> 0) * LNG_POW2_31) Or _
((.V3 And (LNG_POW2_31 Xor -1)) \ LNG_POW2_24 Or -(.V3 < 0) * LNG_POW2_7) Xor .V2
.V0 = ((.V0 And (LNG_POW2_15 - 1)) * LNG_POW2_16 Or -((.V0 And LNG_POW2_15) <> 0) * LNG_POW2_31) Or _
((.V0 And (LNG_POW2_31 Xor -1)) \ LNG_POW2_16 Or -(.V0 < 0) * LNG_POW2_15)
' .V2 = UAdd32(.V2, .V1)
' .V1 = RotL32(.V1, 13) Xor .V2
' .V0 = UAdd32(.V0, .V3)
' .V3 = RotL32(.V3, 7) Xor .V0
' .V2 = RotL32(.V2, 16)
If (.V2 Xor .V1) >= 0 Then
.V2 = ((.V2 Xor &H80000000) + .V1) Xor &H80000000
Else
.V2 = .V2 + .V1
End If
.V1 = ((.V1 And (LNG_POW2_18 - 1)) * LNG_POW2_13 Or -((.V1 And LNG_POW2_18) <> 0) * LNG_POW2_31) Or _
((.V1 And (LNG_POW2_31 Xor -1)) \ LNG_POW2_19 Or -(.V1 < 0) * LNG_POW2_12) Xor .V2
If (.V0 Xor .V3) >= 0 Then
.V0 = ((.V0 Xor &H80000000) + .V3) Xor &H80000000
Else
.V0 = .V0 + .V3
End If
.V3 = ((.V3 And (LNG_POW2_24 - 1)) * LNG_POW2_7 Or -((.V3 And LNG_POW2_24) <> 0) * LNG_POW2_31) Or _
((.V3 And (LNG_POW2_31 Xor -1)) \ LNG_POW2_25 Or -(.V3 < 0) * LNG_POW2_6) Xor .V0
.V2 = ((.V2 And (LNG_POW2_15 - 1)) * LNG_POW2_16 Or -((.V2 And LNG_POW2_15) <> 0) * LNG_POW2_31) Or _
((.V2 And (LNG_POW2_31 Xor -1)) \ LNG_POW2_16 Or -(.V2 < 0) * LNG_POW2_15)
lRounds = lRounds - 1
Loop
End With
End Sub
#Else
[ IntegerOverflowChecks (False) ]
Private Sub pvCompress(uCtx As CryptoHalfSiphashContext, ByVal lRounds As Long)
With uCtx
Do While lRounds > 0
.V0 += .V1
.V1 = ((.V1 << 5) Or (.V1 >> 27)) Xor .V0
.V2 += .V3
.V3 = ((.V3 << 8) Or (.V3 >> 24)) Xor .V2
.V0 = (.V0 << 16) Or (.V0 >> 16)
.V2 += .V1
.V1 = ((.V1 << 13) Or (.V1 >> 19)) Xor .V2
.V0 += .V3
.V3 = ((.V3 << 7) Or (.V3 >> 25)) Xor .V0
.V2 = (.V2 << 16) Or (.V2 >> 16)
lRounds -= 1
Loop
End With
End Sub
#End If
Private Function pvCompressArray(uCtx As CryptoHalfSiphashContext, ByVal lSize As Long, uBlock As ArrayLong128, NotUsed As Long) As Long
Dim lIdx As Long
With uCtx
For lIdx = 0 To lSize - 1
.V3 = .V3 Xor uBlock.Item(lIdx)
pvCompress uCtx, .UpdateIters
.V0 = .V0 Xor uBlock.Item(lIdx)
Next
End With
End Function
Public Sub CryptoHalfSiphashInit(uCtx As CryptoHalfSiphashContext, baKey() As Byte, _
Optional ByVal UpdateIters As Long = 2, _
Optional ByVal FinalizeIters As Long = 4, _
Optional ByVal OutSize As Long = 4)
Static K(0 To 1) As Long
Dim lIdx As Long
If UBound(baKey) + 1 < LNG_KEYSZ Then
K(0) = 0: K(1) = 0
If UBound(baKey) >= 0 Then
Call CopyMemory(K(0), baKey(0), UBound(baKey) + 1)
End If
Else
Call CopyMemory(K(0), baKey(0), LNG_KEYSZ)
End If
With uCtx
If OutSize > 4 Then
lIdx = &HEE
Else
lIdx = 0
End If
.V0 = K(0)
.V1 = K(1) Xor lIdx
.V2 = &H6C796765 Xor K(0)
.V3 = &H74656462 Xor K(1)
.NPartial = 0
.NInput = 0
.UpdateIters = UpdateIters
.FinalizeIters = FinalizeIters
.OutSize = OutSize
End With
End Sub
Public Sub CryptoHalfSiphashUpdate(uCtx As CryptoHalfSiphashContext, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1)
Dim B As Long
Dim lIdx As Long
Dim lBlocks As Long
With uCtx
If Size < 0 Then
Size = UBound(baInput) + 1 - Pos
End If
.NInput = .NInput + Size
If .NPartial > 0 And Size > 0 Then
lIdx = LNG_BLOCKSZ - .NPartial
If lIdx > Size Then
lIdx = Size
End If
Call CopyMemory(.Partial(.NPartial), baInput(Pos), lIdx)
.NPartial = .NPartial + lIdx
Pos = Pos + lIdx
Size = Size - lIdx
End If
Do While Size > 0 Or .NPartial = LNG_BLOCKSZ
If .NPartial <> 0 Then
Call CopyMemory(B, .Partial(0), LNG_BLOCKSZ)
.NPartial = 0
.V3 = .V3 Xor B
pvCompress uCtx, .UpdateIters
.V0 = .V0 Xor B
ElseIf Size >= 128 * LNG_BLOCKSZ Then
lBlocks = Size \ (128 * LNG_BLOCKSZ)
For lIdx = 0 To lBlocks - 1
Call CallWindowProc(AddressOf pvCompressArray, VarPtr(uCtx), 128, VarPtr(baInput(Pos)), VarPtr(0))
Pos = Pos + 128 * LNG_BLOCKSZ
Size = Size - 128 * LNG_BLOCKSZ
Next
ElseIf Size >= LNG_BLOCKSZ Then
lIdx = Size \ LNG_BLOCKSZ
Call CallWindowProc(AddressOf pvCompressArray, VarPtr(uCtx), lIdx, VarPtr(baInput(Pos)), VarPtr(0))
Pos = Pos + lIdx * LNG_BLOCKSZ
Size = Size - lIdx * LNG_BLOCKSZ
Else
Call CopyMemory(.Partial(0), baInput(Pos), Size)
.NPartial = Size
Exit Do
End If
Loop
End With
End Sub
Public Sub CryptoHalfSiphashFinalize(uCtx As CryptoHalfSiphashContext, baOutput() As Byte)
Dim B As Long
Dim lIdx As Long
With uCtx
ReDim baOutput(0 To .OutSize - 1) As Byte
#If HasOperators Then
B = CLng(.NInput) << 24
#Else
B = .NInput And &HFF
' B = RotL32(B, 24)
B = ((B And (LNG_POW2_7 - 1)) * LNG_POW2_24 Or -((B And LNG_POW2_7) <> 0) * LNG_POW2_31) Or _
((B And (LNG_POW2_31 Xor -1)) \ LNG_POW2_8 Or -(B < 0) * LNG_POW2_23)
#End If
Call CopyMemory(B, .Partial(0), .NPartial)
.V3 = .V3 Xor B
pvCompress uCtx, .UpdateIters
.V0 = .V0 Xor B
If .OutSize > 4 Then
lIdx = &HEE
Else
lIdx = &HFF
End If
.V2 = .V2 Xor lIdx
pvCompress uCtx, .FinalizeIters
B = .V1 Xor .V3
If .OutSize < 4 Then
lIdx = .OutSize
Else
lIdx = 4
End If
Call CopyMemory(baOutput(0), B, lIdx)
If .OutSize > 4 Then
.V1 = .V1 Xor &HDD
pvCompress uCtx, .FinalizeIters
B = .V1 Xor .V3
If .OutSize < 8 Then
lIdx = .OutSize - 4
Else
lIdx = 4
End If
Call CopyMemory(baOutput(4), B, lIdx)
End If
End With
End Sub
Private Function ToUtf8Array(sText As String) As Byte()
Const CP_UTF8 As Long = 65001
Dim baRetVal() As Byte
Dim lSize As Long
lSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(sText), Len(sText), ByVal 0, 0, 0, 0)
If lSize > 0 Then
ReDim baRetVal(0 To lSize - 1) As Byte
Call WideCharToMultiByte(CP_UTF8, 0, StrPtr(sText), Len(sText), baRetVal(0), lSize, 0, 0)
Else
baRetVal = vbNullString
End If
ToUtf8Array = baRetVal
End Function
Private Function ToHex(baData() As Byte) As String
Dim lIdx As Long
Dim sByte As String
ToHex = String$(UBound(baData) * 2 + 2, 48)
For lIdx = 0 To UBound(baData)
sByte = LCase$(Hex$(baData(lIdx)))
If Len(sByte) = 1 Then
Mid$(ToHex, lIdx * 2 + 2, 1) = sByte
Else
Mid$(ToHex, lIdx * 2 + 1, 2) = sByte
End If
Next
End Function
Public Function CryptoHalfSiphash24ByteArray(baKey() As Byte, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1) As Byte()
Dim uCtx As CryptoHalfSiphashContext
CryptoHalfSiphashInit uCtx, baKey, UpdateIters:=2, FinalizeIters:=4
CryptoHalfSiphashUpdate uCtx, baInput, Pos, Size
CryptoHalfSiphashFinalize uCtx, CryptoHalfSiphash24ByteArray
End Function
Public Function CryptoHalfSiphash24Long(baKey() As Byte, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1) As Long
Dim baOuput() As Byte
baOuput = CryptoHalfSiphash24ByteArray(baKey, baInput, Pos, Size)
Call CopyMemory(CryptoHalfSiphash24Long, baOuput(0), 4)
End Function
Public Function CryptoHalfSiphash24Text(sKey As String, sText As String) As String
CryptoHalfSiphash24Text = ToHex(CryptoHalfSiphash24ByteArray(ToUtf8Array(sKey), ToUtf8Array(sText)))
End Function
Public Function CryptoHalfSiphash13ByteArray(baKey() As Byte, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1) As Byte()
Dim uCtx As CryptoHalfSiphashContext
CryptoHalfSiphashInit uCtx, baKey, UpdateIters:=1, FinalizeIters:=3
CryptoHalfSiphashUpdate uCtx, baInput, Pos, Size
CryptoHalfSiphashFinalize uCtx, CryptoHalfSiphash13ByteArray
End Function
Public Function CryptoHalfSiphash13Long(baKey() As Byte, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1) As Long
Dim baOuput() As Byte
baOuput = CryptoHalfSiphash13ByteArray(baKey, baInput, Pos, Size)
Call CopyMemory(CryptoHalfSiphash13Long, baOuput(0), 4)
End Function
Public Function CryptoHalfSiphash13Text(sKey As String, sText As String) As String
CryptoHalfSiphash13Text = ToHex(CryptoHalfSiphash13ByteArray(ToUtf8Array(sKey), ToUtf8Array(sText)))
End Function
'--- mdSiphash.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)
Private Declare PtrSafe Function VariantChangeType Lib "oleaut32" (Dest As Variant, Src As Variant, ByVal wFlags As Integer, ByVal vt As VbVarType) As Long
Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As LongPtr, ByVal cchWideChar As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
#Else
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function VariantChangeType Lib "oleaut32" (Dest As Variant, Src As Variant, ByVal wFlags As Integer, ByVal vt As VbVarType) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
#End If
Private Const LNG_BLOCKSZ As Long = 8
Private Const LNG_KEYSZ As Long = 16
Public Type CryptoSiphashContext
#If HasPtrSafe Then
V0 As LongLong
V1 As LongLong
V2 As LongLong
V3 As LongLong
#Else
V0 As Variant
V1 As Variant
V2 As Variant
V3 As Variant
#End If
Partial(0 To LNG_BLOCKSZ - 1) As Byte
NPartial As Long
NInput As Currency
UpdateIters As Long
FinalizeIters As Long
OutSize As Long
End Type
#If HasPtrSafe Then
#If Not HasOperators Then
Private LNG_POW2(0 To 63) As LongLong
Private LNG_SIGN_BIT As LongLong ' 2 ^ 63
#End If
Private LNG_ZERO As LongLong
Private LNG_IV(0 To 3) As LongLong
#Else
Private LNG_POW2(0 To 63) As Variant
Private LNG_SIGN_BIT As Variant
Private LNG_ZERO As Variant
Private LNG_IV(0 To 3) As Variant
#End If
#If Not HasOperators Then
#If HasPtrSafe Then
Private Function RotL64(ByVal lX As LongLong, ByVal lN As Long) As LongLong
#Else
Private Function RotL64(lX As Variant, ByVal lN As Long) As Variant
#End If
'--- RotL64 = LShift(X, n) Or RShift(X, 64 - n)
Debug.Assert lN <> 0
RotL64 = ((lX And (LNG_POW2(63 - lN) - 1)) * LNG_POW2(lN) Or -((lX And LNG_POW2(63 - lN)) <> 0) * LNG_SIGN_BIT) Or _
((lX And (LNG_SIGN_BIT Xor -1)) \ LNG_POW2(64 - lN) Or -(lX < 0) * LNG_POW2(lN - 1))
End Function
#If HasPtrSafe Then
Private Function UAdd64(ByVal lX As LongLong, ByVal lY As LongLong) As LongLong
#Else
Private Function UAdd64(lX As Variant, lY As Variant) As Variant
#End If
If (lX Xor lY) >= 0 Then
UAdd64 = ((lX Xor LNG_SIGN_BIT) + lY) Xor LNG_SIGN_BIT
Else
UAdd64 = lX + lY
End If
End Function
Private Sub pvCompress(uCtx As CryptoSiphashContext, ByVal lRounds As Long)
With uCtx
Do While lRounds > 0
.V0 = UAdd64(.V0, .V1)
.V2 = UAdd64(.V2, .V3)
.V1 = RotL64(.V1, 13)
.V3 = RotL64(.V3, 16)
.V1 = .V1 Xor .V0
.V3 = .V3 Xor .V2
.V0 = RotL64(.V0, 32)
.V2 = UAdd64(.V2, .V1)
.V0 = UAdd64(.V0, .V3)
.V1 = RotL64(.V1, 17)
.V3 = RotL64(.V3, 21)
.V1 = .V1 Xor .V2
.V3 = .V3 Xor .V0
.V2 = RotL64(.V2, 32)
lRounds = lRounds - 1
Loop
End With
End Sub
#Else
[ IntegerOverflowChecks (False) ]
Private Sub pvCompress(uCtx As CryptoSiphashContext, ByVal lRounds As Long)
With uCtx
Do While lRounds > 0
.V0 += .V1
.V2 += .V3
.V1 = (.V1 << 13) Or (.V1 >> 51)
.V3 = (.V3 << 16) Or (.V3 >> 48)
.V1 = .V1 Xor .V0
.V3 = .V3 Xor .V2
.V0 = (.V0 << 32) Or (.V0 >> 32)
.V2 += .V1
.V0 += .V3
.V1 = (.V1 << 17) Or (.V1 >> 47)
.V3 = (.V3 << 21) Or (.V3 >> 43)
.V1 = .V1 Xor .V2
.V3 = .V3 Xor .V0
.V2 = (.V2 << 32) Or (.V2 >> 32)
lRounds -= 1
Loop
End With
End Sub
#End If
#If Not HasPtrSafe Then
Private Function CLngLng(vValue As Variant) As Variant
Const VT_I8 As Long = &H14
Call VariantChangeType(CLngLng, vValue, 0, VT_I8)
End Function
#End If
Public Sub CryptoSiphashInit(uCtx As CryptoSiphashContext, baKey() As Byte, _
Optional ByVal UpdateIters As Long = 2, _
Optional ByVal FinalizeIters As Long = 4, _
Optional ByVal OutSize As Long = 8)
#If HasPtrSafe Then
Static K(0 To 1) As LongLong
#Else
Static K(0 To 1) As Variant
#End If
Dim lIdx As Long
If LNG_IV(0) = 0 Then
LNG_IV(0) = CLngLng("&H736f6d6570736575")
LNG_IV(1) = CLngLng("&H646f72616e646f6d")
LNG_IV(2) = CLngLng("&H6c7967656e657261")
LNG_IV(3) = CLngLng("&H7465646279746573")
LNG_ZERO = CLngLng(0)
#If Not HasOperators Then
LNG_POW2(0) = CLngLng(1)
For lIdx = 1 To 63
LNG_POW2(lIdx) = CVar(LNG_POW2(lIdx - 1)) * 2
Next
LNG_SIGN_BIT = LNG_POW2(63)
#End If
End If
If UBound(baKey) + 1 < LNG_KEYSZ Then
K(0) = LNG_ZERO: K(1) = LNG_ZERO
#If HasPtrSafe Then
If UBound(baKey) >= 0 Then
Call CopyMemory(K(0), baKey(0), UBound(baKey) + 1)
End If
#Else
lIdx = UBound(baKey) + 1
If lIdx > 0 Then
Call CopyMemory(ByVal VarPtr(K(0)) + 8, baKey(0), IIf(lIdx > 8, 8, lIdx))
End If
lIdx = UBound(baKey) - 7
If lIdx > 0 Then
Call CopyMemory(ByVal VarPtr(K(1)) + 8, baKey(8), lIdx)
End If
#End If
Else
#If HasPtrSafe Then
Call CopyMemory(K(0), baKey(0), LNG_KEYSZ)
#Else
K(0) = LNG_ZERO: K(1) = LNG_ZERO
Call CopyMemory(ByVal VarPtr(K(0)) + 8, baKey(0), 8)
Call CopyMemory(ByVal VarPtr(K(1)) + 8, baKey(8), 8)
#End If
End If
With uCtx
If OutSize > 8 Then
lIdx = &HEE
Else
lIdx = 0
End If
.V0 = LNG_IV(0) Xor K(0)
.V1 = LNG_IV(1) Xor K(1) Xor lIdx
.V2 = LNG_IV(2) Xor K(0)
.V3 = LNG_IV(3) Xor K(1)
.NPartial = 0
.NInput = 0
.UpdateIters = UpdateIters
.FinalizeIters = FinalizeIters
.OutSize = OutSize
End With
End Sub
Public Sub CryptoSiphashUpdate(uCtx As CryptoSiphashContext, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1)
#If HasPtrSafe Then
Static B As LongLong
#Else
Static B As Variant
#End If
Dim lIdx As Long
With uCtx
If Size < 0 Then
Size = UBound(baInput) + 1 - Pos
End If
.NInput = .NInput + Size
If .NPartial > 0 And Size > 0 Then
lIdx = LNG_BLOCKSZ - .NPartial
If lIdx > Size Then
lIdx = Size
End If
Call CopyMemory(.Partial(.NPartial), baInput(Pos), lIdx)
.NPartial = .NPartial + lIdx
Pos = Pos + lIdx
Size = Size - lIdx
End If
Do While Size > 0 Or .NPartial = LNG_BLOCKSZ
If .NPartial <> 0 Then
#If HasPtrSafe Then
Call CopyMemory(B, .Partial(0), LNG_BLOCKSZ)
#Else
B = LNG_ZERO
Call CopyMemory(ByVal VarPtr(B) + 8, .Partial(0), LNG_BLOCKSZ)
#End If
.NPartial = 0
ElseIf Size >= LNG_BLOCKSZ Then
#If HasPtrSafe Then
Call CopyMemory(B, baInput(Pos), LNG_BLOCKSZ)
#Else
B = LNG_ZERO
Call CopyMemory(ByVal VarPtr(B) + 8, baInput(Pos), LNG_BLOCKSZ)
#End If
Pos = Pos + LNG_BLOCKSZ
Size = Size - LNG_BLOCKSZ
Else
Call CopyMemory(.Partial(0), baInput(Pos), Size)
.NPartial = Size
Exit Do
End If
.V3 = .V3 Xor B
pvCompress uCtx, .UpdateIters
.V0 = .V0 Xor B
Loop
End With
End Sub
Public Sub CryptoSiphashFinalize(uCtx As CryptoSiphashContext, baOutput() As Byte)
#If HasPtrSafe Then
Static B As LongLong
#Else
Static B As Variant
#End If
Dim lIdx As Long
With uCtx
ReDim baOutput(0 To .OutSize - 1) As Byte
#If HasOperators Then
B = CLngLng(.NInput) << 56
#Else
B = RotL64(CLngLng(.NInput) And &HFF, 56)
#End If
#If HasPtrSafe Then
Call CopyMemory(B, .Partial(0), .NPartial)
#Else
Call CopyMemory(ByVal VarPtr(B) + 8, .Partial(0), .NPartial)
#End If
.V3 = .V3 Xor B
pvCompress uCtx, .UpdateIters
.V0 = .V0 Xor B
If .OutSize > 8 Then
lIdx = &HEE
Else
lIdx = &HFF
End If
.V2 = .V2 Xor lIdx
pvCompress uCtx, .FinalizeIters
B = .V0 Xor .V1 Xor .V2 Xor .V3
If .OutSize < 8 Then
lIdx = .OutSize
Else
lIdx = 8
End If
#If HasPtrSafe Then
Call CopyMemory(baOutput(0), B, lIdx)
#Else
Call CopyMemory(baOutput(0), ByVal VarPtr(B) + 8, lIdx)
#End If
If .OutSize > 8 Then
.V1 = .V1 Xor &HDD
pvCompress uCtx, .FinalizeIters
B = .V0 Xor .V1 Xor .V2 Xor .V3
If .OutSize < 16 Then
lIdx = .OutSize - 8
Else
lIdx = 8
End If
#If HasPtrSafe Then
Call CopyMemory(baOutput(8), B, lIdx)
#Else
Call CopyMemory(baOutput(8), ByVal VarPtr(B) + 8, lIdx)
#End If
End If
End With
End Sub
Public Function CryptoSiphash24ByteArray(baKey() As Byte, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1) As Byte()
Dim uCtx As CryptoSiphashContext
CryptoSiphashInit uCtx, baKey, UpdateIters:=2, FinalizeIters:=4
CryptoSiphashUpdate uCtx, baInput, Pos, Size
CryptoSiphashFinalize uCtx, CryptoSiphash24ByteArray
End Function
Private Function ToUtf8Array(sText As String) As Byte()
Const CP_UTF8 As Long = 65001
Dim baRetVal() As Byte
Dim lSize As Long
lSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(sText), Len(sText), ByVal 0, 0, 0, 0)
If lSize > 0 Then
ReDim baRetVal(0 To lSize - 1) As Byte
Call WideCharToMultiByte(CP_UTF8, 0, StrPtr(sText), Len(sText), baRetVal(0), lSize, 0, 0)
Else
baRetVal = vbNullString
End If
ToUtf8Array = baRetVal
End Function
Private Function ToHex(baData() As Byte) As String
Dim lIdx As Long
Dim sByte As String
ToHex = String$(UBound(baData) * 2 + 2, 48)
For lIdx = 0 To UBound(baData)
sByte = LCase$(Hex$(baData(lIdx)))
If Len(sByte) = 1 Then
Mid$(ToHex, lIdx * 2 + 2, 1) = sByte
Else
Mid$(ToHex, lIdx * 2 + 1, 2) = sByte
End If
Next
End Function
Public Function CryptoSiphash24Text(sKey As String, sText As String) As String
CryptoSiphash24Text = ToHex(CryptoSiphash24ByteArray(ToUtf8Array(sKey), ToUtf8Array(sText)))
End Function
Public Function CryptoSiphash13ByteArray(baKey() As Byte, baInput() As Byte, Optional ByVal Pos As Long, Optional ByVal Size As Long = -1) As Byte()
Dim uCtx As CryptoSiphashContext
CryptoSiphashInit uCtx, baKey, UpdateIters:=1, FinalizeIters:=3
CryptoSiphashUpdate uCtx, baInput, Pos, Size
CryptoSiphashFinalize uCtx, CryptoSiphash13ByteArray
End Function
Public Function CryptoSiphash13Text(sKey As String, sText As String) As String
CryptoSiphash13Text = ToHex(CryptoSiphash13ByteArray(ToUtf8Array(sKey), ToUtf8Array(sText)))
End Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment