У меня есть пароль, сохраненный в переменной оболочки (которая была считана из ввода командной строки).
У меня также есть файл ключей, хранящийся в файле (который был создан с помощью dd
и /dev/urandom
).
Поскольку мне нужно, чтобы оба эти параметра использовались для расшифровки моего жесткого диска, я хотел бы применить к ним операцию XOR, сохранить результат в файле и использовать его в качестве ключа.
Поэтому мне хотелось бы узнать, как проще всего это сделать.
xxd
было бы идеально, если бы оно позволяло -b
и -p
в то же время, но, судя по всему, этого не происходит...
Редактировать: Я буду использовать это вhttps://github.com/xavierm02/combine-keys
решение1
Ваша оболочка может обрабатывать побитовые операции, однако для любой серьезной обработки это будетужасномедленно, и не может обрабатывать больше, чем 20 цифр за раз. Тем не менее:
sh <<\CMD
printf 'printf "%%b" "\\0$((%04o^04))"' "'a" |\
. /dev/stdin
CMD
#OUTPUT
A
bc
Раньше я использовал для извлечения байтов в двоичном формате, поэтому ваш вопрос побудил меня поискать в Google...
Исключающее ИЛИ (XOR) для GNU bc
Если вы нашли этот вопрос в Интернете, скорее всего, вы ищете эквивалент
^
оператора C в bc.Тревожный факт: ничего подобного не существует в
bc
. Вbc
оператор «стрелка вверх» используется для возведения в степень целых чисел, то есть2^x
возвращает степень числа 2, а не x с перевернутым битом 2. Если вы ищете эквиваленты побитовым операторам для XOR, а также AND, OR и нескольким более экзотическим родственникам, ознакомьтесь с логикой этого сайта.bc и его родственниками, которые содержат функции для выполнения каждого из них.Если вы ищете логическое выражение
XOR
для использования в операторе if, например, логическое&&
и||
, попробуйте использовать!=
скобки и заключать условия в них. Например:
c=0;if((a==1)!=(b==2)){c=3}
Устанавливает c в 3, если a равно 1 или b равно 2, но не если a равно 1 и b равно 2 одновременно
(Когда-то это был секрет внутреннего устройства функции logic.bc xor(), но теперь он заменен более быстрым алгоритмом.)
Вышеизложенное из bc
FAQ. logic.bc
Функция, упомянутая выше, включает bitwise
логику, которую вы ищете. Ее можно найтиздесь. Его описание:
Большой набор функций для выполненияпобитовыйТакие функции, как AND, OR, NOT и XOR. Использует дополнение до двух для отрицательных чисел, в отличие от предыдущих версий этого файла, которые вообще не поддерживались. Некоторые из функций здесь будут использовать глобальную переменную битовой ширины, которая сама по себе инициализируется как часть этого файла, для эмуляции размеров байт/слов, имеющихся в большинстве компьютеров. Если эта переменная установлена в ноль, предполагается бесконечная битовая ширина. Многие функции будут отображать предупреждение, если есть подозрение, что было сгенерировано вторичное представление числа с плавающей точкой, например:
1.1111... is an SFPR of
10.0000...;`Эти предупреждения можно отключить, установив глобальную переменную
sfpr_warn
на0
(по умолчанию 1).
- Фиксированный размер слова
- Бесконечный размер слова
- Обычный побитовый
- Дополнение по двум
- Сдвиг битов
- Код Грея
- «Умножение»
- Плавающая запятая
- «Умножение» с плавающей точкой
- Код Грея + Плавающая точка
решение2
Я использовал двоичный файл 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);
}
решение3
У меня что-то почти заработало в SH, но оно слишком медленное
#!/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