GPG는 공개 키가 주어지면 MD5 지문을 어떻게 생성합니까?

GPG는 공개 키가 주어지면 MD5 지문을 어떻게 생성합니까?

publickey.pubASCII Armor(Radix-64)로 호출되고 인코딩된 파일 내에 다음 GPG 공개 키가 저장되어 있습니다 .

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.3ia

mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
+oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
hiXZ
=K7lL
-----END PGP PUBLIC KEY BLOCK-----

다음을 입력하면:

$ gpg --with-fingerprint publickey.pub

키의 지문을 얻습니다.

키 지문 = 00 C9 21 8E D1 AB 70 37 DD 67 A2 3A 0A 6F 8D A5

이제 GPG는 어떻게 하는가? 내 말은, 사용하지 않고도 실행할 수 gpg있고 여전히 동일한 지문을 얻을 수 있는 명령이 있습니까? 예를 들어 SSH를 사용하면 공개 키가 주어지면 다음을 수행할 수 있습니다.

$ cat ~/.ssh/id_rsa.pub | awk '{print $2}' | base64 -D | md5

그러면 다음과 같은 해시가 반환됩니다.

$ ssh-keygen -l -f ~/.ssh/id_rsa.pub

공개 키의 실제 내용은 다음과 같아야 한다는 것을 알고 있습니다.

mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
+oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
hiXZ

=K7lLBase64로 인코딩된 CRC 체크섬을 참조하는 마지막 부분이 없습니다 . 하지만 다음을 입력하면:

$ echo -n "mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N
>     syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J
>     +oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR
>     tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF
>     EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3
>     p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e
>     cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF
>     hiXZ" | base64 -D | md5

다음과 같은 결과가 나타납니다.

4697e84969da935454c7f2cdc19aaf08

보시다시피 일치하지 않습니다.00 C9 21 8E...

RFC 4880 확인 ->https://www.rfc-editor.org/rfc/rfc4880#section-12.2:

V3 키의 경우 8옥텟 키 ID는
RSA 키 공개 모듈러스의 하위 64비트로 구성됩니다.


V3 키의 지문은 키 자료(공용 모듈 n, 뒤에 지수 e가 옴) 를 형성하는 MPI의 본문(2옥텟 길이는 아님)을 MD5로 해싱하여 형성됩니다 . V3 키와 MD5는 모두
더 이상 사용되지 않습니다.

V4 지문은 옥텟 0x99의 160비트 SHA-1 해시이며,
그 뒤에 2옥텟 패킷 길이가 오고 그 뒤에
버전 필드로 시작하는 전체 공개 키 패킷이 옵니다. 키 ID는 지문의 하위 64비트입니다.

명령줄 명령으로 어떻게 변환되나요?

편집 1: 나는 다음을 사용하여 이를 수행하려고 합니다 pgpdump -i.

$ pgpdump -i publickey.pub
Old: Public Key Packet(tag 6)(141 bytes)
    Ver 3 - old
    Public key creation time - Mon Apr 28 17:19:48 MSD 1997
    Valid days - 0[0 is forever]
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - d6 76 92 93 7f a0 c9 33 e2 da b3 c6 f2 8f 67 0b 3f 5f 0b 03 d1 8f 84 e7 fc bb 3f 60 c8 c3 8b 87 4b fe 0d b3 24 1b 82 47 6b 66 13 c1 95 70 ef eb c0 d0 8a 81 d7 5a c6 fd d3 8a b2 af b8 99 07 52 c2 e4 8b 4a f4 c8 2a 94 af 99 da 6b cf aa c1 9b 1c cf 09 fa 86 22 6f c9 1f db 32 7a 1e fa d8 ac fe cd 60 1d 2d 37 d6 18 ba 6d 88 0a dc 7e 84 88 ba 68 a1 97 74 1d 40 4c 0e 5e af 06 26 bb 43 7d 
    RSA e(5 bits) - 11 
Old: User ID Packet(tag 13)(41 bytes)
    User ID - Ralf S. Engelschall <[email protected]>
Old: Signature Packet(tag 2)(149 bytes)
    Ver 3 - old
    Hash material(5 bytes):
        Sig type - Generic certification of a User ID and Public Key packet(0x10).
        Creation time - Mon Apr 28 17:19:48 MSD 1997
    Key ID - 0x0E5EAF0626BB437D
    Pub alg - RSA Encrypt or Sign(pub 1)
    Hash alg - MD5(hash 1)
    Hash left 2 bytes - 29 5a 
    RSA m^d mod n(1023 bits) - 62 bf fb 8a 5c c2 1c 68 93 e1 64 b8 bc 02 e4 f9 ee 87 fd 68 78 e6 07 88 a6 30 c7 46 77 a7 4f 51 2e f0 ed 36 57 6b e9 50 fe 68 bf 49 96 dc 5d 3d 30 11 cd 9f 0c e7 45 2a a0 5f 63 32 bd b9 1a 27 e1 78 56 21 8a 5c 30 e3 53 95 64 0d de 70 b5 e5 2e 07 5a d7 eb 74 bd 6b 37 12 0f e2 d9 bd 1a ad 04 03 68 8a bb 3d e4 5d 8d d1 03 83 09 c6 e3 10 5a a9 a0 2a 7e 0c 70 39 72 7e 2c f5 85 86 25 d9 
        -> PKCS-1

