Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Base64 coder/decoder


  • Please log in to reply
42 replies to this topic
guest123
  • Guests
  • Last active:
  • Joined: --
Sorry to be such a noob :oops: but if i want to use this scipt to encode some text, where do i put it, and more to the point, can you explain how I use this?

cheers
guest

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
Copy/Paste the Base64Encode function in your code, call it like this: encoded := Base64Encode(textToEncode)
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

  • Guests
  • Last active:
  • Joined: --
Sorry i dont understand, could you post an example of what the script should look like if for example i wanted to encode the word ''password''

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
I believe you should learn to walk before running...
I don't know what you are trying to do, but if you don't understand how to assign a string to a variable and call a function, you should first read the easy tutorial before going further.
I don't try to be snappy or something, it is just that you can't do much if you don't know such basic things.
BTW, don't use Base64 to hide passwords, this is not really encryption, anybody with base computing knowledge would be able to find your password.
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

Guest123
  • Guests
  • Last active:
  • Joined: --
Don't worry, fixed it now, thanks for your help.
:D

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
I added a version to the original post, to handle binary buffers as well as AHK strings.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
If someone is interested in direct conversion between hex and base64, here is a script.

John Anfdrew
  • Guests
  • Last active:
  • Joined: --
Sorry if this post is bit disjoined, but it's kinda late.

I tried to use it to test some other Base64 string generated by another program, Second Life. However, It won't display the results correctly.

Locked := true
	Gui, Add, Edit,w250  +Center vKey
	Gui, Add, Button,w250  +Center , Unlock
	Gui, Show, Center,

ButtonUnlock:
GuiControlGet, Key
SubmitedKeyDecoded := InvBase64(Key) 
SubmitedEncoded:= Base64(Key)
MsgBox, %SubmitedKeyDecoded %
MsgBox, %SubmitedEncoded%
return


Is what I added to the top, But I I get back are blank responses and "?????" Is ther something I need to do or an I totally misunderstanding with script?

And is there a imple way to Xor these strings?

I want to eventually use it in conjunction with:
http://secondlife.co...orBase64Strings

I really novice when it comes to this sort of thing. ^_^;[/url]

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
For experimenting this looks better:
StringCaseSense On 

Chars = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 



Gui Add, Edit, w250 vKey 

Gui Add, Button, w120, Encode 

Gui Add, Button, w120 xp+130, Decode 

Gui Show, Center

Return



ButtonClose:

ButtonEscape:

ExitApp



ButtonEncode: 

  GuiControlGet Key

  GuiControl,,Key, % Base64(Key)

return



ButtonDecode: 

  GuiControlGet Key

  GuiControl,,Key, % InvBase64(Key)

return



Base64(string) { 

   Loop Parse, string 

   { 

      If Mod(A_Index,3) = 1 

         buffer := Asc(A_LoopField) << 16 

      Else If Mod(A_Index,3) = 2 

         buffer += Asc(A_LoopField) << 8 

      Else { 

         buffer += Asc(A_LoopField) 

         out := out . Code(buffer>>18) . Code(buffer>>12) . Code(buffer>>6) . Code(buffer) 

      } 

   } 

   If Mod(StrLen(string),3) = 0 

      Return out 

   If Mod(StrLen(string),3) = 1 

      Return out . Code(buffer>>18) . Code(buffer>>12) "==" 

   Return out . Code(buffer>>18) . Code(buffer>>12) . Code(buffer>>6) "=" 

} 



InvBase64(code) {

   StringReplace code, code, =,,All 

   Loop Parse, code 

   { 

      If Mod(A_Index,4) = 1 

         buffer := DeCode(A_LoopField) << 18 

      Else If Mod(A_Index,4) = 2 

         buffer += DeCode(A_LoopField) << 12 

      Else If Mod(A_Index,4) = 3 

         buffer += DeCode(A_LoopField) << 6 

      Else { 

         buffer += DeCode(A_LoopField) 

         out := out . Chr(buffer>>16) . Chr(255 & buffer>>8) . Chr(255 & buffer) 

      } 

   } 

   If Mod(StrLen(code),4) = 0 

      Return out 

   If Mod(StrLen(code),4) = 2 

      Return out . Chr(buffer>>16) 

   Return out . Chr(buffer>>16) . Chr(255 & buffer>>8) 

} 



Code(i) {   ; <== Chars[i & 63], 0-base index 

   Global Chars 

   StringMid i, Chars, (i&63)+1, 1 

   Return i 

} 



DeCode(c) { ; c = a char in Chars ==> position [0,63]

   Global Chars 

   Return InStr(Chars,c,1) - 1 

}


Richard
  • Guests
  • Last active:
  • Joined: --
Hi,

I just want to point out for anyone having trouble with this script that it MUSt be placed in the autoexecute section of the script (i.e. before any labels, hotkeys etc.)

Otherwise, Chars will not be a global, and all the results will be BLANK!

TT2009
  • Guests
  • Last active:
  • Joined: --
Hi Laszlo,

I can't get your second script to work. Perhaps it is because I don't understand how to use it? What are the bin, n, and code variables supposed to be?

Also your first script doesn't seem to handle punctuation: !@#$%^&* etc. Does the second one, being binary, handle these characters?

