mifare-access-condition-builder 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6003272e84a05fd5886ce5690dc75bc25fc389b8379b215f5a5a9d8adafc6af9
4
+ data.tar.gz: 6eb0b72658c878a0a0d06e006387f85b898babeef3a14c20343b5fb6be62ee76
5
+ SHA512:
6
+ metadata.gz: 9bf4ac69c61585e825ac25255fb0fd769d24c17c8003e578492481340b2cca2ba45a1a0a49b7d5116f552a3dd2cebf80b77777805ad595c24c72abc14dd370de
7
+ data.tar.gz: 8ab182615b9e2b111b67012011169230f66fcce9ba222e63311b5aeb3d465eb30abc018ea2f76f18676ee2af8339c5bb512307e7d32e556be001d9654aab2ea7
checksums.yaml.gz.sig ADDED
Binary file
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2011-12-19
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ mifare-access-condition-builder
2
+ ===============================
3
+
4
+ https://github.com/larskanis/mifare-access-condition-builder
5
+
6
+ A GUI to calculate the access condition bytes of sectors of Mifare contactless chip cards
7
+
8
+ REQUIREMENTS
9
+ ------------
10
+
11
+ * Ruby
12
+ * Fox toolkit (required on MacOS and Linux, builtin on Windows)
13
+
14
+ INSTALL + RUN
15
+ --------------
16
+
17
+ * On Windows install the Rubyinstaller (with or without Devkit) https://rubyinstaller.org/downloads/
18
+ * On Linux use `sudo apt install ruby-dev g++ libxrandr-dev libfox-1.6-dev` or similar
19
+
20
+ Then run on the command line:
21
+
22
+ ```sh
23
+ $ gem install mifare-access-condition-builder
24
+ $ mifare_access_condition_builder
25
+ ```
26
+
27
+ ![Screenshot](screenshot.png?raw=true "GUI of the mifare-access-condition-builder")
28
+
29
+ LICENSE
30
+ -------
31
+
32
+ (The MIT License)
33
+
34
+ Copyright (c) 2024 Lars Kanis - Sincnovation Falkenstein GmbH
35
+
36
+ Permission is hereby granted, free of charge, to any person obtaining
37
+ a copy of this software and associated documentation files (the
38
+ 'Software'), to deal in the Software without restriction, including
39
+ without limitation the rights to use, copy, modify, merge, publish,
40
+ distribute, sublicense, and/or sell copies of the Software, and to
41
+ permit persons to whom the Software is furnished to do so, subject to
42
+ the following conditions:
43
+
44
+ The above copyright notice and this permission notice shall be
45
+ included in all copies or substantial portions of the Software.
46
+
47
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
48
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
50
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
51
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
52
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
53
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+ require "rubocop/rake_task"
6
+
7
+ Minitest::TestTask.create
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[test rubocop]
11
+ task gem: :build
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'mifare_access_condition_builder'
5
+ require 'fox16'
6
+
7
+ app = Fox::FXApp.new("MifAccMain", "ComCard")
8
+ MifareAccessConditionBuilder::MainWindow.new(app)
9
+ app.create
10
+ app.run
@@ -0,0 +1,3 @@
1
+ module MifareAccessConditionBuilder
2
+ VERSION = '1.1.0'
3
+ end
@@ -0,0 +1,301 @@
1
+ #! /usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ ###########################################################################
4
+ # Copyright (C) 2004 by Lars Kanis
5
+ # <kanis@comcard.de>
6
+ #
7
+ # Copyright: See COPYING file that comes with this distribution
8
+ ###########################################################################
9
+ #
10
+
11
+ require 'rubygems'
12
+ require 'fox16'
13
+ require 'fox16/colors'
14
+
15
+ module MifareAccessConditionBuilder
16
+
17
+ autoload :VERSION, 'mifare_access_condition_builder/version'
18
+
19
+ class MainWindow < Fox::FXMainWindow
20
+ include Fox
21
+
22
+ AccBlock = Struct.new :bits, :descs, :key_b_readable
23
+
24
+ def initialize(app)
25
+ # Initialize base class
26
+ super(app, "Mifare Access Condition Builder #{VERSION}", nil, nil, DECOR_ALL, 0, 0, 750, 250)
27
+
28
+ # Tooltips einschalten und auf dauerhafte Anzeige einstellen.
29
+ FXToolTip.new(getApp(), TOOLTIP_PERMANENT)
30
+
31
+ # scrollwindow = FXScrollWindow.new(self, LAYOUT_FILL_X | LAYOUT_FILL_Y)
32
+ top = FXVerticalFrame.new(self, LAYOUT_FILL_X | LAYOUT_FILL_Y){|theFrame|
33
+ theFrame.padLeft = theFrame.padRight = theFrame.padBottom = theFrame.padTop = 5
34
+ theFrame.vSpacing = 5
35
+
36
+ FXHorizontalFrame.new(theFrame, LAYOUT_FILL_X|LAYOUT_FILL_Y){|hex_frame|
37
+ FXLabel.new(hex_frame, 'Hex-Eingabe (3 Byte):')
38
+ @hex_input = FXTextField.new(hex_frame,0, nil, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X){|this|
39
+ this.connect(SEL_COMMAND, method(:hex_changed))
40
+ this.text = 'FF 07 80'
41
+ }
42
+ }
43
+ @message = FXLabel.new(theFrame, ''){|this|
44
+ this.textColor = FXColor::Red
45
+ }
46
+
47
+ @acc_blocks = []
48
+ FXMatrix.new(theFrame, 8, MATRIX_BY_COLUMNS | LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0){|matrix|
49
+ [''].+(DataBitsHead).each{|labeltext|
50
+ FXLabel.new(matrix, labeltext, nil, LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
51
+ }
52
+
53
+ for blocknr in 0..2 do
54
+ acc_block = AccBlock.new nil, []
55
+ FXLabel.new(matrix, "Block #{blocknr}", nil, LAYOUT_FILL_X)
56
+ acc_block.bits = FXTextField.new(matrix,10, nil, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
57
+ acc_block.bits.connect(SEL_COMMAND, method(:bits_changed))
58
+ FXLabel.new(matrix,'->')
59
+ for desc in 0...5
60
+ acc_block.descs << FXLabel.new(matrix, '', nil, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X|TEXTFIELD_READONLY){|this|
61
+ this.backColor = FXColor::LightGoldenrod1
62
+ bits_field = acc_block.bits
63
+ this.connect(SEL_LEFTBUTTONPRESS){|sender, sel, ptr|
64
+ desc_clicked(sender, sel, ptr, bits_field, acc_block.key_b_readable ? :data_key_b_readable : :data_key_b_secret)
65
+ }
66
+ }
67
+ end
68
+ @acc_blocks << acc_block
69
+ end
70
+ }
71
+ FXMatrix.new(theFrame, 10, MATRIX_BY_COLUMNS | LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0){|matrix|
72
+ [''].+(TrailerBitsHead).each{|labeltext|
73
+ FXLabel.new(matrix, labeltext, nil, LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
74
+ }
75
+
76
+ acc_block = AccBlock.new nil, []
77
+ FXLabel.new(matrix, "Block 3", nil, LAYOUT_FILL_X)
78
+ acc_block.bits = FXTextField.new(matrix,10, nil, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
79
+ acc_block.bits.connect(SEL_COMMAND, method(:bits_changed))
80
+ FXLabel.new(matrix,'->')
81
+ for desc in 0...7
82
+ acc_block.descs << FXLabel.new(matrix,'', nil, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X|TEXTFIELD_READONLY){|this|
83
+ this.backColor = FXColor::PaleGreen
84
+ bits_field = acc_block.bits
85
+ this.connect(SEL_LEFTBUTTONPRESS){|sender, sel, ptr|
86
+ desc_clicked(sender, sel, ptr, bits_field, :trailer)
87
+ }
88
+ }
89
+ end
90
+ @acc_blocks << acc_block
91
+ }
92
+ }
93
+ # sinnvolle default-Werte in Felder eintragen
94
+ hex_changed
95
+ end
96
+
97
+ def create
98
+ super
99
+ show(PLACEMENT_SCREEN)
100
+ app.addTimeout(1) do
101
+ @hex_input.setFocus
102
+ end
103
+ end
104
+
105
+ def display_error
106
+ begin
107
+ yield
108
+ rescue InvalidArgument => e
109
+ @message.text = e.to_s
110
+ else
111
+ @message.text = ''
112
+ end
113
+ end
114
+
115
+ def hex_changed(sender=nil, sel=nil, ptr=nil)
116
+ hex = @hex_input.text
117
+ # puts "hex-input: #{hex}"
118
+
119
+ bits = nil
120
+ display_error do
121
+ bits = acc_hex_to_bits(hex)
122
+ # puts bits
123
+
124
+ @acc_blocks.each_with_index do |bl, blidx|
125
+ bl.bits.text = bits[blidx]
126
+ end
127
+ end
128
+
129
+ display_bits_desc
130
+ end
131
+
132
+ def bits_changed(sender=nil, sel=nil, ptr=nil)
133
+ blocksbits = @acc_blocks.map{|ab| ab.bits.text }
134
+ # puts "bits-input: #{blocksbits.inspect}"
135
+
136
+ hex = ''
137
+ display_error do
138
+ hex = acc_bits_to_hex(blocksbits).upcase
139
+ # puts hex
140
+ end
141
+ display_bits_desc
142
+
143
+ @hex_input.text = [hex[0,2], hex[2,2], hex[4..-1]].join(" ")
144
+ end
145
+
146
+ class InvalidArgument < RuntimeError # :nodoc:
147
+ end
148
+
149
+ def acc_hex_to_bits(hex)
150
+ hex = hex.gsub(/\s/, '')
151
+ raise InvalidArgument, "3 Byte Hex-String erwartet: #{hex.inspect}" unless hex=~/^[0-9a-f]{6,6}$/i
152
+
153
+ blocksbits = ['','','','']
154
+ nibbles = [hex[2,1].hex, hex[5,1].hex, hex[4,1].hex]
155
+ nibbles.each do |nibble|
156
+ # puts "nibble: #{nibble.inspect}"
157
+ blocksbits.each_with_index do |blockbits, bbidx|
158
+ onoff = (nibble >> bbidx) & 1
159
+ # puts "onoff: #{onoff.inspect} bits: #{blockbits.inspect}"
160
+ blockbits << (onoff>0 ? '1' : '0')
161
+ end
162
+ end
163
+ hex2 = acc_bits_to_hex(blocksbits)
164
+ raise InvalidArgument, "Hex-Daten sind inkonsistent: #{hex}!=#{hex2}" unless hex.upcase==hex2.upcase
165
+
166
+ return blocksbits
167
+ end
168
+
169
+ def acc_bits_to_hex(blocksbits)
170
+ raise InvalidArgument, "Bits fuer 4 Bloecke erwartet: #{blocksbits.inspect}" unless blocksbits.length==4
171
+
172
+ blocksbits.each_with_index do |bit, bidx|
173
+ raise InvalidArgument, "3 Bit String für Block #{bidx} erwartet: #{bit.inspect}" unless bit=~/^[0-1]{3,3}$/i
174
+ end
175
+
176
+ nibbles = [0,0,0]
177
+ blocksbits.each_with_index do |blockbits, bbidx|
178
+ nibbles.each_with_index do |nibble, nidx|
179
+ onoff = blockbits[nidx,1].hex
180
+ nibble |= onoff << bbidx
181
+ nibbles[nidx] = nibble
182
+ end
183
+ end
184
+ return sprintf("%x%x%x%x%x%x",
185
+ nibbles[1] ^ 0xf, nibbles[0] ^ 0xf,
186
+ nibbles[0], nibbles[2] ^ 0xf,
187
+ nibbles[2], nibbles[1])
188
+ end
189
+
190
+ DataBitsHead = ['bits','','read', 'write', 'increment', 'dec,tran,dec', 'description']
191
+ DataBitsDesc = {
192
+ '000' => [['A|B', 'A|B', 'A|B', 'A|B'], ['A', 'A', 'A', 'A'], 'transport config'],
193
+ '010' => [['A|B', '-' , '-' , '-' ], ['A', '-', '-', '-'], 'read/write block'],
194
+ '100' => [['A|B', 'B' , '-' , '-' ], ['A', '-', '-', '-'], 'read/write block'],
195
+ '110' => [['A|B', 'B' , 'B' , 'A|B'], ['A', '-', '-', 'A'], 'value block'],
196
+ '001' => [['A|B', '-' , '-' , 'A|B'], ['A', '-', '-', 'A'], 'value block'],
197
+ '011' => [['B' , 'B' , '-' , '-' ], ['-', '-', '-', '-'], 'read/write block'],
198
+ '101' => [['B' , '-' , '-' , '-' ], ['-', '-', '-', '-'], 'read/write block'],
199
+ '111' => [['-' , '-' , '-' , '-' ], ['-', '-', '-', '-'], 'read/write block'],
200
+ }
201
+ TrailerBitsHead = ['bits','', 'read A', 'write A', 'read ACC', 'write ACC', 'read B', 'write B', 'description']
202
+ TrailerBitsDesc = {
203
+ '000' => ['-', 'A', 'A' , '-', 'A', 'A', 'Key B may be read'],
204
+ '010' => ['-', '-', 'A' , '-', 'A', '-', 'Key B may be read'],
205
+ '100' => ['-', 'B', 'A|B', '-', '-', 'B', ' '],
206
+ '110' => ['-', '-', 'A|B', '-', '-', '-', ' '],
207
+ '001' => ['-', 'A', 'A' , 'A', 'A', 'A', 'Key B may be read, transport config'],
208
+ '011' => ['-', 'B', 'A|B', 'B', '-', 'B', ' '],
209
+ '101' => ['-', '-', 'A|B', 'B', '-', '-', ' '],
210
+ '111' => ['-', '-', 'A|B', '-', '-', '-', ' '],
211
+ }
212
+
213
+ def display_bits_desc
214
+ @acc_blocks.each_with_index do |acc_block, blidx|
215
+ if blidx==3
216
+ descs = TrailerBitsDesc[acc_block.bits.text] || Array.new(6,'')
217
+ else
218
+ trailer = TrailerBitsDesc[@acc_blocks.last.bits.text]
219
+ ws_descs, wr_descs, desc = DataBitsDesc[acc_block.bits.text] || [Array.new(4,'')]*2
220
+ if trailer && trailer[4].tr("-","").empty?
221
+ descs = ws_descs + [desc] # Key B can't be read
222
+ acc_block.key_b_readable = false
223
+ else
224
+ descs = wr_descs + [desc] # Key B may be read
225
+ acc_block.key_b_readable = true
226
+ end
227
+ end
228
+ descs.each_with_index{|desc, descidx| acc_block.descs[descidx].text = desc.to_s }
229
+ end
230
+ end
231
+
232
+ def desc_clicked(sender, sel, ptr, bits_field, data_or_trailer)
233
+ sd = SelectionDialog.new(data_or_trailer, sender, "Select Access Conditions", opts: DECOR_ALL, height: 320, width: 600)
234
+ if sd.execute > 0
235
+ bits = sd.selected_bits
236
+ bits_field.text = bits
237
+ bits_changed
238
+ end
239
+ end
240
+
241
+ class SelectionDialog < FXDialogBox
242
+ include Fox
243
+
244
+ attr_reader :selected_bits
245
+
246
+ def initialize(data_or_trailer, *args)
247
+ super(*args)
248
+
249
+ if data_or_trailer == :data_key_b_readable || data_or_trailer == :data_key_b_secret
250
+ FXLabel.new(self, "Mögliche Bit-Kombinationen für Datenblöcke:")
251
+
252
+ FXMatrix.new(self, 7, MATRIX_BY_COLUMNS | LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) do |matrix|
253
+ DataBitsHead.each do |labeltext|
254
+ FXLabel.new(matrix, labeltext, nil, LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
255
+ end
256
+
257
+ DataBitsDesc.sort.each do |bits, (ws_descs, wr_descs, desc)|
258
+ descs = (data_or_trailer == :data_key_b_readable ? wr_descs : ws_descs) + [desc]
259
+ field = FXLabel.new(matrix, bits, nil, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X|TEXTFIELD_READONLY){|this| this.backColor = FXColor::LightGoldenrod1 }
260
+ FXLabel.new(matrix,'->')
261
+ for desc in descs
262
+ FXLabel.new(matrix, desc, nil, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X|TEXTFIELD_READONLY) do |this|
263
+ this.backColor = FXColor::LightGoldenrod1
264
+ b = bits
265
+ this.connect(SEL_LEFTBUTTONPRESS) do
266
+ @selected_bits = b
267
+ self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
273
+ elsif data_or_trailer == :trailer
274
+ FXLabel.new(self, "Mögliche Bit-Kombinationen für Trailerblöcke:")
275
+
276
+ FXMatrix.new(self, 9, MATRIX_BY_COLUMNS | LAYOUT_FILL_X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) do |matrix|
277
+ TrailerBitsHead.each do |labeltext|
278
+ FXLabel.new(matrix, labeltext, nil, LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
279
+ end
280
+
281
+ TrailerBitsDesc.each do |bits, descs|
282
+ field = FXLabel.new(matrix, bits, nil, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X|TEXTFIELD_READONLY){|this| this.backColor = FXColor::PaleGreen }
283
+ FXLabel.new(matrix,'->')
284
+ for desc in descs
285
+ FXLabel.new(matrix, desc, nil, TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X|TEXTFIELD_READONLY) do |this|
286
+ this.backColor = FXColor::PaleGreen
287
+ b = bits
288
+ this.connect(SEL_LEFTBUTTONPRESS) do
289
+ @selected_bits = b
290
+ self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil)
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end
297
+ end
298
+ end
299
+
300
+ end
301
+ end
data/screenshot.png ADDED
Binary file
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mifare-access-condition-builder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ original_platform: ''
7
+ authors:
8
+ - Lars Kanis
9
+ bindir: exe
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDLjCCAhagAwIBAgIBDDANBgkqhkiG9w0BAQsFADA9MQ4wDAYDVQQDDAVrYW5p
14
+ czEXMBUGCgmSJomT8ixkARkWB2NvbWNhcmQxEjAQBgoJkiaJk/IsZAEZFgJkZTAe
15
+ Fw0yNDA1MDIxMTAwNDVaFw0yNTA1MDIxMTAwNDVaMD0xDjAMBgNVBAMMBWthbmlz
16
+ MRcwFQYKCZImiZPyLGQBGRYHY29tY2FyZDESMBAGCgmSJomT8ixkARkWAmRlMIIB
17
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApop+rNmg35bzRugZ21VMGqI6
18
+ HGzPLO4VHYncWn/xmgPU/ZMcZdfj6MzIaZJ/czXyt4eHpBk1r8QOV3gBXnRXEjVW
19
+ 9xi+EdVOkTV2/AVFKThcbTAQGiF/bT1n2M+B1GTybRzMg6hyhOJeGPqIhLfJEpxn
20
+ lJi4+ENAVT4MpqHEAGB8yFoPC0GqiOHQsdHxQV3P3c2OZqG+yJey74QtwA2tLcLn
21
+ Q53c63+VLGsOjODl1yPn/2ejyq8qWu6ahfTxiIlSar2UbwtaQGBDFdb2CXgEufXT
22
+ L7oaPxlmj+Q2oLOfOnInd2Oxop59HoJCQPsg8f921J43NCQGA8VHK6paxIRDLQID
23
+ AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUvgTdT7fe
24
+ x17ugO3IOsjEJwW7KP4wDQYJKoZIhvcNAQELBQADggEBAH+LA+CcA9vbbqtuhK4J
25
+ lG1lQwA+hCKiueQgVsepNbXyDzx6PMC8ap/bFaKSaoUWABBA/bsh3jDNXT/eVZrN
26
+ lFP8cVGrznSYIBG8D/QQmJKpvDBJgnC4Zk01HkhYlqJC4qCTn9X+/uZNHLPLbAEL
27
+ xl3P43zyL3GQb1IP9bp0xV6oxwG9FO9Rk8bYDojky/69ylowFI5aODS39v01Siu2
28
+ FsEjM9tMSNb7lQRywQ/432KXi+8AAPTm+wdGnlt3wLE9w2TTpGUBsNKk+QiytTZO
29
+ zwbjAdVlRm0pg/vpDzzFmRf1GYVckMm8hpCRt8BP0akAbNyw1snYvZBwgLqxztru
30
+ bEo=
31
+ -----END CERTIFICATE-----
32
+ date: 2024-12-17 00:00:00.000000000 Z
33
+ dependencies:
34
+ - !ruby/object:Gem::Dependency
35
+ name: fxruby
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.6.20
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.6.20
48
+ description: 'Calculate the access condition bytes of sectors of Mifare contactless
49
+ chip cards '
50
+ email:
51
+ - lars.kanis@sincnovation.com
52
+ executables:
53
+ - mifare_access_condition_builder
54
+ extensions: []
55
+ extra_rdoc_files: []
56
+ files:
57
+ - History.txt
58
+ - README.md
59
+ - Rakefile
60
+ - exe/mifare_access_condition_builder
61
+ - lib/mifare_access_condition_builder.rb
62
+ - lib/mifare_access_condition_builder/version.rb
63
+ - screenshot.png
64
+ homepage: https://github.com/larskanis/mifare-access-condition-builder
65
+ licenses:
66
+ - MIT
67
+ metadata:
68
+ homepage_uri: https://github.com/larskanis/mifare-access-condition-builder
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 2.5.0
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 3.6.0.dev
84
+ specification_version: 4
85
+ summary: Calculate the access condition bytes of sectors of Mifare contactless chip
86
+ cards
87
+ test_files: []
metadata.gz.sig ADDED
Binary file