Some examples:
CustomSortList()
Code: Select all
Structure CustomStruct
Value$
EndStructure
; Procedure must take two pointer values as parameter and return:
; #PB_Sort_Lesser if first < second
; #PB_Sort_Greater first > second
; #PB_Sort_Equal if first = second
;
; The functions are intended to sort structured lists, but you can use it on atomic types too by using
; the predefined structures like "Long" or "Integer" for the parameter types
;
Procedure CustomCompare(*a.CustomStruct, *b.CustomStruct)
; Sort by numeric value in the string
If Val(*a\Value$) < Val(*b\Value$)
ProcedureReturn #PB_Sort_Lesser
ElseIf Val(*a\Value$) > Val(*b\Value$)
ProcedureReturn #PB_Sort_Greater
Else
ProcedureReturn #PB_Sort_Equal
EndIf
EndProcedure
NewList Test.CustomStruct()
AddElement(Test()) : Test()\Value$ = "0005"
AddElement(Test()) : Test()\Value$ = "2"
AddElement(Test()) : Test()\Value$ = "42"
AddElement(Test()) : Test()\Value$ = "7"
AddElement(Test()) : Test()\Value$ = "23"
AddElement(Test()) : Test()\Value$ = "100"
AddElement(Test()) : Test()\Value$ = "101"
CustomSortList(Test(), @CustomCompare(), #PB_Sort_Ascending)
ForEach Test()
Debug Test()\Value$
Next
CreatePasswordHash() / VerifyPasswordHash()
Code: Select all
; Create a hash value from a password for storage
Hash$ = CreatePasswordHash("secret")
Debug Hash$
; Multiple calls with the same password result in a different hash due to the use of a random salt
; So do not compare the hashes to check if a password is correct
Debug CreatePasswordHash("secret")
; Instead, VerifyPasswordHash() must be used to check a password
Debug VerifyPasswordHash("secret", Hash$) ; correct
Debug VerifyPasswordHash("secret2", Hash$) ; incorrect
; The optional "WorkFactor" parameter can be used to increase the work needed to check a hash to make brute-force attacks harder
; The default is 10 (the recommended value). An increase by 1 makes the computation take 2x as long as before.
Debug CreatePasswordHash("secret", 12)
#PB_Cipher_HMAC flag
Code: Select all
; For the HMAC computation you use any regular fingerprint function and specify a digest algorithm combined
; with the #PB_Cipher_HMAC flag. You also must specify a secret key to use in the HMAC computation.
; You can optionally specify the string format for the HMAC key (default is UTF-8)
; Use hmacSha256 with both key and message in ascii
; Should be 4643978965ffcec6e6d73b36a39ae43ceb15f7ef8131b8307862ebc560e7f988
UseSHA2Fingerprint()
Debug StringFingerprint("the message to hash here", #PB_Cipher_SHA2|#PB_Cipher_HMAC, 256, #PB_Ascii, "the shared secret key here", #PB_Ascii)
DeriveCypherKey() function
Code: Select all
; The DeriveCyptherKey() function lets you generate a key of any length for encryption (or other purposes)
; from a password.
;
; Input:
; - the password
; - a salt value (should be randomly choosen but does not have to be secret)
; - an iteration count (more iterations means more work to compute the key, so harder brute-force attacks)
; - the output buffer and size of the key in bits
; - A cypther plugin for a digest function and the bit size for the digest function
;
; To get the same key for decryption the function has the be called with the same parameters again.
; Only the password has to be kept secret. The rest just has to be remembered somewhere (or hard-coded).
;
; This function implements the PBKDF2 algorithm so it should be able to create matching keys for other
; tools that use the same set of parameters
UseSHA2Fingerprint()
*Key = AllocateMemory(32)
; Create a 256bit key using SHA-512 hash function and 500000 iterations
; The key size does not have to match the size of the hash function
DeriveCipherKey("SecretPassword", "NonSecretSalt", 500000, *Key, 256, #PB_Cipher_SHA2, 512)
ShowMemoryViewer(*Key, 32)
CompareStructure(), CompareList(), etc.
See here:
https://www.purebasic.fr/english/viewto ... 29#p606129