1

i am writing a batch script file (.bat) where i need to decode a base64 (Base64 utility for Windows) text and them encode to hex. I can do this. The problem is that i need to store the result in a variable.

For example:

I execute this in cmd:

base64 -d -s ZGG01YZq3ZJLbK3Cz1nOhA | hexdump

The result print to standard output is:

000000 64 61 b4 d5 86 6a dd 92 4b 6c ad c2 cf 59 ce 84

000010 01 b4 d5 86 6a dd 92 4b 6c ad c2 cf 59 ce

I need to store only the first line without any space and without the prefix 000000. To be clear, i need to store 6461b4d5866add924b6cadc2cf59ce84 in the variable readValue1.

Im triying with this code in the .bat file, but its crash:

call :decodefunction 

:decodefunction
SETLOCAL ENABLEDELAYEDEXPANSION
SET count=1
for /f "delims=" %%a IN ('base64 -d -s ZGG01YZq3ZJLbK3Cz1nOhA | hexdump') DO (
  SET readValue!count!=%%a
  SET /a count=!count!+1
)
ECHO %readValue1%
ECHO %readValue2%
ENDLOCAL
C. M.
  • 13
  • 3

2 Answers2

0

This code does what you requested:

:decodefunction
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "tokens=1*" %%a IN ('base64 -d -s ZGG01YZq3ZJLbK3Cz1nOhA ^| hexdump') DO (
  SET "readValue1=%%b"
  GOTO break
)
:break
SET "readValue1=%readValue1: =%"
ECHO %readValue1%
ENDLOCAL
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Thanks, its work with this modification. The method decode store in the variable "key" the result of the operation: `call :decode key,ZGG01YZq3ZJLbK3Cz1nOhA :decode SETLOCAL ENABLEDELAYEDEXPANSION for /f "tokens=1*" %%a IN ('base64 -d -s %~2 ^| hexdump') DO ( SET "readValue1=%%b" GOTO break %~1 ) :break SET "readValue1=%readValue1: =%" ENDLOCAL & set "%~1=%readValue1%"` – C. M. Aug 23 '23 at 13:31
0

You could also solve this problem in a very different way using my printf.exe version 2.11 program.

My printf.exe application is a Windows console program that is a wrapper for the well-known printf CRT function, thus allowing text and formatted numeric values ​​to be displayed in the cmd.exe window. In addition, my program printf.exe also allows to perform Reverse Polish Notation arithmetic operations on 32-bit integers and 64-bit double floating-point numbers using the same method and functions of the stack-based Hewlett-Packard calculators.

The new printf.exe version 2.11 also manages character string operations and allows to write scripts (programs) using the simplest programming scheme. The Batch file below contains a printf.exe program that perform a decode of a Base64-encoded string:

@echo off
setlocal

rem Basic Base64 decoding in Aacini's printf.exe
rem Antonio Perez Ayala

rem Download printf.exe package from:
rem https://www.dostips.com/forum/viewtopic.php?f=3&t=7312&p=68956#p68956

goto begin

https://datatracker.ietf.org/doc/html/rfc4648#section-4

            +--first octet--+-second octet--+--third octet--+
        +-> |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| >-+
Decode  |   +-----------+---+-------+-------+---+-----------+   |  Encode
        +-< |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0| <-+
            +--1.index--+--2.index--+--3.index--+--4.index--+

The Encoding process converts 3 bytes into 4 characters of the Base64 alphabet.
The Decoding process converts 4 characters from the Base64 alphabet into 3 bytes.
The Base64 alphabet consists of digits, upcase- and lowcase-letters, plus two additional characters:
"+" and "/" for standard conversion, or "-" and "_" for "URL and filename safe" conversion.

:begin

set "Base64Alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

set "Encoded=ZGG01YZq3ZJLbK3Cz1nOhA"

