Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 740 – 디지털 증명에 대한 색인 지원

Author:
William Woodruff <william at yossarian.net>, Facundo Tuesca <facundo.tuesca at trailofbits.com>, Dustin Ingram <di at python.org>
Sponsor:
Donald Stufft <donald at stufft.io>
PEP-Delegate:
Donald Stufft <donald at stufft.io>
Discussions-To:
Discourse thread
Status:
Final
Type:
Standards Track
Topic:
Packaging
Created:
08-Jan-2024
Post-History:
02-Jan-2024, 29-Jan-2024
Resolution:
17-Jul-2024

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

Important

This PEP is a historical document. The up-to-date, canonical spec, Index hosted attestations, is maintained on the PyPA specs page.

×

See the PyPA specification update process for how to propose changes.

Important

This PEP is a historical document. The up-to-date, canonical documentation can now be found at PyPI - Digital Attestations.

×

See PEP 1 for how to propose changes.

초록

이 PEP는 PyPI와 같은 Python 패키지 저장소에서 디지털 서명된 증명과 이를 검증하는 데 사용하는 메타데이터를 업로드하고 배포하는 일과 관련된 일련의 변경 사항을 제안합니다.

이러한 변경 사항은 두 가지 하위 구성 요소로 이루어집니다.

  • 현재 표준화되지 않은 PyPI 업로드 API를 변경하여, 클라이언트가 디지털 증명을 증명 객체로 업로드할 수 있게 합니다.
  • HTML 및 JSON “simple” API를 변경하여, 클라이언트가 개별 릴리스 파일에 대한 디지털 증명과 Trusted Publishing 메타데이터를 모두 출처 객체로 가져올 수 있게 합니다.

이 PEP는 릴리스 업로드 시 디지털 증명을 의무화하는 것이나 pip 같은 설치 클라이언트가 이후에 이를 검증하는 것에 관한 정책 권고를 하지 않습니다.

근거와 동기

Python 패키지에 디지털 서명이 필요하다는 요구는 패키지 유지 관리자와 다운스트림 사용자 모두에게서 반복적으로 제기되어 왔습니다.

  • 유지 관리자는 자신이 업로드한 패키지의 무결성과 진본성을 입증하기를 원합니다.
  • 개별 다운스트림 사용자는 색인의 정직성을 추가로 신뢰하지 않고도 패키지의 무결성과 진본성을 검증하기를 원합니다.
  • (운영 체제 배포판과 같은) “대량” 다운스트림 사용자는 유사한 검증을 수행하고, 경우에 따라 자체 다운스트림 패키징 생태계를 위해 이를 다시 공개하거나 연서명하기를 원합니다.

이 제안은 위의 각 사용 사례를 모두 수용하고자 합니다.

또한 이 제안은 다음과 같은 동기를 제시합니다.

  • Python 패키지 배포물에 대한 검증 가능한 출처: 현재 많은 Python 패키지에는 소스 호스트의 URL과 같은 인증되지 않은 출처 메타데이터가 포함되어 있습니다. 암호학적 증명 형식을 사용하면 이러한 패키지와 소스 호스트 사이에 강력한 인증된 연결을 만들 수 있으며, 이를 통해 색인과 다운스트림 사용자 모두 패키지가 주장하는 소스 저장소에서 비롯되었는지 암호학적으로 검증할 수 있습니다.
  • 공격자 요구 조건 상향: Python 패키지를 탈취하려는 공격자는 정교함(미숙함부터 정교함까지)과 표적성(기회주의적 공격부터 표적 공격까지)이라는 차원으로 설명할 수 있습니다.

    디지털 증명은 추가적인 정교함을 요구합니다. 공격자는 비공개 서명 자료(또는 서명 신원)에 접근할 수 있을 만큼 충분히 정교해야 합니다.

  • 색인 검증 가능성: 현재 색인이 제공하는 유일한 증명은 릴리스 파일마다 선택적으로 제공되는 PGP 서명입니다(PGP 서명 참조). 색인에는 서명에 맞는 공개 키를 식별하는 메커니즘이 없으므로, 색인은 이러한 서명의 형식이 올바른지나 서명이 유효한지를 검사하지 않으며, 검사할 수도 없습니다. 이 PEP는 색인이 증명의 유효성을 검증하는 데 필요한 모든 메타데이터가 출처 객체에 포함되도록 보장함으로써 이 한계를 극복합니다.

