Intorduction | Validating Receipts Locally | Validating Receipts With the App Store | Receipt Fields

본 페이지는 About Receipt Validation 문서의 Validating Receipts Locally 부분을 번역해 놓은 페이지 입니다. 발 번역이라 이상한 부분이 있을 수 있습니다. 발견즉시 댓글을 달아 주세요.


Validating Receipts Locally
로컬 영수증 유효성 검사

Perform receipt validation immediately after your app is launched, before displaying any user interface or spawning any child processes. Implement this check in themain function, before the NSApplicationMain function is called. For additional security, you may repeat this check periodically while your application is running.

앱이 모든 사용자 인터페이스 또는 산란 자식 프로세스를 표시하기 전에, 출시 직후 영수증 유효성 검사를 수행합니다.NSApplicationMain 함수가 호출되기 전에 themain 함수에서이 검사를 구현합니다. 응용 프로그램이 실행되는 동안 추가적인 보안을 위해 주기적으로 검사를 반복 할 수 있습니다.

Locate and Parse the Receipt
찾아 영수증을 구문 분석

When an application is installed from the App Store, it contains an application receipt that is cryptographically signed, ensuring that only Apple can create valid receipts. The receipt is stored inside the application bundle. Call the appStoreReceiptURL method of the NSBundle class to locate the receipt.

응용 프로그램이 앱 스토어에서 설치하는 경우, 그것은 단지 애플이 유효한 영수증을 만들 수 있도록, 암호화 서명 된 응용 프로그램의 영수증을 포함하고 있습니다.영수증은 응용 프로그램 번들 내부에 저장됩니다.영수증을 찾을 수 NSBundle 클래스의 appStoreReceiptURL 메서드를 호출합니다.

The receipt is a binary file with the structure shown in Figure 1-1.

Figure 1-1  Structure of a receipt

The outermost portion (labeled Receipt in the figure) is a PKCS #7 container, as defined by RFC 2315, with its payload encoded using ASN.1 (Abstract Syntax Notation One), as defined by ITU-T X.690. The payload is composed of a set of receipt attributes. Each receipt attribute contains a type, a version, and a value.

RFC 2315에 정의 된 가장 바깥 쪽 부분 (그림에서 표시된 영수증) 인코딩은 페이로드와 같은 ITU-T X.690에 정의 된 ASN.1 (추상 구문 표기법 1)를 사용하여, 위 컨테이너 PKCS입니다.페이로드 영수증 속성의 집합으로 구성되어 있습니다. 각 영수증 속성은 유형, 버전 및 값을 포함합니다.

The structure of the payload is defined using ASN.1 notation in Listing 1-1. You can use this definition with the asn1c tool to generate data type declarations and functions for decoding the payload, rather than writing that part of your code by hand. You may need to install asn1c first; it is available through MacPorts andSourceForge.

페이로드의 구조는 1-1 목록에 ASN.1 표기법을 사용하여 정의됩니다. 당신은 오히려 손으로 코드의 해당 부분을 작성하는 것보다 디코딩 페이로드 데이터 형식 선언과 함수를 생성하는 asn1c 도구를 사용하여이 정의를 사용할 수 있습니다. 당신은 asn1c를 먼저 설치해야 할 수도 있습니다, ​​그것은 MacPorts를 andSourceForge를 통해 사용할 수 있습니다.

For information about keys found in a receipt, see “Receipt Fields.”

영수증에있는 키에 대한 자세한 내용은 "영수증 필드"를 참조하십시오.

To generate the code, save the payload description shown in Listing 1-1 to a file and, in Terminal, run the following command:

코드를 생성하려면, 파일 1-1 리스팅에 표시된 페이로드 설명을 저장하고, 터미널에서 다음 명령을 실행합니다 :

asn1c -fnative-types filename

After the asn1c tool finishes generating files in the current directory, add the files it generated to your Xcode project.

asn1c 도구는 현재 디렉토리에 생성 파일을 완료 한 후, 당신의 Xcode 프로젝트에 생성 된 파일을 추가합니다.

