콘텐츠로 이동

지문

문서
02
상태
초안
판
v0.5
날짜
2026-10-13

지문(해시)은 파일 내용으로 계산한 64글자다. 파일이 한 글자라도 바뀌면 지문이 완전히 달라진다. 지문만 보고 내용을 알아낼 수는 없다.


  • SHA-256 (미국 표준 FIPS 180-4). 소문자 16진수 64글자로 적는다.
  • 원본 파일의 바이트 그대로 뜬다. 파일 이름, 시각, 폴더는 지문에 들어가지 않는다.
  • 원본을 열쇠로 잠근 뒤에도 지문은 잠그기 전 원본의 것이다. 잠근 파일의 지문은 「보관 지문」으로 따로 둔다(4절).
언제 어디서 manifest 칸
기록이 끝나는 순간 기기 (폰, 스캐너, 카메라) sha256_device
저장소에 도착할 때 저장소 (받으면서 바로) sha256_store
  • 둘이 다르면 저장하지 않고 기탁자에게 알린다. 오는 길에 무언가 바뀐 것이다.
  • 둘이 같으면 이 지문이 그 기록의 원본 지문이 된다.
  • 기기에서 잠근 뒤 보내면(09-열쇠 3절) 저장고는 원본을 볼 수 없다. 기기가 잠근 파일의 지문도 함께 보내고, 저장고는 그것을 보관 지문으로 맞춰 본다. 원본 지문(sha256_store)은 기기가 뜬 값을 그대로 적는다.
  • 기기에서 뜰 수 없는 경우(예: 국학진흥원에서 이미 스캔된 파일 묶음을 받을 때)에는 sha256_device를 비워 두고, 받은 파일 그대로의 지문을 첫 지문으로 삼는다. 묶음 파일(zip)의 지문도 함께 남겨, 어느 묶음에서 나왔는지 거슬러 갈 수 있게 한다. arkive가 지금 하는 방식이다.

secretary v0는 이 칸을 sha256_phone, sha256_server로 부른다. 같은 값이다(03-manifest 6절).

  • 저장소는 하루 한 번 보관 중인 파일의 지문을 다시 떠서 맞춰 본다.
  • 결과는 지우지 않는 기록으로 남긴다. 맞으면 「확인함」, 다르거나 없으면 「바뀜」·「없음」과 시각.
  • 바뀐 것이 나오면 기탁자에게 알리고, 백업에서 같은 지문의 파일을 찾아 되살린다.
  • 지금 arkive는 요청할 때만 확인하고(/api/fixity), secretary는 아직 정기 확인이 없다.

원본을 열쇠로 잠그면 관리자는 원본을 볼 수 없으니 원본 지문을 다시 뜰 수도 없다. 그래서 지문을 둘로 나눈다.

이름 무엇의 지문 누가 맞춰 보나
원본 지문 (sha256_store) 잠그기 전 원본 기탁자 (자기 기기에서 풀어서)
보관 지문 (sha256_stored) 잠근 파일 관리자 (정기 확인)

잠그지 않은 동안(secretary v0, 지금의 arkive)은 둘이 같으므로 원본 지문만 둔다.

고문서나 책은 면이 여러 장이다. 면마다 지문을 뜨고, 그 지문들을 둘씩 묶어 위로 올라가면 맨 위에 권 지문 하나가 남는다. 이것을 머클 트리라 한다.

권 지문
/ \
ㄱ+ㄴ ㄷ+ㄹ
/ \ / \
1면 2면 3면 4면
지문 지문 지문 지문
  • 한 면이라도 바뀌면 권 지문이 달라지고, 어느 면이 바뀌었는지 짚어 낼 수 있다.
  • 한 면이 그 권에 들어 있다는 것을 다른 면을 보여 주지 않고 증명할 수 있다. 위로 올라가는 길에 있는 지문 몇 개만 건네면 된다(포함 증명).

