【问题标题】:Base64 Encode "string" - command-line Windows?Base64 编码“字符串” - 命令行 Windows?
【发布时间】:2016-05-05 09:15:31
【问题描述】:

我找到了许多在 Windows 上使用命令行对整个文件进行 base64 编码的方法,但我似乎找不到一种简单的方法来使用命令行实用程序对“字符串”进行批量编码。

如何做到这一点,例如在批处理文件中使用?

【问题讨论】:

  • >"%TEMP%\EncodeBase64.tmp" echo string将字符串写入临时文件怎么样,接下来用实用程序对临时文件"%TEMP%\EncodeBase64.tmp"进行编码,然后用for /F "usebackq delims=" %%I in ("%TEMP%\EncodeBase64.tmp") do set "StringVariable=%%I"从文件中读取编码后的字符串,最后删除临时文件带有del "%TEMP%\EncodeBase64.tmp"的文件?
  • 听说过CertUtil.exe,Windows 的原生工具,包含许多有用的动词?例如,CertUtil -encodeCertUtil -decode 将文件编码/解码到/从 Base64; (也很有帮助:CertUtil -hashfile [{SHA1|MD5}] 计算文件的哈希值...) - 使用临时文件,您还可以处理字符串...
  • 你们中的一个人需要发布certutil 解决方案作为答案。

标签: windows batch-file


【解决方案1】:

这是一个 PowerShell 单行程序,您可以从 cmd 控制台运行,该控制台将对字符串进行 Base64 编码。

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

它可能没有 npocmaka 的解决方案那么快,但你可以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

请注意,doskey 不能在批处理脚本中使用——只能在控制台中使用。如果您想在批处理脚本中使用它,请创建一个函数。

@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

或者,如果您更喜欢批处理 + JScript 混合:

@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)));

编辑:@Hackoo 的批处理 + VBScript 混合:

<!-- : 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>

