Sha256: dd9ac4b04743e3ddd694aef6a00b59dee3670c989db620130ec6f85940853025

Contents?: true

Size: 1.5 KB

Versions: 2

Compression:

Stored size: 1.5 KB

Contents

# frozen_string_literal: true

require 'openssl'

module AppleReceipt
  # Validator allows one to check the validity of a receipt.
  class Validator
    INTERMEDIATE_CERT_MAPPING = {
      3 => 'AppleWorldwideDeveloperRelationsCertificationAuthority',
      2 => 'AppleITunesStoreCertificationAuthority'
    }.freeze

    def initialize(receipt, certificates: [])
      populate_certificate_store(receipt.version, certificates)
      @receipt = receipt
    end

    def populate_certificate_store(version, provided_certificates)
      if provided_certificates.any?
        add_certificates(provided_certificates)
      else
        add_named_certificate('AppleRootCA')
        add_named_certificate(INTERMEDIATE_CERT_MAPPING[version])
      end
    end

    def add_named_certificate(name)
      cert_path = File.expand_path("../../certificates/#{name}.cer", __dir__)
      cert_file = File.read(cert_path)
      store.add_cert(OpenSSL::X509::Certificate.new(cert_file))
    end

    def add_certificates(certificates)
      certificates.each do |cert|
        store.add_cert(cert)
      end
    end

    def valid?
      store.verify(receipt.certificate) &&
        public_key.verify(OpenSSL::Digest::SHA1.new,
                          receipt.signature, signed_data)
    end

    def public_key
      receipt.certificate.public_key
    end

    def signed_data
      [receipt.version, receipt.data].pack('CA*')
    end

    def store
      @store ||= OpenSSL::X509::Store.new
    end

    private

    attr_reader :receipt
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
apple_receipt-0.2.2 lib/apple_receipt/validator.rb
apple_receipt-0.2.1 lib/apple_receipt/validator.rb