shell でバイナリを扱う。進数変換する。 なるべく分かりやすい単純なコードで。
コードを単純にするために決め事を使う
- hexの指定は大文字で 例 ok: 0A, FF, 1A ( ng: 0a, ff, fa )
- HEXの指定は大文字で
- ibaseを先に指定したばあいは、obaseはその進数で
- 桁数の大きいものを扱うときは、適宜 export BC_LINE_LENGTH="100000000000"などとする。そうしないとbcが勝手に適当に改行を入れる。
10進数 > 2進数の文字列
num=123
echo "obase=2;ibase=10;$num" | bc
2進数の文字列 > 10進数
bits="1010"
echo "obase=10;ibase=2;$bits" | bc
10進数 > 16進数の文字列
num=123
echo "obase=16;ibase=10;$num" | bc
16進数の文字列 > 10進数
hex="FF"
echo "obase=10;ibase=16;$hex" | bc
2進数の文字列 > 16進数の文字列
bits="1010"
echo "obase=16;ibase=2;$bits" | bc
16進数の文字列 > 2進数の文字列
hex="0A"
echo "obase=2;ibase=16;$hex" | bc
- バイナリをパイプに通すときは注意。不安ならファイルに落とすこと。
16進数の文字列(1バイト) > バイナリ
hex="A0"
printf "%b" "\x$hex"
#確認 printf "%b" "\x$hex" | od -tx1
10進数(256未満) > バイナリ
num="200"
printf "%b" "\x$(echo "obase=16;ibase=10;$num" | bc)"
#確認 printf "%b" "\x$(echo "obase=16;ibase=10;$num" | bc)" | od -tx1
fff > 0fff 16進数の文字列をバイト単位になるように0埋め
hex="aaa"
length_of_hex=${#hex}
if test $(expr $length_of_hex % 2 ) -eq 0
then
printf "$hex"
else
printf "0$hex"
fi
#if test $(expr $length_of_hex % 2 ) -eq 0; then printf "$hex"; else printf "0$hex"; fi
バイト数指定
hex=FFF
size=4
hex_padded=$(printf "%0"$( expr $size "*" 2)"s" $hex)
(
for byte in $(echo $hex_padded | fold -w2 -b)
do
printf "%b" "\x$byte"
done
)
#| od -tx1
可変長 (最短のバイト数)
- 「16進数の文字列をバイト単位になるように0埋め」及び上の「バイト数指定」の後半部分をfunctionにして使う。
function hex_string_padding ()
{
(
hex="$1"
length_of_hex=${#hex}
if test $(expr $length_of_hex % 2 ) -eq 0; then printf "$hex"; else printf "0$hex"; fi
)
}
function print_bin_padded_hex ()
{
(
hex_padded="$1"
for byte in $(echo $hex_padded | fold -w2 -b); do printf "%b" "\x$byte"; done
)
}
hex=FFF
hex_padded=$(hex_string_padding $hex)
print_bin_padded_hex $hex_padded
- バイナリをパイプに通すときは注意。不安ならファイルに落とすこと。
バイナリファイルから、頭、バイト数を指定して切り出し、16進数文字列へ (ネットワークバイトオーダー (何もしないで順番に) )
file_bin=/tmp/binfile
head=0
size=4
cat $file_bin | dd bs=1 skip=$head count=$size | od -An -tx1 | tr -d "\n "| dd conv=ucase
バイナリファイルから、頭、バイト数を指定して切り出し、10進数へ (ネットワークバイトオーダー (何もしないで順番に) )
file_bin=/tmp/binfile
head=0
size=4
hex=$(cat $file_bin | dd bs=1 skip=$head count=$size | od -An -tx1 | tr -d "\n "| dd conv=ucase)
echo "obase=10;ibase=16;$hex" | bc
バイナリ読み込み ssh-rsa の公開鍵を分解する。
- 「バイナリファイルから、頭、バイト数を指定して切り出し、10進数へ」をfunctionにして使う。
(
SSH_RSA_PUB_KEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNckEuuAeiPesx99s/ivWoXQGdJIMKRl0I0HiSLMCdK/dUrXy5ycyy51cEtv0t/AGQCkAxqiYBCWiVhLV/1qpZuONL9UT8cTa4TO749lFVaucxLNN7nvUtbtA4InKqRjsjqK27vCzyWxiMVIMX0jNpD0rPCwkTK2Ja6knCRN7kA2c3UyNmX4IoQ0xqT0vaUNuxtOe9SkmT3DLizDMbYByzJWVgotbZfOu1QbbClpLt/TbDd5l3fcGNsRzT8Cnd8zdvXk5ZsiUDKKhynvA4Tt/LN9LjZgxTyoEYJewYzf51E8gH057A9zXguBTTAiHMgD8xgeGzh4AVEEFJ1ZO6oCft [email protected]"
function hex_from_bin_file()
{
(
file_bin="$1"
head="$2"
size="$3"
hex=$(cat $file_bin | dd bs=1 skip=$head count=$size | od -An -tx1 | tr -d "\n "| dd conv=ucase)
export BC_LINE_LENGTH="100000000000"
echo $hex
) 2>/dev/null
}
function num_from_bin_file()
{
(
file_bin="$1"
head="$2"
size="$3"
hex=$(cat $file_bin | dd bs=1 skip=$head count=$size | od -An -tx1 | tr -d "\n "| dd conv=ucase)
export BC_LINE_LENGTH="100000000000"
echo "obase=10;ibase=16;$hex" | bc
) 2>/dev/null
}
file_bin=$(mktemp -t convrsa)
echo $SSH_RSA_PUB_KEY | cut -d" " -f2 | base64 -D >>$file_bin
head=0
length=$(num_from_bin_file $file_bin $head 4)
head=$(expr 4 + $head)
value_string=$(cat $file_bin | dd bs=1 skip=$head count=$length 2>/dev/null)
head=$(expr $length + $head)
echo "type:"
echo "length : $length bytes"
echo $value_string
length=$(num_from_bin_file $file_bin $head 4)
head=$(expr 4 + $head)
value_num=$(num_from_bin_file $file_bin $head $length)
head=$(expr $length + $head)
echo "e:"
echo "length : $length bytes"
echo $value_num
length=$(num_from_bin_file $file_bin $head 4)
head=$(expr 4 + $head)
value_hex=$(hex_from_bin_file $file_bin $head $length)
value_num=$(num_from_bin_file $file_bin $head $length)
head=$(expr $length + $head)
echo "n:"
echo "length : $length bytes"
echo $value_num
echo "-"
echo $value_hex
)
test