XOR de uma variável shell e um arquivo binário

2

Eu tenho uma senha armazenada em uma variável do shell (que foi lida na entrada da linha de comando).

Eu também tenho um arquivo de chaves armazenado em um arquivo (que foi criado usando dd e /dev/urandom ).

Como eu quero exigir que ambos descriptografem meu disco rígido, eu gostaria de os XOR, armazená-los em um arquivo e usá-los como chave.

Por isso, gostaria de saber qual seria a maneira mais simples de fazer isso.

xxd seria um ajuste perfeito se permitisse -b e -p ao mesmo tempo, mas aparentemente, não ...

Editar: vou usá-lo em link

    
por xavierm02 05.05.2014 / 20:52

3 respostas

2

Seu shell pode manipular ops bit a bit, no entanto, para qualquer processamento sério, ele será terrivelmente lento e não poderá manipular nada mais do que 20 ou mais dígitos de cada vez. Ainda:

sh <<\CMD 
    printf 'printf "%%b" "\0$((%04o^04))"'  "'a" |\
    . /dev/stdin
CMD

#OUTPUT
A

Eu usei bc no passado para pegar bytes em binário, então sua pergunta me levou a pesquisar ...

Exclusive-or (XOR) para o GNU bc

If you've found your way across the internet to this question, chances are you're looking for bc's equivalent of C's ^ operator.

Disturbing fact: no such thing exists in bc. In bc, the up-arrow operator is used for integer exponentiation, that is, 2^x returns a power of 2 and not x with bit 2 flipped. If you're looking for equivalents to the bitwise operators for XOR as well as AND, OR and a few more exotic relatives, check out this site's logic.bc, and its relatives which contain functions to perform each of these.

If you're looking for a logical XOR to put in an if statement, like logical && and ||, try using != and surrounding your conditions with brackets. e.g.:

c=0;if((a==1)!=(b==2)){c=3}

Will set c to 3, if a is 1 or b is 2, but not if a is 1 and b is 2 at the same time

(Once upon a time, this was the secret to the internals of the logic.bc xor() function, but this has been superseded by a faster algorithm.)

O texto acima é da bc FAQ. A função logic.bc mencionada acima inclui a lógica bitwise que você está procurando. Pode ser encontrado aqui . Sua descrição:

A large suite of functions to perform bitwise functions such as AND, OR, NOT and XOR. Uses twos complement for negative numbers, unlike previous versions of this file, which had no support at all. Some of the functions here will use the global bitwidth variable, which itself is initialised as part of this file, to emulate byte/word sizes found in most computers. If this variable is set to zero, an infinite bitwidth is assumed. Many functions will display a warning if there is suspicion that a secondary floating point representation of a number has been generated, e.g.:

1.1111... is an SFPR of10.0000...;'

These warnings can be disabled by setting the global variable sfpr_warn to 0 (default is 1).

  • Tamanho de palavras fixas
  • Tamanho infinito de palavras
  • Comum bit a bit
  • Dois complementos
  • Mudança de bit
  • código cinza
  • 'Multiplicação'
  • Ponto flutuante
  • Ponto flutuante 'Multiplicação'
  • Código cinza + ponto flutuante
por 06.05.2014 / 07:04
1

Eu usei um binário C.

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "No argument given.\n");
        exit(1);
    }
    char *filename = argv[1];

    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        fprintf(stderr, "Could not open given file.");
        exit(1);
    }
    int c1;
    int c2;
    do {
        c1 = fgetc(stdin);
        c2 = fgetc(file);
        if (c1 == EOF) {
            while (c2 != EOF) {
                printf("%c", c2);
                c2 = fgetc(file);
            }
            break;
        } else  if (c2 == EOF) {
            while (c1 != EOF) {
                printf("%c", c1);
                c1 = fgetc(stdin);
            }
            break;
        }
        int c = c1 ^ c2;
        printf("%c", c);
    } while (true);

    exit(0);
}
    
por 06.05.2014 / 00:39
0

Eu tenho algo quase trabalhando em SH, mas é muito lento

#!/bin/sh

small_hex_to_bin() {
    hex=$1
    hex_length=${#1}
    bin=$(echo "ibase=16;obase=2;$hex" | bc)
    bin_length=$((4*$hex_length))
    bin=$(printf %0*d $bin_length $bin)
    echo $bin
}

hex_to_bin() {
    hex=$1
    hex_length=${#hex}
    for i in $(seq 1 $hex_length); do
        hex_digit=$(expr substr $hex $i 1)
        bin_digits=$(small_hex_to_bin $hex_digit)
        echo -n $bin_digits
    done
    echo ""
}

bin_to_hex() {
    bin=$1
    hex=$(echo "ibase=2;obase=10000;$bin" | bc)
    echo $hex
}

char_to_hex() {
    char=$1
    hex_lower=$(printf %x \'$char\')
    hex=$(echo $hex_lower | tr '[:lower:]' '[:upper:]')
    echo $hex
}

char_to_bin() {
    char=$1
    hex=$(char_to_hex $char)
    bin=$(small_hex_to_bin $hex)
    echo $bin
}

string_to_bin() {
    s=$1
    l=${#s}
    for i in $(seq 1 $l); do
        char=$(expr substr $s $i 1)
        bin=$(char_to_bin $char)
        echo -n $bin
    done
    echo ""
}

file_to_bin() {
    filename=$1
    hex_spaces=$(xxd -u -p $filename)
    hex=$(echo $hex_spaces | tr -d '\n' | tr -d ' ')
    bin=$(hex_to_bin $hex)
    echo $bin
}

min() {
    if [ $1 -ge $2 ]; then
        echo $2
    else
        echo $1
    fi
}

bit_xor() {
    if [ $1 -eq $2 ]; then
        echo 0
    else
        echo 1
    fi
}

xor() {
    b1=$1
    b2=$2
    l1=${#b1}
    l2=${#b2}
    l=$(min $l1 $l2)
    for i in $(seq 1 $l); do
        c1=$(expr substr $b1 $i 1)
        c2=$(expr substr $b2 $i 1)
        c=$(bit_xor $c1 $c2)
        echo -n $c
    done
    next_i=$(($l + 1))
    if [ $l -ne $l1 ]; then
        for i in $(seq $next_i $l1); do
            c1=$(expr substr $b1 $i 1)
            echo -n $c1
        done
    fi
    if [ $l -ne $l2 ]; then
        for i in $(seq $next_i $l2); do
            c2=$(expr substr $b2 $i 1)
            echo -n $c2
        done
    fi
    echo ""
}

#stdin=$(cat)
#file=$(cat $1)
#hex_to_bin $1
file_to_bin $1
    
por 06.05.2014 / 12:39