이 PEP는 서명 생성을 위한 증명 문을 포함하는 범용 증명 형식을 제안하며, 색인 제공자가 Trusted Publishing과 같이 서명 검증에 적합한 신원 출처와 함께 이 형식을 채택하기를 기대합니다.

설계 시 고려 사항

이 PEP는 자체적으로 제안하는 변경 사항과, Python 패키징의 동일하거나 인접한 영역에서 이루어진 이전 작업을 평가할 때 다음과 같은 설계 고려 사항을 제시합니다.

  1. 색인 접근성: Python 패키지에 대한 디지털 증명은 “분리된” 리소스로서 색인 자체에서 직접 가져올 수 있는 것이 이상적입니다.

    이렇게 하면 (배포 형식 자체를 수정할 필요가 없어지므로) 일부 호환성 문제가 단순해지고, (스트리밍 압축 해제를 하지 않고도 각 증명을 해당 패키지보다 먼저 가져올 수 있으므로) 잠재적인 설치 클라이언트의 동작도 단순해집니다.

  2. 색인 자체에 의한 검증: 설치 클라이언트가 검증할 수 있게 하는 것에 더해, 각 디지털 증명은 이상적으로는 색인 자체에서도 어떤 형태로든 검증할 수 있어야 합니다.

    이렇게 하면 색인에 업로드되는 증명의 전반적인 품질이 높아지고(예를 들어 사용자가 실수로 잘못되었거나 유효하지 않은 증명을 업로드하는 것을 방지합니다), 색인 자체의 UI 및 UX 개선(업로드된 각 패키지에 대한 “출처” 보기 등)도 가능해집니다.

  3. 일반 적용성: 디지털 증명은 형식(sdist 또는 wheel)이나 내부 내용과 관계없이 색인에 업로드되는 모든 패키지에 적용할 수 있어야 합니다.
  4. 메타데이터 지원: 이 PEP는 암호학적 봉투 안에 추가 메타데이터가 존재하는 것이 이상적이라는 점을 강조하기 위해 단순히 “디지털 서명”이 아니라 “디지털 증명”이라는 용어를 사용합니다.

    예를 들어, 배포물의 이름과 내용 사이의 도메인 분리를 방지하기 위해, 이 PEP는 in-toto 프로젝트의 ‘Statements’를 사용하여 배포물의 내용을 (SHA-256 다이제스트를 통해) 파일 이름에 결합합니다.

이전 작업

PGP 서명

PyPI를 비롯한 여러 색인은 전통적으로 업로드된 배포 파일에 대한 PGP 서명을 지원해 왔습니다. 이러한 서명은 업로드할 때 함께 제공할 수 있었습니다. 설치 클라이언트는 PEP 503 API의 data-gpg-sig 속성, PEP 691 API의 gpg-sig 키, 또는 같은 위치에 있는 .asc 접미사가 붙은 URL을 통해 이 서명을 가져올 수 있었습니다.

한 조사에서 대다수의 서명을 공개 키와 연결하거나 달리 의미 있게 검증할 수 없다는 사실이 밝혀졌습니다. 이러한 서명 자체도 전체 업로드 중 극히 적은 비율에 불과했습니다. 이에 따라 PyPI에서는 2023년 5월부터 PGP 서명 업로드가 비활성화되었습니다.

이전에 PyPI에서 지원되던 형태의 PGP 서명은 위의 고려 사항 (1)과 (3)은 충족했지만 (2)와 (4)는 충족하지 못했습니다. (2)를 충족하지 못한 것은 외부 키 서버와 키 배포가 필요했기 때문입니다. (4)를 충족하지 못한 것은 PGP 서명이 일반적으로 서명된 관련 메타데이터 없이 입력 파일만을 대상으로 만들어졌기 때문입니다.

휠 서명

PEP 427(및 현재 유지되는 PyPA 대응 문서)는 휠 형식을 명시합니다.

