Access Protocol: Difference between revisions
Jump to navigation
Jump to search
(Created page with " = Overview = == Catalyst App == * [https://github.com/Hive13/HiveWeb GitHub link] * Actually do something with the temperatures presented to it. * Add in OpenID Support ** F...") |
No edit summary |
||
Line 40: | Line 40: | ||
* Each request is sent from the RFID to the server as a POST with a JSON body. | * Each request is sent from the RFID to the server as a POST with a JSON body. | ||
* Each device has a key pre-shared with the server to mutually authenticate w/o SSL, which some of our MCUs have no hope of doing. | * Each device has a key pre-shared with the server to mutually authenticate w/o SSL, which some of our MCUs have no hope of doing. | ||
* The body object contains a | * The body object contains a <code>device</code> key with the name of the device requesting access - if the server doesn't know about this device, it'll fail. | ||
* The data object also contains an operation - if not | * The data object also contains an operation - if not, <code>access</code> is assumed. Other options are <code>vend</code> and <code>log</code>. Currently, <code>log</code> does nothing but return a success. | ||
* Finally, for | * Finally, for <code>vend</code> or <code>access</code>, the data object contains a <code>badge</code> key, containing the presented badge number as an integer. | ||
* The checksum is computed like this: ([https://github.com/Hive13/HiveWeb/blob/master/lib/HiveWeb/View/ChecksummedJSON.pm Here's where it's done on the server.]) | * The checksum is computed like this: ([https://github.com/Hive13/HiveWeb/blob/master/lib/HiveWeb/View/ChecksummedJSON.pm Here's where it's done on the server.]) | ||
*# Sort all of the keys recursively on the data object. | *# Sort all of the keys recursively on the data object. | ||
*# Remove all unnecessary whitespace. | *# Remove all unnecessary whitespace. | ||
*# Prepend the device's shared key. | *# Prepend the device's shared key. | ||
*# Take the SHA-512 checksum of that string - encode as a hex string | *# Take the SHA-512 checksum of that string - encode as a hex string - it's case-insensitive everywhere, but I use uppercase. | ||
*# Create an object with keys of data, device, and checksum - that object is the body of the request or response. | *# Create an object with keys of <code>data</code>, <code>device</code>, and <code>checksum</code> - that object is the body of the request or response. | ||
* Each data object has a | * Each data object has a <code>random</code> field - this is random per-packet data to stop replay attacks | ||
* Each request should contain a | * Each request should contain a <code>random_response</code> field - this must be copied from the request to the response if present; this solves a different subset of replay attacks. | ||
== General-purpose logging == | == General-purpose logging == | ||
* JSON body with data, device, and checksum as described above - TBD what to do about an unknown device. | * JSON body with data, device, and checksum as described above - TBD what to do about an unknown device. | ||
* Data field has key | * Data field has key <code>option</code> set to <code>log</code> | ||
* An optional keys is | * An optional keys is <code>current_timestamp</code> in milliseconds, to batch several logs and let the server figure out the timesamps - <code>millis()</code> in Arduino-land works here. | ||
* Key | * Key <code>messages</code> is an array of message objects, containing keys as below: | ||
** | ** <code>absolute_timestamp</code> has the server compare it to <code>current_timestamp</code> to figure out when the message was generated. Optional. | ||
** | ** <code>relative_timestamp</code> is how long ago (this number is only positive) the message was generated. Optional. | ||
** If neither are specified, the server will timestamp the message with when it hit the DB. | ** If neither are specified, the server will timestamp the message with when it hit the DB. | ||
** | ** <code>data</code> is the message text. No reasonable length limit. Required; the array member will be silently discarded without it. | ||
** | ** <code>severity</code> is the 0-7 standard syslog values (panic, alert, crit, error, warn, notice, info, debug). Optional; defaults to info. | ||
* Key | * Key <code>temperatures</code> is an array of temperature reading objects to log, containing keys as below: | ||
** | ** <code>absolute_timestamp</code> and <code>relative_timestamp</code> function as in <code>messages</code>. | ||
** | ** <code>temperature</code> is the reading, in '''''tenths''''' of a degree Fahrenheit. This is done to remove the need for floating-point libraries on microcontrollers, as they are large. Required. | ||
** | ** <code>item</code> is which item the temperature is measuring. Note that a device must have permission to that item to log temperatures for it. Required; the array member will be silently discarded if missing or unauthorized. | ||
== Current protocol weaknesses and notes == | == Current protocol weaknesses and notes == | ||
Line 79: | Line 79: | ||
== Database Layout == | == Database Layout == | ||
* Conventions | * Conventions | ||
** All tables have a ${table_name}_id column that's a UUID as the primary key | ** All tables have a <code>${table_name}_id</code> column that's a UUID as the primary key | ||
** Many-to-many tables have the two tables they connect in alpha order | ** Many-to-many tables have the two tables they connect in alpha order | ||
*** They do not have their own, separate ID field | *** They do not have their own, separate ID field | ||
Line 87: | Line 87: | ||
** Catalyst convention is to use Pascal case for table names. | ** Catalyst convention is to use Pascal case for table names. | ||
** Postgres convention is to use Snake case for table names. | ** Postgres convention is to use Snake case for table names. | ||
* | * <code>members</code> stores member information. | ||
** It needs renamed to | ** It needs renamed to <code>member</code> for consistency, though the app calls it <code>Member</code> with a name override. | ||
** It also needs old fields blown away. | ** It also needs old fields blown away. | ||
* | * <code>badge</code> stores a badge number and which member it belongs to - you can have multiple badges per account | ||
* | * <code>mgroup</code> stores the names and IDs of various groups, such as members, leadership, laser certified, &c. It's called mgroup because <code>group</code> is an SQL reserved word. | ||
* | * <code>member_mgroup</code> is a many-to-many association table to join members to groups. | ||
* | * <code>device</code> stores information about a device - its shared key and name right now. | ||
* | * <code>item</code> stores information about items that can be accessed - doors, tools, and so on. | ||
* | * <code>device_item</code> is a many-to-many showing which devices can service which items. | ||
* | * <code>item_mgroup"</code> is a many-to-many granting access to an item to a group. | ||
[[Category:RFID]] | [[Category:RFID]] |
Revision as of 19:20, 26 July 2017
Overview
Catalyst App
- GitHub link
- Actually do something with the temperatures presented to it.
- Add in OpenID Support
- Facebook/Foursquare Checkins to the hive on entry
- Twitter updates on entry
- IRC Notifications
Hardware
- Arduino/ESP8266 Firmware GitHub link
- RFID Hardware link will go here
Future
- Screen to display information
- Current measurement to measure how long a tool is on.
- Log temperature readings for any number of devices
- Log soda sold out information
- Log general stuff
current use cases
- Doors
- Tools
- How to end use
- Timeout
- Current monitoring
- "Finish" button
- Least controversial method so far is tap card to enable tool, push a button to disable tool when finished. No timeout.
- How to end use
- Vending machines
- Need to deduct credits/dollars from a stored value securely.
- Member registration/payment terminal
- Need to securely add credits/dollars to a stored value.
- Need to also be able to associate a card ID with an account. Maybe multiple card/phone IDs? PIN as well
Protocol and Database Info
Server <-> RFID reader protocol
- Each request is sent from the RFID to the server as a POST with a JSON body.
- Each device has a key pre-shared with the server to mutually authenticate w/o SSL, which some of our MCUs have no hope of doing.
- The body object contains a
device
key with the name of the device requesting access - if the server doesn't know about this device, it'll fail. - The data object also contains an operation - if not,
access
is assumed. Other options arevend
andlog
. Currently,log
does nothing but return a success. - Finally, for
vend
oraccess
, the data object contains abadge
key, containing the presented badge number as an integer. - The checksum is computed like this: (Here's where it's done on the server.)
- Sort all of the keys recursively on the data object.
- Remove all unnecessary whitespace.
- Prepend the device's shared key.
- Take the SHA-512 checksum of that string - encode as a hex string - it's case-insensitive everywhere, but I use uppercase.
- Create an object with keys of
data
,device
, andchecksum
- that object is the body of the request or response.
- Each data object has a
random
field - this is random per-packet data to stop replay attacks - Each request should contain a
random_response
field - this must be copied from the request to the response if present; this solves a different subset of replay attacks.
General-purpose logging
- JSON body with data, device, and checksum as described above - TBD what to do about an unknown device.
- Data field has key
option
set tolog
- An optional keys is
current_timestamp
in milliseconds, to batch several logs and let the server figure out the timesamps -millis()
in Arduino-land works here. - Key
messages
is an array of message objects, containing keys as below:absolute_timestamp
has the server compare it tocurrent_timestamp
to figure out when the message was generated. Optional.relative_timestamp
is how long ago (this number is only positive) the message was generated. Optional.- If neither are specified, the server will timestamp the message with when it hit the DB.
data
is the message text. No reasonable length limit. Required; the array member will be silently discarded without it.severity
is the 0-7 standard syslog values (panic, alert, crit, error, warn, notice, info, debug). Optional; defaults to info.
- Key
temperatures
is an array of temperature reading objects to log, containing keys as below:absolute_timestamp
andrelative_timestamp
function as inmessages
.temperature
is the reading, in tenths of a degree Fahrenheit. This is done to remove the need for floating-point libraries on microcontrollers, as they are large. Required.item
is which item the temperature is measuring. Note that a device must have permission to that item to log temperatures for it. Required; the array member will be silently discarded if missing or unauthorized.
Current protocol weaknesses and notes
- You can capture a packet going to the server and replay it again and again and the server will accept it and process it.
- This could add junk log entries to the access log.
- This could also drain someone's soda credits.
- Solution is the server tells the client what nonce it expects back in the next packet, and stores that in the DB. We'd also need an operation to get that nonce if the MCU lost it, and a "wrong nonce" error.
- You CANNOT replay the response to a successful badge swipe and open the door, because
- The MCU only listens after a badge is presented (or a temperature is logged, but it won't call door_open() from that function).
- The MCU generates a new "random_response" field
- The MCU verifies that the response packet's field matches what it sent.
Database Layout
- Conventions
- All tables have a
${table_name}_id
column that's a UUID as the primary key - Many-to-many tables have the two tables they connect in alpha order
- They do not have their own, separate ID field
- They have the primary key as the two tables in alpha order
- There is a second key of the two columns reversed (this way is needed for the other foreign key)
- Table names are singular
- Catalyst convention is to use Pascal case for table names.
- Postgres convention is to use Snake case for table names.
- All tables have a
members
stores member information.- It needs renamed to
member
for consistency, though the app calls itMember
with a name override. - It also needs old fields blown away.
- It needs renamed to
badge
stores a badge number and which member it belongs to - you can have multiple badges per accountmgroup
stores the names and IDs of various groups, such as members, leadership, laser certified, &c. It's called mgroup becausegroup
is an SQL reserved word.member_mgroup
is a many-to-many association table to join members to groups.device
stores information about a device - its shared key and name right now.item
stores information about items that can be accessed - doors, tools, and so on.device_item
is a many-to-many showing which devices can service which items.item_mgroup"
is a many-to-many granting access to an item to a group.