Listing 1-1  ASN.1 definition of the payload format

ReceiptModule DEFINITIONS ::=
BEGIN
 
ReceiptAttribute ::= SEQUENCE {
    type    INTEGER,
    version INTEGER,
    value   OCTET STRING
}
 
Payload ::= SET OF ReceiptAttribute
 
END

Compute the Hash of the GUID
GUID의 해시를 계산

In OS X, use the method described in “Get the GUID on OS X” to fetch the computer’s GUID.

OS X에서 컴퓨터의 GUID를 가져 오기 위해 "OS X에서 GUID를 가져 오기"에 설명 된 방법을 사용합니다.

In iOS, use the value returned by the identifierForVendor property of UIDevice as the computer’s GUID.

이오스, 컴퓨터의 GUID로 UIDevice의 identifierForVendor 속성에 의해 반환 된 값을 사용합니다.

To compute the hash, first concatenate the GUID value with the opaque value (the attribute of type 4) and the bundle identifier. Use the raw bytes from the receipt without performing any UTF-8 string interpretation or normalization. Then compute the SHA-1 hash of this concatenated series of bytes.

해시를 계산하려면 먼저 불투명 한 값 (유형 4의 속성)와 번들 식별자 GUID 값을 연결합니다. 모든 UTF-8 문자열을 해석 또는 정규화를 수행하지 않고 영수증에서 원시 바이트를 사용합니다. 그런 다음 바이트의이 연결된 일련의 SHA-1 해시를 계산합니다.

Validate the Receipt
영수증 검증

To validate the receipt, perform the following tests, in order:
영수증을 확인하려면, 다음과 같은 순서로 검사를 수행합니다 :

  1. Locate the receipt.
    영수증을 찾습니다.

    If no receipt is present, validation fails.
    어떤 영수증이 없으면 유효성 검사가 실패합니다.

  2. Verify that the receipt is properly signed by Apple.
    영수증이 제대로 애플에 의해 서명되어 있는지 확인합니다.

    If it is not signed by Apple, validation fails.
    그것은 애플에 의해 서명되어 있지 않은 경우, 유효성 검사가 실패합니다.

  3. Verify that the bundle identifier in the receipt matches a hard-coded constant containing the CFBundleIdentifier value you expect in the Info.plist file.
    영수증의 번들 식별자는의 Info.plist 파일에서 기대 CFBundleIdentifier 값을 포함하는 하드 코딩 된 상수를 일치하는지 확인합니다.

    If they do not match, validation fails.
    일치하지 않는 경우 유효성 검사가 실패합니다.

  4. Verify that the version identifier string in the receipt matches a hard-coded constant containing the CFBundleShortVersionString value you expect in theInfo.plist file.
    영수증의 버전 식별자 문자열이 theInfo.plist 파일에서 기대 CFBundleShortVersionString 값을 포함하는 하드 코딩 된 상수를 일치하는지 확인합니다.

    If they do not match, validation fails.
    일치하지 않는 경우 유효성 검사가 실패합니다.

  5. Compute the hash of the GUID as described in “Compute the Hash of the GUID.”
    에 설명 된대로 GUID의 해시 계산 "GUID의 해시를 계산합니다."

    If the result does not match the hash in the receipt, validation fails.
    결과가 영수증 해시 일치하지 않는 경우 유효성 검사가 실패합니다.

If all of the tests pass, validation passes.
모든 테스트가 통과하면, 유효성 검사를 통과합니다.

If your app supports the Volume Purchase Program, check the receipt’s expiration date.
앱이 볼륨 구매 프로그램을 지원하는 경우, 영수증의 만료 날짜를 확인합니다.

Respond to Receipt Validation Failure
영수증 유효성 검사 실패에 응답

Validation can fail for a variety of reasons. For example, when users copy your application from one Mac to another, the GUID no longer matches, causing receipt validation to fail.