이 형식은 휠에 직접 내장되는 디지털 서명을 JWS 또는 S/MIME 형식으로 지원합니다. 이러한 서명은 PEP 376 RECORD를 대상으로 명시됩니다. 이 RECORD는 휠에 기록된 각 파일의 암호학적 다이제스트를 포함하도록 수정됩니다.

휠 서명은 완전히 명시되어 있지만 널리 사용되지는 않는 것으로 보입니다. 공식 wheel 도구는 2018년에 릴리스된 0.32.0 버전에서 서명 생성 및 검증 지원을 폐기했습니다.

또한 휠 서명은 위의 고려 사항 중 어느 것도 충족하지 못합니다. 서명이 “첨부된” 방식이고, 색인 자체에서 검증할 수 없으며, 휠만 지원하기 때문입니다.

명세

업로드 엔드포인트 변경 사항

현재 업로드 API는 표준화되어 있지 않습니다. 그러나 이 API에 대해 다음과 같은 변경을 제안합니다.

  • 현재의 최상위 content 및 gpg_signature 필드에 더해, 색인은 attestations를 추가 multipart 폼 필드로 반드시 받아들여야 합니다.
  • 새로운 attestations 필드는 반드시 JSON 배열이어야 합니다.
  • attestations 배열은 반드시 하나 이상의 항목을 가져야 합니다. 각 항목은 개별 증명을 나타내는 JSON 객체입니다.
  • 각 증명 객체는 반드시 색인이 검증할 수 있는 것이어야 합니다. 색인이 attestations의 증명 중 하나라도 검증하지 못하면 색인은 반드시 업로드를 거부해야 합니다. 증명 객체의 형식은 증명 객체에서 정의하고, 증명을 검증하는 절차는 증명 검증에서 정의합니다.

색인 변경 사항

Simple 색인

simple 저장소 API에 다음과 같은 변경이 이루어집니다.

  • 업로드된 파일에 증명이 하나 이상 있으면, 색인은 해당 배포 파일과 연관된 증명을 담은 출처 파일을 제공할 수 있습니다. 출처 파일의 형식은 반드시 JSON으로 인코딩된 출처 객체여야 합니다. 이 객체는 반드시 파일의 증명을 포함해야 합니다.

    색인은 data-provenance 속성을 통해 출처 파일의 위치를 알립니다.

  • 출처 파일이 있으면 색인은 파일 링크에 data-provenance 속성을 포함할 수 있습니다. data-provenance 속성의 값은 반드시 완전한 URL이어야 합니다. 이 값은 해당 URL에서 파일의 출처를 찾을 수 있음을 알립니다. 이 URL은 반드시 보안 오리진을 나타내야 합니다.

    다음 표는 릴리스 파일 URL, data-provenance 값, 그리고 그에 따라 결정되는 출처 파일 URL의 예를 보여 줍니다.

    파일 URL data-provenance 프로비넌스 URL
    https://example.com/sampleproject-1.2.3.tar.gz https://example.com/sampleproject-1.2.3.tar.gz.provenance https://example.com/sampleproject-1.2.3.tar.gz.provenance
    https://example.com/sampleproject-1.2.3.tar.gz https://other.example.com/sampleproject-1.2.3.tar.gz/provenance https://other.example.com/sampleproject-1.2.3.tar.gz/provenance
    https://example.com/sampleproject-1.2.3.tar.gz ../relative (유효하지 않음: 완전한 URL이 아님)
    https://example.com/sampleproject-1.2.3.tar.gz http://unencrypted.example.com/provenance (유효하지 않음: 안전한 출처가 아님)
  • 색인은 프로비넌스 파일을 수정하기로 선택할 수 있습니다(MAY). 예를 들어, 색인은 서드파티 감사 기관이나 다른 서비스의 증명 같은 추가 증명과 검증 자료를 덧붙이도록 허용할 수 있습니다(MAY).

    파일의 프로비넌스가 변경될 수 있는 이유에 대한 추가 논의는 프로비넌스 객체의 변경 항목을 참조하십시오.

JSON 기반 Simple API

