body 무결성 검증 방법
Rest API에서 유저 인증은 jwt 사용하여 인증정보가 일치하였을때, 전송되는 body가 변조되지 않았다는것을 보장하려는 방법에 대해서 찾아보게 되었다.
JWT 인증은 “사용자의 신원”을 보장하지만, body 데이터가 중간에 변조되지 않았다는 것을 보장하지는 않기 때문에 body 본문이 클라이언트가 의도한 값인지 추가적인 무결성 검증이 필요하다.
✅ 문제 정리
- POST 요청 등 body 데이터가 중간에 변조되지 않았는지 확인하고 싶음
- JWT는 사용자 인증 용도이므로 body 자체의 무결성은 보호하지 않음
✅ 가능한 해결 방법
1. HMAC (해시 기반 메시지 인증 코드) 서명 사용
클라이언트가 보내는 body에 대해 서명을 생성해서(클라이언트와 서버가 공유하는 비밀키로 HMAC 해시를 만들어) 서명을 헤더나 별도 필드에 실어 함께 전송하고 서버는 동일키로 HMAC을 재계산하여 일치하는지 비교하여 무결성을 검증.
💡 동작 방식
- 클라이언트는 body 데이터를 JSON 문자열로 변환 후, 비밀 키로 HMAC-SHA256 서명 생성
예) signature = Base64( HMAC_SHA256(secretKey, JSON.stringify({ “price”: 10000 })) )
- 이 서명을 헤더 또는 별도 필드에 포함해서 서버에 전송
예) HTTP 헤더로 X-Signature: signature 추가, JSON 바디와 함께 전송
- 요새는 비표준 헤더속성에 X-를 붙이지 않는다고 한다. 참고참고.
- 서버는 동일한 방식으로 body를 서명해보고, 클라이언트 서명과 비교
예) 헤더 X-Signature와, 읽어들인 바디로 HMAC 재계산
✅ 장점
- 변조 여부를 서버가 검증 가능
- 유저가 해당 데이터를 의도적으로 보냈는지 확인 가능
- 구현이 비교적 간단하고 속도가 빠름
✅ 단점
- secretKey는 클라이언트/서버 간에 공유되어 있어야 하며 외부에 노출되면 안 된다. 따라서 안전하게 키가 서버와 클라이언트에 공유되도록 주의해야한다.
- JSON 직렬화 시 필드 순서·공백까지 일관되게 유지해야 함
- Replay공격 방지를 위해 타임스탬프/nonce를 함께 포함하고 검증
2. JWT Payload에 중요한 데이터 포함하기
JWT는 자체적으로 서명을 포함하기 때문에, 중요한 데이터(price 등)를 JWT 안에 넣으면 위조가 불가능하기에
JWT Payload에 이 JWT를 Authorization 헤더에 넣고 전송하고 서버는 JWT의 서명을 검증하고 price 정보도 JWT 내에서 읽어서 검증하는 방법.
✅ 장점
- JWT 자체로 인증과 무결성 보장
- 별도 서명 필드 불필요
✅ 단점
- JWT에 너무 많은 정보를 담으면 보안/관리상 어려움 발생
- 유저와 관련된 클레임이 아니라면 비추천. (사용자 고유 데이터인 경우 추천)
- 자주 변경되는 데이터의 경우 JWT 발급 타이밍 문제 발생
3. JSON Web Signature 서명 사용 - 요청 body 자체를 JWT로 만들기
요청 전체를 서명하는 방법으로,
클라이언트 요청 전체 데이터를 JWT 형식(JWS)으로 감싸고, 서명된 토큰으로 보내면
서버는 공개키(RSA/ECDSA) 또는 대칭키(HMAC)으로 JWS 서명을 검증하는 방식.
- JWT: “클레임이 담긴 JSON 토큰”
- JWS: “위 JSON을 서명으로 감싼 컨테이너” → 서명된 JWT = JWS 객체
💡 동작 방식
- 요청 페이로드 전체를 JWS 포맷으로 감싸서(JOSE 라이브러리 활용), JWT처럼 서명하고 전송(JWT의 Payload는 실제 요청 데이터 전체)
- 서버는 JWT의 JOSE 같은 라이브러리로 서명을 검증하고 내부 데이터를 payload(JSON)를 꺼내 확인.
✅ 장점
- 서명 검증로직이 표준화되어 있고, spring security JWT지원과 연계 가능
- 비밀키 노출시 라우팅이나 공개키(RSA/ECDSA) 방식도 가능
✅ 단점
- 바디를 전부 JWS로 감싸므로, 기존 DTO 매핑 처리 로직 변경 필요(기존 DTO 바인딩 로직을 JWS 파싱 흐름에 맞춰 바꿔야 함)
4. mTLS 및 API Gateway 활용
mTLS(상호 TLS 인증)를 걸면 클라이언트 인증서 그 자체가 “이 요청은 올바른 클라이언트에서 왔고, 중간 변조가 없다”를 보장.
AWS API Gateway의 SigV4, Kong의 HMAC 플러그인 같은,
API Gateway 레벨 서명 기능을 활용하면, 애플리케이션 코드를 건드리지 않고 메시지 무결성을 검증이 가능.
✅ 상황에 따른 사용
- 내부시스템, 클라이언트와 비밀키 공유 가능 HMAC-SHA256 + Spring Filter 서명 방식 (간단, 빠름)
- 이미 JWT를 사용 중이며 데이가 사용자 고유 데이터등이라면 JWT Payload에 포함
- 서드파티와 같이 보안이 매우 중요한 상황이면 body 전체를 JWS 서명 처리, JWS (공개키 기반 서명)
- 인증서 관리, 클라우드 네이티브 환경이라면 → mTLS + API Gateway (SigV4, Kong HMAC)조합
✅ 이 외 무결성을 보장하기 위한 방법
- 주기적인 키 회전(key rotation) 정책 수립
- 재전송(replay) 공격 방지를 위해 서명 대상에 타임스탬프 또는 nonce를 포함하여 무결성 보장을 높일 수 있다.