유효성 검사는 여러 가지 이유로 실패 할 수 있습니다. 예를 들어, 사용자가 다른 하나의 맥에서 응용 프로그램을 복사, GUID는 더 이상 일치, 영수증 유효성 검사가 실패하는 원인이됩니다.

Exit If Validation Fails in OS X
유효성 검사 OS X에 실패하면 종료

If validation fails in OS X, call exit with a status of 173. This exit status notifies the system that your application has determined that its receipt is invalid. At this point, the system attempts to obtain a valid receipt and may prompt for the user’s iTunes credentials.

유효성 검사 OS X에 실패하는 경우, 173 상태로 종료를 호출합니다. 이 종료 상태는 응용 프로그램의 접수가 유효 함을 확인하는 시스템을 알립니다. 이 시점에서, 시스템은 유효한 영수증을 얻기 위해 시도하고 사용자의 아이튠즈 자격 증명을 묻는 메시지를 표시 할 수 있습니다.

If the system successfully obtains a valid receipt, it relaunches the application. Otherwise, it displays an error message to the user, explaining the problem.

시스템이 성공적으로 유효한 영수증을 얻는 경우, 응용 프로그램을 다시 실행합니다. 그렇지 않으면, 문제를 설명하는 사용자에게 오류 메시지를 표시합니다.

Do not display any error message to the user if validation fails. The system is responsible for trying to obtain a valid receipt or informing the user that the receipt is not valid.

유효성 검사가 실패하면 사용자에게 오류 메시지가 표시되지 않습니다. 이 시스템은 유효한 영수증을 얻기 위해 노력하거나 영수증이 유효하지 않음을 사용자에게 알리는 책임이 있습니다.

Refresh the Receipt If Validation Fails in iOS
유효성 검사 이오스 실패하면 영수증을 새로 고침

If validation fails in iOS, use the SKReceiptRefreshRequest class to refresh the receipt.
유효성 검사가 IOS에 실패하는 경우, 영수증을 새로 SKReceiptRefreshRequest 클래스를 사용합니다.

Do not try to terminate the app. At your option, you may give the user a grace period or restrict functionality inside your app.
응용 프로그램을 종료하지 마십시오. 여러분의 선택에 따라, 사용자에게 유예 기간을 부여하거나 응용 프로그램 내부의 기능을 제한 할 수 있습니다.

Set a Minimum System Version for Mac Apps
맥 애플 리케이션을위한 최소 시스템 버전을 설정

Include the LSMinimumSystemVersion key with a value of 10.6.6 or greater in your application’s Info.plist file. If receipt validation fails on versions of OS X earlier than 10.6.6, your application quits immediately after launch with no explanation to the user. Earlier versions of OS X do not interpret the exit status of 173, so they do not try to obtain a valid receipt or display any error message.

10.6.6 또는 응용 프로그램의의 Info.plist 파일에 큰의 값 LSMinimumSystemVersion 키를 포함합니다. 영수증 확인은 10.6.6 이전 OS X 버전에 실패 할 경우, 응용 프로그램이 사용자에게없는 설명과 출시 후 즉시 종료됩니다. OS X의 초기 버전은 173 종료 상태를 해석하지 않습니다, ​​그래서 그들은 유효한 영수증을 얻거나 오류 메시지를 표시하지 않습니다.

Don’t Localize Your Version Number
버전 번호를 지역화하지 않습니다

If your application is localized, the CFBundleShortVersionString key should not appear in any of your application’s InfoPlist.strings files. The unlocalized value from your Info.plist file is stored in the receipt—attempting to localize the value for this key can cause receipt validation to fail.

응용 프로그램이 지역화 된 경우, CFBundleShortVersionString 키는 응용 프로그램의 InfoPlist.strings 파일 중 하나에 나타나지 않아야합니다. 귀하의 Info.plist 파일에서 지역화되지 않은 값은 실패 영수증 - 시도이 키에 대한 값을 지역화하는 것은 발생할 수 있습니다 영수증 검증에 저장됩니다.

Protect Your Validation Check
유효성 검사 체크인 보호

