itunes_receipt_decoder 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/itunes_receipt_decoder.rb +0 -4
- data/lib/itunes_receipt_decoder/decode/base.rb +1 -1
- data/lib/itunes_receipt_decoder/decode/transaction_receipt.rb +36 -8
- data/lib/itunes_receipt_decoder/decode/unified_receipt.rb +40 -4
- data/lib/itunes_receipt_decoder/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be8ac7da532b84da681984f7e5e51e8677133d77
|
4
|
+
data.tar.gz: fc0888f8a80f019e20059535fe6e926ed5c56e40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 056453f28cb7f4b62464736c07cbdc90bfe53aa1802d371075fe418146646d11312047cbec620edea1620c4f0b1b4a80319992db6bbf63f93b28314ce3ada481
|
7
|
+
data.tar.gz: b9d31eb78fef4c3753aa19f610cf092474757bee9b01339b303e8a853a286c30405244fcea628a00bb375a9460b97c4cd9b48e3fbab4bb8b1577a8989c39ae89
|
@@ -1,8 +1,4 @@
|
|
1
|
-
require 'time'
|
2
|
-
require 'openssl'
|
3
|
-
require 'cfpropertylist'
|
4
1
|
require 'itunes_receipt_decoder/version'
|
5
|
-
require 'itunes_receipt_decoder/decode/base'
|
6
2
|
require 'itunes_receipt_decoder/decode/transaction_receipt'
|
7
3
|
require 'itunes_receipt_decoder/decode/unified_receipt'
|
8
4
|
|
@@ -9,7 +9,7 @@ module ItunesReceiptDecoder
|
|
9
9
|
class Base
|
10
10
|
##
|
11
11
|
# The raw receipt, i.e. not base64 encoded
|
12
|
-
attr_reader :raw_receipt, :receipt, :options, :
|
12
|
+
attr_reader :raw_receipt, :receipt, :options, :environment
|
13
13
|
|
14
14
|
##
|
15
15
|
# Initializes with a raw (base64 decoded receipt)
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'cfpropertylist'
|
3
|
+
require 'itunes_receipt_decoder/decode/base'
|
4
|
+
|
1
5
|
##
|
2
6
|
# ItunesReceiptDecoder
|
3
7
|
module ItunesReceiptDecoder
|
@@ -7,9 +11,33 @@ module ItunesReceiptDecoder
|
|
7
11
|
##
|
8
12
|
# ItunesReceiptDecoder::Decode::TransactionReceipt
|
9
13
|
class TransactionReceipt < Base
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
PUBLIC_KEY = OpenSSL::PKey::RSA.new <<-PUBLIC_KEY
|
15
|
+
-----BEGIN PUBLIC KEY-----
|
16
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApLyvMpRDPgu8N4fNY4ny
|
17
|
+
zNm+IE1atP6HZ9Ka3hpUnaLz34fkTMuTEXigMI80QcHTvmZtR2yYuOx61cndpeTq
|
18
|
+
xnD0NdCR97PYChGZqzpiOr179FZP258kk1FQfCDVZk1m8xikE5YiFv0xp/Q5Zpv7
|
19
|
+
YmlcS5+UqEvo7FtkWhh5ihZ1Y0KkSdmMM96te9Y5BPTinQppjOtLEihLNEgHmw5Z
|
20
|
+
+R9isAOfNrhOo9N1WdTzOgXKxTM7+MAGCQiT2+dNvxHzUiylFjUV80ECzQLR/PX4
|
21
|
+
xYS9Y2qG1raZ9oauX/0D1CiKWl2vvGV00fcaw5II9BytaegCTA6VFQe8vmpvwbOt
|
22
|
+
oQIDAQAB
|
23
|
+
-----END PUBLIC KEY-----
|
24
|
+
PUBLIC_KEY
|
25
|
+
|
26
|
+
def style
|
27
|
+
:transaction
|
28
|
+
end
|
29
|
+
|
30
|
+
def signature_valid?
|
31
|
+
version, sig, cert_length, cert =
|
32
|
+
payload.fetch('signature').unpack('m').first.unpack('c a128 N a*')
|
33
|
+
return false unless
|
34
|
+
version == 2 &&
|
35
|
+
sig.size == 128 &&
|
36
|
+
cert.size == cert_length &&
|
37
|
+
(cert = OpenSSL::X509::Certificate.new(cert)) &&
|
38
|
+
cert.verify(PUBLIC_KEY)
|
39
|
+
data = [version, purchase_info].pack('ca*')
|
40
|
+
cert.public_key.verify(OpenSSL::Digest::SHA1.new, sig, data)
|
13
41
|
end
|
14
42
|
|
15
43
|
private
|
@@ -24,16 +52,16 @@ module ItunesReceiptDecoder
|
|
24
52
|
end
|
25
53
|
|
26
54
|
def parse_purchase_info
|
27
|
-
|
55
|
+
result = parse_plist(purchase_info)
|
56
|
+
result.keys.each do |key|
|
28
57
|
new_key = key.tr('-', '_').to_sym
|
29
|
-
|
58
|
+
result[new_key] = result.delete(key)
|
30
59
|
end
|
31
|
-
|
60
|
+
result
|
32
61
|
end
|
33
62
|
|
34
63
|
def purchase_info
|
35
|
-
@purchase_info ||=
|
36
|
-
parse_plist(payload.fetch('purchase-info').unpack('m').first)
|
64
|
+
@purchase_info ||= payload.fetch('purchase-info').unpack('m').first
|
37
65
|
end
|
38
66
|
|
39
67
|
def payload
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'openssl'
|
3
|
+
require 'itunes_receipt_decoder/decode/base'
|
4
|
+
|
1
5
|
##
|
2
6
|
# ItunesReceiptDecoder
|
3
7
|
module ItunesReceiptDecoder
|
@@ -7,6 +11,18 @@ module ItunesReceiptDecoder
|
|
7
11
|
##
|
8
12
|
# ItunesReceiptDecoder::Decode::UnifiedReceipt
|
9
13
|
class UnifiedReceipt < Base
|
14
|
+
PUBLIC_KEY = OpenSSL::PKey::RSA.new <<-PUBLIC_KEY
|
15
|
+
-----BEGIN PUBLIC KEY-----
|
16
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyjhUpstWqsgkOUjpjO7s
|
17
|
+
X7h/JpG8NFN6znxjgGF3ZF6lByO2Of5QLRVWWHAtfsRuwUqFPi/w3oQaoVfJr3sY
|
18
|
+
/2r6FRJJFQgZrKrbKjLtlmNoUhU9jIrsv2sYleADrAF9lwVnzg6FlTdq7Qm2rmfN
|
19
|
+
UWSfxlzRvFduZzWAdjakh4FuOI/YKxVOeyXYWr9Og8GN0pPVGnG1YJydM05V+RJY
|
20
|
+
DIa4Fg3B5XdFjVBIuist5JSF4ejEncZopbCj/Gd+cLoCWUt3QpE5ufXN4UzvwDtI
|
21
|
+
jKblIV39amq7pxY1YNLmrfNGKcnow4vpecBqYWcVsvD95Wi8Yl9uz5nd7xtj/pJl
|
22
|
+
qwIDAQAB
|
23
|
+
-----END PUBLIC KEY-----
|
24
|
+
PUBLIC_KEY
|
25
|
+
|
10
26
|
##
|
11
27
|
# ASN.1 Field types
|
12
28
|
#
|
@@ -15,6 +31,8 @@ module ItunesReceiptDecoder
|
|
15
31
|
0 => :environment,
|
16
32
|
2 => :bundle_id,
|
17
33
|
3 => :application_version,
|
34
|
+
4 => :opaque_value,
|
35
|
+
5 => :sha1_hash,
|
18
36
|
12 => :creation_date,
|
19
37
|
17 => :in_app,
|
20
38
|
19 => :original_application_version,
|
@@ -34,9 +52,22 @@ module ItunesReceiptDecoder
|
|
34
52
|
original_purchase_date expires_date
|
35
53
|
cancellation_date)
|
36
54
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
55
|
+
def style
|
56
|
+
:unified
|
57
|
+
end
|
58
|
+
|
59
|
+
def uuid_valid?(uuid)
|
60
|
+
digest = OpenSSL::Digest::SHA1.new
|
61
|
+
digest << uuid.scan(/[0-9A-F]{2}/).map(&:hex).pack('c*')
|
62
|
+
digest << @receipt[:opaque_value]
|
63
|
+
digest << @raw_bundle_id
|
64
|
+
digest.digest == @receipt[:sha1_hash]
|
65
|
+
end
|
66
|
+
|
67
|
+
def signature_valid?
|
68
|
+
serial = pkcs7.signers.first.serial.to_i
|
69
|
+
cert = pkcs7.certificates.find { |c| c.serial.to_i == serial }
|
70
|
+
cert && cert.verify(PUBLIC_KEY)
|
40
71
|
end
|
41
72
|
|
42
73
|
private
|
@@ -55,7 +86,12 @@ module ItunesReceiptDecoder
|
|
55
86
|
fields.each do |seq|
|
56
87
|
type, _version, value = seq.value.map(&:value)
|
57
88
|
next unless (field = RECEIPT_FIELDS[type.to_i])
|
58
|
-
|
89
|
+
if %i(opaque_value sha1_hash).include?(field)
|
90
|
+
result[field] = value
|
91
|
+
else
|
92
|
+
@raw_bundle_id = value if field == :bundle_id
|
93
|
+
build_result(result, field, value)
|
94
|
+
end
|
59
95
|
end
|
60
96
|
result
|
61
97
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itunes_receipt_decoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mbaasy.com
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: CFPropertyList
|