2010-06-02 10 views
5

Ich versuche, eine Arbeit in Bash-Scripting zu erreichen. Ich habe eine Zeichenfolge, die ich mit meinem Schlüssel XOR machen möchte.bitweise XOR eine Zeichenfolge in Bash

#!/bin/sh 
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH 

teststring="abcdefghijklmnopqr" 

Nun wie XOR den Wert von testring und speichern Sie es in einer Variablen mit bash?

Jede Hilfe wird geschätzt.

Grundsätzlich versuche ich das Ergebnis von follwing VB Script zu kopieren:

Function XOREncryption(CodeKey, DataIn) 

Dim lonDataPtr 
Dim strDataOut 
Dim temp 
Dim tempstring 
Dim intXOrValue1 
Dim intXOrValue2 


For lonDataPtr = 1 To Len(DataIn) Step 1 
    'The first value to be XOr-ed comes from the data to be encrypted 
    intXOrValue1 = Asc(Mid(DataIn, lonDataPtr, 1)) 
    'The second value comes from the code key 
    intXOrValue2 = Asc(Mid(CodeKey, ((lonDataPtr Mod Len(CodeKey)) + 1), 1)) 

    temp = (intXOrValue1 Xor intXOrValue2) 
    tempstring = Hex(temp) 
    If Len(tempstring) = 1 Then tempstring = "0" & tempstring 

    strDataOut = strDataOut + tempstring 
Next 
XOREncryption = strDataOut 
End Function 
+0

Wäre es nicht einfach "teststring =" abcdefghijklmnopqr "^ key"? –

+0

das dosen; t Arbeit – ricky2002

+0

vielleicht, wenn es eine Möglichkeit gibt, den Wert von testring in Perl von Bash-Skript übergeben und XOR es dort. – ricky2002

Antwort

0

bitweise Exklusiv-Oder in BASH beiden Operanden erfordert numerisch zu sein. Da es keine integrierte Möglichkeit gibt, den Ordinalwert (ASCII) eines Zeichens in bash zu ermitteln, müssen Sie, sagen wir, Perl verwenden, um diesen Wert zu erhalten.

Bearbeiten: wie unten erwähnt, funktioniert ord nur auf das erste Zeichen einer Zeichenfolge.

let a=`perl -e 'print ord $_ for split //, $ARGV[0]' string`^123; echo $a 

Natürlich, wenn Sie in Perl sind, dann könnten Sie auch alles tun es:

let a=`perl -e '$ordinal .= ord $_ for split //, $ARGV[0]; print $ordinal^$ARGV[1]' string 123` 

bearbeiten: es stellt mich heraus Sie den Ordnungswert eine Zeichenfolge greifen in BASH mit printf. Einfach die Zeichenfolge mit ' voranstellen.

printf "%d" "'string" 

in BASH also nur:

let a=$(printf "%d" "'string")^123; echo $a 
+0

Ich habe so etwas in bash, aber es zeigt 0 als Ausgabe ... username = 'whoami' test = 'perl -e 'drucke ord $ strUrl^key'' echo $ {test} mache ich einen Fehler? – ricky2002

+0

Sie müssen den' Perl'-Befehl entweder in Backticks oder $() einfügen $ strUrl' ist undefiniert, und 'key' ist ein Bareword. –

+0

Ist das die richtige Art, es zu tun? Ich bekomme eine zweistellige Zahl als Ausgabe, aber ich erwartete eine lange Zahl ber. key = secret StrUrl = cdcdcdc StrUrl = $ (($ (printf "% d" " 'StrUrl")^$ (printf "% d" "' key"))); echo $ StrUrl – ricky2002

1

Wenn Sie Perl Einzeiler gehen zu entscheiden, hier ist das, was ich mit

perl -e '@a=split("", $ARGV[0]); @b=split("", $ARGV[1]); print unpack "H2", chr(ord(shift @a)^ord(shift @b)) while @a; print "\n"' aab aaa 

in Perl Zip-Funktion kam 6 würde einen besseren Job machen ...

4

Mit Hilfe von these hints schrieb ich dieses Skript schnell Pedro Antwort zu vervollständigen:

#!/bin/bash 

function ascii2dec 
{ 
    RES="" 
    for i in `echo $1 | sed "s/./& /g"` 
    do 
    RES="$RES `printf \"%d\" \"'$i\"`" 
    done 
    echo $RES 
} 

