Class: AppInfo::Android::Signature::Info
- Inherits:
-
Object
- Object
- AppInfo::Android::Signature::Info
- Includes:
- Helper::IOBlock
- Defined in:
- lib/app_info/android/signatures/info.rb
Overview
APK signature scheme signurate info
FORMAT: OFFSET DATA TYPE DESCRIPTION
-
@+0 bytes uint64: size in bytes (excluding this field)
-
@+8 bytes payload
-
@-24 bytes uint64: size in bytes (same as the one above)
-
@-16 bytes uint128: magic value
Constant Summary collapse
- SIG_SIZE_OF_BLOCK_SIZE =
Signature block information
8
- SIG_MAGIC_BLOCK_SIZE =
16
- SIG_BLOCK_MIN_SIZE =
32
- SIG_MAGIC =
Magic value: APK Sig Block 42
[ 0x41, 0x50, 0x4b, 0x20, 0x53, 0x69, 0x67, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x34, 0x32 ].freeze
Instance Attribute Summary collapse
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#magic ⇒ Object
readonly
Returns the value of attribute magic.
-
#pairs ⇒ Object
readonly
Returns the value of attribute pairs.
-
#total_size ⇒ Object
readonly
Returns the value of attribute total_size.
Instance Method Summary collapse
- #cdir_offset ⇒ Object
- #file_io ⇒ Object
-
#initialize(version, parser, logger) ⇒ Info
constructor
A new instance of Info.
- #pares_signatures_pairs ⇒ Object
- #signature_block ⇒ Object
-
#signers(block_id) ⇒ Object
Find singers.
- #start_buffer ⇒ Object
- #zip64? ⇒ Boolean
- #zip_io ⇒ Object
Methods included from Helper::IOBlock
#left_bytes_check, #length_prefix_block, #loop_length_prefix_io
Constructor Details
#initialize(version, parser, logger) ⇒ Info
Returns a new instance of Info.
34 35 36 37 38 39 40 |
# File 'lib/app_info/android/signatures/info.rb', line 34 def initialize(version, parser, logger) @version = version @parser = parser @logger = logger pares_signatures_pairs end |
Instance Attribute Details
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
32 33 34 |
# File 'lib/app_info/android/signatures/info.rb', line 32 def logger @logger end |
#magic ⇒ Object (readonly)
Returns the value of attribute magic.
32 33 34 |
# File 'lib/app_info/android/signatures/info.rb', line 32 def magic @magic end |
#pairs ⇒ Object (readonly)
Returns the value of attribute pairs.
32 33 34 |
# File 'lib/app_info/android/signatures/info.rb', line 32 def pairs @pairs end |
#total_size ⇒ Object (readonly)
Returns the value of attribute total_size.
32 33 34 |
# File 'lib/app_info/android/signatures/info.rb', line 32 def total_size @total_size end |
Instance Method Details
#cdir_offset ⇒ Object
137 138 139 140 141 142 |
# File 'lib/app_info/android/signatures/info.rb', line 137 def cdir_offset @cdir_offset ||= lambda { eocd_buffer = zip_io.get_e_o_c_d(start_buffer) eocd_buffer[12..16].unpack1('V') }.call end |
#file_io ⇒ Object
152 153 154 |
# File 'lib/app_info/android/signatures/info.rb', line 152 def file_io @file_io ||= ::File.open(@parser.file, 'rb') end |
#pares_signatures_pairs ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/app_info/android/signatures/info.rb', line 93 def pares_signatures_pairs block = signature_block block.rewind # get pairs size @total_size = block.size - (SIG_SIZE_OF_BLOCK_SIZE + SIG_MAGIC_BLOCK_SIZE) # get pairs block @pairs = StringIO.new(block.read(@total_size)) # get magic value block.seek(block.pos + SIG_SIZE_OF_BLOCK_SIZE) @magic = block.read(SIG_MAGIC_BLOCK_SIZE) end |
#signature_block ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/app_info/android/signatures/info.rb', line 107 def signature_block @signature_block ||= lambda { logger.debug "cdir_offset: #{cdir_offset}" file_io.seek(cdir_offset - (Info::SIG_MAGIC_BLOCK_SIZE + Info::SIG_SIZE_OF_BLOCK_SIZE)) = file_io.read(Info::SIG_SIZE_OF_BLOCK_SIZE) if .size < Info::SIG_SIZE_OF_BLOCK_SIZE raise NotFoundError, "APK Signing Block size out of range: #{.size}" end = .unpack1('Q') total_size = offset = cdir_offset - total_size - Info::SIG_SIZE_OF_BLOCK_SIZE if offset.negative? raise NotFoundError, "APK Signing Block offset out of range: #{offset}" end file_io.seek(offset) header = file_io.read(Info::SIG_SIZE_OF_BLOCK_SIZE).unpack1('Q') if header != raise NotFoundError, "APK Signing Block header and footer mismatch: #{header} != #{}" end io = file_io.read(total_size) StringIO.new(io) }.call end |
#signers(block_id) ⇒ Object
Find singers
FORMAT: OFFSET DATA TYPE DESCRIPTION
-
@+0 bytes uint64: size in bytes
-
@+8 bytes payload block
-
@+0 bytes uint32: id
-
@+4 bytes payload: value
-
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/app_info/android/signatures/info.rb', line 50 def signers(block_id) count = 0 until @pairs.eof? left_bytes = left_bytes_check( @pairs, UINT64_SIZE, NotFoundError, "Insufficient data to read size of APK Signing Block ##{count}" ) pair_buf = @pairs.read(UINT64_SIZE) pair_size = pair_buf.unpack1('Q') if pair_size < UINT32_SIZE || pair_size > UINT32_MAX_VALUE raise NotFoundError, "APK Signing Block ##{count} size out of range: #{pair_size} > #{UINT32_MAX_VALUE}" end if pair_size > left_bytes raise NotFoundError, "APK Signing Block ##{count} size out of range: #{pair_size} > #{left_bytes}" end # fetch next signer block position next_pos = @pairs.pos + pair_size.to_i id_block = @pairs.read(UINT32_SIZE) id_bytes = id_block.unpack('C*') if id_bytes == block_id logger.debug "Signature block id v#{@version} scheme (0x#{id_block.unpack1('H*')}) found" value = @pairs.read(pair_size - UINT32_SIZE) return StringIO.new(value) end @pairs.seek(next_pos) count += 1 end block_id_hex = block_id.reverse.pack('C*').unpack1('H*') raise NotFoundError, "Not found block id 0x#{block_id_hex} in APK Signing Block." end |
#start_buffer ⇒ Object
144 145 146 |
# File 'lib/app_info/android/signatures/info.rb', line 144 def start_buffer @start_buffer ||= zip_io.start_buf(file_io) end |
#zip64? ⇒ Boolean
89 90 91 |
# File 'lib/app_info/android/signatures/info.rb', line 89 def zip64? zip_io.zip64_file?(start_buffer) end |
#zip_io ⇒ Object
148 149 150 |
# File 'lib/app_info/android/signatures/info.rb', line 148 def zip_io @zip_io ||= @parser.zip end |