정하는 것:

  • 묶는 방법: 인증서 투명성 표준 RFC 6962 2.1절의 방식을 그대로 쓴다(RFC 9162에도 같은 정의). 잎은 SHA-256(0x00 ‖ 원본 지문 32바이트), 가지는 SHA-256(0x01 ‖ 왼쪽 ‖ 오른쪽). 홀수일 때 마지막 것을 복사해 짝을 맞추지 않는다. 복사하면 서로 다른 목록이 같은 뿌리를 갖는 구멍이 생긴다.
  • 잎은 원본 파일이다. 대부분 파일 하나가 면 하나다. arkive의 한 고문서처럼 스캔 한 장에 두 면이 들어 있으면 그 스캔 파일이 잎 하나이고, 두 면은 그 파일 안의 영역으로 가리킨다(03-manifest 4절).
  • 순서는 권 안의 면 순서(IIIF 매니페스트 순서)다. 같은 파일이 여러 면에 쓰이면 처음 나온 자리에 한 번만 넣는다.
  • 면이 더해지거나 순서가 바뀌면 새 권 지문을 만들고 옛 것은 남긴다. 판 번호를 올린다.

녹음은 지금 파일 하나가 잎 하나다. HGP 9월 규격은 말하는 사람이 바뀔 때마다 조각을 나눠 따로 지문을 뜨자고 한다(대목마다 봉인하려고). 그것은 녹음을 조각으로 나눠 저장할 때 다시 정한다.

하루 동안 생긴 기록들의 원본 지문을 같은 방법(5절)으로 묶은 뿌리 하나다.

  • 기탁자마다 따로 묶는다. 다른 사람 기록과 섞지 않는다.
  • 하루는 기록이 시작된 때의 현지 날짜, 자정 기준이다(secretary와 같음). cheroki는 새벽 4시 기준이라 다르다.
  • 순서는 시작 시각 순, 같으면 기록 번호(id) 순.
  • 닫는 때는 그날이 끝나고 48시간 뒤다. 폰이 오래 오프라인이었다가 늦게 올라온 기록이 있으면 그날의 하루 지문을 새 판으로 다시 만들고 옛 판은 남긴다.
  • 노드원 전체로는 그날 닫힌 기탁자별 하루 지문들을 다시 같은 방법으로 묶어 노드 하루 지문 하나를 만든다.

밖에 새기기(앵커): HGP 9월 규격대로 노드 하루 지문 한 줄만 밖에 새긴다. 오래 남는 곳(비트코인 시각 증명, OpenTimestamps)과 바로 확인되는 곳(공개 원장) 두 곳이다. 새기는 것은 뿌리와 시각뿐이고, 내용도 이름도 개별 지문도 나가지 않는다. 지금은 하지 않는다. 하루 지문을 만드는 것까지가 지금이고, 새기는 것은 secretary v2 때 한다.

공개 기록 하나씩 (등록부 줄, 결정 0016): 범위가 「공개」인 기록은 하나씩 공개 원장에 올릴 수 있다. 앵커가 아니라 9월 규격 HGP-0005 10절의 등록부다. 올리는 것은 판 번호, 기록 전체의 지문(RFC 8785로 적은 바이트의 SHA-256), 앞 기록의 등록부 줄 번호 셋뿐이다. 그 밖의 칸은 모두 기록 안에 둔다. 공개가 아닌 기록은 있다는 것도 드러내지 않으므로 하루 뿌리에만 들어간다. 기록 안에 비공개 값의 지문을 둘 때는 무작위 32바이트(소금)를 섞는다. 경우의 수가 적은 값(온도, 날짜)은 소금 없이는 맞혀 볼 수 있다. 지금은 provenance(실물 제품 이력)가 쓴다.

7. 지문이 증명하는 것과 못 하는 것

섹션 제목: “7. 지문이 증명하는 것과 못 하는 것”
증명한다 증명하지 못한다
처음 지문을 뜬 뒤로 파일이 바뀌지 않았다 내용이 참이다
밖에 새긴 뒤라면, 그 시각에 이미 있었다 누가 만들었다 (서명이 해야 한다, 8절)
한 면이 그 권에, 한 기록이 그날에 들어 있다 그 사람이 동의했다 (서약이 해야 한다)

