シェル変数とバイナリファイルのXOR

シェル変数とバイナリファイルのXOR

シェル変数にパスワードが保存されています (これはコマンドライン入力から読み取られました)。

また、キーファイルはファイルに保存されています (これは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過去にバイナリでバイトを取得するために使用したことがあるので、あなたの質問がきっかけでグーグルで検索することにしました...

GNU bc の排他的論理和 (XOR)

インターネットでこの質問にたどり着いた場合、おそらく C の^演算子に相当する bc を探しているのでしょう。

気になる事実: にはそのようなものは存在しませんbc。 ではbc、上矢印演算子は整数の累乗に使用されます。つまり、 は2^xビット 2 を反転した x ではなく、2 の累乗を返します。 XOR のビット演算子、AND、OR、その他のいくつかの特殊な類似演算子に相当するものを探している場合は、このサイトの logic.bc と、これらを実行する関数を含む類似のファイルを確認してください。

XORif ステートメントに論理演算子&&andなどを挿入したい場合は||!=条件を括弧で囲んで and を使用してみてください。例:

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

a が 1 または b が 2 の場合は c を 3 に設定しますが、a が 1 かつ b が 2 の場合は設定しません。

(かつては、これが logic.bc xor() 関数の内部の秘密でしたが、より高速なアルゴリズムに置き換えられました。)

上記はbcFAQからの抜粋です。logic.bc上記で言及した機能には、bitwiseあなたが探しているロジックが含まれています。ここ. その説明:

実行できる機能の大規模なスイートビット単位AND、OR、NOT、XOR などの関数。このファイルの以前のバージョンではまったくサポートされていなかったのとは異なり、負の数には 2 の補数を使用します。ここでの関数の一部は、ほとんどのコンピューターで見られるバイト/ワード サイズをエミュレートするために、このファイルの一部として初期化されるグローバル ビット幅変数を使用します。この変数が 0 に設定されている場合、無限のビット幅が想定されます。多くの関数では、数値の 2 次浮動小数点表現が生成された疑いがある場合、警告が表示されます。例:

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

これらの警告は、グローバル変数sfpr_warnを に設定することで無効にできます0 (デフォルトは 1)。

  • 固定ワードサイズ
  • 無限の単語サイズ
  • 共通ビット単位
  • 2の補数
  • ビットシフト
  • グレイコード
  • '乗算'
  • 浮動小数点
  • 浮動小数点の「乗算」
  • グレイコード + 浮動小数点

答え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

関連情報