Cheers,
TT

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
These scripts are obsolete now. In XP+ you should use the Windows Crypto API, as Titan discovered:
;;;;; ----- Binary to base64/formatted-HEX conversion by the Crypto API, for XP+  (2HEX, 2Base64)

; http://msdn.microsoft.com/en-us/library/aa380285(VS.85).aspx

; http://www.autohotkey.com/forum/viewtopic.php?p=238120#238120



; fmt = 1:base64, 4:hex-table, 5:hex+ASCII, 10:offs+hex, 11:offs+hex+ASCII, 12:raw-hex



BinaryToString(ByRef bin, sz=0, fmt=12) {   ; return base64 or formatted-hex

   n := sz>0 ? sz : VarSetCapacity(bin)

   DllCall("Crypt32.dll\CryptBinaryToStringA", UInt,&bin, UInt,n, UInt,fmt, UInt,0, UIntP,cp, "CDECL UInt") ; get size

   VarSetCapacity(str,cp)

   DllCall("Crypt32.dll\CryptBinaryToStringA", UInt,&bin, UInt,n, UInt,fmt, UInt,&str, UIntP,cp, "CDECL UInt")

   Return str

}



StringToBinary(ByRef bin, hex, fmt=12) {    ; return length, result in bin

   DllCall("Crypt32.dll\CryptStringToBinaryA", UInt,&hex, UInt,StrLen(hex), UInt,fmt, UInt,0, UIntP,cp, UInt,0,UInt,0,"CDECL UInt") ; get size

   VarSetCapacity(bin,cp)

   DllCall("Crypt32.dll\CryptStringToBinaryA", UInt,&hex, UInt,StrLen(hex), UInt,fmt, UInt,&bin, UIntP,cp, UInt,0,UInt,0,"CDECL UInt")

   Return cp

}

                                            ; TEST

VarSetCapacity(bin,100,122)                 ; 100 z-chars

fmt = 11                                    ; table: offs+hex+ASCII

MsgBox % hex:= BinaryToString(bin,100,fmt)  ; encode



len := StringToBinary(bin1,hex,fmt)         ; decode

VarSetCapacity(bin1,-1)                     ; use only with string in bin1

bin1 := SubStr(bin1,1,len)                  ; strip of garbage at the end

MsgBox %len%: %bin1%                        ; show len, original data


Jamie
  • Members
  • 129 posts
  • Last active: Dec 02 2012 04:59 AM
  • Joined: 26 Mar 2010
For some reason these dll calls are not working for me. I'm on Vista and I've checked the inputs and return values and everything appears to be okay except for the output value. The space allocated is what i would expect, and the function is returning nonzero for success. Except that the output variable is blank.

So I'm going to go back to the AHK version.

This will probably be the smallest nit-pick ever, but in the binary version of Base64Decode, I think this:
VarSetCapacity(bin, 3*StrLen(code)//4, 0)
   StringReplace code, code, =,,All
should instead be this:
StringReplace code, code, =,,All
   VarSetCapacity(bin, 3*StrLen(code)//4, 0)
In the first snippet, the variable capacity is larger than the number of encoded bytes if the base64 string ends with trailing = characters.

The variable capacity appears to work as a way to keep track of the number of bytes in a binary blob. However, this is extremely dangerous because there is no guarantee that the capacity will be equal to the requested capacity -- it may be larger. But it just happens to be equal in all the cases that have mattered so far.

(As a side note, perhaps the use of VarSetCapacity to query the capacity should carry strong warnings, as these may easily lead to unsafe code.)

Nonetheless, I'm abandoning the use of variable capacity to keep track of blob sizes, and keeping track of them manually, so I've also changed Base64Decode to return the number of bytes decoded:
Base64Decode(ByRef bin, code) {
   StringReplace code, code, =,,All
   decodedbytes := 3*StrLen(code)//4
   VarSetCapacity(bin, decodedbytes, 0)
   ...
   return decodedbytes
}


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
No, you need the VarSetCapacity and StringReplace in the original order in Base64Decode, to force rounding up to the used length. In Base64Encode the allocated memory is only used, if the size is not given, or if it was wrong. There is nothing unsafe with it: if the capacity is too large, you just encode some garbage in the end of the allocated buffer.

Jamie
  • Members
  • 129 posts
  • Last active: Dec 02 2012 04:59 AM
  • Joined: 26 Mar 2010
Hmm, the way I see it, if you were to have "xx==" then there are 4 characters but only 2 base64 digits, so 3*StrLen//4 will return 3 decoded bytes or 6//4 = 1 decoded bytes depending on whether you strip out the equal signs first.

In the case of a string ending in "xxx=", there are again 4 characters but 3 base64 digits, and 3*strlen//4 will be either 3 decoded bytes or 9//4 = 2 decoded bytes.

If there are not a multiple of 4 base64 digits, then in the very last base64 digit, only some of the six available bits are used. So the actual length in bytes should be rounded down from the number of base64 digits times 3/4.

Usually extra space at the end is not a problem but if for some reason you do need the exact size, I still think you need to compute it by stripping out the equals signs first.

The general practice of using capacity to keep track of exact blob size is probably okay but could potentially be hazardous. But I agree there is nothing unsafe with the functions, since as you mentioned they do not require you to use the capacity as an indicator of blob size.