JSON simple API에 다음과 같은 변경 사항이 적용됩니다:

  • 업로드된 파일에 증명이 하나 이상 있으면, 색인은 해당 파일의 file 딕셔너리에 provenance 키를 포함할 수 있습니다(MAY).

    provenance 키의 값은 JSON 문자열이거나 null이어야 합니다(SHALL). provenance가 null이 아니면, 그 값은 연관된 프로비넌스 파일을 가리키는 URL이어야 합니다(SHALL).

    전체 프로비넌스 객체 대신 SHA-256 다이제스트를 JSON API에 포함하기로 한 기술적 결정에 대한 설명은 부록 3: 단순 JSON API 크기 고려 사항 항목을 참조하십시오.

이러한 변경 사항을 적용하려면 JSON API의 버전을 변경해야 합니다:

  • api-version은 버전 1.3 이상을 지정해야 합니다(SHALL).

증명 객체

증명 객체는 여러 개의 필수 키를 가진 JSON 객체입니다. 명시적으로 나열된 키가 모두 제공되기만 하면 애플리케이션이나 서명자는 추가 키를 포함할 수 있습니다. 증명 객체의 필수 구조는 아래에 의사 코드로 제공됩니다.

@dataclass
class Attestation:
    version: Literal[1]
    """
    The attestation object's version, which is always 1.
    """

    verification_material: VerificationMaterial
    """
    Cryptographic materials used to verify `envelope`.
    """

    envelope: Envelope
    """
    The enveloped attestation statement and signature.
    """


@dataclass
class Envelope:
    statement: bytes
    """
    The attestation statement.

    This is represented as opaque bytes on the wire (encoded as base64),
    but it MUST be an JSON in-toto v1 Statement.
    """

    signature: bytes
    """
    A signature for the above statement, encoded as base64.
    """

@dataclass
class VerificationMaterial:
    certificate: str
    """
    The signing certificate, as `base64(DER(cert))`.
    """

    transparency_entries: list[object]
    """
    One or more transparency log entries for this attestation's signature
    and certificate.
    """

transparency_entries에 있는 각 객체의 전체 데이터 모델은 부록 2: 투명성 로그 항목의 데이터 모델 항목에 제공됩니다. 증명 객체는 하나 이상의 투명성 로그 항목을 포함하는 것이 좋으며(SHOULD), 서명된 시간의 다른 출처(예: RFC 3161 타임스탬프 기관(Time Stamping Authority)이나 Roughtime 서버)를 위한 추가 키를 포함할 수 있습니다(MAY).

증명 객체에는 버전이 있으며, 이 PEP는 버전 1을 규정합니다. 불필요한 암호 민첩성을 최소화하기 위해 각 버전은 단일 암호 스위트에 묶입니다. 버전 1의 스위트는 다음과 같습니다:

  • 인증서는 X.509 인증서로 규정되며, RFC 5280의 프로필을 준수합니다.
  • 메시지 서명 알고리즘은 ECDSA이며, 공개 키에는 P-256 곡선을, 암호 다이제스트 함수로는 SHA-256을 사용합니다.

향후 PEP는 새로운 버전 번호를 선택함으로써 이 스위트(및 증명 객체의 전반적인 형태)를 변경할 수 있습니다.

증명 진술 및 서명 생성

증명 진술은 증명 객체 안에서 암호학적으로 서명되는 실제 주장(즉, envelope.statement)입니다.

증명 진술은 JSON 형식의 v1 in-toto Statement 객체로 인코딩됩니다. 직렬화할 때 진술은 불투명한 바이너리 블롭으로 취급되므로 정규화가 필요하지 않습니다. JSON으로 인코딩된 진술의 예시는 부록 4: 증명 문(statement) 예시에 제공됩니다.

증명 진술은 v1 in-toto Statement일 뿐만 아니라 다음과 같은 제약도 받습니다:

  • in-toto subject에는 단 하나의 subject만 포함되어야 합니다.
  • subject[0].name은 배포판의 파일 이름이며, 유효한 소스 배포판 또는 휠 배포판 파일 이름이어야 합니다.
  • subject[0].digest에는 SHA-256 다이제스트가 포함되어야 합니다. 다른 다이제스트가 있을 수도 있습니다. 다이제스트는 16진수 문자열로 표현되어야 합니다.
  • 다음 predicateType 값이 지원됩니다:

