mifare-access-condition-builder 1.1.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 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