Local Database

Google 세이프 브라우징 v5는 클라이언트가 저장소가 없는 실시간 모드를 선택하지 않는 한 클라이언트가 로컬 데이터베이스를 유지할 것으로 예상합니다. 이 로컬 데이터베이스의 형식과 저장은 클라이언트가 결정합니다. 이 로컬 데이터베이스의 콘텐츠는 개념적으로 다양한 목록이 파일로 포함된 폴더로 생각할 수 있으며, 이러한 파일의 콘텐츠는 SHA256 해시 또는 가장 일반적으로 사용되는 해시 길이인 4바이트 해시 접두사가 있는 해당 접두사입니다.

사용 가능한 목록

목록은 고유한 이름으로 식별되며, 이 이름은 목록에서 예상되는 해시의 길이를 나타내는 접미사를 포함하는 이름 지정 규칙을 따릅니다. 위협 유형은 동일하지만 해시 길이가 다른 해시 목록은 별도의 이름이 지정된 목록으로, 해시 길이를 나타내는 접미사로 한정됩니다.

다음 목록은 해시 목록 메서드와 함께 사용할 수 있습니다.

목록 이름 상응하는 v4 ThreatType 열거형 설명
gc-32b 없음 이 목록은 전역 캐시 목록입니다. 실시간 작동 모드에서만 사용되는 특수 목록입니다.
se-4b SOCIAL_ENGINEERING 이 목록에는 SOCIAL_ENGINEERING 위협 유형의 위협이 포함되어 있습니다.
mw-4b MALWARE 이 목록에는 데스크톱 플랫폼의 MALWARE 위협 유형 위협이 포함되어 있습니다.
uws-4b UNWANTED_SOFTWARE 이 목록에는 데스크톱 플랫폼의 UNWANTED_SOFTWARE 위협 유형의 위협이 포함되어 있습니다.
uwsa-4b UNWANTED_SOFTWARE 이 목록에는 Android 플랫폼의 UNWANTED_SOFTWARE 위협 유형의 위협이 포함되어 있습니다.
pha-4b POTENTIALLY_HARMFUL_APPLICATION 이 목록에는 Android 플랫폼의 POTENTIALLY_HARMFUL_APPLICATION 위협 유형의 위협이 포함되어 있습니다.

나중에 추가 목록이 제공될 수 있으며, 이때 위의 표가 확장되고 hashList.list 메서드의 결과에 최신 목록과 유사한 결과가 표시됩니다.

데이터베이스 업데이트

클라이언트는 정기적으로 hashList.get 메서드 또는 hashLists.batchGet 메서드를 호출하여 데이터베이스를 업데이트합니다. 일반적인 클라이언트는 한 번에 여러 목록을 업데이트하려고 하므로 hashLists.batchGet 메서드를 사용하는 것이 좋습니다.

목록 이름은 변경되지 않습니다. 또한 목록이 표시되면 삭제되지 않습니다. 목록이 더 이상 유용하지 않은 경우 비워지지만 계속 존재합니다. 따라서 Google 세이프 브라우징 클라이언트 코드에 이러한 이름을 하드코딩하는 것이 적절합니다.

hashList.get 메서드hashLists.batchGet 메서드 모두 증분 업데이트를 지원합니다. 증분 업데이트를 사용하면 대역폭을 절약하고 성능을 개선할 수 있습니다. 증분 업데이트는 클라이언트의 목록 버전과 목록의 최신 버전 간의 델타를 전송하여 작동합니다. 클라이언트가 새로 배포되었으며 사용 가능한 버전이 없는 경우 전체 업데이트를 사용할 수 있습니다. 증분 업데이트에는 삭제 색인과 추가가 포함됩니다. 클라이언트는 먼저 지정된 색인의 항목을 로컬 데이터베이스에서 삭제한 다음 추가를 적용해야 합니다.

마지막으로 손상을 방지하기 위해 클라이언트는 저장된 데이터를 서버에서 제공한 체크섬과 대조해야 합니다. 체크섬이 일치하지 않을 때마다 클라이언트는 전체 업데이트를 실행해야 합니다.

목록 콘텐츠 디코딩

해시 및 해시 접두사 디코딩

모든 목록은 크기를 줄이기 위해 특수 인코딩을 사용하여 전송됩니다. 이 인코딩은 Google 세이프 브라우징 목록에 개념적으로 랜덤 정수와 통계적으로 구분할 수 없는 해시 또는 해시 접두사 집합이 포함되어 있음을 인식하여 작동합니다. 이러한 정수를 정렬하고 인접한 차이를 취하면 이러한 인접한 차이는 어떤 의미에서는 '작음'일 것으로 예상됩니다. 그러면 Golomb-Rice 인코딩이 이 소형성을 활용합니다.

