Base64 Encode "string" - command-line Windows?
Asked Answered
S

10

66

I have found numerous ways to base64 encode whole files using the command-line on Windows, but I can't seem to find a simple way to batch encode just a "string" using a command-line utility.

How does one do this, for use in a batch file for example?

Stunt answered 5/5, 2016 at 9:15 Comment(3)
What about writing the string into a temporary file with >"%TEMP%\EncodeBase64.tmp" echo string, next encode the temporary file "%TEMP%\EncodeBase64.tmp" with a utility, then read the encoded string from file with for /F "usebackq delims=" %%I in ("%TEMP%\EncodeBase64.tmp") do set "StringVariable=%%I" and finally delete the temporary file with del "%TEMP%\EncodeBase64.tmp"?Lumumba
Ever heard of CertUtil.exe, a native tool of Windows with many useful verbs? for instance, CertUtil -encode and CertUtil -decode encode/decode a file to/from Base64; (also helpful: CertUtil -hashfile [{SHA1|MD5}] computes a hash value over a file...) - with a temporary file you can also process strings...Unsteady
One of y'all fellas needs to post the certutil solution as an answer.Mossgrown
M
67

Here's a PowerShell one-liner you can run from a cmd console that'll Base64 encode a string.

powershell "[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(\"Hello world!\"))"

It's probably not as fast as npocmaka's solution, but you could set a console macro with it.

doskey btoa=powershell "[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(\"$*\"))"
doskey atob=powershell "[Text.Encoding]::UTF8.GetString([convert]::FromBase64String(\"$*\"))"

btoa Hello world!
btoa This is fun.
btoa wheeeeee!
atob SGVsbG8gd29ybGQh

Be advised that doskey doesn't work in batch scripts -- only the console. If you want do use this in a batch script, make a function.

@echo off
setlocal

call :btoa b64[0] "Hello world!"
call :btoa b64[1] "This is fun."
call :btoa b64[2] "wheeeeee!"
call :atob b64[3] SGVsbG8gd29ybGQh

set b64
goto :EOF

:btoa <var_to_set> <str>
for /f "delims=" %%I in (
    'powershell "[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(\"%~2\"))"'
) do set "%~1=%%I"
goto :EOF

:atob <var_to_set> <str>
for /f "delims=" %%I in (
    'powershell "[Text.Encoding]::UTF8.GetString([convert]::FromBase64String(\"%~2\"))"'
) do set "%~1=%%I"
goto :EOF

Or if you'd prefer a batch + JScript hybrid:

@if (@CodeSection==@Batch) @then
@echo off & setlocal

call :btoa b64[0] "Hello world!"
call :btoa b64[1] "This is fun."
call :btoa b64[2] "wheeeeee!"
call :atob b64[3] SGVsbG8gd29ybGQh

set b64
goto :EOF

:btoa <var_to_set> <str>
:atob <var_to_set> <str>
for /f "delims=" %%I in ('cscript /nologo /e:JScript "%~f0" %0 "%~2"') do set "%~1=%%I"
goto :EOF

@end // end batch / begin JScript hybrid code
var htmlfile = WSH.CreateObject('htmlfile');
htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=10" />');
WSH.Echo(htmlfile.parentWindow[WSH.Arguments(0).substr(1)](WSH.Arguments(1)));

Edit: batch + VBScript hybrid for @Hackoo:

<!-- : batch portion
@echo off & setlocal

call :btoa b64[0] "Hello world!"
call :btoa b64[1] "This is fun."
call :btoa b64[2] "wheeeeee!"
call :atob b64[3] SGVsbG8gd29ybGQh

set b64
goto :EOF

:btoa <var_to_set> <str>
:atob <var_to_set> <str>
for /f "delims=" %%I in ('cscript /nologo "%~f0?.wsf" %0 "%~2"') do set "%~1=%%I"
goto :EOF

: VBScript -->
<job>
    <script language="VBScript">
        Set htmlfile = WSH.CreateObject("htmlfile")
        htmlfile.write("<meta http-equiv='x-ua-compatible' content='IE=10' />")
        if WSH.Arguments(0) = ":btoa" then
            WScript.Echo htmlfile.parentWindow.btoa(WSH.Arguments(1))
        else
            WScript.Echo htmlfile.parentWindow.atob(WSH.Arguments(1))
        end if
    </script>