이 진술에 대한 서명은 v1 DSSE 서명 프로토콜을 사용하여 구성되며, PAYLOAD_TYPE은 application/vnd.in-toto+json이고 PAYLOAD_BODY는 위의 JSON으로 인코딩된 진술입니다. 다른 PAYLOAD_TYPE은 허용되지 않습니다.

프로비넌스 객체

색인은 업로드된 증명을, 그 검증에 도움이 되는 메타데이터와 함께 JSON으로 직렬화된 객체 형태로 제공합니다.

이러한 프로비넌스 객체는 위에서 설명한 Simple Index와 JSON 기반 Simple API 양쪽을 통해 제공되며, 다음과 같은 구조를 가집니다:

{
    "version": 1,
    "attestation_bundles": [
      {
        "publisher": {
          "kind": "important-ci-service",
          "claims": {},
          "vendor-property": "foo",
          "another-property": 123
        },
        "attestations": [
          { /* attestation 1 ... */ },
          { /* attestation 2 ... */ }
        ]
      }
    ]
}

또는 의사 코드로 나타내면 다음과 같습니다:

@dataclass
class Publisher:
    kind: string
    """
    The kind of Trusted Publisher.
    """

    claims: object | None
    """
    Any context-specific claims retained by the index during Trusted Publisher
    authentication.
    """

    _rest: object
    """
    Each publisher object is open-ended, meaning that it MAY contain additional
    fields beyond the ones specified explicitly above. This field signals that,
    but is not itself present.
    """

@dataclass
class AttestationBundle:
    publisher: Publisher
    """
    The publisher associated with this set of attestations.
    """

    attestations: list[Attestation]
    """
    The set of attestations included in this bundle.
    """

@dataclass
class Provenance:
    version: Literal[1]
    """
    The provenance object's version, which is always 1.
    """

    attestation_bundles: list[AttestationBundle]
    """
    One or more attestation "bundles".
    """
  • version은 1입니다. 증명 객체와 마찬가지로 프로비넌스 객체에도 버전이 있으며, 이 PEP는 버전 1만 정의합니다.
  • attestation_bundles는 하나 이상의 증명 “번들”을 포함하는 필수 JSON 배열입니다. 각 번들은 서명 신원(예: Trusted Publishing 신원)에 대응하며, 하나 이상의 증명 객체를 포함합니다.

    Publisher 모델에서 언급했듯이, 각 AttestationBundle.publisher 객체는 해당 Trusted Publisher에 고유하지만 최소한 다음을 포함해야 합니다:

    • kind 키. 이 키는 Trusted Publisher의 종류를 고유하게 식별하는 JSON 문자열이어야 합니다.
    • claims 키: Trusted Publisher 인증 과정에서 색인이 보존한 모든 컨텍스트별 클레임을 담은 JSON 객체여야 합니다.

    게시자 객체의 그 밖의 모든 키는 게시자별로 다릅니다. 게시자 객체의 전체 예시는 부록 1: 신뢰할 수 있는 게시자(Trusted Publisher) 표현 예시에 나와 있습니다.

    각 증명 객체 배열은 업로드 엔드포인트 변경 사항와 프로비넌스 객체의 변경에서 설명한 대로 업로드 시점에 업로더가 attestations 필드를 통해 제공한 attestations 배열의 상위 집합입니다.

프로비넌스 객체의 변경

프로비넌스 객체는 불변이 아니며, 시간이 지나면서 변경될 수 있습니다. 프로비넌스 객체가 변경되는 이유에는 다음이 포함되며, 이에 국한되지 않습니다.

  • 기존 서명 신원에 대한 새 증명 추가: 색인은 이미 업로드된 파일에 대한 더 새로운 버전의 증명처럼, 기존 서명 신원의 추가 증명을 허용할 수 있습니다.
  • 새 서명 신원 및 관련 증명 추가: 색인은 제3자 감사자나 색인 자신처럼 파일 업로더가 아닌 다른 출처에서 온 증명을 지원할 수 있습니다. 이러한 증명은 비동기적으로 수행될 수 있으므로, 색인이 이를 사후에 프로비넌스 객체에 삽입해야 합니다.

