광고 네트워크의 광고주 식별자 복호화

을(를) 사용하는 광고 네트워크 Authorized Buyers를 통해 광고를 채우는 자바스크립트 태그는 Android 및 iOS 기기 모두의 광고주 식별자를 수신합니다. 정보는 %%EXTRA_TAG_DATA%% 또는 관리되는 JavaScript 태그의 %%ADVERTISING_IDENTIFIER%% 매크로 살펴보겠습니다 이 섹션의 나머지 부분에서는 %%EXTRA_TAG_DATA%%이지만 다음을 확인하세요. <ph type="x-smartling-placeholder"></ph> IDFA 또는 광고 ID를 사용한 리마케팅에서 자세히 알아보세요. %%ADVERTISING_IDENTIFIER%% 암호화된 proto 버퍼에서 MobileAdvertisingId입니다.

타임라인

  1. 광고 네트워크가 JavaScript 인앱 태그를 업데이트함 구매자 UI를 통해 아래에 설명된 대로 %%EXTRA_TAG_DATA%% 매크로를 추가합니다.
  2. 게재 시 앱이 Google 모바일 광고 SDK를 광고주 식별자를 안전하게 전달할 수 있습니다.
  3. 앱이 %%EXTRA_TAG_DATA%%와 함께 JavaScript 태그를 다시 수신합니다. 매크로는 해당 식별자가 포함된 암호화된 광고 네트워크 프로토콜 버퍼로 채워집니다.
  4. 앱은 이 태그를 실행하여 낙찰된 광고의 광고 네트워크를 호출합니다. 있습니다.
  5. 이 정보를 사용 (수익 창출)하려면 광고 네트워크에서 프로토콜 버퍼: <ph type="x-smartling-placeholder">
      </ph>
    1. WebSafeBase64를 사용하여 websafe 문자열을 바이트 문자열로 다시 디코딩합니다.
    2. 아래에 설명된 스키마를 사용하여 복호화합니다.
    3. 프로토콜 역직렬화 및 광고주 ID 가져오기 ExtraTagData.advertising_id 또는 ExtraTagData.hashed_idfa입니다.

종속 항목

  1. WebSafeBase64 인코더와 같이 작동합니다.
  2. SHA-1 HMAC를 지원하는 암호화 라이브러리(예: Openssl)
  3. Google 프로토콜 버퍼 컴파일러를 제공합니다.

웹 안전 문자열 디코딩

%%EXTRA_TAG_DATA%% 매크로를 통해 전송된 정보가 URL을 통해 전송되어야 하는 경우 Google 서버는 웹 보안 base64 (RFC 3548)로 이를 인코딩합니다.

시도하기 전에 ASCII 문자를 암호로 다시 디코딩해야 bytestring입니다. 아래의 샘플 C++ 코드는 OpenSSL을 기반으로 합니다. 프로젝트의 BIO_f_base64()를 포함하며, Google 샘플의 일부임 복호화 코드와 동일합니다.

string AddPadding(const string& b64_string) {
  if (b64_string.size() % 4 == 3) {
    return b64_string + "=";
  } else if (b64_string.size() % 4 == 2) {
    return b64_string + "==";
  }
  return b64_string;
}

// Adapted from http://www.openssl.org/docs/man1.1.0/crypto/BIO_f_base64.html
// Takes a web safe base64 encoded string (RFC 3548) and decodes it.
// Normally, web safe base64 strings have padding '=' replaced with '.',
// but we will not pad the ciphertext. We add padding here because
// openssl has trouble with unpadded strings.
string B64Decode(const string& encoded) {
  string padded = AddPadding(encoded);
  // convert from web safe -> normal base64.
  int32 index = -1;
  while ((index = padded.find_first_of('-', index + 1)) != string::npos) {
    padded[index] = '+';
  }
  index = -1;
  while ((index = padded.find_first_of('_', index + 1)) != string::npos) {
    padded[index] = '/';
  }

  // base64 decode using openssl library.
  const int32 kOutputBufferSize = 256;
  char output[kOutputBufferSize];

  BIO* b64 = BIO_new(BIO_f_base64());
  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
  BIO* bio = BIO_new_mem_buf(const_cast<char*>(padded.data()),
                             padded.length());
  bio = BIO_push(b64, bio);
  int32 out_length = BIO_read(bio, output, kOutputBufferSize);
  BIO_free_all(bio);
  return string(output, out_length);
}