function dec2ascii 
{ 
    RES="" 
    for i in $* 
    do 
    RES="$RES`printf \\\\$(printf '%03o' $i)`" 
    done 
    echo $RES 
} 

function xor 
{ 
    KEY=$1 
    shift 
    RES="" 
    for i in $* 
    do 
    RES="$RES $(($i ^$KEY))" 
    done 

    echo $RES 
} 


KEY=127 
TESTSTRING="abcdefghijklmnopqr" 

echo "Original String: $TESTSTRING" 
STR_DATA=`ascii2dec "$TESTSTRING"` 
echo "Original String Data: $STR_DATA" 
XORED_DATA=`xor $KEY $STR_DATA` 
echo "XOR-ed Data: $XORED_DATA" 
RESTORED_DATA=`xor $KEY $XORED_DATA` 
echo "Restored Data: $RESTORED_DATA" 
RESTORED_STR=`dec2ascii $RESTORED_DATA` 
echo "Restored String: $RESTORED_STR" 

Ergebnis:

iMac:Desktop fer$ bash test.sh 
Original String: abcdefghijklmnopqr 
Original String Data: 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 
XOR-ed Data: 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 
Restored Data: 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 
Restored String: abcdefghijklmnopqr 
+0

Dies ist XORing mit einem Schlüssel von nur einem Byte. –

0

Woks in busybox (die Paste nicht zwei Ströme erhalten könnte), auch gemacht der Schlüssel zu wiederholen

