In 2017 I've started to use libsodium ( https://www.libsodium.org ) for security features in one of my applications.
2 days ago I noticed that I cannot compile my old application with the x64 compiler because of sodium and updated the libraries to the most recent version 1.0.18 and added x64 support.
Just in case you're interested here's an example I've created as first PoC.
At first you need a few files - I decided to include them as static library to prevent the requirement to ship additional files with my application:
- libsodium.lib => get from libsodium zip file from folder Win32\Release\v100\static or the x64 folder https://download.libsodium.org/libsodium/releases/ - e.g. libsodium-1.0.18-msvc.zip
- BufferOverflowU.lib -> get it from the Windows Driver Kit Version 7.1.0 https://www.microsoft.com/en-us/downloa ... x?id=11800
- advapi32.lib -> get it from the Windows Driver Kit Version 7.1.0 https://www.microsoft.com/en-us/downloa ... x?id=11800
- gshandler.obj -> only required for x64 (else you get an error related to __GSHandlerCheck ) -> https://github.com/Aekras1a/Labs/blob/m ... andler.obj
And here's my small example:
Code: Select all
EnableExplicit
Procedure.s CMHEX_MemToHexStr(*Mem, Cnt, WithSpace.i=#False)
Protected iCnt.i
Protected sRes.s=""
For iCnt=0 To Cnt-1
sRes+RSet(Hex(PeekA(*Mem+iCnt), #PB_Ascii), 2, "0")
If WithSpace
sRes+" "
EndIf
Next
If WithSpace
sRes=Left(sRes, Len(sRes)-1)
EndIf
ProcedureReturn sRes
EndProcedure
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
ImportC "x86\BufferOverflowU.lib"
EndImport
ImportC "x86\advapi32.lib"
EndImport
ImportC "x86\libsodium.lib"
CompilerElse
ImportC "x64\BufferOverflowU.lib"
EndImport
ImportC "x64\advapi32.lib"
EndImport
ImportC "x64\gshandler.obj"
EndImport
ImportC "x64\libsodium.lib"
CompilerEndIf
sodium_init()
crypto_secretbox_keygen(*k) ; memory area with 'crypto_secretbox_keybytes()' size - is filled with a secret 'key'
crypto_secretbox_keybytes()
crypto_secretbox_noncebytes()
crypto_secretbox_macbytes()
randombytes_buf(*buf, size.i)
crypto_secretbox_easy(*ciphertext, *messagetext, messagelen.q, *nonce, *key) ; returns 0 on success
crypto_secretbox_open_easy(*decrypted, *ciphertext, ciphertextlen.q, *nonce, *key) ; returns 0 on success
; key should be crypto_secretbox_KEYBYTES bytes and nonce should be crypto_secretbox_NONCEBYTES bytes.
; ciphertext should be at least crypto_secretbox_MACBYTES + messagelen bytes long
crypto_sign_publickeybytes()
crypto_sign_secretkeybytes()
crypto_sign_seedbytes()
crypto_sign_bytes()
crypto_sign_keypair(*public_key, *secret_key)
crypto_sign_seed_keypair(*public_key, *secret_key, *seed)
; public_key should be crypto_sign_PUBLICKEYBYTES bytes
; secret key should be crypto_sign_SECRETKEYBYTES bytes
; seed should be crypto_sign_SEEDBYTES bytes
crypto_sign_detached(*signature_out, *siglen_out, *message_in, messagelen.q, *secretkey_in)
; It is safe to ignore return value *siglen (quad) and always consider a signature as crypto_sign_BYTES bytes long: shorter signatures will be transparently padded with zeros if necessary.
; *siglen can be NULL
crypto_sign_verify_detached(*signature, *message, messagelen.q, *publickey) ; returns 0 on success and -1 if signature verification fails
; https://download.libsodium.org/doc/helpers/memory_management.html
sodium_malloc(size.q) ; returns a pointer from which exactly size contiguous bytes of memory can be accessed.
sodium_free(*ptr) ; unlocks and deallocates memory allocated using sodium_malloc()
EndImport
Define *key
Define *nonce
Define *encrypted
Define *decrypted
Define *Message
Define *PublicKey
Define *SecretKey
Define *Signature
Define SigCnt.q
Define iConsoleOpen.i=#False
Repeat ; single repeat
If Not OpenConsole("Libsodium Test")
Debug "ERROR! OpenConsole"
Break
EndIf
iConsoleOpen=#True
If sodium_init()<0
Debug "ERROR! sodium_init"
Break
EndIf
; ######## SECRET KEY CRYPTOGRAPHY ############
Define iNonceSize.i=crypto_secretbox_noncebytes()
Define iEncryptedsize.i
Define iDecryptedSize.i
Define iMessageSize.i
Define sMessage.s
Define iUseMalloc.i
iUseMalloc=#True
sMessage="This is just a test"
iMessageSize=StringByteLength(sMessage, #PB_UTF8)
iEncryptedsize=crypto_secretbox_macbytes()+iMessageSize
iDecryptedSize=iEncryptedsize-crypto_secretbox_macbytes()
*key=sodium_malloc(crypto_secretbox_keybytes())
If iUseMalloc
*Message=sodium_malloc(iMessageSize+1)
*nonce=sodium_malloc(iNonceSize)
*encrypted=sodium_malloc(iEncryptedsize+1)
*decrypted=sodium_malloc(iDecryptedSize+1)
Else
*Message=AllocateMemory(iMessageSize)
*nonce=AllocateMemory(iNonceSize)
*encrypted=AllocateMemory(iEncryptedsize)
*decrypted=AllocateMemory(iDecryptedSize)
EndIf
Debug "Msg: "+*Message
Debug "Nce: "+*nonce
Debug "enc: "+*encrypted
Debug "dec: "+*decrypted
If Not *Message Or Not *key Or Not *nonce Or Not *encrypted Or Not *decrypted
PrintN("ERROR! AllocMem")
Break
EndIf
PokeS(*Message, sMessage, iMessageSize, #PB_UTF8|#PB_String_NoZero)
If Not crypto_secretbox_keygen(*key)
PrintN("ERROR! crypto_secretbox_keygen")
Break
EndIf
If Not randombytes_buf(*nonce, iNonceSize)
PrintN("ERROR! randombytes_buf")
Break
EndIf
PrintN("KEY : "+CMHEX_MemToHexStr(*key, crypto_secretbox_keybytes()))
PrintN("NONCE: "+CMHEX_MemToHexStr(*nonce, iNonceSize))
PrintN("MSG : Text >"+PeekS(*Message, iMessageSize, #PB_UTF8)+"< HEX: >"+CMHEX_MemToHexStr(*Message, iMessageSize)+"<")
If crypto_secretbox_easy(*encrypted, *Message, iMessageSize, *nonce, *key)
PrintN("ERROR! crypto_secretbox")
Break
EndIf
PrintN("ENCRYPTED:"+CMHEX_MemToHexStr(*encrypted, iEncryptedsize))
If crypto_secretbox_open_easy(*decrypted, *encrypted, iEncryptedsize, *nonce, *key)
PrintN("ERROR! crypto_secretbox_open_easy")
Break
EndIf
PrintN("DECRYPTED:"+CMHEX_MemToHexStr(*decrypted, iDecryptedSize)+" - Text >"+PeekS(*decrypted, iDecryptedSize, #PB_UTF8)+"<")
sodium_free(*key)
If iUseMalloc
sodium_free(*Message)
sodium_free(*nonce)
sodium_free(*encrypted)
sodium_free(*decrypted)
Else
FreeMemory(*Message)
FreeMemory(*nonce)
FreeMemory(*encrypted)
FreeMemory(*decrypted)
EndIf
; ######### PUBLIC KEY SIGNATURE ###########
*PublicKey=AllocateMemory(crypto_sign_publickeybytes())
*SecretKey=sodium_malloc(crypto_sign_secretkeybytes())
*Signature=AllocateMemory(crypto_sign_bytes())
If Not *PublicKey Or Not *SecretKey Or Not *Signature
PrintN("ERROR! AllocMem")
Break
EndIf
If crypto_sign_keypair(*PublicKey, *SecretKey)
PrintN("ERROR! crypto_sign_keypair")
Break
EndIf
PrintN("PublicKey >"+CMHEX_MemToHexStr(*PublicKey, MemorySize(*PublicKey))+"<")
PrintN("SecretKey >"+CMHEX_MemToHexStr(*SecretKey, crypto_sign_secretkeybytes())+"<")
; ######### Sign/signVerify detached test ###########
*Message=AllocateMemory(100)
If crypto_sign_detached(*Signature, @SigCnt, *Message, MemorySize(*Message), *SecretKey)
PrintN("ERROR! crypto_sign_detached")
Break
EndIf
PrintN("SIGNATURE: >"+CMHEX_MemToHexStr(*Signature, MemorySize(*Signature))+"< SigCnt >"+SigCnt+"< ")
Select crypto_sign_verify_detached(*Signature, *Message, MemorySize(*Message), *PublicKey)
Case 0
PrintN("SIGNATURE VALID!")
Default
PrintN("ERROR!!! Signature invalid!!!")
EndSelect
FreeMemory(*PublicKey)
sodium_free(*SecretKey)
FreeMemory(*Signature)
Until #True
If iConsoleOpen
PrintN("Press return to close console")
Input()
CloseConsole()
EndIf