XOR de una variable de shell y un archivo binario

XOR de una variable de shell y un archivo binario

Tengo una contraseña almacenada en una variable de shell (que se leyó desde la entrada de la línea de comando).

También tengo un archivo de claves almacenado en un archivo (que se creó usando ddy /dev/urandom).

Como quiero exigir que ambos descifren mi disco duro, me gustaría realizar un XOR, almacenarlo en un archivo y usarlo como clave.

Por lo tanto, me gustaría saber cuál sería la forma más sencilla de hacerlo.

xxdencajaría perfectamente si lo permitiera -by -pal mismo tiempo, pero aparentemente no lo hace...


Editar: lo usaré enhttps://github.com/xavierm02/combine-keys

Respuesta1

Su shell puede manejar operaciones bit a bit; sin embargo, para cualquier procesamiento serio, serámuylento y no puede manejar nada más que unos 20 dígitos a la vez. Aún:

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

#OUTPUT
A

Lo he usado bcen el pasado para capturar bytes en binario, por lo que tu pregunta me hizo buscar en Google...

Exclusivo-o (XOR) para GNU bc

Si ha encontrado esta pregunta en Internet, es probable que esté buscando el equivalente de bc al ^operador de C.

Dato inquietante: no existe tal cosa en bc. En bc, el operador de flecha hacia arriba se usa para la exponenciación de números enteros, es decir, 2^xdevuelve una potencia de 2 y no x con el bit 2 invertido. Si está buscando equivalentes a los operadores bit a bit para XOR, así como AND, OR y algunos parientes más exóticos, consulte logic.bc de este sitio y sus parientes que contienen funciones para realizar cada una de estas.

Si está buscando una lógica XORpara incluir en una declaración if, como lógica &&y ||, intente usar !=y rodear sus condiciones entre corchetes. p.ej:

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

Establecerá c en 3, si a es 1 o b es 2, pero no si a es 1 y b es 2 al mismo tiempo.

(Érase una vez, este era el secreto de los aspectos internos de la función logic.bc xor(), pero ha sido reemplazado por un algoritmo más rápido).

Lo anterior es de las bcpreguntas frecuentes. La logic.bcfunción mencionada anteriormente incluye la bitwiselógica que estás buscando. se puede encontraraquí. Su descripción:

Un gran conjunto de funciones para realizarbit a bitfunciones como AND, OR, NOT y XOR. Utiliza complemento a dos para números negativos, a diferencia de las versiones anteriores de este archivo, que no tenían ningún soporte. Algunas de las funciones aquí utilizarán la variable global de ancho de bits, que a su vez se inicializa como parte de este archivo, para emular los tamaños de bytes/palabras que se encuentran en la mayoría de las computadoras. Si esta variable se establece en cero, se supone un ancho de bits infinito. Muchas funciones mostrarán una advertencia si se sospecha que se ha generado una representación secundaria de punto flotante de un número, por ejemplo:

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

Estas advertencias se pueden desactivar configurando la variable global sfpr_warnen 0 (el valor predeterminado es 1).

  • Tamaño de palabra fijo
  • Tamaño de palabra infinito
  • bit a bit común
  • complemento a dos
  • cambio de bits
  • código gris
  • 'Multiplicación'
  • Punto flotante
  • Punto flotante 'Multiplicación'
  • Código Gray + Punto flotante

Respuesta2

Usé un binario 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);
}

Respuesta3

Tengo algo que casi funciona en SH pero es demasiado 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

información relacionada