Skip to content

Latest commit

 

History

History
6 lines (5 loc) · 14.6 KB

03_CheckingSHA.md

File metadata and controls

6 lines (5 loc) · 14.6 KB

Below you will find an example of how to send and receive HTTPS in NodeRed and parse the LoRa data and check the SHA256 token. Please refer to the wiki to get more explanation.

Copy the below code, and import through the clipboard in NodeRed

[{"id":"e0e4fb1f.e20908","type":"http in","z":"65bb5a5b.a49fc4","name":"LoRa Post Catcher","url":"/lorapost","method":"post","swaggerDoc":"","x":201.61456298828125,"y":308.0035400390625,"wires":[["5671845e.7e62dc"]]},{"id":"40bca731.7a2f48","type":"debug","z":"65bb5a5b.a49fc4","name":"","active":true,"console":"false","complete":"lorapayload","x":1098.6111145019531,"y":305.3263854980469,"wires":[]},{"id":"c4e87a33.a564f8","type":"http response","z":"65bb5a5b.a49fc4","name":"LoRa Post Catcher","x":1112.8958435058594,"y":225,"wires":[]},{"id":"5671845e.7e62dc","type":"function","z":"65bb5a5b.a49fc4","name":"Parse Catch Input","func":"// Check if the body has a DevEUI_uplink parameter (Thingpark) or uses a simple format (KPN LoRa Developer Portal)\nif (msg.payload.hasOwnProperty(\"DevEUI_uplink\")) {\n    body = msg.payload.DevEUI_uplink;\n} // Check if the body has the right parameters for Developer Portal\nelse if (msg.payload.hasOwnProperty(\"payload_hex\")){\n    // Developer portal has a simpler json format without DevEUI_uplink\n    body = msg.payload;\n}else{\n    node.error(\"Not a valid Thingpark or Developer Portal message\", msg);\n    return;   \n}\n\n// Check if the query paramaters are there before continuing\nvar RequiredKeys = [\"LrnDevEui\",\"LrnFPort\",\"LrnInfos\",\"AS_ID\",\"Time\",\"Token\"];\nfor(var i=0; i < RequiredKeys.length; i++) {\n    key = RequiredKeys[i];\n    if (!msg.req.query.hasOwnProperty(key)){\n        node.error(\"Missing Query Parameter '\" + key + \"'\", msg);\n        return;\n    }\n}\n\n// Check if the body has the right parameters\nRequiredBodyElements = [\"CustomerID\",\"DevEUI\",\"FPort\",\"FCntUp\",\"payload_hex\"];\nfor(var i=0; i < RequiredBodyElements.length; i++) {\n    key = RequiredBodyElements[i];\n    if (!body.hasOwnProperty(key)){\n        node.error(\"Missing DevEUI_uplink Element  '\" + key + \"'\", msg);\n        return;\n    }\n}\n\nmsg.lorapayload = body.payload_hex;\nmsg.body = body;\n\n//Enter your LRC-AS key below\nvar LRC_AS_key = \"xxxxxxxxxxx\";\n\n//Read body msg.payload for SHA\nmsg.body_parameters = body.CustomerID + body.DevEUI + body.FPort + body.FCntUp + body.payload_hex;\n\n//Read query parameters with msg.req.query\nmsg.query_sha = msg.req.query;\n\n//Store Token to compare\nmsg.PostToken = msg.req.query.Token;\n\n//Node-Red does not get the + in the ThingPark timestamp correctly and needs to be added\nmsg.query_sha.Time = msg.query_sha.Time.replace(\" \", \"+\"); \n\n// Create a string of query parameters without Token\nvar query_str = \"\";\nfor(var k in msg.query_sha) {\n    if (k != \"Token\"){\n        query_str += k + \"=\" + msg.query_sha[k] + \"&\";\n    }\n}\nmsg.query_str = query_str.slice(0,-1); // Delete last '&' sign in the string\n\nmsg.SHA_string_no_key = msg.body_parameters + msg.query_str; // Save a SHA string withouth a key\nmsg.SHA_string = msg.SHA_string_no_key + LRC_AS_key;  // Save a SHA string, including the key\n\nreturn msg;","outputs":1,"noerr":0,"x":412.8957824707031,"y":308,"wires":[["de9d1630.c91118"]]},{"id":"1954c90d.e316a7","type":"catch","z":"65bb5a5b.a49fc4","name":"","scope":null,"x":452.1632080078125,"y":225.2916717529297,"wires":[["ef742052.e5f7a"]]},{"id":"ef742052.e5f7a","type":"function","z":"65bb5a5b.a49fc4","name":"Handle Error","func":"// Add a topic property to our message to let other nodes know\n// that this message is an error.\nmsg.topic = \"error\";\n\n// The payload of this error message should say something \n// about the error. This payload is going to be passed back\n// to our HTTPS Response node. Note that the msg.error.message\n// is the message we gave as input in the node.error()\nmsg.payload = \"Encoutered Error: \"+ msg.error.message;\n\nreturn msg;","outputs":1,"noerr":0,"x":625.4514465332031,"y":225,"wires":[["a05a01db.44e9b"]]},{"id":"a05a01db.44e9b","type":"function","z":"65bb5a5b.a49fc4","name":"Create Post Resp","func":"if (msg.topic === \"error\"){\n    // In case of an error, do nothing with the message and\n    // pass it on to the reponse node. The msg.payload\n    // already contains the right information\n    return msg;\n}else{\n    // We know we have received a valid message\n    // Let's just pass back the lora data we have received\n    msg.payload = \"Received payload: \" + msg.lorapayload;\n}\nreturn msg;","outputs":1,"noerr":0,"x":866.4514465332031,"y":225,"wires":[["c4e87a33.a564f8"]]},{"id":"de9d1630.c91118","type":"function","z":"65bb5a5b.a49fc4","name":"SHA256 Check","func":"/**\n * [js-sha256]{@link https://github.com/emn178/js-sha256}\n *\n * @version 0.3.1\n * @author Chen, Yi-Cyuan [[email protected]]\n * @copyright Chen, Yi-Cyuan 2014-2016\n * @license MIT\n */\n(function (root) {\n  'use strict';\n \n  var NODE_JS = typeof process == 'object' && process.versions && process.versions.node;\n  if (NODE_JS) {\n    root = global;\n  }\n  var TYPED_ARRAY = typeof Uint8Array != 'undefined';\n  var HEX_CHARS = '0123456789abcdef'.split('');\n  var EXTRA = [-2147483648, 8388608, 32768, 128];\n  var SHIFT = [24, 16, 8, 0];\n  var K =[0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n          0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n          0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n          0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n          0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n          0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n          0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n          0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];\n \n  var blocks = [];\n \n  var sha224 = function (message) {\n    return sha256(message, true);\n  };\n \n  var sha256 = function (message, is224) {\n    var notString = typeof message != 'string';\n    if (notString && message.constructor == root.ArrayBuffer) {\n      message = new Uint8Array(message);\n    }\n \n    var h0, h1, h2, h3, h4, h5, h6, h7, block, code, first = true, end = false,\n        i, j, index = 0, start = 0, bytes = 0, length = message.length,\n        s0, s1, maj, t1, t2, ch, ab, da, cd, bc;\n \n    if (is224) {\n      h0 = 0xc1059ed8;\n      h1 = 0x367cd507;\n      h2 = 0x3070dd17;\n      h3 = 0xf70e5939;\n      h4 = 0xffc00b31;\n      h5 = 0x68581511;\n      h6 = 0x64f98fa7;\n      h7 = 0xbefa4fa4;\n    } else { // 256\n      h0 = 0x6a09e667;\n      h1 = 0xbb67ae85;\n      h2 = 0x3c6ef372;\n      h3 = 0xa54ff53a;\n      h4 = 0x510e527f;\n      h5 = 0x9b05688c;\n      h6 = 0x1f83d9ab;\n      h7 = 0x5be0cd19;\n    }\n    block = 0;\n    do {\n      blocks[0] = block;\n      blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n      blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n      blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n      blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n      if (notString) {\n        for (i = start;index < length && i < 64;++index) {\n          blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];\n        }\n      } else {\n        for (i = start;index < length && i < 64;++index) {\n          code = message.charCodeAt(index);\n          if (code < 0x80) {\n            blocks[i >> 2] |= code << SHIFT[i++ & 3];\n          } else if (code < 0x800) {\n            blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];\n            blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n          } else if (code < 0xd800 || code >= 0xe000) {\n            blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];\n            blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n            blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n          } else {\n            code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\n            blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];\n            blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];\n            blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n            blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n          }\n        }\n      }\n      bytes += i - start;\n      start = i - 64;\n      if (index == length) {\n        blocks[i >> 2] |= EXTRA[i & 3];\n        ++index;\n      }\n      block = blocks[16];\n      if (index > length && i < 56) {\n        blocks[15] = bytes << 3;\n        end = true;\n      }\n \n      var a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;\n      for (j = 16;j < 64;++j) {\n        // rightrotate\n        t1 = blocks[j - 15];\n        s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);\n        t1 = blocks[j - 2];\n        s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);\n        blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0;\n      }\n \n      bc = b & c;\n      for (j = 0;j < 64;j += 4) {\n        if (first) {\n          if (is224) {\n            ab = 300032;\n            t1 = blocks[0] - 1413257819;\n            h = t1 - 150054599 << 0;\n            d = t1 + 24177077 << 0;\n          } else {\n            ab = 704751109;\n            t1 = blocks[0] - 210244248;\n            h = t1 - 1521486534 << 0;\n            d = t1 + 143694565 << 0;\n          }\n          first = false;\n        } else {\n          s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));\n          s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));\n          ab = a & b;\n          maj = ab ^ (a & c) ^ bc;\n          ch = (e & f) ^ (~e & g);\n          t1 = h + s1 + ch + K[j] + blocks[j];\n          t2 = s0 + maj;\n          h = d + t1 << 0;\n          d = t1 + t2 << 0;\n        }\n        s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));\n        s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));\n        da = d & a;\n        maj = da ^ (d & b) ^ ab;\n        ch = (h & e) ^ (~h & f);\n        t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];\n        t2 = s0 + maj;\n        g = c + t1 << 0;\n        c = t1 + t2 << 0;\n        s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));\n        s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));\n        cd = c & d;\n        maj = cd ^ (c & a) ^ da;\n        ch = (g & h) ^ (~g & e);\n        t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];\n        t2 = s0 + maj;\n        f = b + t1 << 0;\n        b = t1 + t2 << 0;\n        s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));\n        s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));\n        bc = b & c;\n        maj = bc ^ (b & d) ^ cd;\n        ch = (f & g) ^ (~f & h);\n        t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];\n        t2 = s0 + maj;\n        e = a + t1 << 0;\n        a = t1 + t2 << 0;\n      }\n \n      h0 = h0 + a << 0;\n      h1 = h1 + b << 0;\n      h2 = h2 + c << 0;\n      h3 = h3 + d << 0;\n      h4 = h4 + e << 0;\n      h5 = h5 + f << 0;\n      h6 = h6 + g << 0;\n      h7 = h7 + h << 0;\n    } while (!end);\n \n    var hex = HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +\n              HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +\n              HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +\n              HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +\n              HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +\n              HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +\n              HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +\n              HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +\n              HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +\n              HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +\n              HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +\n              HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +\n              HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +\n              HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +\n              HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +\n              HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +\n              HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +\n              HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +\n              HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +\n              HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] +\n              HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] +\n              HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] +\n              HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] +\n              HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] +\n              HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] +\n              HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] +\n              HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] +\n              HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F];\n    if (!is224) {\n      hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] +\n             HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] +\n             HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] +\n             HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F];\n    }\n    return hex;\n  };\n   \n  if (!root.JS_SHA256_TEST && NODE_JS) {\n    sha256.sha256 = sha256;\n    sha256.sha224 = sha224;\n    module.exports = sha256;\n  } else if (root) {\n    root.sha256 = sha256;\n    root.sha224 = sha224;\n  }\n}(this));\n\n// The code above is a sha256() function\n// Below we do the actual check\nvar Token = sha256(msg.SHA_string);\nif (Token != msg.PostToken) {\n    // Pass an error with the SHA string (no key!!) back for debugging\n    node.error(\"Token did not match on \" + msg.SHA_string_no_key, msg);\n    return;\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":630.1632385253906,"y":307.7708435058594,"wires":[["a05a01db.44e9b","40bca731.7a2f48"]]}]