An attacker may try to circumvent the validation code by patching your application binary or altering the basic operating system routines that the validation code depends upon. Resilience against these types of attacks requires a variety of coding techniques, including the following:

공격자는 패치 응용 프로그램 바이너리 또는 유효성 검사 코드에 의존하는 기본 운영 체제 루틴을 변경하여 유효성 검사 코드를 우회하기 위해 시도 할 수 있습니다. 이러한 유형의 공격에 대한 복원은 다음과 같은 코딩 기술의 다양한 필요

  • Inline the code for cryptographic checks instead of using the APIs provided by the system.
    대신에 시스템에서 제공하는 API를 사용하는 암호화 검사에 대한 코드를 인라인.

  • Avoid simple code constructions that provide a trivial target for patching the application binary.
    패치 응용 프로그램 이진에 대한 사소한 대상을 제공하는 간단한 코드 구조물을 피하십시오.

    For example, avoid writing code like the following:
    예를 들어, 다음과 같은 코드를 작성하지 :

    if (failedValidation) {
       exit(173);
    }
  • Implement code robustness techniques, such as obfuscation.
    같은 난독 같은 코드 견고성 기술을 구현합니다.

    If multiple applications use the same code for performing validation, this common code signature can be targeted by tools that patch application binaries.
    여러 응용 프로그램이 유효성 검사를 수행하기 위해 동일한 코드를 사용하는 경우,이 공통 코드 서명은 패치 응용 프로그램 이진있는 도구의 대상이 될 수 있습니다.

  • Ensure that, even if the exit function fails to terminate your application, your application stops running.
    exit 함수는 응용 프로그램을 종료하는 데 실패하더라도 다음을 확인하여 응용 프로그램 실행이 중지됩니다.

Test During the Development Process
개발 과정에서 테스트

In order to test your main application during the development process, you need a valid receipt so that your application launches. To set this up, do the following:
응용 프로그램이 실행되도록 개발 과정에서의 주요 응용 프로그램을 테스트하기 위해, 당신은 유효한 영수증이 필요합니다. 이 설정하려면 다음을 수행하십시오 :

  1. Make sure you have Internet access so you can connect to Apple’s servers.
    당신이 애플의 서버에 연결할 수 있도록 인터넷에 액세스 할 수 있는지 확인합니다.

  2. Launch your application by double-clicking on it (or in some way cause Launch Services to launch it).
    그 (또는 원인 발사 서비스를 실행하는 몇 가지 방법)을 두 번 클릭하여 응용 프로그램을 시작합니다.

After you launch your application, the following occurs:
응용 프로그램을 실행하면 다음과 같은 결과가 발생합니다 :

  • Your application fails to validate its receipt because there is no receipt present, and it exits with a status of 173.
    응용 프로그램은 아무 영수증 존재가없고, 173의 상태로 종료하기 때문에 영수증을 확인하는 데 실패합니다.

  • The system interprets the exit status and attempts to obtain a valid receipt. Assuming your application signing certificate is valid, the system installs a valid receipt for the application. The system may prompt you for your iTunes credentials.
    시스템 종료 상태를 해석하고 유효한 영수증을 얻기 위해 시도합니다. 응용 프로그램 서명 인증서를 가정하는 것은 유효하다, 시스템은 응용 프로그램에 대한 유효한 영수증을 설치합니다.시스템은 아이튠즈 자격 증명을 입력하라는 메시지가 표시 될 수 있습니다.

  • The system relaunches your application, and your application successfully validates the receipt.
    시스템은 응용 프로그램을 다시 실행하고 응용 프로그램이 성공적으로 영수증을 확인합니다.

With this development receipt installed, you can launch your application by any method—for example, with gdb or the Xcode debugger.
이 개발 영수증이 설치된, 당신은 어떤 방법 - 예를 들어, GDB 또는 Xcode의 디버거를 사용하여 응용 프로그램을 시작할 수 있습니다.

Validate In-App Purchases
인 - 앱 구매를 검증