증명 검증

배포 파일에 대해 증명 객체를 검증하려면 다음 각 항목을 검증해야 합니다.

  • version이 1입니다. 검증자는 다른 버전을 반드시 거부해야 합니다.
  • verification_material.certificate가 사전에 신뢰된 기관(예: 검증 클라이언트에 이미 들어 있는 신뢰 루트)이 발급한 유효한 서명 인증서입니다.
  • verification_material.certificate가 패키지를 게시한 Trusted Publisher의 머신 신원과 같은 적절한 서명 주체를 식별합니다.
  • envelope.statement가 유효한 in-toto v1 Statement이며, 그 주체와 다이제스트는 반드시 배포 파일의 파일명 및 내용과 일치해야 합니다. 배포의 파일 이름의 경우, statement의 subject는 동등하더라도 정규화된 형태일 수 있으므로 적절한 소스 배포판 또는 wheel 파일 이름 형식에 따라 파싱하여 매칭을 수행해야 합니다(MUST).
  • envelope.signature가 v1 DSSE 서명 프로토콜에 따라 재구성된, verification_material.certificate에 대응하는 envelope.statement의 유효한 서명입니다.

위의 필수 단계에 더해, 검증자는 정책에 따라 verification_material.transparency_entries를 추가로 검증할 수 있습니다. 예를 들어 투명성 로그 항목을 최소 하나 이상 요구하거나 일정 개수 이상의 항목을 요구할 수 있습니다. 투명성 항목을 검증할 때 검증자는 각 항목의 포함 시각이 서명 인증서의 유효 기간 안에 있는지 반드시 확인해야 합니다.

보안 영향

이 PEP는 주로 “기계적인” 성격을 띱니다. 즉, 증명의 유효성이나 증명 간 임계값 등에 관한 상위 수준의 보안 “정책”을 규정하지 않고, 검증 가능한 디지털 증명을 구성하고 제공하기 위한 구조를 제공합니다.

증명의 암호 민첩성

알고리즘 민첩성은 암호 체계에서 악용 가능한 취약점이 흔히 발생하는 원인입니다. 이 PEP는 두 가지 방식으로 알고리즘 민첩성을 제한합니다.

  • 모든 알고리즘은 매개변수를 기하급수적으로 조합한 모음이 아니라 단일 스위트로 지정됩니다. 이렇게 하면 (예를 들어) 공격자가 강력한 서명 알고리즘과 약한 해시 함수를 함께 선택하여 체계 전체를 무력화하는 것이 불가능해집니다.
  • 증명 객체에는 버전이 있으며, 해당 버전에 지정된 알고리즘 스위트만 포함할 수 있습니다. 향후 특정 스위트가 안전하지 않은 것으로 판단되면, 클라이언트는 해당 스위트를 포함하는 증명의 검증을 일괄 거부하거나 조건부로 처리할 수 있습니다.

색인 신뢰

이 PEP는 색인 자체에 대한 신뢰를 높이지(또는 낮추지) 않습니다. 패키지 내용을 수정할 수 있는 부정직한 색인은 패키지 증명도 부정직하게 수정하거나 누락할 수 있습니다. 따라서 색인이 수정되지 않은 패키지 배포물을 정직하게 전달할 것이라는 신뢰는 여전히 사실상 필요합니다. 따라서 이 PEP가 전제하는 색인 신뢰는 PGP나 휠 서명 같은 이전 메커니즘에 명시되지 않은 채 깔려 있던 전제와 같습니다.

이 PEP는 PEP 458 및/또는 PEP 480과 같은 향후의 색인 신뢰 메커니즘을 가로막거나 배제하지 않습니다.

권장 사항

이 PEP는 서명 인증서가 주장하는 유효 기간을 뒷받침하는 서명된 시간의 검증 가능한 출처를 증명 객체가 하나 이상 포함할 것을 권장합니다. 다만 이를 의무화하지는 않습니다. 이 PEP를 구현하는 색인은 이 요구 사항을 엄격하게 강제하도록 선택할 수 있습니다.

부록 1: 신뢰할 수 있는 게시자(Trusted Publisher) 표현 예시

