11 KiB
title, source_type, url, archive_url, status, confidence, tags, related_projects, related_branches, created, last_reviewed
| title | source_type | url | archive_url | status | confidence | tags | related_projects | related_branches | created | last_reviewed | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Stripe — Webhook Signatures (official-vendor-doc) | official-doc | https://stripe.com/docs/webhooks/signatures | https://web.archive.org/web/20260629/https://stripe.com/docs/webhooks/signatures | raw | high |
|
|
|
2026-06-29 | 2026-06-29 |
Stripe — Webhook Signatures (공식)
Layer:
raw/official-docs/— Stripe 공식 문서의 원문 발췌 및 출처 기록. Strength 분류:official-vendor-doc— Stripe 공식 개발자 문서 (stripe.com/docs/webhooks/...).
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-webhook-outbound-contract | D1 (HMAC-SHA256 서명 스키마), D2 (타임스탬프 기반 Replay Attack 방지) 및 secret key rotation 정책 결정 근거. |
컨텍스트
feature-webhook-outbound-contract 의 D1, D2 는 아웃바운드 웹훅의 발송자 인증과 리플레이 공격 방지를 위해 헤더 기반 서명 스키마를 수립한다. 본 문서는 Stripe 가 (a) Stripe-Signature 헤더 포맷 (t=timestamp,v1=sig), (b) timestamp + '.' + payload 형태의 서명 조립식, (c) 5분 오차 허용(tolerance window) 리플레이 검증, (d) constant-time byte comparison 을 통한 timing attack 방지, (e) 키 로테이션 시 복수 서명 포함 등을 직접 진술하는 공식 표준 근거이다.
출처 / Source
- 원본 URL: https://stripe.com/docs/webhooks/signatures
- 부속 URL (최선의 조치): https://stripe.com/docs/webhooks/best-practices
- 저자 / 조직: Stripe, Inc. — Stripe Developer Documentation
- 마지막 확인일: 2026-06-29
핵심 인용 / Key quotes (verbatim)
[§Verifying signatures] "Stripe signs the webhook events it sends to your endpoints by including a signature in each event's Stripe-Signature header. This allows you to verify that the events were sent by Stripe, not by a third party."
[§Verifying signatures] "The Stripe-Signature header contains a timestamp and one or more signatures. The timestamp is prefixed by t=, and each signature is prefixed by a scheme. Schemes start with v. Currently, the only supported live signature scheme is v1."
[§Verifying signatures] "Stripe generates the signature using a hash-based message authentication code (HMAC) with SHA-256."
[§Step 1: Extract the timestamp and signatures] "Step 1: Extract the timestamp and signatures: Split the header, using the , character as the separator, to get a list of elements. Then split each element, using the = character as the separator, to get a prefix and value pair."
[§Step 2: Prepare the signed_payload string] "Step 2: Prepare the signed_payload string: Concatenate: The timestamp (as a string), The character ., The actual JSON payload (that is, the request body)"
[§Step 3: Determine the expected signature] "Step 3: Determine the expected signature: Compute an HMAC with the SHA256 hash function. Use the endpoint's signing secret as the key, and the signed_payload string as the message."
[§Step 4: Compare the signatures] "Step 4: Compare the signatures: Compare the signature (or signatures) in the header to the expected signature. To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures."
[§Preventing replay attacks] "A replay attack is when an attacker intercepts a valid payload and its signature, then re-transmits them. To prevent such attacks, Stripe includes a timestamp in the Stripe-Signature header. When verifying signatures, your integration should check that the timestamp is within a tolerance window (defaulting to 5 minutes) of the current time."
[§Preventing replay attacks] "Stripe generates a new signature and timestamp for each retry attempt."
[§Secrets rotation] "If you need to rotate secrets, or if you have multiple active secrets, Stripe includes multiple signatures in the header. For example, if you have two active secrets, the header contains: Stripe-Signature: t=1672531199,v1=sig1,v1=sig2"
Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| STRIPE-WEBHOOK-C1 | Stripe는 발신자 인증을 위해 모든 웹훅 이벤트의 Stripe-Signature 헤더에 서명을 포함함 |
"Stripe signs the webhook events it sends to your endpoints by including a signature in each event's Stripe-Signature header." | official-vendor-doc |
웹훅 발신자 신원 검증 | 일반 클라이언트-서버 REST API 인증 |
| STRIPE-WEBHOOK-C2 | 서명 헤더는 타임스탬프(t=)와 서명 리스트(v1=)로 구성되며 쉼표(,)로 구분됨 |
"The Stripe-Signature header contains a timestamp and one or more signatures. The timestamp is prefixed by t=, and each signature is prefixed by a scheme. Schemes start with v. Currently, the only supported live signature scheme is v1." | official-vendor-doc |
서명 포맷 파싱 및 결합 구조 | JSON 페일로드 이외의 이진 데이터 지원 여부 |
| STRIPE-WEBHOOK-C3 | 서명 생성에는 해시 기반 메시지 인증 코드인 HMAC-SHA256 알고리즘을 사용함 | "Stripe generates the signature using a hash-based message authentication code (HMAC) with SHA-256." | official-vendor-doc |
암호학적 서명 생성 알고리즘 선택 | asymmetric RSA/ECDSA 서명 방식 지원 |
| STRIPE-WEBHOOK-C4 | 서명 대상 페이로드는 타임스탬프 문자열 + '.' + raw JSON 본문 형태로 조립됨 |
"Concatenate: The timestamp (as a string), The character ., The actual JSON payload (that is, the request body)" | official-vendor-doc |
서명 검증 원본 데이터 조립식 | 페이로드 내 화이트스페이스/개행 문자 무관성 |
| STRIPE-WEBHOOK-C5 | 서명 생성 시 각 웹훅 엔드포인트별 고유 secret key가 키 값으로 사용됨 | "Compute an HMAC with the SHA256 hash function. Use the endpoint's signing secret as the key, and the signed_payload string as the message." | official-vendor-doc |
비밀 키 범위설정 및 매핑 | 다중 엔드포인트 간의 단일 마스터 키 사용 방식 |
| STRIPE-WEBHOOK-C6 | timing attack을 차단하기 위해 서명 문자열 비교 시 constant-time 비교 방식을 적용해야 함 | "Compare the signature (or signatures) in the header to the expected signature. To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures." | official-vendor-doc |
서명 비교 시 하드웨어 수준 부채널 공격 방어 | 일반 문자열 equals 비교의 안전성 |
| STRIPE-WEBHOOK-C7 | replay attack 방지를 위해 수신단은 타임스탬프와 현재 시각의 오차를 5분 윈도우 내로 제한해야 함 | "To prevent such attacks, Stripe includes a timestamp in the Stripe-Signature header. When verifying signatures, your integration should check that the timestamp is within a tolerance window (defaulting to 5 minutes) of the current time." | official-vendor-doc |
리플레이 공격 방어 윈도우 수립 | NTP 비동기화 상태에서의 강제 복구 |
| STRIPE-WEBHOOK-C8 | 재시도(retry) 발생 시 Stripe는 매번 새로운 타임스탬프와 그에 대응하는 새 서명을 생성하여 발송함 | "Stripe generates a new signature and timestamp for each retry attempt." | official-vendor-doc |
재시도 요청 수신 시 타임스탬프 갱신 정책 | 수신 측의 재시도 유일성 판별 방법 |
| STRIPE-WEBHOOK-C9 | 시크릿 로테이션 또는 복수 시크릿 존재 시 헤더에 v1 접두사를 가진 서명이 다중으로 포함됨 |
"If you need to rotate secrets, or if you have multiple active secrets, Stripe includes multiple signatures in the header." | official-vendor-doc |
시크릿 로테이션 중단 최소화 설계 | 특정 서명 매칭 시 다른 서명의 무효화 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
STRIPE-WEBHOOK-C2,C4: 헤더 문자열 포맷(t=...,v1=...) 및 payload 조립 방식 (t.body).STRIPE-WEBHOOK-C3,C5: HMAC-SHA256 알고리즘 사용과 엔드포인트별 단일 secret mapping.STRIPE-WEBHOOK-C6: constant-time comparison (MessageDigest.isEqual) 필수 적용.STRIPE-WEBHOOK-C7: replay window 기본값 5분 (300초).STRIPE-WEBHOOK-C9: 로테이션 단계에서 다중 signature 전송 메커니즘 지원.
- 이 자료가 증명하지 않는 것:
- 수신단 시스템 시각 보정 (NTP) — 수신 서버의 NTP 동기화가 실패하여 발생하는 타임스탬프 불일치 예외 처리 흐름은 명시하지 않음.
- DB 기반 Key-Rotation 스키마 — 복수 Active Secret을 보관하기 위한 데이터베이스 테이블 구조 및 캐싱 메커니즘은 증명하지 않음.
- 서명 해시 인코딩 포맷 — 본문에는 명시되지 않았으나 관례적으로 HMAC 결과값을 Hexadecimal(16진수) 문자열로 인코딩하여 매칭한다는 점.
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- Spring Core
RestClient를 활용해 외부 요청을 보낼 때, 직렬화된 JSON payload의 바이트 배열이 변경(예: Jackson Indent 출력, UTF-8 외 인코딩)되면 서명이 깨지므로, 반드시 JSON 직렬화 직후의 raw byte array를 그대로 서명 계산에 투입해야 함. - 다중 Secret을 지원하기 위해
application.yml및 Database 구조가 List 형태의 Secret Key를 매핑할 수 있도록 설계되어야 함.
- Spring Core
메모 / Notes
- Constant-time comparison: Java에서는
java.security.MessageDigest.isEqual(byte[], byte[])가 constant-time 비교를 제공하므로 이를 서명 검증 유틸에 필수로 사용해야 함. - Header Parsing: 쉼표로 파싱할 때
t=1672531199와v1=sig1을 각각 맵핑하고, 서명 목록(List<String>)과 단일 타임스탬프(String)로 분리해 내는 견고한 파서 필요. - Rotation Window:
overlap-24h또는manual로테이션 시 120초~300초 간 복수 서명이 발송될 수 있으므로, 수신 측은 목록 중 하나라도 일치하면 성공으로 판정해야 함.
Related / 관련
- 관련 raw 자료: raw/official-docs/github-webhook-signature.md, raw/official-docs/svix-webhook-best-practices.md
- 이 자료를 인용한 wiki 요약: (미작성)
- 이 자료를 인용하는 branch: raw/branch-notes/feature-webhook-outbound-contract.md
- 인용하는 project: raw/project-notes/ca-skeleton-operational-contract.md