암호화된 바이트 문자열의 구조

ASCII 문자를 다시 바이트 문자열로 디코딩하면 전송합니다. 암호화된 바이트 문자열에는 다음 세 가지 섹션이 있습니다.

  • initialization_vector: 16바이트
  • ciphertext: 일련의 20바이트 섹션입니다.
  • integrity_signature: 4바이트
{initialization_vector (16 bytes)}{ciphertext (20-byte sections)}{integrity_signature (4 bytes)}

ciphertext 바이트 배열은 여러 20바이트로 분할됩니다. 섹션이나 섹션 사이에 1~20바이트입니다. 원본의 각 섹션마다 byte_array: 상응하는 20바이트 ciphertext 다음으로 생성됩니다.

<byte_array <xor> HMAC(encryption_key, initialization_vector || counter_bytes)>

여기서 ||는 연결입니다.

정의

변수 세부정보
initialization_vector 16바이트 - 노출에 고유합니다.
encryption_key 32바이트 - 계정 설정 시 제공됩니다.
integrity_key 32바이트 - 계정 설정 시 제공됩니다.
byte_array 20바이트 섹션으로 구성된 직렬화된 ExtraTagData 객체입니다.
counter_bytes 섹션의 서수를 보여주는 바이트 값입니다. 아래를 참고하세요.
final_message %%EXTRA_TAG_DATA%% 매크로를 통해 전송된 총 바이트 배열입니다 (WebSafeBase64 인코딩 제외).
연산자 세부정보
hmac(key, data) SHA-1 HMAC: key를 사용하여 data를 암호화합니다.
a || b 문자열 ab 문자열과 연결합니다.

카운터_바이트 계산

counter_bytes는 다음 각 20바이트 섹션의 순서를 표시합니다. ciphertext입니다. 마지막 섹션에는 1과 20바이트(포함)입니다. counter_bytes를 올바른 값으로 채우는 방법 hmac() 함수를 실행할 때 20바이트 섹션 계산 (나머지 포함) 다음 참조 표를 사용하세요.

섹션 번호 counter_bytes
0 없음
1... 256 1바이트입니다. 값은 0에서 255까지 순차적으로 증가합니다.
257~512 2바이트입니다. 첫 번째 바이트의 값은 0이고, 두 번째 바이트의 값은 0부터 255까지 순차적으로 증가합니다.
513~768 3바이트입니다. 처음 두 바이트의 값은 0이고 마지막 바이트의 값입니다. 0부터 255까지 순차적으로 증가합니다.

맨 위로

암호화 스키마

이 암호화 체계는 암호화된 데이터를 복호화하는 데 사용된 것과 동일한 지역 밀착형 타겟팅 신호를 사용합니다.

  1. 직렬화: 다음 형식의 ExtraTagData 객체의 인스턴스입니다. 먼저 프로토콜 버퍼에 정의되고 SerializeAsString()을 바이트 배열로 변환합니다.

  2. 암호화: 바이트 배열은 크기 오버헤드를 최소화하면서 고가용성을 보장하도록 설계된 있습니다. 암호화 체계는 키 있는 HMAC 알고리즘을 사용하여 initialization_vector를 기반으로 하는 보안 비밀 패드 노출 이벤트입니다.

암호화 의사코드

byte_array = SerializeAsString(ExtraTagData object)
pad = hmac(encryption_key, initialization_vector ||
      counter_bytes )  // for each 20-byte section of byte_array
ciphertext = pad <xor> byte_array // for each 20-byte section of byte_array
integrity_signature = hmac(integrity_key, byte_array ||
                      initialization_vector)  // first 4 bytes
final_message = initialization_vector || ciphertext || integrity_signature

복호화 체계

복호화 코드는 1) 암호화를 통해 프로토콜 버퍼를 복호화해야 합니다. 2) 무결성 키로 무결성 비트를 확인합니다. 키는 계정 설정 중에 제공됩니다. 데이터를 사용하는 방법에 대한 구체적으로 설명해 주시기 바랍니다. 대부분의 경우 여러분은 필요에 따라 조정할 수 있습니다.

  1. 패드 생성: HMAC(encryption_key, initialization_vector || counter_bytes)
  2. XOR: 이 결과를 가져와서 다음 값으로 <xor> 사용하여 암호화를 반전시킵니다.
  3. 확인: 무결성 서명이 <ph type="x-smartling-placeholder">HMAC(integrity_key, byte_array || initialization_vector)</ph>