이 부록은 단순 JSON API의 project.files[].provenance 목록 안에 있는 publisher 키의 가상 예시를 제공합니다:

"publisher": {
    "kind": "GitHub",
    "claims": {
        "ref": "refs/tags/v1.0.0",
        "sha": "da39a3ee5e6b4b0d3255bfef95601890afd80709"
    },
    "repository_name": "HolyGrail",
    "repository_owner": "octocat",
    "repository_owner_id": "1",
    "workflow_filename": "publish.yml",
    "environment": null
}

부록 2: 투명성 로그 항목의 데이터 모델

이 부록에는 증명 객체 안의 투명성 로그 항목에 대한 의사 코드 형태의 데이터 모델이 담겨 있습니다. 각 투명성 로그 항목은 서명된 포함 시각의 출처 역할을 하며, 온라인이나 오프라인으로 검증할 수 있습니다.

@dataclass
class TransparencyLogEntry:
    log_index: int
    """
    The global index of the log entry, used when querying the log.
    """

    log_id: str
    """
    An opaque, unique identifier for the log.
    """

    entry_kind: str
    """
    The kind (type) of log entry.
    """

    entry_version: str
    """
    The version of the log entry's submitted format.
    """

    integrated_time: int
    """
    The UNIX timestamp from the log from when the entry was persisted.
    """

    inclusion_proof: InclusionProof
    """
    The actual inclusion proof of the log entry.
    """


@dataclass
class InclusionProof:
    log_index: int
    """
    The index of the entry in the tree it was written to.
    """

    root_hash: str
    """
    The digest stored at the root of the Merkle tree at the time of proof
    generation.
    """

    tree_size: int
    """
    The size of the Merkle tree at the time of proof generation.
    """

    hashes: list[str]
    """
    A list of hashes required to complete the inclusion proof, sorted
    in order from leaf to root. The leaf and root hashes are not themselves
    included in this list; the root is supplied via `root_hash` and the client
    must calculate the leaf hash.
    """

    checkpoint: str
    """
    The signed tree head's signature, at the time of proof generation.
    """

    cosigned_checkpoints: list[str]
    """
    Cosigned checkpoints from zero or more log witnesses.
    """

부록 3: 단순 JSON API 크기 고려 사항

이 PEP의 이전 초안에서는 각 provenance object를 JSON 단순 API의 해당 부분에 직접 삽입하도록 요구했습니다.

현재 버전의 이 PEP에서는 대신 출처 증명 객체의 SHA-256 다이제스트를 삽입합니다. 이는 크기와 네트워크 대역폭을 고려한 결과입니다:

  1. 일반적인 증명 객체의 크기는 JSON 기준으로 약 5.3 KB로 추정합니다.
  2. 색인이 결국 릴리스 파일당 약 3개의 증명을 호스팅하게 될 것으로 보수적으로 추정합니다. 이는 결합된 출처 증명 객체당 약 15.9 KB의 JSON에 해당합니다.
  3. 2024년 5월 기준으로 PyPI의 평균적인 프로젝트에는 약 21개의 릴리스 파일이 있습니다. 이 평균은 시간이 지나면서 늘어날 것으로 보수적으로 예상합니다.
  4. 이 수치들을 종합하면 일반적인 프로젝트는 60~70개의 증명을 호스팅하게 될 수 있습니다. 이는 “project detail” 엔드포인트에 약 339 KB의 JSON이 추가된다는 뜻입니다.

프로젝트에 릴리스가 수백 개나 수천 개 있거나 릴리스당 파일이 수십 개 있는 “병적인” 경우에는 이 수치가 훨씬 더 나빠집니다.

부록 4: 증명 문(statement) 예시

SHA-256 다이제스트가 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855인 소스 배포판 sampleproject-1.2.3.tar.gz가 주어졌을 때, 다음은 JSON 객체로 나타낸 적절한 in-toto Statement입니다:

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    {
      "name": "sampleproject-1.2.3.tar.gz",
      "digest": {"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}
    }
  ],
  "predicateType": "https://some-arbitrary-predicate.example.com/v1",
  "predicate": {
    "something-else": "foo"
  }
}