To validate an in-app purchase, your application performs the following tests, in order:
응용 프로그램 내 구입을 확인하려면, 응용 프로그램이 순서대로 다음 테스트를 수행합니다 :

  1. Parse and validate the application’s receipt, as described in the previous sections.
    분석하고 이전 섹션에서 설명한대로 응용 프로그램의 영수증을 확인합니다.

    If the receipt is not valid, none of the in-app purchases are valid.
    영수증이 유효하지 않은 경우, 응용 프로그램 내 구입의 것도 유효하지 않습니다.

  2. Parse the in-app purchase receipts (the values for the attributes of type 17).
    인 - 앱 구매 영수증 (유형 17의 특성에 대한 값) 구문 분석합니다.

    Each in-app purchase receipt consists of a set of attributes, like the application’s receipt does. The structure for these receipts is defined in Listing 1-2. As when parsing the receipt, you can generate some of your code from the ASN.1 description using the asn1c tool. Ignore all attributes with types that do not appear in the table—they are reserved for use by the system and their contents may change at any time.

    응용 프로그램의 접수가하는 것처럼 각각의 응용 프로그램 내 구입 영수증은 속성의 집합으로 구성됩니다. 이 영수증에 대한 구조는 Listing 1-2에 정의되어 있습니다.영수증을 구문 분석 할 때, 당신은 asn1c 도구를 사용하여 ASN.1 설명에서 일부 코드를 생성 할 수 있습니다. 에 나타나지 않는 유형의 모든 속성을 무시 테이블들은 시스템 사용을 위해 예약되어 해당 내용을 언제든지 변경 될 수 있습니다.

    For information about the fields in a receipt, see “Receipt Fields.”
    영수증의 필드에 대한 자세한 내용은 "영수증 필드"를 참조하십시오.

  3. Compare the product identifier in question to the product identifier of each in-app purchase receipt.
    각 응용 프로그램 내 구입 영수증의 제품 식별자에 문제가있는 제품 ID를 비교합니다.

    If there is a receipt that matches, validation succeeds. Otherwise, validation fails.
    일치, 유효성 검사가 성공하는 영수증이있는 경우. 그렇지 않으면 유효성 검사가 실패합니다.

When validation succeeds, your application enables the purchased functionality—for example, by downloading content or adding features. When validation fails, your application simply does not enable the functionality.

유효성 검사가 성공하면 응용 프로그램 구입 기능을 위해 수 있습니다 예를 들어, 콘텐츠를 다운로드하거나 기능을 추가하여. 유효성 검사에 실패 할 경우, 응용 프로그램은 단순히 기능을 사용하지 않습니다.

Listing 1-2  ASN.1 definition of the in-app purchase receipt format

InAppAttribute ::= SEQUENCE {
    type                   INTEGER,
    version                INTEGER,
    value                  OCTET STRING
}
 
InAppReceipt ::= SET OF InAppAttribute

The attributes for the original transaction identifier and original transaction date are used when a purchase is redownloaded. The redownloaded purchase is given a new transaction identifier, but it contains the identifier and date of the original purchase.

구매가 다시 다운로드 할 때 원래의 트랜잭션 식별자와 원래 트랜잭션 날짜 속성이 사용됩니다.다시 다운로드 구매는 새 트랜잭션 식별자를 부여하지만, 그것은 원래 구입의 ID 및 날짜를 ​​포함합니다.

Implementation Tips
구현 팁

This section contains several code listings for your reference as you implement receipt validation.
당신은 영수증 유효성 검사를 구현하는이 절은 당신의 참고를위한 몇 가지 코드 샘플이 포함되어 있습니다.

Get the GUID in OS X
OS X에서 GUID를 얻을 수

In OS X, follow the model in Listing 1-3 (or even use this exact same code), so that the method you use to get the GUID in your validation code is exactly the same as the method used when the application’s receipt was created.

