add support for compressed secp256k1 keys encoded with base58btc
Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
parent
b4d7daf379
commit
bf1b855328
|
@ -18,7 +18,9 @@
|
|||
"is-html": "^2.0.0",
|
||||
"js-status-chat-name": "git+https://github.com/status-im/js-status-chat-name.git#v0.1.2",
|
||||
"morgan": "^1.9.1",
|
||||
"multibase": "^1.0.1",
|
||||
"qrcode": "^1.3.0",
|
||||
"secp256k1": "^4.0.1",
|
||||
"univeil": "^0.1.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -68,12 +68,18 @@ const handleSite = (req, res) => {
|
|||
|
||||
/* Open User Profile from Chat Key in Status */
|
||||
const handleChatKey = (req, res) => {
|
||||
/* We accept upper case for chat keys */
|
||||
const chatKey = req.params[0].toLowerCase()
|
||||
let chatKey = req.params[0]
|
||||
let uncompressedKey = chatKey
|
||||
|
||||
try {
|
||||
chatName = StatusIm.chatKeyToChatName(chatKey)
|
||||
if (!chatKey.startsWith('0x')) { /* decompress/deserialize key */
|
||||
uncompressedKey = utils.decompressKey(chatKey)
|
||||
} else { /* We accept upper case for hexadecimal public keys */
|
||||
chatKey = chatKey.toLowerCase()
|
||||
}
|
||||
chatName = StatusIm.chatKeyToChatName(uncompressedKey)
|
||||
} catch(error) {
|
||||
console.error(`Failed to parse: "${req.params[0]}", Error:`, error.message)
|
||||
console.error(`Failed to parse: "${uncompressedKey}", Error:`, error.message)
|
||||
res.render('index', { title: 'Invalid chat key format!', error })
|
||||
return
|
||||
}
|
||||
|
@ -130,9 +136,14 @@ router.get('/health', (req, res) => res.send('OK'))
|
|||
router.get('/b/:url(*)', handleSite)
|
||||
router.get('/browse/:url(*)', handleSite) /* Legacy */
|
||||
|
||||
router.get(/^\/u\/(z[0-9a-zA-Z]{46,49})$/, handleChatKey)
|
||||
router.get(/^\/u\/(z[0-9a-zA-Z]+)$/, handleError('Incorrect length of chat key'))
|
||||
router.get(/^\/u\/(fe701[0-9a-fA-F]{66})$/, handleChatKey)
|
||||
router.get(/^\/u\/(fe701[0-9a-fA-F]+)$/, handleError('Incorrect length of chat key'))
|
||||
router.get(/^\/u\/(f[0-9a-fA-F]{66})$/, handleChatKey)
|
||||
router.get(/^\/u\/(f[0-9a-fA-F]+)$/, handleError('Incorrect length of chat key'))
|
||||
router.get(/^\/u\/(0[xX]04[0-9a-fA-F]{128})$/, handleChatKey)
|
||||
router.get(/^\/u\/(0[xX]04[0-9a-fA-F]{1,127})$/, handleError('Incorrect length of chat key'))
|
||||
router.get(/^\/u\/(0[xX]04[0-9a-fA-F]{129,})$/, handleError('Incorrect length of chat key'))
|
||||
router.get(/^\/u\/(0[xX]04[0-9a-fA-F]+)$/, handleError('Incorrect length of chat key'))
|
||||
router.get(/^\/user\/(0[xX]04[0-9a-fA-F]{128})$/, handleChatKey) /* Legacy */
|
||||
|
||||
router.get(/^\/u\/([^><]*[A-Z]+[^><]*)$/, handleRedirect)
|
||||
|
|
|
@ -8,6 +8,8 @@ import appleSiteAssociation from '../resources/apple-app-site-association.json'
|
|||
|
||||
const host = 'join.status.im'
|
||||
const chatKey = 'e139115a1acc72510388fcf7e1cf492784c9a839888b25271465f4f1baa38c2d3997f8fd78828eb8628bc3bb55ababd884c6002d18330d59c404cc9ce3e4fb35'
|
||||
const multibaseKey = 'fe70103e139115a1acc72510388fcf7e1cf492784c9a839888b25271465f4f1baa38c2d'
|
||||
const compressedKey = 'zQ3shuoHL7WZEfKdexM6EyDRDhXBgcKz5SVw79stVMpmeyUvG'
|
||||
const chatName = 'Lavender Trivial Goral'
|
||||
|
||||
const srv = request(app)
|
||||
|
@ -103,6 +105,40 @@ test('test chat key routes', t => {
|
|||
})
|
||||
})
|
||||
|
||||
test('test multibase chat key routes', t => {
|
||||
t.test(`/u/${multibaseKey.substr(0,12)}... - VALID`, async t => {
|
||||
const res = await get(`/u/${multibaseKey}`)
|
||||
t.eq(res.statusCode, 200, 'returns 200')
|
||||
t.eq(meta(res, 'al:ios:url'), `status-im://u/${multibaseKey}`, 'contains ios url')
|
||||
t.eq(meta(res, 'al:android:url'), `status-im://u/${multibaseKey}`, 'contains android url')
|
||||
t.eq(html(res, 'div.info'), `Chat and transact with <span>${multibaseKey}</span> in Status.`, 'contains prompt')
|
||||
t.eq(html(res, '#header'), chatName, 'contains chat name')
|
||||
})
|
||||
|
||||
t.test(`/u/${multibaseKey.substr(0,12)}... - TOO SHORT`, async t => { /* error on too short chat key */
|
||||
const res = await get(`/u/${multibaseKey.substr(0,46)}`)
|
||||
t.eq(res.statusCode, 400, 'returns 400')
|
||||
t.eq(html(res, 'code#error'), 'Incorrect length of chat key', 'contains error')
|
||||
})
|
||||
})
|
||||
|
||||
test('test compressed chat key routes', t => {
|
||||
t.test(`/u/${compressedKey.substr(0,12)}... - VALID`, async t => {
|
||||
const res = await get(`/u/${compressedKey}`)
|
||||
t.eq(res.statusCode, 200, 'returns 200')
|
||||
t.eq(meta(res, 'al:ios:url'), `status-im://u/${compressedKey}`, 'contains ios url')
|
||||
t.eq(meta(res, 'al:android:url'), `status-im://u/${compressedKey}`, 'contains android url')
|
||||
t.eq(html(res, 'div.info'), `Chat and transact with <span>${compressedKey}</span> in Status.`, 'contains prompt')
|
||||
t.eq(html(res, '#header'), chatName, 'contains chat name')
|
||||
})
|
||||
|
||||
t.test(`/u/${compressedKey.substr(0,12)}... - TOO SHORT`, async t => { /* error on too short chat key */
|
||||
const res = await get(`/u/${compressedKey.substr(0,46)}`)
|
||||
t.eq(res.statusCode, 400, 'returns 400')
|
||||
t.eq(html(res, 'code#error'), 'Incorrect length of chat key', 'contains error')
|
||||
})
|
||||
})
|
||||
|
||||
test('test public channel routes', t => {
|
||||
t.test('/status-test - VALID', async t => {
|
||||
const res = await get('/status-test')
|
||||
|
|
|
@ -2,6 +2,9 @@ const QRCode = require('qrcode')
|
|||
const uts46 = require('idna-uts46-hx')
|
||||
const isHtml = require('is-html')
|
||||
const univeil = require('univeil')
|
||||
const { Buffer } = require('buffer')
|
||||
const multibase = require('multibase')
|
||||
const secp256k1 = require('secp256k1')
|
||||
|
||||
const isAndroid = (req) => (
|
||||
req.headers['user-agent'].toLowerCase().indexOf("android") > -1
|
||||
|
@ -42,6 +45,23 @@ const normalizeEns = (name) => (
|
|||
|
||||
const showSpecialChars = (str) => univeil(str)
|
||||
|
||||
/* check for multiformat variant encoding of the
|
||||
* multicodec secp256k1 key identifier e7 */
|
||||
const isMultiFormatSecp256k1 = (bytes) => (
|
||||
Buffer.from([231, 1]).compare(bytes.slice(0, 2)) == 0
|
||||
)
|
||||
|
||||
/* decodes base58btc encoding and decompresses a serialized secp256k1 */
|
||||
const decompressKey = (key) => {
|
||||
let cBytes = multibase.decode(key)
|
||||
if (isMultiFormatSecp256k1(cBytes)) {
|
||||
cBytes = cBytes.slice(2)
|
||||
}
|
||||
let pubKey = secp256k1.publicKeyConvert(cBytes, compressed=false)
|
||||
let multibaseHex = multibase.encode('base16', pubKey).toString()
|
||||
return '0x' + multibaseHex.substr(1)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isAndroid,
|
||||
isIOS,
|
||||
|
@ -49,4 +69,5 @@ module.exports = {
|
|||
isValidUrl,
|
||||
normalizeEns,
|
||||
showSpecialChars,
|
||||
decompressKey,
|
||||
}
|
||||
|
|
92
yarn.lock
92
yarn.lock
|
@ -102,6 +102,13 @@ balanced-match@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base-x@^3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d"
|
||||
integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
base64-js@^1.0.2:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
|
@ -139,6 +146,11 @@ bindings@^1.5.0:
|
|||
dependencies:
|
||||
file-uri-to-path "1.0.0"
|
||||
|
||||
bn.js@^4.4.0:
|
||||
version "4.11.9"
|
||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
|
||||
integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
|
||||
|
||||
body-parser@1.18.3:
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4"
|
||||
|
@ -197,6 +209,11 @@ braces@^2.3.1, braces@^2.3.2:
|
|||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
brorand@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
|
||||
|
||||
buffer-alloc-unsafe@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||
|
@ -228,6 +245,14 @@ buffer@^5.4.3:
|
|||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
buffer@^5.5.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786"
|
||||
integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==
|
||||
dependencies:
|
||||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
byline@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
|
||||
|
@ -619,6 +644,19 @@ ejs@~2.5.7:
|
|||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.9.tgz#7ba254582a560d267437109a68354112475b0ce5"
|
||||
integrity sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ==
|
||||
|
||||
elliptic@^6.5.2:
|
||||
version "6.5.3"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
|
||||
integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==
|
||||
dependencies:
|
||||
bn.js "^4.4.0"
|
||||
brorand "^1.0.1"
|
||||
hash.js "^1.0.0"
|
||||
hmac-drbg "^1.0.0"
|
||||
inherits "^2.0.1"
|
||||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.0"
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
|
@ -922,6 +960,23 @@ has-values@^1.0.0:
|
|||
is-number "^3.0.0"
|
||||
kind-of "^4.0.0"
|
||||
|
||||
hash.js@^1.0.0, hash.js@^1.0.3:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
|
||||
integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
minimalistic-assert "^1.0.1"
|
||||
|
||||
hmac-drbg@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
||||
integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
|
||||
dependencies:
|
||||
hash.js "^1.0.3"
|
||||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
html-tags@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
|
||||
|
@ -1338,6 +1393,16 @@ mime@^1.4.1:
|
|||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
|
||||
integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
|
||||
|
||||
minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
|
||||
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
|
@ -1379,6 +1444,14 @@ ms@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
multibase@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/multibase/-/multibase-1.0.1.tgz#4adbe1de0be8a1ab0274328b653c3f1903476724"
|
||||
integrity sha512-KcCxpBVY8fdVKu4dJMAahq4F/2Z/9xqEjIiR7PiMe7LRGeorFn2NLmicN6nLBCqQvft6MG2Lc9X5P0IdyvnxEw==
|
||||
dependencies:
|
||||
base-x "^3.0.8"
|
||||
buffer "^5.5.0"
|
||||
|
||||
nan@^2.12.1:
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||
|
@ -1406,6 +1479,16 @@ negotiator@0.6.2:
|
|||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||
|
||||
node-addon-api@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
|
||||
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
|
||||
|
||||
node-gyp-build@^4.2.0:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.2.tgz#3f44b65adaafd42fb6c3d81afd630e45c847eb66"
|
||||
integrity sha512-Lqh7mrByWCM8Cf9UPqpeoVBBo5Ugx+RKu885GAzmLBVYjeywScxHXPGLa4JfYNZmcNGwzR0Glu5/9GaQZMFqyA==
|
||||
|
||||
nodemon@^1.17.5:
|
||||
version "1.19.4"
|
||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.4.tgz#56db5c607408e0fdf8920d2b444819af1aae0971"
|
||||
|
@ -1783,6 +1866,15 @@ safe-regex@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
secp256k1@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.1.tgz#b9570ca26ace9e74c3171512bba253da9c0b6d60"
|
||||
integrity sha512-iGRjbGAKfXMqhtdkkuNxsgJQfJO8Oo78Rm7DAvsG3XKngq+nJIOGqrCSXcQqIVsmCj0wFanE5uTKFxV3T9j2wg==
|
||||
dependencies:
|
||||
elliptic "^6.5.2"
|
||||
node-addon-api "^2.0.0"
|
||||
node-gyp-build "^4.2.0"
|
||||
|
||||
semver-diff@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
|
||||
|
|
Loading…
Reference in New Issue