certificate_model: migrate to crypto/hash APIs
MERGED2026components/certificate_modelcrypto
2026. 8. 29.
DonghanPark
Chromium의 //crypto 라이브러리 API 개편 작업으로, components/certificate_model 내에서 사용하던 구형 해시 API(crypto/sha2.h)를 새로운 해시 API(crypto/hash.h)로 마이그레이션했습니다.
문제 설명
Chromium에서는 암호화 관련 API를 도메인별 하위 네임스페이스(crypto::hash, crypto::hmac 등)로 정리하고 인터페이스를 통일하기 위한 마이그레이션 작업이 진행되고 있습니다.
- 상위 작업인 Issue 374310081(hash 인터페이스 개편)과 Issue 374334448(hmac 인터페이스 개편)에서 새 API가 만들어졌고 이에 맞춰 코드베이스 전체의 호출부를 교체하는 마이그레이션(Issue 372283556)이 진행 중입니다.
- 기존
crypto/sha2.h의crypto::SHA256Hash()는 평평한crypto네임스페이스에 놓여 있고 네이밍도 예전 스타일을 따르고 있었습니다. components/certificate_model/x509_certificate_model_base.cc에서도 인증서 데이터(Certificate Data)와 SPKI(Subject Public Key Info)의 SHA-256 해시를 계산할 때 이 구형 API를 쓰고 있어 교체가 필요했습니다.
// 구 API (crypto/sha2.h)
namespace crypto {
CRYPTO_EXPORT std::array<uint8_t, kSHA256Length> SHA256Hash(base::span<const uint8_t> input);
}
// 신 API (crypto/hash.h)
namespace crypto::hash {
CRYPTO_EXPORT std::array<uint8_t, kSha256Size> Sha256(base::span<const uint8_t> data);
}해결 내용
components/certificate_model/x509_certificate_model_base.cc에서 crypto/sha2.h 헤더 include를 crypto/hash.h로 교체하고, crypto::SHA256Hash() 호출부를 신규 API인 crypto::hash::Sha256()으로 수정했습니다.
- 헤더 include 교체:
crypto/sha2.h→crypto/hash.h X509CertificateModelBase::HashCertSHA256()수정X509CertificateModelBase::HashSpkiSHA256()수정- 코드 포맷팅:
git cl format으로 Chromium C++ 스타일 가이드에 맞게 줄바꿈 정리
주요 변경 내용
--- a/components/certificate_model/x509_certificate_model_base.cc
+++ b/components/certificate_model/x509_certificate_model_base.cc
@@ -15,7 +15,7 @@
#include "base/strings/string_util.h"
#include "base/strings/string_view_util.h"
#include "components/strings/grit/components_strings.h"
-#include "crypto/sha2.h"
+#include "crypto/hash.h"
#include "net/cert/qwac.h"
#include "net/cert/time_conversions.h"
#include "net/cert/x509_util.h"
@@ -351,8 +351,8 @@ OptionalStringOrError X509CertificateModelBase::GetSubjectOrgUnitName() const {
}
std::string X509CertificateModelBase::HashCertSHA256() const {
- auto hash =
- crypto::SHA256Hash(net::x509_util::CryptoBufferAsSpan(cert_data_.get()));
+ auto hash = crypto::hash::Sha256(
+ net::x509_util::CryptoBufferAsSpan(cert_data_.get()));
return base::HexEncodeLower(hash);
}
@@ -382,7 +382,7 @@ std::string X509CertificateModelBase::GetTitle() const {
std::string X509CertificateModelBase::HashSpkiSHA256() const {
CHECK(is_valid());
- auto hash = crypto::SHA256Hash(tbs_.spki_tlv);
+ auto hash = crypto::hash::Sha256(tbs_.spki_tlv);
return base::HexEncodeLower(hash);
}테스트 방법
단위 테스트(Unit Test) 실행
components_unittests타깃의 certificate model 관련 테스트를 실행해 기존 동작에 영향이 없는지 확인했습니다.autoninja -C out/Default components_unittests out/Default/components_unittests --gtest_filter="*CertificateModel*"Gerrit LUCI CQ Dry Run
Gerrit에 CL을 업로드한 뒤 CQ Dry Run으로 빌드와 단위 테스트가 모두 통과(Passed)하는 것을 확인했습니다.
배운 점
1. 기술적 학습 (메모리 안전성과 모던 C++ 아키텍처)
base::span과 Fat Pointer 원리:- C++20 표준에 도입된
std::span및 Chromium의base::span은 시작 주소와 크기(size_t)를 함께 묶어 관리하는 경량 뷰(Fat Pointer / Bounded Pointer) 객체입니다. - 포인터만 넘길 때 놓치기 쉬운 버퍼 오버플로우(Buffer Overflow)를 경계 검사(Bounds Check)로 잡아낼 수 있습니다. Chromium과 Microsoft의 보안 분석에 따르면 심각도 높은 보안 취약점의 약 70%가 메모리 안전성 문제에서 비롯되는데
span기반 인터페이스로의 전환(Spanification)이 이를 줄이기 위한 대표적인 노력임을 배웠습니다.
- C++20 표준에 도입된
- 연속 메모리(Contiguous Memory)와 복사 없는 뷰(Zero-Copy):
- C++ 표준이 보장하는 연속 메모리 특성(
vector는 C++03,string은 C++11부터) 덕분에std::vector,std::string, C 배열, BoringSSL의CryptoBuffer등 서로 다른 컨테이너를 새 객체로 복사하지 않고 포인터와 크기만 담은span뷰(64비트 기준 16바이트)로 일관되게 전달할 수 있다는 점을 이해했습니다. - 데이터가 연속된 메모리에 놓이므로 공간 지역성(Spatial Locality)을 잘 살릴 수 있고 노드를 따라가는 포인터 체이싱(Pointer Chasing)에 비해 캐시 미스가 적습니다.
- C++ 표준이 보장하는 연속 메모리 특성(
- 스택 할당과 추가 비용 없는 전달:
span은 포인터와 크기만 가진 단순한 구조체여서 보통 스택이나 레지스터에 놓이고 생성과 소멸에 드는 비용이 사실상 없습니다(Zero-overhead).span자체는 힙을 할당하지 않기 때문에 데이터를 복사해 넘길 때 따라오는 할당 비용과 단편화(Fragmentation) 부담을 피할 수 있습니다.
2. 오픈소스 분석 및 문서 탐색 노하우
- 설계 의도와 Git 커밋 로그 추적:
- 트래킹 이슈(Issue 372283556)에 자세한 배경이 없을 때는 상위 이슈(Issue 374310081)와
crypto/hash.h의 최초 도입 커밋 로그를 따라가면 이 API가 왜 만들어졌는지(spanified,single-shot, 컴파일 타임 크기 검증) 설계 의도를 파악할 수 있다는 것을 배웠습니다.
- 트래킹 이슈(Issue 372283556)에 자세한 배경이 없을 때는 상위 이슈(Issue 374310081)와
file:docs검색을 통한 공식 가이드 탐색:- Chromium Code Search에서
file:docs <키워드>(e.g.file:docs span)로 검색하면 공식 보안/가이드 문서(docs/unsafe_buffers.md)를 빠르게 찾을 수 있었습니다.
- Chromium Code Search에서
3. 코드 포맷팅 및 기여 프로세스
- 코드 컨벤션 준수: Chromium에서는
git cl format으로 clang-format 기반 스타일 규칙(80자 줄 길이 제한, include 알파벳 정렬, 함수 인자 줄바꿈 등)을 맞춰 두어야 한다는 점을 배웠습니다. 이번 변경에서도 함수 이름이 길어지면서 줄바꿈 위치(auto hash = crypto::hash::Sha256(...))가 함께 조정되었습니다. - 프로세스 학습: GitHub 이슈 할당부터 브랜치 생성, 코드 마이그레이션,
git cl format적용,git cl upload를 통한 패치셋 업로드, LUCI CQ Dry Run 검증까지 Chromium 기여의 한 사이클을 경험했습니다.
참고 자료
- Gerrit CL 8310509
- GitHub Issue #312: [crypto hash] components/certificate_model
- Chromium Issue 372283556: //crypto: migrate callers to new APIs
- Chromium Issue 374310081: //crypto: rework hash interface
- Chromium Issue 374334448: //crypto: rework hmac interface
- C++20 std::span 표준 문서 (cppreference)
- 미국 백악관 ONCD 기술 보고서 (Back to the Building Blocks: A Path Toward Secure and Measurable Software)
- 미국 CISA 메모리 안전성 가이드 (The Case for Memory Safe Roadmaps)
- Chromium Memory Safety 공식 문서 (The Chromium Projects: Memory Safety)
- Microsoft MSRC 연구 자료 (A proactive approach to more secure code)
- Chromium Safe Buffers 가이드 (docs/unsafe_buffers.md)
- Google C++ Style Guide
- Chromium C++ Style Guide
- crypto/hash.h 소스 코드
- x509_certificate_model_base.cc 소스 코드