OS X에서 유효성 검사 코드에서 GUID를 얻기 위해 사용하는 방법은 응용 프로그램의 접수를 만들 때 사용되는 메소드와 정확히 동일하므로, 목록 1-3 (또는이 동일한 코드를 사용)의 모델을 따르는 .

Listing 1-3  Get the computer’s GUID

#import <IOKit/IOKitLib.h>
#import <Foundation/Foundation.h>
 
// Returns a CFData object, containing the computer's GUID.
CFDataRef copy_mac_address(void)
{
    kern_return_t             kernResult;
    mach_port_t               master_port;
    CFMutableDictionaryRef    matchingDict;
    io_iterator_t             iterator;
    io_object_t               service;
    CFDataRef                 macAddress = nil;
 
    kernResult = IOMasterPort(MACH_PORT_NULL, &master_port);
    if (kernResult != KERN_SUCCESS) {
        printf("IOMasterPort returned %d\n", kernResult);
        return nil;
    }
 
    matchingDict = IOBSDNameMatching(master_port, 0, "en0");
    if (!matchingDict) {
        printf("IOBSDNameMatching returned empty dictionary\n");
        return nil;
    }
 
    kernResult = IOServiceGetMatchingServices(master_port, matchingDict, &iterator);
    if (kernResult != KERN_SUCCESS) {
        printf("IOServiceGetMatchingServices returned %d\n", kernResult);
        return nil;
    }
 
    while((service = IOIteratorNext(iterator)) != 0) {
        io_object_t parentService;
 
        kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane,
                &parentService);
        if (kernResult == KERN_SUCCESS) {
            if (macAddress) CFRelease(macAddress);
 
            macAddress = (CFDataRef) IORegistryEntryCreateCFProperty(parentService,
                    CFSTR("IOMACAddress"), kCFAllocatorDefault, 0);
            IOObjectRelease(parentService);
        } else {
            printf("IORegistryEntryGetParentEntry returned %d\n", kernResult);
        }
 
        IOObjectRelease(service);
    }
    IOObjectRelease(iterator);
 
    return macAddress;
}

Parse the Receipt and Verify Its Signature

영수증을 구문 분석하고 그 서명을 확인

Use the following code listings as an outline of one possible implementation of receipt validation using OpenSSL and asn1c. These listings are provided to guide you as you write your own code, by highlighting relevant APIs and data structures, not to use as a copy-and-paste solution.

OpenSSL을하고 asn1c를 사용하여 수신 확인의 한 가지 가능한 구현의 개요 다음 코드 목록을 사용합니다. 이 목록은 당신이 당신의 자신의 코드를 작성할 때 복사 및 붙여 넣기 솔루션으로 사용하지 않는, 관련 API 및 데이터 구조를 강조하여 당신을 안내하기 위해 제공됩니다.

If you use OpenSSL, statically link your binary against it. Dynamic linking against OpenSSL is deprecated and results in build warnings.

OpenSSL을 사용하는 경우, 정적으로로부터 바이너리를 연결합니다. OpenSSL에 대한 동적 링크는 경고를 구축에 사용되지 않으며 결과입니다.

Make sure your code does the following as outlined in the listings:
목록에 설명 된대로 코드는 다음 작업을 수행해야합니다 :

  1. Verify the signature (Listing 1-4).

  2. Parse the payload (Listing 1-5).

  3. Extract the receipt attributes (Listing 1-6).

  4. Compute the hash of the GUID (Listing 1-7).

Listing 1-4  Verify the signature using OpenSSL
목록 1-4 OpenSSL을 사용하여 서명을 확인

/* The PKCS #7 container (the receipt) and the output of the verification. */
BIO *b_p7;
PKCS7 *p7;
 
/* The Apple root certificate, as raw data and in its OpenSSL representation. */
BIO *b_x509;
X509 *Apple;
 
/* The root certificate for chain-of-trust verification. */
X509_STORE *store = X509_STORE_new();
 
/* ... Initialize both BIO variables using BIO_new_mem_buf() with a buffer and its size ... */
 
