itunes_receipt_decoder 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|