【讨论】:

  • @rojo 不错的脚本,我喜欢它!我想知道在 vbscript 中是否有与您的代码等效的代码?
  • @Hackoo 我只是希望 VBScript 中有一种方法可以通过名称动态引用对象方法。就像在 JScript / Javascript 中一样,您可以通过 object.methodnameobject["methodname"] 引用一个方法,但是如果没有像 eval() 这样的变通方法,VBScript 似乎不允许第二个约定。您可以使用WSH.Echo eval("htmlfile.parentWindow." &amp; Mid(WSH.Arguments(0), 2) &amp; "(""" &amp; WSH.Arguments(1) &amp; """)") 代替那个5 行的if 块,但我不喜欢使用eval()
  • 谢谢!对我来说,它可以使用单引号(Windows):powershell '[convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(\"word\"))'
【解决方案2】:

根据问题上的cmets,您可以使用certutil。例如,

certutil -encode raw.txt encoded.txt

certutil -f -encode raw.txt encoded.txt

-f 表示“强制覆盖”。否则如果输出文件(上面的encoded.txt)已经存在,就会报错。

但是,这会将输出格式化为编码的.txt 文件,就像它是证书 PEM 文件一样,包含 BEGIN 和 END 行,并在最大字符处分割行。因此,您需要在批处理场景中进行进一步处理,如果字符串很长,则需要做一些额外的工作。

【讨论】:

  • 成功!非常感谢!对于前面的评论者,请注意还有一个 -decode 动词可以将文件从 base64 解码为文本。
  • @aaronsteers 我认为该评论更多的是关于它不适用于命令行的标准输入/输出的事实;您必须将内容放在 file 中,此工具才能为您提供帮助。所以尝试以批处理/管道方式做任何事情都会变得很尴尬。
  • "a bit of extra work": certutil -encodehex -f raw.txt encoded.txt 0x40000001
  • 它不适用于证书文件。标题保持不变。
【解决方案3】:

This script 可以在 XP 及以上版本的每台机器上解码/编码 base64 字符串,无需安装 .net 或 Internet Explorer 10/11。它甚至可以处理特殊的 javascript 转义符号:

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

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

这个接受一个参数 - 你想编码为 base 64 的字符串并打印结果(但至少需要安装 internet explorer 10):

@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>

【讨论】:

  • IE 10 中引入了window.btoawindow.atob 方法。如果将ie=edge 替换为ie=10,您的脚本将与早期版本的Windows 兼容。
  • @npocmaka:我打算在使用 bat2exe 将其转换为 exe 后运行我的 bat 脚本。我只是从我自己的脚本中调用你的脚本吗?那么解码后如何将解码后的密码放回我自己的脚本中的密码变量中?
  • 再想这行不通,因为我必须在 bat2exe 中包含您的脚本。这意味着用户可以用它来解码密码。
【解决方案4】:

如果您安装了适用于 Windows 的 OpenSSL,您可以使用它来对字符串“Hello”进行编码:

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

| set /p= 是为了抑制 echo 通常输出的换行符。

这将在 bash 中产生与以下相同的结果:

echo -n 'Hello' | openssl base64

输出:

SGVsbG8=

【讨论】:

    【解决方案5】:

    这可以(技术上)完全在批处理中完成,方法是在批处理中创建一个加密\解密 VBS 脚本,该脚本可以使用您希望对其数据进行加密\解密的变量的名称进行调用。

    注意:下面的 scipt 是一个独立的子程序。

    用于密码或其他变量的混合批处理 Vbs 加密器/解密器。 对存储在定义文件中的数据执行操作 - 不创建文件。

    注意:vbs 中的文件扩展名与您保存密码/文本的文件类型相匹配。

    使用这个程序用你想设置的变量的名字和要执行的偏移量来调用它。

    但是您的主程序需要用户输入:

        Set /p YourVariableName=
    

    将输入存储到文件中

        ECHO %YourVariableName%>YourSaveFile.txt
    

    使用正偏移量 (IE: +26) 调用它来加密,并使用等效的负偏移量来解密。 (即:-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
        ```
    
    
    
    

    【讨论】:

    • 如果我运行,我会从 Windows 脚本主机获得一个弹出窗口:go.bat 设置了 3 个变量并调用 encrypter.bat 脚本:c:\temp\encrypter.vbs 第 5 行字符 1 错误权限被拒绝代码 800A0046 源 MS VBScript 运行时错误 我在 Win'7 Pro 上以管理员身份运行 cmd。也许我应该澄清一下。在 Cryptme 变量中,您的意思是我输入了我想要加密/解密的内容,比如在我的密码中?那么 Dataforencryption 是什么意思呢?我想看看我是否可以在我的脚本中以某种方式使用它,它的用户名 = 和密码 = 以纯文本形式公开。
    • 用更清晰的方法更新答案并描述它的用途。
    • 这里肯定是吹毛求疵,但 Base64 编码不加密(解码不解密)
    【解决方案6】:

    请注意,doskey 不能在批处理脚本中使用——只能在控制台中使用。如果您想在批处理脚本中使用它,请创建一个函数

    或使用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$^&^|"""""""
    

    限制

    字符串不能以&lt;SPACE&gt; &lt;TAB&gt; &lt;0xFF&gt; =开头
    因为SET /P 用于write without trailing CRLF

    @dbenham 提到了undocumented verbs of CERTUTILCryptBinaryToStringA 函数的类型 0x40000001 记录为:

    不要将任何换行符附加到编码字符串。默认行为是使用回车/换行 (CR/LF) 对 (0x0D/0x0A) 来表示新行。
    Windows Server 2003 和 Windows XP:不支持此值。强>

    【讨论】:

      【解决方案7】:

      使用 Powershell 实现最佳、可靠...。但是,文本的长度有一些限制。

      统一码

          @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%
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-22
        • 2018-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多