모듈러스와 지수를 어떻게 추출해야 합니까? 출력의 이 부분에 대해 뭔가를 해야 할 것 같습니다.

Hash left 2 bytes - 29 5a 
RSA m^d mod n(1023 bits) - 62 bf fb 8a 5c c2 1c 68 93 e1 64 b8 bc 02 e4 f9 ee 87 fd 68 78 e6 07 88 a6 30 c7 46 77 a7 4f 51 2e f0 ed 36 57 6b e9 50 fe 68 bf 49 96 dc 5d 3d 30 11 cd 9f 0c e7 45 2a a0 5f 63 32 bd b9 1a 27 e1 78 56 21 8a 5c 30 e3 53 95 64 0d de 70 b5 e5 2e 07 5a d7 eb 74 bd 6b 37 12 0f e2 d9 bd 1a ad 04 03 68 8a bb 3d e4 5d 8d d1 03 83 09 c6 e3 10 5a a9 a0 2a 7e 0c 70 39 72 7e 2c f5 85 86 25 d9  

나는 해당 16진수의 이진 값을 에코하려고 했습니다.

29 5a(해시 왼쪽 2바이트) 다음과 연결됨: 62 bf fb 8a 5c c2 1c 68 93 e1 64 b8 bc 02 e4 f9 ee 87 fd 68 78 e6 07 88 a6 30 c7 46 77 a7 4f 51 2e f0 ed 36 57 6b e9 50 fe 68 bf 49 96 dc 5d 3d 30 11 cd 9f 0c e7 45 2a a0 5f 63 32 bd b9 1a 27 e1 78 56 21 8a 5c 30 e3 53 95 64 0d de 70 b5 e5 2e 07 5a d7 eb 74 bd 6b 37 12 0f e2 d9 bd 1a ad 04 03 68 8a bb 3d e4 5d 8d d1 03 83 09 c6 e3 10 5a a9 a0 2a 7e 0c 70 39 72 7e 2c f5 85 86 25 d9

그리고 내가 내린 명령은 다음과 같습니다.

$ echo -ne "\x29\x5a\x62\xbf\xfb\x8a\x5c\xc2\x1c\x68\x93\xe1\x64\xb8\xbc\x02\xe4\xf9\xee\x87\xfd\x68\x78\xe6\x07\x88\xa6\x30\xc7\x46\x77\xa7\x4f\x51\x2e\xf0\xed\x36\x57\x6b\xe9\x50\xfe\x68\xbf\x49\x96\xdc\x5d\x3d\x30\x11\xcd\x9f\x0c\xe7\x45\x2a\xa0\x5f\x63\x32\xbd\xb9\x1a\x27\xe1\x78\x56\x21\x8a\x5c\x30\xe3\x53\x95\x64\x0d\xde\x70\xb5\xe5\x2e\x07\x5a\xd7\xeb\x74\xbd\x6b\x37\x12\x0f\xe2\xd9\xbd\x1a\xad\x04\x03\x68\x8a\xbb\x3d\xe4\x5d\x8d\xd1\x03\x83\x09\xc6\xe3\x10\x5a\xa9\xa0\x2a\x7e\x0c\x70\x39\x72\x7e\x2c\xf5\x85\x86\x25\xd9" | md5

해당 16진수의 이진 데이터를 출력한 다음 해당 이진 데이터에 대한 MD5 해시를 계산해야 하지만, 내가 얻는 해시는 여전히 다릅니다.

6f09f2ac5c5af1c6dd3833e584387103

pgpdump내가 잘못하고 있다는 것을 알고 있지만 출력을 올바르게 해석하는 방법과 연결하고 해시해야 하는 부분에 대한 정보를 찾지 못했습니다 ...

편집하다:Jens Erat 덕분에 이 작은 "OpenPGP의 지문 괴짜"를 통해 다음과 같은 결론을 내릴 수 있습니다.

을 위한V3 키 RSA 1024비트해시된 키MD5, 지문은 다음을 기준으로 계산됩니다.129바이트로 구성된128바이트의RSA n MPI(바이트 오프셋에서 시작14(첫 번째 바이트가 오프셋에 있는 경우)1)로 내보낸 원시 OpenPGP 공개 키의 gpg --export $UID)와 연결됨1byte는 오프셋의 바이트입니다.144따라서2오프셋의 길이 바이트142그리고143, RFC 4880에 따르면.

