나는 이것이 너무 명백하고 인터넷에서 검색해도 내 문제와 관련된 결과가 표시되지 않는다고 생각합니다. 루트 비밀번호를 보고 있는데 /etc/shadow
다음과 같습니다.
$6$Etg2ExUZ$F9NTP7omafhKIlqaBMqng1.....
비밀번호는 두 번째 기호 $
다음에 나옵니다 . sha512 해시를 사용하지만 16진수로 표시되지 않습니다. 내 질문은 일반적으로 16진수로 표시되는 sha512 해시의 출력이 다음 문자열로 변환되는 방법입니다.
F9NTP7omafhKIlqaBMqng1....
16진수가 아닌 문자를 사용합니까?
답변1
sha512(또는 모든 해시)의 출력은 (매우 큰) 숫자를 인코딩하는 일련의 비트(이 경우 512비트)이며 바이트 또는 원하는 다른 분할로 나눌 수 있습니다.
16진수 표현은 각 4비트 블록을 16진수 숫자로 변환하며 사용자에게 해시 값을 나타내는 일반적인 방법이지만 해시 함수 자체에 고유한 것은 아닙니다. 원시 바이트, 10진수 또는 0과 1로 구성된 긴 문자열일 수도 있습니다. 저자와 독자가 숫자를 어떻게 코딩해야 하는지에 대해 동의하는 것이 중요합니다.
이 경우 원시 바이트는 작동하지 않습니다. shadow
파일이 레코드를 구분하기 위해 줄바꿈을 사용하므로 해당 바이트를 사용할 수 없고, 파일에 다른 이상한 문자가 포함되어 있으면 사람들이 읽거나 복사하기가 어렵기 때문입니다. 이것이 바로 여러분이 볼 수 있는 해시에 ASCII 인코딩이 자주 사용되는 이유입니다.
그러나 16진수, 10진수 및 2진수로 된 ASCII 표현은 모두 상당히 비효율적인 메커니즘입니다. 16진수는 원래 바이트 크기(입력 4비트에서 하나의 ASCII 출력 바이트)를 두 배로 늘립니다. 짧은 해시의 경우에는 문제가 되지 않습니다. MD5는 128비트, 16바이트 또는 32개의 16진수로 관리 가능하지만, 긴 해시의 경우 금방 관리하기 어려워질 수 있습니다. 그러나 이와 같은 512비트 해시의 경우 해시 값에만 128바이트가 필요합니다. 십진수나 이진수는 더 나쁠 수도 있지만 아마도 그렇지는 않을 것입니다.매우이 경우 모두가 동의하는 한 그 시간이 얼마나 오래 지속되는지가 중요합니다.
이 특정 사례의 경우,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
일단 설치되면 양방향으로 이러한 변환을 수행합니다. 예를 들어 crypt
MIME 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 코드를 조정하세요.