#!/bin/sh 
numitems() { i=0;while read ITEM; do i=$(($i + 1)) ; done; echo $i; } 
starmap() { while read ITEM; do $1 $ITEM; done; } 
ord() { printf '%d\n' "'$1"; } 
chr() { printf \\$(printf '%03o' $1); } 
split_chars() { echo -n "$1" | sed 's/./&\n/g'; } 
xor() { echo $(($1^$2)); } 
map_ord() { split_chars "$1" | starmap ord; } 
encrypt() 
{ 
KEY=$1;STR=$2; 
while [ ${#KEY} -lt ${#STR} ]; do KEY="$KEY$KEY"; done; #make key longer then str 
[ -e /tmp/paste_col1 ] && rm -rf /tmp/paste_col1 
[ -e /tmp/paste_col1t ] && rm -rf /tmp/paste_col1t 
[ -e /tmp/paste_col2 ] && rm -rf /tmp/paste_col2 
map_ord "$KEY">/tmp/paste_col1t 
map_ord "$STR">/tmp/paste_col2 
head -n `wc -l /tmp/paste_col2 |sed -r 's|^([0-9]+)\s.*|\1|'` /tmp/paste_col1t>/tmp/paste_col1 #trim lines 
[ -e /tmp/paste_col1t ] && rm -rf /tmp/paste_col1t 
paste /tmp/paste_col1 /tmp/paste_col2 | starmap xor | starmap chr 
[ -e /tmp/paste_col1 ] && rm -rf /tmp/paste_col1 
[ -e /tmp/paste_col2 ] && rm -rf /tmp/paste_col2 
echo 
} 
KEY="12345678" 
TESTSTRING="abcdefghasdfasdfasfdas" 
encrypt "$KEY" "$TESTSTRING" 
ENC="`encrypt \"$KEY\" \"$TESTSTRING\"`" 
encrypt "$KEY" "$ENC" # we should get $TESTSTRING again 
+0

Die Ausgabe könnte ein beliebiger Byte-Wert sein, 'chr', der Steuerzeichen erzeugt, ist keine gute Idee. Deshalb verwendet der Code in der Frage "Hex" für die Ausgabe. –

1

noch eine andere Antwort

function xenc { 
    local data=$1 key=$2 
    local _data _key ndata nkey count i _res 
    _data=($(eval printf "'%d '" $(printf "%s" "$data" | sed -e '$!N;${s/./"'"'"'&" /g;s/""/\\&/g}'))) 
    _key=($(eval printf "'%d '" $(printf "%s" "$key" | sed '$!N;${s/./"'"'"'&" /g;s/""/\\&/g}'))) 
    ndata=${#_data[@]} nkey=${#_key[@]} 
    ((count = ndata < nkey ? nkey : ndata)) 
    for ((i = 0; i < count; i++)); do 
    ((_res[i] = ${_data[i]:-0}^${_key[i%nkey]:-0})) 
    done 
    printf "\\\\\\%o" "${_res[@]}" | xargs printf 
} 
res=$(xenc abcdefghijklmnopqrstuvwxyz FLqFb8LU0TY) 
xenc "$res" FLqFb8LU0TY 
+0

Sie können eine Schleife verwenden 'data = abcdef; für ((i = 0; i <$ {# Daten}; i ++)); printf '% d' "'$ {data: i: 1}"; done ', um das komplexe Konstrukt mit eval zu vermeiden und einen externen Befehl 'sed' aufzurufen. –

+0

Da es sehr gut möglich ist, Steuerzeichen mit dem Xor auszugeben, ist es sinnvoll, das kodierte Ergebnis als hexadezimale Ziffern darzustellen (als Frageanforderung). –

+0

@JosEduSol Tatsächlich ist dies eine vernünftige Lösung für die gestellte Frage: Ein Bash-Skript, das zwei Strings (als ASCII-Werte) enthält. Zu diesem Zweck ändern Sie "printf" \\\\\\\\\\\\ "$ {_ res [@]}" | xargs printf' zum einfacheren 'printf '% 02x'" $ {_ res [@]} "' –

0

Die ähnlichsten Transformation nur die Funktion zu bash wäre:
(# bedeutet Kommentar):

# Function XOREncryption(CodeKey, DataIn) 
XOREncryption(){ 
    local CodeKey=$1 
    local DataIn=$2 
    # Dim lonDataPtr strDataOut temp tempstring intXOrValue1 intXOrValue2 
    local lonDataPtr strDataOut temp tempstring intXOrValue1 intXOrValue2 

    # For lonDataPtr = 1 To Len(DataIn) Step 1 
    for ((lonDataPtr=0; lonDataPtr < ${#DataIn}; lonDataPtr++)); do 
     #The first value to be XOr-ed comes from the data to be encrypted 
    # intXOrValue1 = Asc(Mid(DataIn, lonDataPtr, 1)) 
    intXOrValue1=$(toAsc "${DataIn:$lonDataPtr:1}") 
    echo "val1=$intXOrValue1 and=<${DataIn:$lonDataPtr:1}> and $(toAsc "${DataIn:$lonDataPtr:1}")" 
     #The second value comes from the code key 
    echo "Ptr=$lonDataPtr Mod=<$((lonDataPtr % ${#CodeKey}))>" 
    # intXOrValue2 = Asc(Mid(CodeKey, ((lonDataPtr Mod Len(CodeKey)) + 1), 1)) 
    intXOrValue2=$(toAsc "${CodeKey:$((lonDataPtr % ${#CodeKey})):1}") 
    echo "val1=$intXOrValue1 val2=<${CodeKey:$((lonDataPtr % ${#CodeKey})):1}> and |$intXOrValue2|" 
    # temp = (intXOrValue1 Xor intXOrValue2) 
    temp=$((intXOrValue1^intXOrValue2)) 
    echo "temp=$temp" 
     # tempstring = Hex(temp) 
    tempstring=$(printf '%02x' "$temp") 
    echo "tempstring=$tempstring" 
    # strDataOut = strDataOut + tempstring 
     strDataOut+=$tempstring 
    echo 
    # Next 
    done 
    # XOREncryption = strDataOut 
    printf '%s\n' "$strDataOut" 
# End Function 
} 

die Kommentare entfernen und reinigen Sie den Code:

#!/bin/bash 

Asc() { printf '%d' "'$1"; } 

XOREncryption(){ 
    local key=$1 DataIn=$2 
    local ptr DataOut val1 val2 

    for ((ptr=0; ptr < ${#DataIn}; ptr++)); do 
     val1=$(Asc "${DataIn:$ptr:1}") 
     val2=$(Asc "${key:$((ptr % ${#key})):1}") 
     DataOut+=$(printf '%02x' "$((val1^val2))") 
    done 
    printf '%s\n' "$DataOut" 
} 

CodeKey="$1" 
teststring="$2" 
XOREncryption "$CodeKey" "$teststring" 

Lauf es:

$ ./script.sh "123456789" "abcdefghijklmnopqr" 
5050505050505050505b595f595b5947494b