printf "\n"             /* Final format                 */ ^
        Base64Alpha     /* "ABC..789+/"                 Enter Base64 alphabet       */ ^
        ]0              /*                              Store its address in R0     */ ^
        Encoded         /* "Base64"                     Enter encoded indices       */ ^
        getc1           /* 'B' 'a' 's' 'e' '6' '4' 6    Separate individual indices */ ^
        (               /* WHILE another (group of 4) index?                        */ ^
           ==0? ;       /*    index count == 0 ?  QUIT  */ ^
                                                                /*      ===== First index =====         */ ^
           shift        /*    'a' 's' 'e' '6' '4' 5 'B'                 Get first index                 */ ^
           [0           /*    'a' 's' 'e' '6' '4' 5 'B' "ABC..789+/"    Enter Base64                    */ ^
        /" <> /"        /*    'a' 's' 'e' '6' '4' 5 "ABC..789+/" 'B'    Exchange they                   */ ^
           1 dupc       /*    'a' 's' 'e' '6' '4' 5 "ABC..789+/" "B"    Convert char to string          */ ^
           index        /*    'a' 's' 'e' '6' '4' 5 "ABC..789+/" 1 1    Index position 0-63 and count   */ ^
           ==0? /" < < /" :             /* Is not valid index? :  Drop count=0 and Base64, and REPEAT   */ ^
        /" < /"         /*    'a' 's' 'e' '6' '4' 5 "ABC..789+/" 1      Drop count                      */ ^
           2 /" << /"   /*    'a' 's' 'e' '6' '4' 5 "ABC..789+/" 4      Shift index left 2 bits and get */ ^
                                                                /*      - first 6 bits of first octet   */ ^
           ]1           /*    'a' 's' 'e' '6' '4' 5 "ABC..789+/" 4      Store they in R1                */ ^
        /" < < /"       /*    'a' 's' 'e' '6' '4' 5                     Drop they and Base64            */ ^
           ==0?         /*    IF no more indices? :     */ ^
              FMT{ "%%c" [1 OUT FMT} ;  /* Show previous 6-bits octet and QUIT */ ^
                                                                /*      ===== Second index =====        */ ^
           shift        /*    's' 'e' '6' '4' 4 'a'                     Get second index                */ ^
           [0           /*    's' 'e' '6' '4' 4 'a' "ABC..789+/"        Enter Base64                    */ ^
        /" <> /"        /*    's' 'e' '6' '4' 4 "ABC..789+/" 'a'        Exchange they                   */ ^
           1 dupc       /*    's' 'e' '6' '4' 4 "ABC..789+/" "a"        Convert char to string          */ ^
           index        /*    's' 'e' '6' '4' 4 "ABC..789+/" 26 1       Index position 0-63 and count   */ ^
           ==0? /" < < /" :             /* Is not valid index? :  Drop count=0 and Base64, and REPEAT   */ ^
        /" < /"         /*    's' 'e' '6' '4' 4 "ABC..789+/" 26         Drop count                      */ ^
           ]2           /*    's' 'e' '6' '4' 4 "ABC..789+/" 26         Store 2.index in R2             */ ^
           4 /" >> /"   /*    's' 'e' '6' '4' 4 "ABC..789+/" 6          Shift 2.index right 4 bits and get */ ^
                                                                /*      - last 2 bits of first octet    */ ^
           ]+1          /*                                              Complete first octet in R1      */ ^
           FMT{ "%%c" [1 OUT FMT}                               /*      Show it                         */ ^
        /" < < /"       /*    's' 'e' '6' '4' 4                         Drop 2 bits and Base64          */ ^
           [2           /*    's' 'e' '6' '4' 4 26                      Recover 2.index                 */ ^
           0x0F /" & /" /*    's' 'e' '6' '4' 4 10                      Get last 4 bits of 2.index      */ ^
           4 /" << /"   /*    's' 'e' '6' '4' 4 160                     Shift they left 4 bits and get  */ ^
                                                                /*      - first 4 bits of second octet  */ ^
           ]2           /*    's' 'e' '6' '4' 4 160                     Store they in R2                */ ^
        /" < /"         /*    's' 'e' '6' '4' 4                         Drop they                       */ ^
           ==0?         /*    IF no more indices? :     */ ^
              FMT{ "%%c" [2 OUT FMT} ;  /* Show previous 4-bits octet and QUIT */ ^
                                                        /*      ===== Third index =====         */ ^
           shift        /*    'e' '6' '4' 3 's'                 Get third index                 */ ^
           [0           /*    'e' '6' '4' 3 's' "ABC..789+/"    Enter Base64                    */ ^
        /" <> /"        /*    'e' '6' '4' 3 "ABC..789+/" 's'    Exchange they                   */ ^
           1 dupc       /*    'e' '6' '4' 3 "ABC..789+/" "s"    Convert char to string          */ ^
           index        /*    'e' '6' '4' 3 "ABC..789+/" 44 1   Index position 0-63 and count   */ ^
           ==0? /" < < /" :        /* Is not valid index? :  Drop count=0 and Base64, and REPEAT */ ^
        /" < /"         /*    'e' '6' '4' 3 "ABC..789+/" 44     Drop count                      */ ^
           ]3           /*    'e' '6' '4' 3 "ABC..789+/" 44     Store 3.index in R3             */ ^
           2 /" >> /"   /*    'e' '6' '4' 3 "ABC..789+/" 11     Shift 3.index right 2 bits and get */ ^
                                                        /*      - last 4 bits of second octet   */ ^
           ]+2          /*                                      Complete second octet in R2     */ ^
           FMT{ "%%c" [2 OUT FMT}                       /*      Show it                         */ ^
        /" < < /"       /*    'e' '6' '4' 3                     Drop 4 bits and Base64          */ ^
           [3           /*    'e' '6' '4' 3 44                  Recover 3.index                 */ ^
           0x03 /" & /" /*    'e' '6' '4' 3 0                   Get last 2 bits of 3.index      */ ^
           6 /" << /"   /*    'e' '6' '4' 3 0                   Shift they left 6 bits and get  */ ^
                                                        /*      - first 2 bits of third octet   */ ^
           ]3           /*    'e' '6' '4' 3 0                   Store they in R3                */ ^
        /" < /"         /*    'e' '6' '4' 3                     Drop they                       */ ^
           ==0?         /*    IF no more indices? :     */ ^
              FMT{ "%%c" [3 OUT FMT} ;  /* Show previous 2-bits octet and QUIT */ ^
                                                        /*      ===== Fourth index =====        */ ^
           shift        /*    '6' '4' 2 'e'                     Get fourth index                */ ^
           [0           /*    '6' '4' 2 'e' "ABC..789+/"        Enter Base64                    */ ^
        /" <> /"        /*    '6' '4' 2 "ABC..789+/" 'e'        Exchange they                   */ ^
           1 dupc       /*    '6' '4' 2 "ABC..789+/" "e"        Convert char to string          */ ^
           index        /*    '6' '4' 2 "ABC..789+/" 30 1       Index position 0-63 and count   */ ^
           ==0? /" < < /" :        /* Is not valid index? :  Drop count=0 and Base64, and REPEAT */ ^
        /" < /"         /*    '6' '4' 2 "ABC..789+/" 30         Drop count                      */ ^
                                                        /*      4.index contains the last 6 bits of third octet */ ^
           ]+3          /*                                      Complete third octet in R3      */ ^
           FMT{ "%%c" [3 OUT FMT}                       /*      Show it                         */ ^
        /" < < /"       /*    '6' '4' 2                         Drop 6 bits and Base64          */ ^
           :            /* REPEAT       */ ^
        )               /* ENDWHILE     */ ^
        OUT             /* End the line */

Although it may seem complicated, the printf.exe instructions are very simple. HP calculator users can start writing printf.exe programs in minutes after understanding the differences and the programming scheme. This program could replace the base64 utility you use to decode your Base64 string ZGG01YZq3ZJLbK3Cz1nOhA (or any other). Also, the same program could be modified to also perform the task of the hexdump command, but without the spaces, just the way you like it! In the following program, the verbose comments from the first version have been removed, so you can see that the resulting program is really short:

@echo off

if "%~1" == "" echo Usage: %0 base64string & goto :EOF

printf ^
    hexa(       /* Subroutine to show a char as two hexadecimal digits */ ^
        ]9      /* Store char in R9       */ ^
        FMT{ "%%0.2x" [9 OUT FMT}     /* Show it with the proper format */ ^
        ^<      /* Drop it                */ ^
        )       /* End of hexa subroutine */ ^
    "\n" "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ]0 "%~1" getc1 ( ==0? ; ^
    /* First index:  */ /" shift [0 <> 1 dupc index ==0? < < : < 2 << ]1 < < ==0? [1 hexa ; /" ^
    /* Second index: */ /" shift [0 <> 1 dupc index ==0? < < : < ]2 4 >> ]+1 [1 hexa < < [2 0x0F & 4 << ]2 < ==0? [2 hexa ; /" ^
    /* Third index:  */ /" shift [0 <> 1 dupc index ==0? < < : < ]3 2 >> ]+2 [2 hexa < < [3 0x03 & 6 << ]3 < ==0? [3 hexa ; /" ^
    /* Fourth index: */ /" shift [0 <> 1 dupc index ==0? < < : < ]+3 [3 hexa < < : ) OUT /"

If you store this program in Base64Decode.bat file, for example, then you can get your result this way:

for /F %%a in ('Base64Decode.bat ZGG01YZq3ZJLbK3Cz1nOhA') do set "readValue1=%%a"
echo %readValue1%

Output:

6461b4d5866add924b6cadc2cf59ce8400

You can download the printf.exe package from this link

Aacini
  • 65,180
  • 12
  • 72
  • 108