/* Initialize b_out as an output BIO to hold the receipt payload extracted during signature verification. */
BIO *b_out = BIO_new(BIO_s_mem());
 
/* Capture the content of the receipt file and populate the p7 variable with the PKCS #7 container. */
p7 = d2i_PKCS7_bio(b_p7, NULL);
 
/* ... Load the Apple root certificate into b_X509 ... */
 
/* Initialize b_x509 as an input BIO with a value of the Apple root certificate and load it into X509 data structure. Then add the Apple root certificate to the structure. */
Apple = d2i_X509_bio(b_x509, NULL);
X509_STORE_add_cert(store, Apple);
 
/* Verify the signature. If the verification is correct, b_out will contain the PKCS #7 payload and rc will be 1. */
int rc = PKCS7_verify(p7, NULL, store, NULL, b_out, 0);
 
/* For additional security, you may verify the fingerprint of the root certificate and verify the OIDs of the intermediate certificate and signing certificate. The OID in the certificate policies extension of the intermediate certificate is (1 2 840 113635 100 5 6 1), and the marker OID of the signing certificate is (1 2 840 113635 100 6 11 1). */

Listing 1-5  Parse the payload using asn1c
목록 1-5 asn1c을 사용하여 페이로드를 구문 분석

#include "Payload.h" /* This header file is generated by asn1c. */
 
/* The receipt payload and its size. */
void *pld = NULL;
size_t pld_sz;
 
/* Variables used to parse the payload. Both data types are declared in Payload.h. */
Payload_t *payload = NULL;
asn_dec_rval_t rval;
 
/* ... Load the payload from the receipt file into pld and set pld_sz to the payload size ... */
 
/* Parse the buffer using the decoder function generated by asn1c.  The payload variable will contain the receipt attributes. */
rval = asn_DEF_Payload.ber_decoder(NULL, &asn_DEF_Payload, (void **)&payload, pld, pld_sz, 0);

Listing 1-6  Extract the receipt attributes
목록 1-6 영수증 특성을 추출

/* Variables used to store the receipt attributes. */
OCTET_STRING_t *bundle_id = NULL;
OCTET_STRING_t *bundle_version = NULL;
OCTET_STRING_t *opaque = NULL;
OCTET_STRING_t *hash = NULL;
 
/* Iterate over the receipt attributes, saving the values needed to compute the GUID hash. */
size_t i;
for (i = 0; i < payload->list.count; i++) {
    ReceiptAttribute_t *entry;
 
    entry = payload->list.array[i];
 
    switch (entry->type) {
        case 2:
            bundle_id = &entry->value;
            break;
        case 3:
            bundle_version = &entry->value;
            break;
        case 4:
            opaque = &entry->value;
            break;
        case 5:
            hash = &entry->value;
            break;
        }
    }

Listing 1-7  Compute the hash of the GUID
목록 1-7 GUID의 해시를 계산

/* The GUID returned by copy_mac_address() is a CFDataRef.  Use CFDataGetBytePtr() and CFDataGetLength() to get a pointer to the bytes that make up the GUID and to get its length. */
UInt8 *guid = NULL;
size_t guid_sz;
 
/* Declare and initialize an EVP context for OpenSSL. */
EVP_MD_CTX evp_ctx;
EVP_MD_CTX_init(&evp_ctx);
 
/* A buffer for result of the hash computation. */
UInt8 digest[20];
 
/* Set up the EVP context to compute a SHA-1 digest. */
EVP_DigestInit_ex(&evp_ctx, EVP_sha1(), NULL);
 
/* Concatenate the pieces to be hashed.  They must be concatenated in this order. */
EVP_DigestUpdate(&evp_ctx, guid, guid_sz);
EVP_DigestUpdate(&evp_ctx, opaque->buf, opaque->size);
EVP_DigestUpdate(&evp_ctx, bundle_id->buf, bundle_id->size);
 
/* Compute the hash, saving the result into the digest variable. */
EVP_DigestFinal_ex(&evp_ctx, digest, NULL);

Posted by 창업자닉군
,