</job>
Mossgrown answered 5/5, 2016 at 11:49 Comment(3)
@Mossgrown Nice Script and i like it ! I wonder if there is an equivalent of your code in vbscript ?Waziristan
@Waziristan I just wish there were a way in VBScript to reference an object method dynamically by name. Like in JScript / Javascript you can reference a method both by object.methodname and object["methodname"], but VBScript seems not to allow that second convention without hackish workarounds like eval(). You could use WSH.Echo eval("htmlfile.parentWindow." & Mid(WSH.Arguments(0), 2) & "(""" & WSH.Arguments(1) & """)") in place of that 5-line if block, but I don't like using eval().Mossgrown
Thanks! For me it works but with single quotes (windows) : powershell '[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(\"word\"))'Darius
A
53

According to the comments on the question, you can use certutil. e.g.,

certutil -encode raw.txt encoded.txt

or

certutil -f -encode raw.txt encoded.txt

The -f means "force overwrite". Otherwise you will get an error if the output file (encoded.txt above) already exists.

However, this will format the output into the encoded.txt file as if it were a certificate PEM file, complete with BEGIN and END lines, and split lines at the character max. So you would need to do further processing in a batch scenario, and a bit of extra work if the strings are long at all.

Alehouse answered 10/3, 2017 at 19:4 Comment(4)
Success! Thanks very much! To the previous commenter, note that there is also a -decode verb which can decode files from base64 to text.Basicity
@Basicity I think that comment was more about the fact that it won't work with standard input/output at the command line; you have to put the content in a file before this tool will help you. So trying to do anything in a batch/pipeline manner gets awkward.Alehouse
"a bit of extra work": certutil -encodehex -f raw.txt encoded.txt 0x40000001Laveen
It doesn't work for certificate files. Headers are left untouched.Religious
C
23

If you have OpenSSL for Windows installed you can use this to encode the string "Hello":

echo | set /p="Hello" | openssl base64

The | set /p= is to suppress the newline that echo usually outputs.

This will produce the same result as the following in bash:

echo -n 'Hello' | openssl base64

Output:

SGVsbG8=
Camilla answered 22/8, 2019 at 22:16 Comment(5)
nice! what would be the openssl command to decrypt, in that case? I tried echo | set /p="SGVsbG8=" | openssl enc -a -d, it outputs nothingSeamstress
@Seamstress echo SGVsbG8= | openssl base64 -d works for me. Seems to just ignore the newlineCamilla
oh, that's so weird. looks like it's requiring the newline to decode. perhaps it treats the newline as end of stream. thanks!Seamstress
Nitpick: This echo | set /p="Hello" | openssl base64 should be echo set /p="Hello" | openssl base64 to output the encoded string.Uro
@TemiFakunle when I do that it outputs c2V0IC9wPSJIZWxsbyIgDQo= which is the encoding of set /p="Hello" instead of the encoding of Hello which is SGVsbG8=Camilla
D
12

This script can decode/encode base64 strings on every machine from XP and above without requiring installed .net or internet explorer 10/11.It even can handle special javascript escaped symbols:

// result is IkhlbGxvIg==
base64.bat -encode "\u0022Hello\u0022" -eval yes

// result is SGVsbG8=
base64.bat -encode "Hello"

This one accepts a single argument - the string you want to encode to base 64 and prints the result (but requires at least internet explorer 10 installed):

@echo off

setlocal

set "string=%~1"

::echo %string%^|mshta.exe "%~f0"
for /f "delims=" %%# in ('echo %string%^|mshta.exe "%~f0"') do (
    set b64=%%#
)

set b64

endlocal&exit /b %errorlevel%

<HTA:Application
   ShowInTaskbar = no
   WindowsState=Minimize
   SysMenu=No
   ShowInTaskbar=No
   Caption=No
   Border=Thin
>
<meta http-equiv="x-ua-compatible" content="ie=10" />
<script language="javascript" type="text/javascript">
    window.visible=false;
    window.resizeTo(1,1);

   var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);
   var fso2= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(0);
   var string=fso2.ReadLine();

    var encodedString = btoa(string);

   fso.Write(encodedString);
   window.close();
</script>
Degraded answered 5/5, 2016 at 10:29 Comment(3)
The window.btoa and window.atob methods were introduced in IE 10. Your script would be compatible with earlier versions of Windows if you replace ie=edge with ie=10.Mossgrown
@npocmaka: I plan to run my bat script after converting it to an exe with bat2exe. Do I just call your script from my own script? So after decoding how do I put the decoded password in my password variable back inside my own script?Paternoster
On second thought this won't do since I'll have to include your script with bat2exe. That means a user can just decode the password with it.Paternoster
M
2

This can (technically) be done entirely within Batch, By Creating an encryption\decryption VBS script from within batch that can be called with the name of the Variable whose Data you wish to encrypt\decrypt.

Note: The below scipt is an Independant Subprogram.

Hybrid Batch Vbs Encrypter / Decrypter for passwords or other variables. Performs the action on data stored in the defined file - does not create the file.

Note: file extension in vbs to match the filetype you save password/text to.

To use this program Call it with the name of the Variable you wish to set and the offset to perform.

However your Main program takes user input:

    Set /p YourVariableName=

Store the Input to a File

    ECHO %YourVariableName%>YourSaveFile.txt

Call it with a positive offset (IE: +26) to encrypt, and an equivalent Negative offset to Decrypt. (IE: -26)

    CALL "Insert Filepath To Encrypter.bat Here" YourVariableName +26

Encrypter.bat

    @ECHO OFF
    
    REM :: Do NOT modify the variable names Below, DO INSERT the filepath you used to Store the Data Being Encrypted / Decrypted.

    Set "VarName=%~1"
    Set "offset=%~2"
    Set "SaveLoc=Your Filepath Here"
    
    <"%saveLoc%" (
    Set /p encryptData=
    )
    
    (
    ECHO Dim objFSO 'File System Object
    ECHO Set objFSO = CreateObject("Scripting.FileSystemObject"^)
    ECHO Dim objTS 'Text Stream Object
    ECHO Const ForWriting = 2
    ECHO Set objTS = objFSO.OpenTextFile("%SaveLoc%", ForWriting, True^)
    ECHO objTS.Write(encode("%encryptData%"^)^)
    ECHO wscript.sleep "1000"
    ECHO function encode(s^)
    
    ECHO For i = 1 To Len(s^)
    ECHO newtxt = Mid( s, i, 1^)
    ECHO newtxt = Chr(Asc(newtxt^) %offset%^)
    ECHO coded = coded + (newtxt^)
    ECHO Next
    ECHO encode = coded
    ECHO End function
    ECHO objTS.Close(^)
    ECHO Set bjFSO = Nothing 'Destroy the object.
    ECHO Set objTS = Nothing 'Destroy the object.
    ) >%TEMP%\encrypter.vbs
    
    START /wait %TEMP%\encrypter.vbs
    
    DEL /Q "%TEMP%\encrypter.vbs"
    
    GOTO :EOF
    ```



Montagna answered 15/12, 2019 at 20:12 Comment(3)
I get a popup window from Windows Script Host if I run: go.bat which has the 3 vars set and calls encrypter.bat Script: c:\temp\encrypter.vbs Line 5 Char 1 Error Permission Denied Code 800A0046 Source MS VBScript runtime error I'm running cmd as Admin on Win'7 Pro. Perhaps I should clarify. In the Cryptme variable do you mean I input what I want encrypted/decrypted, so as in my password perhaps? Then what is Dataforencryption meant for? I want to see if I can use this somehow in my script which has a username= and password= exposed in plain text.Paternoster
Have Update the answer with what should be a clearer method and Description of it's use.Montagna
Certainly being nitpicking here but Base64 encoding is not encrypting (and decoding not decrypting)Woolfolk
V
2

I had to modify the oneliner from @rojo a bit to make it work. This works on Windows 11 without any additional software installed:

[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(‘Hello world!’))
Voltage answered 25/1, 2024 at 9:48 Comment(0)
L
1

Be advised that doskey doesn't work in batch scripts -- only the console. If you want do use this in a batch script, make a function

or use a macro:

@echo off
====SETLOCAL DisableDelayedExpansion EnableExtensions


REM Initalize
set ^"LF=^
%===EXPANDS TO NOTHING===%
"
::\n is an escaped LF + caret for line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"


REM MACRO
set ^"$b64.encode=FOR %%$ in (%%$ MainMacro) do if "%%$" == "MainMacro" (%\n%
    ^>nul %__APPDIR__%certutil.exe -f -encodehex args.tmp proc.tmp 0x40000001%\n%
    type proc.tmp%\n%
    echo(%\n%
    del args.tmp proc.tmp%\n%
) 2^>nul ELSE ^<nul ^>args.tmp set/p="


REM EXAMPLES
%$b64.encode%"=I WILL FAIL (string cannot start with =)"
%$b64.encode%^"     leading spaces/tabs will be stripped%\n%
but other characters are%\n%
OK!%\n%
;%%~dp$^&^|"""""""

Limitations

The string must not begin with <SPACE> <TAB> <0xFF> =
because SET /P is used to write without trailing CRLF.

@dbenham mentioned the undocumented verbs of CERTUTIL. The type 0x40000001 of the CryptBinaryToStringA function is documented as:

Do not append any new line characters to the encoded string. The default behavior is to use a carriage return/line feed (CR/LF) pair (0x0D/0x0A) to represent a new line.
Windows Server 2003 and Windows XP: This value is not supported.

Laveen answered 11/4, 2020 at 2:39 Comment(0)
J
1

Optimal, reliable ... with Powershell. However, there are some limitations in the length of the text.

Unicode

    @echo off
    set "string=Everything will be fine"
    for /f "tokens=* delims=" %%i in ('powershell       [convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes("""%string%"""^)^)') do set "encoded=%%i"
    echo %encoded%

UTF8

    @echo off
    set "string=Everything will be fine"
    for /f "tokens=* delims=" %%i in ('powershell       [convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("""%string%"""^)^)') do set "encoded=%%i"
    echo %encoded%
Jodee answered 21/8, 2020 at 18:42 Comment(0)
S
0

This worked for me, this doesn't generate extra lines by certutil, it converts the content of the file data.txt to base64 and saves it to new file data.b64 .

certutil -encode data.txt tmp.b64 && findstr /v /c:- tmp.b64 > data.b64 && del tmp.b64
Staphylococcus answered 14/3, 2023 at 10:54 Comment(0)
B
0

This works for encoding in Powershell 5.1.22621.2506.

"Hello, World!" | % { [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($_)) }

This can be used for decoding:

"SGVsbG8sIFdvcmxkIQ==" | % { [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($_)) }

This approach has the advantages of being a one-liner and supplying the string first (opposed to somewhere in the middle of the code). Also, output is strictly the string, meaning there is no extra text to get rid of (opposed to when using cerutils).

Burnish answered 15/7, 2024 at 23:19 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.