signin: migrate to crypto/hash APIs

MERGED2026components/signincrypto
2026. 9. 5.DonghanPark 프로필 이미지DonghanPark

Chromium //crypto 라이브러리 API 개편 작업의 일환으로, components/signin에서 사용하던 구형 해시 API(crypto/sha2.h)를 신규 해시 API(crypto/hash.h)로 마이그레이션한 기여입니다.

문제 설명

crypto/sha2.hcrypto::SHA256HashString()crypto::SHA256Hash()crypto 네임스페이스에 바로 놓여 있고, 네이밍도 신규 API 규칙(Sha256, kSha256Size)과 어긋나는 예전 스타일을 따르고 있습니다. //crypto 개편에 따라 해시 API는 crypto::hash 네임스페이스로 옮겨졌고, 각 컴포넌트가 호출부를 신규 API로 옮기는 작업이 필요했습니다.

components/signin/ 하위에서도 여러 파일이 여전히 구형 API로 SHA-256을 계산하고 있었습니다.

// 구 API (crypto/sha2.h) — 헤더 주석에 이미 deprecated로 표시되어 있습니다.
namespace crypto {
static const size_t kSHA256Length = 32;  // Length in bytes of a SHA-256 hash.

CRYPTO_EXPORT std::array<uint8_t, kSHA256Length> SHA256Hash(
    base::span<const uint8_t> input);
CRYPTO_EXPORT std::string SHA256HashString(std::string_view str);
}  // namespace crypto

// 신 API (crypto/hash.h)
namespace crypto::hash {
inline constexpr size_t kSha256Size = 32;

CRYPTO_EXPORT std::array<uint8_t, kSha256Size> Sha256(
    base::span<const uint8_t> data);
CRYPTO_EXPORT std::array<uint8_t, kSha256Size> Sha256(std::string_view data);
}  // namespace crypto::hash

입력 쪽은 신 API에도 std::string_view 오버로드가 있어 기존 인자를 그대로 넘길 수 있습니다. 차이는 반환 타입에 있습니다. SHA256HashString()std::string을 돌려주지만 crypto::hash::Sha256()std::array<uint8_t, 32>를 돌려주므로, 해시 결과를 문자열로 다루던 호출부는 별도의 변환이 필요합니다.

해결 내용

components/signin/ 하위 파일의 include와 호출부, 상수, 주석을 신규 API 기준으로 정리했습니다.

  1. 헤더 include 교체: crypto/sha2.hcrypto/hash.h (signin_internals_util.cc는 실제로 해시 API를 쓰지 않는 미사용 include였으므로 대체 없이 제거)
  2. 호출부 교체: crypto::SHA256HashString() / crypto::SHA256Hash()crypto::hash::Sha256()
  3. 반환 타입 변환: 결과를 문자열로 쓰는 GaiaIdHash::FromGaiaId(), session_binding_utils.cc의 assertion payload 생성 로직 등에서 base::as_string_view()를 거쳐 std::string으로 변환 (Base64UrlEncode()처럼 span을 그대로 받는 호출부는 변환 없이 전달)
  4. 상수 교체: crypto::kSHA256Lengthcrypto::hash::kSha256Size (이 상수를 언급하는 헤더·테스트 주석 포함)
  5. git cl format으로 Chromium C++ 스타일에 맞게 줄바꿈 정리

수정된 파일:

  • components/signin/core/browser/signin_internals_util.cc
  • components/signin/public/base/gaia_id_hash.cc
  • components/signin/public/base/gaia_id_hash.h
  • components/signin/public/base/gaia_id_hash_unittest.cc
  • components/signin/public/base/session_binding_utils.cc

주요 변경 내용

--- a/components/signin/public/base/gaia_id_hash.cc
+++ b/components/signin/public/base/gaia_id_hash.cc
@@ -8,14 +8,16 @@
 #include <utility>

 #include "base/base64.h"
-#include "crypto/sha2.h"
+#include "base/strings/string_view_util.h"
+#include "crypto/hash.h"
 #include "google_apis/gaia/gaia_id.h"

 namespace signin {

 // static
 GaiaIdHash GaiaIdHash::FromGaiaId(const GaiaId& gaia_id) {
-  return FromBinary(crypto::SHA256HashString(gaia_id.ToString()));
+  return FromBinary(std::string(
+      base::as_string_view(crypto::hash::Sha256(gaia_id.ToString()))));
 }

@@ -53,7 +55,7 @@
 bool GaiaIdHash::IsValid() const {
-  return gaia_id_hash_.size() == crypto::kSHA256Length;
+  return gaia_id_hash_.size() == crypto::hash::kSha256Size;
 }

테스트 방법

동작을 바꾸지 않는 API 교체이므로 새 테스트를 추가하는 대신 기존 테스트로 회귀가 없는지 확인했습니다.

  1. 단위 테스트 실행components_unittests의 signin 관련 테스트가 그대로 통과하는 것을 확인했습니다.

    autoninja -C out/Default components_unittests
    ./out/Default/components_unittests --gtest_filter="GaiaIdHashTest.*:*SessionBinding*"
  2. Gerrit CQ Dry Run — CL 업로드 후 LUCI CQ Dry Run에서 빌드와 테스트가 모두 통과하는 것을 확인했습니다.

배운 점

  • std::arraystring_viewstd::string 변환 체인: crypto::hash::Sha256()이 돌려주는 std::array<uint8_t, 32>를 문자열로 쓰려면 base::as_string_view()를 거쳐야 합니다. 반대로 Base64UrlEncode()처럼 span을 직접 받는 호출부는 변환이 오히려 불필요합니다. 호출부마다 어떤 타입을 요구하는지 확인하고 최소한의 변환만 넣는 것이 중요하다는 것을 배웠습니다.
  • 주석도 마이그레이션 대상: crypto::kSHA256Length는 코드뿐 아니라 gaia_id_hash.h의 API 설명 주석과 테스트 주석에도 등장했습니다. 상수나 API 이름을 바꿀 때는 이를 언급하는 문서와 주석까지 함께 찾아 고쳐야 리팩토링이 완결된다는 점을 배웠습니다.

참고 자료