Libsodium with Purebasic

Share your advanced PureBasic knowledge/code with the community.
nalor
Enthusiast
Enthusiast
Posts: 115
Joined: Thu Apr 02, 2009 9:48 pm

Libsodium with Purebasic

Post by nalor »

Hi!
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: For simplicity I've uploaded the files required for x86 and x64 here: http://s000.tinyupload.com/index.php?fi ... 6405930621


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
Hope it's of use :)
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5353
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Libsodium with Purebasic

Post by Kwai chang caine »

KEY : A4AB5123A0D0846D7A777AACF6512C6CE0E7351555D5523D214C7EA2CBE855A9
NONCE: FF82AB53072EB164CE53A4FD2D648F5617A84F08AF98880E
MSG : Text >This is just a test< HEX: >54686973206973206A75737420612074657374<
ENCRYPTED:C88FEE1EFBCB498CA9A61492E7E1500893923BB99C69ECBEB288FECDF55CA8FBE8ECC4
DECRYPTED:54686973206973206A75737420612074657374 - Text >This is just a test<
PublicKey >BCBBE1F18D8E110ABBBD7BAD2A8C357C231B632B0503842A500825A2E61D3C36<
SecretKey >E8BB7BBE9A315415865E33BC1CC55AA8B38415653BB39DE538183E153A9D3EAEBCBBE1F18D8E110ABBBD7BAD2A8C357C231B632B0503842A500825A2E61D3C36<
SIGNATURE: >342CCF485C8A552ED90E98FE8EEA60C252ABCB8832A0DE7232EFDC3A091C6171673A14FDFC8EFB6937F5953469C4E08AF3962979F4B078ECD5BC4C53F5055702< SigCnt >64<
SIGNATURE VALID!
Press return to close console
Msg: 7090156
Nce: 7155688
enc: 8794076
dec: 8859628
Works here on W10 X64 / v5.70 X86 :D
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
Post Reply