16進数以外の文字列として保存されたSHA-512パスワード

16進数以外の文字列として保存されたSHA-512パスワード

私はこれがあまりにも明白で、インターネットで検索しても問題に関連する結果が表示されないと思います。ルートパスワードを見ていますが、/etc/shadow次のようになります。

$6$Etg2ExUZ$F9NTP7omafhKIlqaBMqng1.....

パスワードは2番目の記号の後$に続きます。 sha512ハッシュを使用しますが、16進数で表示されません。私の質問は、通常、16進数で表されるsha512ハッシュの出力を次の文字列に変換する方法です。

F9NTP7omafhKIlqaBMqng1....

16進数以外の文字を使用しますか?

答え1

sha512(またはすべてのハッシュ)の出力は、(非常に大きい)数値をエンコードする一連のビット(この場合は512ビット)で、バイトまたは他の任意の分割に分割できます。

16進表現は、各4ビットブロックを16進数に変換し、ユーザーにハッシュ値を表す一般的な方法ですが、ハッシュ関数自体に固有のものではありません。生のバイト、10進数、または0と1で構成される長い文字列でもかまいません。著者と読者が数字をどのようにコーディングするかについて同意することが重要です。

この場合、生のバイトは機能しません。shadowこれは、ファイルがレコードを区切るために改行を使用するため、そのバイトを使用できないため、ファイルに他の奇妙な文字が含まれていると、人々が読み書きするのが難しいためです。これがあなたが見ることができるハッシュにASCIIエンコーディングが頻繁に使用される理由です。

ただし、16進数、10進数、および2進数のASCII表現はすべてかなり非効率的なメカニズムです。 16進数は元のバイトサイズ(入力4ビットから1つのASCII出力バイト)を2倍にします。短いハッシュの場合は問題になりません。 MD5は128ビット、16バイト、または32個の16進数で管理できますが、長いハッシュの場合はすぐに管理するのが難しくなる可能性があります。ただし、このような512ビットハッシュの場合、ハッシュ値にのみ128バイトが必要です。 10進数または2進数はより悪いかもしれませんが、おそらくそうではありません。非常にこの場合、誰もが同意する限り、その時間がどれだけ長く続くかが重要です。


この特定のケースでは、man 3 crypt説明する:

「salt」と「encrypted」の文字がセットから抽出されます。[a-zA-Z0-9./]

a-z(26)、A-Z(26)、0-9(10)、.(1)、/(1)には合計26 + 26 + 10 + 1 + 1 = 64文字があるため、使用できる文字は次のとおりです。64進数で表される使われているようです。つまり、各ASCIIバイトは6ビットのデータ(2 ^ 6 = 64)を表します。 base64(32ビット)の4バイトは元のデータの3バイト(24ビット)を保持するため、33%の拡張位置でのみ開始されます。 。このエンコーディングでは、512ビット値を格納するために86バイトが必要です。

Base64は、a)ASCII内で任意のバイナリデータを保存または転送する必要があり、b)誰もが音声で読み取る必要がない場合に良いデフォルトです。どちらもここにあるので、考える必要はありません。 16進表現は、大文字と小文字が重要ではなく、値がそれほど多くないため、手動でハッシュ値を読み取るか確認する必要がある場合に便利です。ほとんど使用されていませんが、標準的なものもあります。Base32エンコーディング中央(すべて大文字と数字)にありますが、ここでは使用する理由はあまりありません。


あなたは持つことができますbase64ツール一度インストールすると、両方向にこれらの変換を実行します。たとえば、cryptMIME base64エンコーディングは+andの/代わりに.andを使用します/が、ランダムな入力をやや長いASCIIエンコーディング出力に変換する方法を確認できます。しかもオンラインエンコードおよびデコードツールただし、パスワードハッシュの場合、印刷できないバイトと無効なバイトシーケンスが得られるため、あまり役に立ちません。

答え2

ハッシュの出力は文字ではなく一連のバイトです。特定のバイト値はほとんどのテキストプログラムにとって特別な意味を持つため、これらのバイトは通常何らかの方法でエンコードされます。一般的なハッシュエンコーディングは16進数で、ニブルあたり1文字(半バイト)です。他のものも可能です(また一般的です)。シャドウファイルに使用されるファイルは次のようになります。ベース64代わりに、変換文字列を使用して、ハッシュ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz出力のすべての6ビットをリストの文字に変換します。

512ビットハッシュ(64バイト)は、16進符号化の長い128文字の代わりに、Base64などの符号化の86文字(固定長)を使用します。

暗号化エンコードを実行する単純なC関数があります。これをデコードする必要はなく、次のプログラムの出力を内部の実際の値と比較するだけです/etc/shadow

ファイル:passwd-sha512.c

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  if ( argc < 3 || (int) strlen(argv[2]) > 16 ) {
    printf("usage: %s password salt\n", argv[0]);
    printf("--salt must not larger than 16 characters\n");
    return;
  }

  char salt[21];
  sprintf(salt, "$6$%s$", argv[2]);

  printf("%s\n", crypt((char*) argv[1], (char*) salt));
  return;
}

編む:

$ /usr/bin/gcc -lcrypt -o passwd-sha512 passwd-sha512.c

使用法:

$ passwd-sha512 <password> <salt (16 chars max)>

例の文字列から$6$Etg2ExUZ$F9NTP7omafhKIlqaBMqng1.....:

$ ./passwd-sha512 password Etg2ExUZ
$6$Etg2ExUZ$k01JYPOzptT0enZUP........

コマンドラインのパスワードは、他のユーザーが読むことができることを念頭に置いて、stdinまたは他のセキュリティ方法を使用するようにCコードを調整してください。

関連情報