복호화 의사코드

// split up according to length rules
(initialization_vector, ciphertext, integrity_signature) = final_message

// for each 20-byte section of ciphertext
pad = hmac(encryption_key, initialization_vector || counter_bytes)

// for each 20-byte section of ciphertext
byte_array = ciphertext <xor> pad

confirmation_signature = hmac(integrity_key, byte_array ||
                         initialization_vector)
success = (confirmation_signature == integrity_signature)

샘플 C++ 코드

여기에는 Google의 전체 인프라에서 복호화 예시 코드를 참고하세요.

bool DecryptByteArray(
    const string& ciphertext, const string& encryption_key,
    const string& integrity_key, string* cleartext) {
  // Step 1. find the length of initialization vector and clear text.
  const int cleartext_length =
     ciphertext.size() - kInitializationVectorSize - kSignatureSize;
  if (cleartext_length < 0) {
    // The length cannot be correct.
    return false;
  }

  string iv(ciphertext, 0, kInitializationVectorSize);

  // Step 2. recover clear text
  cleartext->resize(cleartext_length, '\0');
  const char* ciphertext_begin = string_as_array(ciphertext) + iv.size();
  const char* const ciphertext_end = ciphertext_begin + cleartext->size();
  string::iterator cleartext_begin = cleartext->begin();

  bool add_iv_counter_byte = true;
  while (ciphertext_begin < ciphertext_end) {
    uint32 pad_size = kHashOutputSize;
    uchar encryption_pad[kHashOutputSize];

    if (!HMAC(EVP_sha1(), string_as_array(encryption_key),
              encryption_key.length(), (uchar*)string_as_array(iv),
              iv.size(), encryption_pad, &pad_size)) {
      printf("Error: encryption HMAC failed.\n");
      return false;
    }

    for (int i = 0;
         i < kBlockSize && ciphertext_begin < ciphertext_end;
         ++i, ++cleartext_begin, ++ciphertext_begin) {
      *cleartext_begin = *ciphertext_begin ^ encryption_pad[i];
    }

    if (!add_iv_counter_byte) {
      char& last_byte = *iv.rbegin();
      ++last_byte;
      if (last_byte == '\0') {
        add_iv_counter_byte = true;
      }
    }

    if (add_iv_counter_byte) {
      add_iv_counter_byte = false;
      iv.push_back('\0');
    }
  }

광고 네트워크 프로토콜 버퍼에서 데이터 가져오기

전달된 데이터를 디코딩하고 복호화하면 %%EXTRA_TAG_DATA%%: 프로토콜 버퍼를 역직렬화할 준비가 되었습니다. 타겟팅을 위한 광고주 식별자를 가져옵니다.

프로토콜 버퍼에 대해 잘 모른다면 이 문서부터 시작하세요.

정의

광고 네트워크 프로토콜 버퍼는 다음과 같이 정의됩니다.

message ExtraTagData {
  // advertising_id can be Apple's identifier for advertising (IDFA)
  // or Android's advertising identifier. When the advertising_id is an IDFA,
  // it is the plaintext returned by iOS's [ASIdentifierManager
  // advertisingIdentifier]. For hashed_idfa, the plaintext is the MD5 hash of
  // the IDFA.  Only one of the two fields will be available, depending on the
  // version of the SDK making the request.  Later SDKs provide unhashed values.
  optional bytes advertising_id = 1;
  optional bytes hashed_idfa = 2;
}

아래 설명된 대로 ParseFromString()를 사용하여 이를 역직렬화해야 합니다. C++ 프로토콜 버퍼 문서

Android advertising_id 및 iOS에 관한 자세한 내용 hashed_idfa 필드, 복호화 참고 광고 ID모바일 앱 타겟팅 IDFA가 포함된 인벤토리를 사용합니다.

Java 라이브러리

암호화 및 디코딩을 위한 암호화 알고리즘을 구현하는 대신 광고주 식별자로 구분되므로 <ph type="x-smartling-placeholder"></ph> DoubleClickCrypto.java. 자세한 내용은 암호화.