4바이트 해시 접두사를 사용하여 a.example.com/, b.example.com/, y.example.com/라는 세 개의 호스트 접미사 경로 접두사 표현식을 전송한다고 가정해 보겠습니다. 또한 k로 표시되는 Rice 매개변수가 다음과 같이 선택되었다고 가정합니다.

  1. 서버는 먼저 이러한 문자열의 전체 해시를 계산합니다. 각각의 해시는 다음과 같습니다.
291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc  a.example.com/
1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c  b.example.com/
f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03  y.example.com/

그런 다음 서버는 위의 각 항목에 대해 4바이트 해시 접두사를 형성합니다. 이는 32바이트 전체 해시의 첫 4바이트이며 big-endian 32비트 정수로 해석됩니다. Big-endianness는 전체 해시의 첫 번째 바이트가 32비트 정수의 최상위 바이트가 된다는 사실을 나타냅니다. 이 단계를 완료하면 정수 0x291bc542, 0x1d32c508, 0xf7a502e5가 생성됩니다.

서버는 이 세 개의 해시 접두사를 사전순으로 정렬해야 합니다 (빅엔디언의 숫자 정렬과 동일). 정렬 결과는 0x1d32c508, 0x291bc542, 0xf7a502e5입니다. 첫 번째 해시 접두사는 변경되지 않은 상태로 first_value 필드에 저장됩니다.

그런 다음 서버는 두 개의 인접한 차이(각각 0xbe9003a 및 0xce893da3)를 계산합니다. k가 30으로 선택된 경우 서버는 이 두 숫자를 각각 길이가 2비트와 30비트인 몫 부분과 나머지 부분으로 나눕니다. 첫 번째 숫자의 경우 몫 부분은 0이고 나머지는 0xbe9003a입니다. 두 번째 숫자의 경우 최상위 두 비트가 바이너리로 11이고 나머지는 0xe893da3이므로 몫 부분은 3입니다. 주어진 몫 q의 경우 정확히 1 + q비트를 사용하여 (1 << q) - 1로 인코딩됩니다. 나머지는 k비트를 사용하여 직접 인코딩됩니다. 첫 번째 숫자의 몫 부분은 0으로 인코딩되고 나머지 부분은 바이너리 001011111010010000000000111010입니다. 두 번째 숫자의 몫 부분은 0111로 인코딩되고 나머지 부분은 001110100010010011110110100011입니다.

이러한 숫자가 바이트 문자열로 형성되면 리틀 엔디언이 사용됩니다. 개념적으로는 최하위 비트부터 긴 비트 문자열이 형성된다고 생각하는 것이 더 쉽습니다. 첫 번째 숫자의 몫 부분을 취하고 첫 번째 숫자의 나머지 부분을 앞에 추가합니다. 그런 다음 두 번째 숫자의 몫 부분을 앞에 추가하고 나머지 부분을 앞에 추가합니다. 그러면 다음과 같은 큰 숫자가 표시됩니다 (명확성을 위해 줄바꿈 및 주석 추가됨).

001110100010010011110110100011 # Second number, remainder part
0111 # Second number, quotient part
001011111010010000000000111010 # First number, remainder part
0 # First number, quotient part

한 줄로 작성하면 다음과 같습니다.

00111010001001001111011010001101110010111110100100000000001110100

이 숫자는 단일 바이트에 사용할 수 있는 8비트를 훨씬 초과합니다. 그러면 little endian 인코딩은 이 숫자의 최하위 8비트를 사용하여 첫 번째 바이트인 01110100으로 출력합니다. 명확성을 위해 위의 비트 문자열을 최하위 비트부터 시작하여 8개 그룹으로 그룹화할 수 있습니다.

0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100

그런 다음 little endian 인코딩은 오른쪽에서 각 바이트를 가져와 바이트 문자열에 넣습니다.

01110100
00000000
11010010
10010111
00011011
11101101
01001001
01110100
00000000

개념적으로 왼쪽의 큰 수에 새 부분을 앞부분에 추가 (즉, 더 많은 유효 자릿수를 추가)하지만 오른쪽에서 인코딩 (즉, 최소 유효 자릿수)하므로 인코딩과 디코딩을 점진적으로 실행할 수 있습니다.

결국 다음과 같은 결과가 발생합니다.

additions_four_bytes {
  first_value: 489866504
  rice_parameter: 30
  entries_count: 2
  encoded_data: "t\000\322\227\033\355It\000"
}

클라이언트는 위의 단계를 역순으로 따라 해시 접두사를 디코딩합니다.

삭제 색인 디코딩

삭제 색인은 32비트 정수를 사용하여 위와 동일한 기술을 사용하여 인코딩됩니다.

업데이트 빈도

클라이언트는 minimum_wait_duration 필드에서 서버의 반환 값을 검사하고 이를 사용하여 데이터베이스의 다음 업데이트를 예약해야 합니다. 이 값은 0일 수 있습니다 (minimum_wait_duration 필드가 완전히 누락됨). 이 경우 클라이언트는 즉시 다른 업데이트를 실행해야 합니다.