Attribute VB_Name = "basConvert" Option Explicit Option Base 0 ' basConvert: Utilities to convert between byte arrays, hex strings, ' strings containing binary values, and 32-bit word arrays. ' NB: On 32-bit Unicode/CJK systems you may need to do a global ' replace of Asc() and Chr() with AscW() and ChrW() respectively. ' Version 2. November 2003: removed cv_BytesFromString which can be ' done with abBytes = StrConv(strInput, vbFromUnicode). ' - Added error handling to catch empty arrays. ' - Made HexFromByte public. ' Version 1. First published January 2002 '************************* COPYRIGHT NOTICE************************* ' This code was originally written in Visual Basic by David Ireland ' and is copyright (c) 2000-2 D.I. Management Services Pty Limited, ' all rights reserved. ' You are free to use this code as part of your own applications ' provided you keep this copyright notice intact. ' This code may only be used as part of an application. It may ' not be reproduced or distributed separately by any means without ' the express written permission of the author. ' David Ireland and DI Management Services Pty Limited make no ' representations concerning either the merchantability of this ' software or the suitability of this software for any particular ' purpose. It is provided "as is" without express or implied ' warranty of any kind. ' Please forward comments or bug reports to <code@di-mgt.com.au>. ' The latest version of this source code can be downloaded from ' www.di-mgt.com.au/crypto.html. '****************** END OF COPYRIGHT NOTICE************************* ' The Public Functions in this module are: ' cv_BytesFromHex(sInputHex): Returns array of bytes ' cv_WordsFromHex(sHex): Returns array of words (Longs) ' cv_HexFromWords(aWords): Returns hex string ' cv_HexFromBytes(aBytes()): Returns hex string ' cv_HexFromString(str): Returns hex string ' cv_StringFromHex(strHex): Returns string of ascii characters ' cv_GetHexByte(sInputHex, iIndex): Extracts iIndex'th byte from hex string ' RandHexByte(): Returns random byte as a 2-digit hex string ' HexFromByte(x): Returns 2-digit hex string representing byte x Public Function cv_BytesFromHex(ByVal sInputHex As String) As Variant ' Returns array of bytes from hex string in big-endian order ' E.g. sHex="FEDC80" will return array {&HFE, &HDC, &H80} Dim i As Long Dim M As Long Dim aBytes() As Byte If Len(sInputHex) Mod 2 <> 0 Then sInputHex = "0" & sInputHex End If M = Len(sInputHex) \ 2 If M <= 0 Then ' Version 2: Returns empty array cv_BytesFromHex = aBytes Exit Function End If ReDim aBytes(M - 1) For i = 0 To M - 1 aBytes(i) = Val("&H" & Mid$(sInputHex, i * 2 + 1, 2)) Next cv_BytesFromHex = aBytes End Function Public Function cv_WordsFromHex(ByVal sHex As String) As Variant ' Converts string <sHex> with hex values into array of words (long ints) ' E.g. "fedcba9876543210" will be converted into {&HFEDCBA98, &H76543210} Const ncLEN As Integer = 8 Dim i As Long Dim nWords As Long Dim aWords() As Long nWords = Len(sHex) \ ncLEN If nWords <= 0 Then ' Version 2: Returns empty array cv_WordsFromHex = aWords Exit Function End If ReDim aWords(nWords - 1) For i = 0 To nWords - 1 aWords(i) = Val("&H" & Mid(sHex, i * ncLEN + 1, ncLEN)) Next cv_WordsFromHex = aWords End Function Public Function cv_HexFromWords(aWords) As String ' Converts array of words (Longs) into a hex string ' E.g. {&HFEDCBA98, &H76543210} will be converted to "FEDCBA9876543210" Const ncLEN As Integer = 8 Dim i As Long Dim nWords As Long Dim sHex As String * ncLEN Dim iIndex As Long 'Set up error handler to catch empty array On Error GoTo ArrayIsEmpty If Not IsArray(aWords) Then Exit Function End If nWords = UBound(aWords) - LBound(aWords) + 1 cv_HexFromWords = String(nWords * ncLEN, " ") iIndex = 0 For i = 0 To nWords - 1 sHex = Hex(aWords(i)) sHex = String(ncLEN - Len(sHex), "0") & sHex Mid$(cv_HexFromWords, iIndex + 1, ncLEN) = sHex iIndex = iIndex + ncLEN Next ArrayIsEmpty: End Function Public Function cv_HexFromBytes(aBytes() As Byte) As String ' Returns hex string from array of bytes ' E.g. aBytes() = {&HFE, &HDC, &H80} will return "FEDC80" Dim i As Long Dim iIndex As Long Dim nLen As Long 'Set up error handler to catch empty array On Error GoTo ArrayIsEmpty nLen = UBound(aBytes) - LBound(aBytes) + 1 cv_HexFromBytes = String(nLen * 2, " ") iIndex = 0 For i = LBound(aBytes) To UBound(aBytes) Mid$(cv_HexFromBytes, iIndex + 1, 2) = HexFromByte(aBytes(i)) iIndex = iIndex + 2 Next ArrayIsEmpty: End Function Public Function cv_HexFromString(str As String) As String ' Converts string <str> of ascii chars to string in hex format ' str may contain chars of any value between 0 and 255. ' E.g. "abc." will be converted to "6162632E" Dim byt As Byte Dim i As Long Dim n As Long Dim iIndex As Long Dim sHex As String n = Len(str) sHex = String(n * 2, " ") iIndex = 0 For i = 1 To n byt = CByte(Asc(Mid$(str, i, 1)) And &HFF) Mid$(sHex, iIndex + 1, 2) = HexFromByte(byt) iIndex = iIndex + 2 Next cv_HexFromString = sHex End Function Public Function cv_StringFromHex(strHex As String) As String ' Converts string <strHex> in hex format to string of ascii chars ' with value between 0 and 255. ' E.g. "6162632E" will be converted to "abc." Dim i As Integer Dim nBytes As Integer nBytes = Len(strHex) \ 2 cv_StringFromHex = String(nBytes, " ") For i = 0 To nBytes - 1 Mid$(cv_StringFromHex, i + 1, 1) = Chr$(Val("&H" & Mid$(strHex, i * 2 + 1, 2))) Next End Function Public Function cv_GetHexByte(ByVal sInputHex As String, iIndex As Long) As Byte ' Extracts iIndex'th byte from hex string (starting at 1) ' E.g. cv_GetHexByte("fecdba98", 3) will return &HBA Dim i As Long i = 2 * iIndex If i > Len(sInputHex) Or i <= 0 Then cv_GetHexByte = 0 Else cv_GetHexByte = Val("&H" & Mid$(sInputHex, i - 1, 2)) End If End Function Public Function RandHexByte() As String ' Returns a random byte as a 2-digit hex string Static stbInit As Boolean If Not stbInit Then Randomize stbInit = True End If RandHexByte = HexFromByte(CByte((Rnd * 256) And &HFF)) End Function Public Function HexFromByte(ByVal x) As String ' Returns a 2-digit hex string for byte x x = x And &HFF If x < 16 Then HexFromByte = "0" & Hex(x) Else HexFromByte = Hex(x) End If End Function Public Function testWordsHex() Dim aWords aWords = cv_WordsFromHex("FEDCBA9876543210") Debug.Print cv_HexFromWords(aWords) End Function