aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-01-04 22:23:07 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-01-04 22:23:07 +0100
commitbdfbd4f162d66c3a6bd7c312a99e0b692e830792 (patch)
tree30b857f73fe62771a94320e3e78030a1345dc3a8
parentb981a525c37d226b3fa59287a6ce338f54583d0c (diff)
downloadPeerTube-bdfbd4f162d66c3a6bd7c312a99e0b692e830792.tar.gz
PeerTube-bdfbd4f162d66c3a6bd7c312a99e0b692e830792.tar.zst
PeerTube-bdfbd4f162d66c3a6bd7c312a99e0b692e830792.zip
Server: use crypto instead of ursa for pod signature
-rw-r--r--package.json1
-rw-r--r--server/helpers/peertube-crypto.js54
-rw-r--r--server/helpers/requests.js46
-rw-r--r--server/initializers/constants.js13
-rw-r--r--server/middlewares/secure.js9
-rw-r--r--server/middlewares/validators/remote/signature.js2
-rw-r--r--server/models/request.js2
7 files changed, 90 insertions, 37 deletions
diff --git a/package.json b/package.json
index 5eadcc363..554ad16df 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,6 @@
69 "safe-buffer": "^5.0.1", 69 "safe-buffer": "^5.0.1",
70 "scripty": "^1.5.0", 70 "scripty": "^1.5.0",
71 "sequelize": "^3.27.0", 71 "sequelize": "^3.27.0",
72 "ursa": "^0.9.1",
73 "winston": "^2.1.1", 72 "winston": "^2.1.1",
74 "ws": "^1.1.1" 73 "ws": "^1.1.1"
75 }, 74 },
diff --git a/server/helpers/peertube-crypto.js b/server/helpers/peertube-crypto.js
index 610cb16cd..0f1e02ad6 100644
--- a/server/helpers/peertube-crypto.js
+++ b/server/helpers/peertube-crypto.js
@@ -1,9 +1,9 @@
1'use strict' 1'use strict'
2 2
3const crypto = require('crypto')
3const bcrypt = require('bcrypt') 4const bcrypt = require('bcrypt')
4const fs = require('fs') 5const fs = require('fs')
5const openssl = require('openssl-wrapper') 6const openssl = require('openssl-wrapper')
6const ursa = require('ursa')
7 7
8const constants = require('../initializers/constants') 8const constants = require('../initializers/constants')
9const logger = require('./logger') 9const logger = require('./logger')
@@ -16,12 +16,51 @@ const peertubeCrypto = {
16 sign 16 sign
17} 17}
18 18
19function checkSignature (publicKey, rawData, hexSignature) { 19function checkSignature (publicKey, data, hexSignature) {
20 const crt = ursa.createPublicKey(publicKey) 20 const verify = crypto.createVerify(constants.SIGNATURE_ALGORITHM)
21 const isValid = crt.hashAndVerify('sha256', new Buffer(rawData).toString('hex'), hexSignature, 'hex') 21
22 let dataString
23 if (typeof data === 'string') {
24 dataString = data
25 } else {
26 try {
27 dataString = JSON.stringify(data)
28 } catch (err) {
29 logger.error('Cannot check signature.', { error: err })
30 return false
31 }
32 }
33
34 verify.update(dataString, 'utf8')
35
36 const isValid = verify.verify(publicKey, hexSignature, constants.SIGNATURE_ENCODING)
22 return isValid 37 return isValid
23} 38}
24 39
40function sign (data) {
41 const sign = crypto.createSign(constants.SIGNATURE_ALGORITHM)
42
43 let dataString
44 if (typeof data === 'string') {
45 dataString = data
46 } else {
47 try {
48 dataString = JSON.stringify(data)
49 } catch (err) {
50 logger.error('Cannot sign data.', { error: err })
51 return ''
52 }
53 }
54
55 sign.update(dataString, 'utf8')
56
57 // TODO: make async
58 const myKey = fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem')
59 const signature = sign.sign(myKey, constants.SIGNATURE_ENCODING)
60
61 return signature
62}
63
25function comparePassword (plainPassword, hashPassword, callback) { 64function comparePassword (plainPassword, hashPassword, callback) {
26 bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) { 65 bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) {
27 if (err) return callback(err) 66 if (err) return callback(err)
@@ -52,13 +91,6 @@ function cryptPassword (password, callback) {
52 }) 91 })
53} 92}
54 93
55function sign (data) {
56 const myKey = ursa.createPrivateKey(fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem'))
57 const signature = myKey.hashAndSign('sha256', data, 'utf8', 'hex')
58
59 return signature
60}
61
62// --------------------------------------------------------------------------- 94// ---------------------------------------------------------------------------
63 95
64module.exports = peertubeCrypto 96module.exports = peertubeCrypto
diff --git a/server/helpers/requests.js b/server/helpers/requests.js
index b0cda09fe..095b95e1c 100644
--- a/server/helpers/requests.js
+++ b/server/helpers/requests.js
@@ -28,31 +28,37 @@ function makeSecureRequest (params, callback) {
28 url: constants.REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path 28 url: constants.REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path
29 } 29 }
30 30
31 // Add data with POST requst ? 31 if (params.method !== 'POST') {
32 if (params.method === 'POST') { 32 return callback(new Error('Cannot make a secure request with a non POST method.'))
33 requestParams.json = {} 33 }
34 34
35 // Add signature if it is specified in the params 35 requestParams.json = {}
36 if (params.sign === true) {
37 const host = constants.CONFIG.WEBSERVER.HOST
38
39 requestParams.json.signature = {
40 host,
41 signature: peertubeCrypto.sign(host)
42 }
43 }
44 36
45 // If there are data informations 37 // Add signature if it is specified in the params
38 if (params.sign === true) {
39 const host = constants.CONFIG.WEBSERVER.HOST
40
41 let dataToSign
46 if (params.data) { 42 if (params.data) {
47 requestParams.json.data = params.data 43 dataToSign = dataToSign = params.data
48 request.post(requestParams, callback)
49 } else { 44 } else {
50 // No data 45 // We do not have data to sign so we just take our host
51 request.post(requestParams, callback) 46 // It is not ideal but the connection should be in HTTPS
47 dataToSign = host
52 } 48 }
53 } else { 49
54 request.get(requestParams, callback) 50 requestParams.json.signature = {
51 host, // Which host we pretend to be
52 signature: peertubeCrypto.sign(dataToSign)
53 }
54 }
55
56 // If there are data informations
57 if (params.data) {
58 requestParams.json.data = params.data
55 } 59 }
60
61 request.post(requestParams, callback)
56} 62}
57 63
58// --------------------------------------------------------------------------- 64// ---------------------------------------------------------------------------
diff --git a/server/initializers/constants.js b/server/initializers/constants.js
index 6ba8a9da0..a6adb75bf 100644
--- a/server/initializers/constants.js
+++ b/server/initializers/constants.js
@@ -118,16 +118,21 @@ const REQUEST_ENDPOINTS = {
118 VIDEOS: 'videos' 118 VIDEOS: 'videos'
119} 119}
120 120
121// ---------------------------------------------------------------------------
122
123const REMOTE_SCHEME = { 121const REMOTE_SCHEME = {
124 HTTP: 'https', 122 HTTP: 'https',
125 WS: 'wss' 123 WS: 'wss'
126} 124}
127 125
126// ---------------------------------------------------------------------------
127
128const SIGNATURE_ALGORITHM = 'RSA-SHA256'
129const SIGNATURE_ENCODING = 'hex'
130
128// Password encryption 131// Password encryption
129const BCRYPT_SALT_SIZE = 10 132const BCRYPT_SALT_SIZE = 10
130 133
134// ---------------------------------------------------------------------------
135
131// Express static paths (router) 136// Express static paths (router)
132const STATIC_PATHS = { 137const STATIC_PATHS = {
133 PREVIEWS: '/static/previews/', 138 PREVIEWS: '/static/previews/',
@@ -143,6 +148,8 @@ let STATIC_MAX_AGE = '30d'
143const THUMBNAILS_SIZE = '200x110' 148const THUMBNAILS_SIZE = '200x110'
144const PREVIEWS_SIZE = '640x480' 149const PREVIEWS_SIZE = '640x480'
145 150
151// ---------------------------------------------------------------------------
152
146const USER_ROLES = { 153const USER_ROLES = {
147 ADMIN: 'admin', 154 ADMIN: 'admin',
148 USER: 'user' 155 USER: 'user'
@@ -180,6 +187,8 @@ module.exports = {
180 REQUESTS_LIMIT, 187 REQUESTS_LIMIT,
181 RETRY_REQUESTS, 188 RETRY_REQUESTS,
182 SEARCHABLE_COLUMNS, 189 SEARCHABLE_COLUMNS,
190 SIGNATURE_ALGORITHM,
191 SIGNATURE_ENCODING,
183 SORTABLE_COLUMNS, 192 SORTABLE_COLUMNS,
184 STATIC_MAX_AGE, 193 STATIC_MAX_AGE,
185 STATIC_PATHS, 194 STATIC_PATHS,
diff --git a/server/middlewares/secure.js b/server/middlewares/secure.js
index 2aae715c4..b6e6d818b 100644
--- a/server/middlewares/secure.js
+++ b/server/middlewares/secure.js
@@ -23,7 +23,14 @@ function checkSignature (req, res, next) {
23 23
24 logger.debug('Checking signature from %s.', host) 24 logger.debug('Checking signature from %s.', host)
25 25
26 const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, host, req.body.signature.signature) 26 let signatureShouldBe
27 if (req.body.data) {
28 signatureShouldBe = req.body.data
29 } else {
30 signatureShouldBe = host
31 }
32
33 const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
27 34
28 if (signatureOk === true) { 35 if (signatureOk === true) {
29 res.locals.secure = { 36 res.locals.secure = {
diff --git a/server/middlewares/validators/remote/signature.js b/server/middlewares/validators/remote/signature.js
index 5880a2c2c..002232c05 100644
--- a/server/middlewares/validators/remote/signature.js
+++ b/server/middlewares/validators/remote/signature.js
@@ -11,7 +11,7 @@ function signature (req, res, next) {
11 req.checkBody('signature.host', 'Should have a signature host').isURL() 11 req.checkBody('signature.host', 'Should have a signature host').isURL()
12 req.checkBody('signature.signature', 'Should have a signature').notEmpty() 12 req.checkBody('signature.signature', 'Should have a signature').notEmpty()
13 13
14 logger.debug('Checking signature parameters', { parameters: { signatureHost: req.body.signature.host } }) 14 logger.debug('Checking signature parameters', { parameters: { signature: req.body.signature } })
15 15
16 checkErrors(req, res, next) 16 checkErrors(req, res, next)
17} 17}
diff --git a/server/models/request.js b/server/models/request.js
index e18f8fe3d..bae227c05 100644
--- a/server/models/request.js
+++ b/server/models/request.js
@@ -122,7 +122,7 @@ function makeRequest (toPod, requestEndpoint, requestsToMake, callback) {
122 'Error sending secure request to %s pod.', 122 'Error sending secure request to %s pod.',
123 toPod.host, 123 toPod.host,
124 { 124 {
125 error: err || new Error('Status code not 20x : ' + res.statusCode) 125 error: err ? err.message : 'Status code not 20x : ' + res.statusCode
126 } 126 }
127 ) 127 )
128 128