다음 명령은 원시 GPG 데이터를 사용하여 지문을 계산합니다.

gpg --export $UID | xxd -p | tr -d '\n ' | tail \
-c +27 | cut -c -256,261-262 | sed -e 's/[0-9a-fA-F]\{2\}/\\\\x&/g' | while read TMP; do \
echo -ne $TMP; done | md5 | sed -e 's/[0-9a-f]\{2\}/ &/g' | \
awk '{print "\n MD5 fingerprint:"toupper($0)"\n"}' 

여기서 $UID는 키 보유자의 UID입니다.

OpenPGP V4 RSA 공개 키의 경우 이야기가 다릅니다.

2048비트 RSA 공개 키의 경우 원시 OpenPGP 키 데이터의 처음 272바이트를 SHA1로 해싱하여 지문을 얻습니다.

gpg --export $UID | head -c 272 | shasum | grep -Eo "[0-9a-f]+" | sed -e 's/[0-9a-f]\{4\}/ &/g' | \
awk '{print "\n RSA 2048 bit SHA1 fingerprint:"toupper($0)"\n"}'

4096비트 RSA 공개 키의 경우 원시 OpenPGP 키 데이터의 처음 528바이트를 SHA1로 해싱하여 지문을 얻습니다.

gpg --export $UID | head -c 528 | shasum | \
grep -Eo "[0-9a-f]+" | sed -e 's/[0-9a-f]\{4\}/ &/g' | \
awk '{print "\n RSA 4096 SHA1 fingerprint:"toupper($0)"\n"}'

충분할 것입니다. 아무튼 gpgsplitV4 키와 함께 사용하는 것이 휴대성이 더 좋은 것 같습니다.

답변1

OpenPGP 키의 경우 SSH만큼 쉽지 않습니다. 지문은 Base64로 인코딩된 공개 키 전체에서 계산되지 않고 일부(바이너리) 부분에서만 계산됩니다.

버전 3 OpenPGP 키의 경우 수행해야 할 작업은 다음과 같습니다.

  1. OpenPGP 공개 키 패킷 구문 분석
  2. RSA의 경우 모듈러스 및 지수 추출
  3. 이진 값을 연결합니다.
  4. 해시섬 계산

pgpdump1단계와 2단계에서는 플래그를 사용하여 숫자를 구문 분석하고 출력할 수 있는 도구를 사용할 수 있습니다 -i.

버전 4 키의 경우 더욱 복잡해집니다.

교육 목적으로 해시섬을 계산하려면 pgpdump추출된 정보에서 직접 작업할 수 있도록 확장하고 사용 가능한 모든 파서 코드를 사용하는 것이 좋습니다. 나는 순수한 쉘 코드를 사용하는 것보다 바이너리 정보를 처리하는 것이 더 쉬울 것이라고 확신합니다.

업데이트:잘못된 정수를 사용했습니다. RSA n대신 에 줄에 있는 것을 사용하십시오 RSA e. 표준 도구를 사용하여 모든 것을 몇 줄로 정리합니다.

pgpdump -i publickey.pub | \
grep -E '(RSA n|RSA e)' | \
cut -d'-' -f2 | \
tr -d "\n " | \
perl -e 'print pack "H*", <STDIN>' | \
md5sum

pgpdump -i필요하지 않은 모든 항목 grep에서 키의 MPI를 덤프하고 모든 공백을 제거하고 를 사용하여 바이너리로 변환한 다음 마지막으로 .cuttrperlmd5sum

제공된 키로 실행:

$ pgpdump -i publickey.pub | \
> grep -E '(RSA n|RSA e)' | \
> cut -d'-' -f2 | \
> tr -d "\n " | \
> perl -e 'print pack "H*", <STDIN>' | \
> md5sum
00c9218ed1ab7037dd67a23a0a6f8da5  -

우리가 찾고 있는 것이 꽤 많은 것 같습니다.

완전성을 위해 다른 툴체인이 필요한 버전 4 키에도 동일합니다. 전체 공개 키 패킷이 필요합니다. OpenPGP 메시지를 분해하는 데 gpgsplit유용합니다. 그런 다음 sha1sum파일의 값을 즉시 계산할 수 있습니다 .

gpgsplit publickey.pub; sha1sum *.public_key

예를 들어, 내 키로 실행하면 다음과 같습니다.

$ gpgsplit publickey.pub; sha1sum *.public_key
0d69e11f12bdba077b3726ab4e1f799aa4ff2279  000001-006.public_key

관련 정보