Page 1 of 1

Opensource base64 functions

Posted: Thu Sep 03, 2009 1:54 pm
by Hroudtwolf
Hi,

The following code shows an PB implementation of the base64 de-/encoder algorithms.

Best regards
Hroudtwolf

(The indentation will be OK after pasting into your editor.)

Code: Select all

; By Hroudtwolf
; 2009-09-03 (ISO 8601)
; PureBasic 4.4x
; Linux, Windows, OS X

EnableExplicit

; ***********************************************************************************
; Simple dataset structure for accessing strictly on ASCII character
; independent by character encoding mode. 
; ***********************************************************************************
Structure ASCII
	a.a
EndStructure

; ***********************************************************************************
; Public function.
; ***********************************************************************************
; Parameters:
; 		*ptrData		-	Pointer the the datablock which you want to encode.
;		nSize			-	Size of the datablock in bytes.
;
; Description:
; 		Use it to encode data to Base64 string.
;
; Return:
; 		Base64 string on success.
; ***********************************************************************************
Procedure.s Base64_Encode ( *ptrData.ASCII , nSize.i )
	Static 		Dim 	cLockUp		.c ( 64 )
	Static 				blInit		.i
	Static 				nI				.i
	Protected			*ptrEnd					= *ptrData + nSize
	Protected 	Dim	bInput		.b ( 3 )
	Protected 	Dim	cOutput		.a ( 4 )
	Protected			sOutput		.s
	Protected			nBlockSize	.i
	
	If Not ( blInit )
		blInit = #True

		; Creating static look up table.
		CopyMemory ( @ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" , @ cLockUp ( 0 ) , 64 * SizeOf ( CHARACTER ) )
	EndIf
	
	While ( *ptrData < *ptrEnd )
		nBlockSize = 0
		; Filling input table.
		For nI = 0 To 2
			If ( *ptrData < *ptrEnd )
				nBlockSize + 1
				bInput ( nI ) = *ptrData\a
				*ptrData + SizeOf ( ASCII )
			Else
				bInput ( nI ) = 0
			EndIf
		Next nI
		
		; Encoding of 3 bytes to 4 6-bit characters.
		If ( nBlockSize )
			cOutput ( 0 ) = cLockUp ( bInput ( 0 ) >> 2 )
			cOutput ( 1 ) = cLockUp ( ( ( bInput ( 0 ) & $03 ) << 4)  | ( ( bInput ( 1 ) & $f0 ) >> 4 ) )
			
			If ( nSize > 1 )
				cOutput ( 2 ) = cLockUp ( ( ( bInput ( 1 ) & $0f ) << 2 ) | ( ( bInput ( 2 ) & $c0 ) >> 6 ) )
			Else
				cOutput ( 2 ) = '='
			EndIf 
			
			If ( nSize > 2 )
				cOutput ( 3 ) = cLockUp ( bInput ( 2 ) & $3f )
			Else
				cOutput ( 3 ) = '='
			EndIf
			For nI = 0 To 3 
				sOutput + Chr ( cOutput ( nI ) )
			Next nI
		EndIf
	Wend
	
	ProcedureReturn sOutput
EndProcedure

; ***********************************************************************************
; Public function.
; ***********************************************************************************
; Parameters:
; 		sInput		-	Input base64 string.
;
; Description:
; 		Use it to decode a base64 string to binary data.
; 		Warning!!! You are full accountability about the returned datablock.
;
; Return:
; 		Pointer to a decoded memory block on success. Otherwise NULL.
; ***********************************************************************************
Procedure.i Base64_Decode ( sInput.s )
	Static 		Dim 	cLockUp			.c ( 81 )
	Static 				blInit			.i
	Protected			*ptrData			.CHARACTER 	= @ sInput
	Protected			nSize				.i				= Len ( sInput ) + 1
	Protected			*ptrEnd							= *ptrData + ( nSize * SizeOf ( CHARACTER ) )
	Protected			nValue			.b
	Protected			nPartSize		.f				= ( nSize - ( nSize / 3.333 ) ) * SizeOf ( CHARACTER ) 
	Protected			*ptrOutput		.BYTE			= AllocateMemory ( Int ( nPartSize ) )
	Protected			*ptrOutputStart				= *ptrOutput
	Protected 	Dim	cInput			.a ( 4 )
	Protected 	Dim	bOutput			.b ( 3 )
	Protected			nBlockSize		.i
	Protected			nI					.i
 
	If Not ( *ptrData )
		ProcedureReturn #Null
	EndIf

	If Not blInit
		blInit = #True
		
		; Creating static look up table.
		CopyMemory ( @ "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\]^_`abcdefghijklmnopq" , @ cLockUp ( 0 ) , 80 * SizeOf ( CHARACTER ) )
	EndIf
	
	While ( *ptrData < *ptrEnd )
		
		nBlockSize = 0
		
		For nI = 0 To 3
			If ( *ptrData < *ptrEnd )
				nValue = 0
				While ( *ptrData < *ptrEnd And Not nValue )
					; Reading a character from base64 string.
					nValue = *ptrData\c : *ptrData + SizeOf ( CHARACTER )
			 
			 		; Adjust of the lookup value.
					If ( nValue < 43 Or nValue > 122 )
						nValue = 0
					Else
						nValue = cLockUp ( nValue - 43 )
					EndIf

					; Detecting the end of the input.							
					If ( nValue = '$' )
				  		nValue = 0 
				   Else
				    	nValue = nValue - 61
				   EndIf
 
				Wend
	 			
	 			; Filling input table.
				If ( *ptrData < *ptrEnd )
					nBlockSize + 1
		 
					If ( nValue )
						cInput ( nI ) = nValue - 1
					EndIf 
				EndIf					
			Else
				Break
			EndIf	
		
		Next nI
		  
		; Decoding of 4 6-bit characters to 3 bytes.  
		If nBlockSize 
			bOutput ( 0 ) = ( cInput ( 0 ) << 2 | cInput ( 1 ) >> 4 ) 
			bOutput ( 1 ) = ( cInput ( 1 ) << 4 | cInput ( 2 ) >> 2 )
			bOutput ( 2 ) = ( ( ( cInput ( 2 ) << 6 ) & $C0 ) | cInput ( 3 ) )
			nI = 0
			; Writting of the decoded byte to the output buffer.
			While ( nI < ( nBlockSize - 1 ) )
				*ptrOutput\b = bOutput ( nI ) 
				*ptrOutput	 + SizeOf ( BYTE )
				nI				 + 1
			Wend
		EndIf
	Wend
	
	ProcedureReturn *ptrOutputStart
EndProcedure

;--- Test

Define.s sInput	= "Feel the pure power! PureBasic."
Define.i	nInput	= StringByteLength ( sInput )
Define.s sBase64 


sBase64 = Base64_Encode ( @ sInput , nInput )

Debug "Encoded: " + sBase64
Debug "Decoded:" + PeekS ( Base64_Decode ( sBase64 ) , nInput )

Posted: Fri Sep 04, 2009 5:21 pm
by infratec
Hi Hroudtwolf,

nice code, but why should someone us it?
The functions already exists in PB:

Base64Encoder()
Base64Decoder()

But it is good to learn something.

Bernd

Posted: Fri Sep 04, 2009 8:14 pm
by Hroudtwolf
Hi,
nice code, but why should someone us it?
It is more for looking (code) than using.

Sometimes you got to reinvent the wheel if you want to learn how it was made.

Best regards

Wolf

Posted: Fri Sep 04, 2009 10:34 pm
by talisman
This is definitely useful for me, thank you very much. I am in the middle of doing a report and essay of various encryption algorithms. Base64 is a good start, much appreciated, believe me! :o