HGP가 증명하는 것은 행위이지 진실이 아니다.

지문만으로는 「누가」를 증명하지 못한다. 기탁자의 열쇠로 지문에 서명해야 한다. 기탁자 서명은 Ed25519 (RFC 8032) 로 한다 (결정 0018). 서명 열쇠는 기탁자의 주인 열쇠에서 끌어내 기기 안에서만 쓴다. 서명하는 것은 원본 지문, 기록 번호, 시각이다. 열쇠가 바뀌면(되찾기, 승계) 새 공개 열쇠와 까닭을 지우지 않는 줄로 남긴다 (09-열쇠 5절). C2PA 방식(X.509 인증서)은 기관이 기탁자일 때 다시 본다. secretary v0.2(11/16)부터.

등록부 줄의 서명 (결정 0016): 공개 원장에 올리는 등록부 줄은 저장고 운영자의 지갑 열쇠(secp256k1)가 서명한다. 이것은 「저장고가 이 시각에 이 기록을 올렸다」는 서명이지, 기탁자나 만든 이의 서명이 아니다. 사람이 미리보기를 보고 하나씩 눌러 올리므로 기계 서명은 아니지만, 열쇠가 서버에 있어 약속으로 막는 것임을 적는다 (01-권한 1절 3·4번).

국제 디지털 아카이브 표준 IIIF(Presentation 3.0)는 면을 캔버스(Canvas), 권을 매니페스트(Manifest) 로 짠다. HGP의 면 지문은 캔버스 하나에, 권 지문은 매니페스트 하나에 대응한다. 그래서 arkive가 지금 만드는 IIIF 매니페스트에 각 캔버스의 원본 지문과 매니페스트의 권 지문을 붙이면, IIIF를 읽는 세계의 어떤 뷰어에서든 「이 면이 그 권의 그 원본 면」인지 확인할 수 있다. IIIF에는 지문 칸이 따로 없다. 매니페스트에 우리 칸을 바로 붙이면 IIIF 공식 검사기를 통과하지 못하므로, IIIF 3.0이 처음부터 둔 칸 두 곳에 싣는다 (결정 0009).

  • 사람이 읽는 값은 metadata에 글로. 캔버스마다 원본 지문, 매니페스트에 권 지문.
  • 기계가 읽는 값은 「지문 묶음」 파일로 따로 내고, 매니페스트의 seeAlso가 가리킨다. type: "Dataset", format: "application/json", profile: "https://hgp.hahoe.io/ns/#fixity-v1". 묶음에는 manifest, hgp:root(권 지문), hgp:root_version, method(권 지문 만든 법), 캔버스마다 canvas, hgp:sha256(원본 지문), derivation(자른 자리, 돌림, 줄인 크기)을 적는다.
  • 프로필 이름은 https://hgp.hahoe.io/ns/#fixity-v1 (08-이름표 4절, 결정 0014). 예전 임시 이름 urn:x-hgp:fixity를 대신한다.
  • 공개 이름표 주소가 생겼으므로 캔버스에는 hgp:sha256을 직접 붙여도 된다. @context에 https://hgp.hahoe.io/ns/v1.jsonld를 IIIF 주소보다 앞에 둔다. 매니페스트에 hgp:root를 붙이는 것은 여전히 검사기가 막는다 (08-이름표 3절).

주의할 점이 하나 있다. arkive의 캔버스가 화면에 그리는 것은 원본 스캔이 아니라 줄인 사본(1600픽셀)이라, 캔버스에 붙는 지문은 그 사본이 아니라 원본 스캔의 지문이고, 사본에는 「어느 원본에서 어떻게 잘라 줄였는지」가 따라붙는다. IIIF 3.0은 길이(duration)가 있는 캔버스도 허용하므로, 녹음 하나도 캔버스 하나로, 하루도 매니페스트 하나로 같은 방식에 얹을 수 있다.