Server: use crypto instead of ursa for pod signature
This commit is contained in:
parent
b981a525c3
commit
bdfbd4f162
7 changed files with 94 additions and 41 deletions
|
@ -69,7 +69,6 @@
|
|||
"safe-buffer": "^5.0.1",
|
||||
"scripty": "^1.5.0",
|
||||
"sequelize": "^3.27.0",
|
||||
"ursa": "^0.9.1",
|
||||
"winston": "^2.1.1",
|
||||
"ws": "^1.1.1"
|
||||
},
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
'use strict'
|
||||
|
||||
const crypto = require('crypto')
|
||||
const bcrypt = require('bcrypt')
|
||||
const fs = require('fs')
|
||||
const openssl = require('openssl-wrapper')
|
||||
const ursa = require('ursa')
|
||||
|
||||
const constants = require('../initializers/constants')
|
||||
const logger = require('./logger')
|
||||
|
@ -16,12 +16,51 @@ const peertubeCrypto = {
|
|||
sign
|
||||
}
|
||||
|
||||
function checkSignature (publicKey, rawData, hexSignature) {
|
||||
const crt = ursa.createPublicKey(publicKey)
|
||||
const isValid = crt.hashAndVerify('sha256', new Buffer(rawData).toString('hex'), hexSignature, 'hex')
|
||||
function checkSignature (publicKey, data, hexSignature) {
|
||||
const verify = crypto.createVerify(constants.SIGNATURE_ALGORITHM)
|
||||
|
||||
let dataString
|
||||
if (typeof data === 'string') {
|
||||
dataString = data
|
||||
} else {
|
||||
try {
|
||||
dataString = JSON.stringify(data)
|
||||
} catch (err) {
|
||||
logger.error('Cannot check signature.', { error: err })
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
verify.update(dataString, 'utf8')
|
||||
|
||||
const isValid = verify.verify(publicKey, hexSignature, constants.SIGNATURE_ENCODING)
|
||||
return isValid
|
||||
}
|
||||
|
||||
function sign (data) {
|
||||
const sign = crypto.createSign(constants.SIGNATURE_ALGORITHM)
|
||||
|
||||
let dataString
|
||||
if (typeof data === 'string') {
|
||||
dataString = data
|
||||
} else {
|
||||
try {
|
||||
dataString = JSON.stringify(data)
|
||||
} catch (err) {
|
||||
logger.error('Cannot sign data.', { error: err })
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
sign.update(dataString, 'utf8')
|
||||
|
||||
// TODO: make async
|
||||
const myKey = fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem')
|
||||
const signature = sign.sign(myKey, constants.SIGNATURE_ENCODING)
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
function comparePassword (plainPassword, hashPassword, callback) {
|
||||
bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) {
|
||||
if (err) return callback(err)
|
||||
|
@ -52,13 +91,6 @@ function cryptPassword (password, callback) {
|
|||
})
|
||||
}
|
||||
|
||||
function sign (data) {
|
||||
const myKey = ursa.createPrivateKey(fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem'))
|
||||
const signature = myKey.hashAndSign('sha256', data, 'utf8', 'hex')
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
module.exports = peertubeCrypto
|
||||
|
|
|
@ -28,31 +28,37 @@ function makeSecureRequest (params, callback) {
|
|||
url: constants.REMOTE_SCHEME.HTTP + '://' + params.toPod.host + params.path
|
||||
}
|
||||
|
||||
// Add data with POST requst ?
|
||||
if (params.method === 'POST') {
|
||||
if (params.method !== 'POST') {
|
||||
return callback(new Error('Cannot make a secure request with a non POST method.'))
|
||||
}
|
||||
|
||||
requestParams.json = {}
|
||||
|
||||
// Add signature if it is specified in the params
|
||||
if (params.sign === true) {
|
||||
const host = constants.CONFIG.WEBSERVER.HOST
|
||||
|
||||
let dataToSign
|
||||
if (params.data) {
|
||||
dataToSign = dataToSign = params.data
|
||||
} else {
|
||||
// We do not have data to sign so we just take our host
|
||||
// It is not ideal but the connection should be in HTTPS
|
||||
dataToSign = host
|
||||
}
|
||||
|
||||
requestParams.json.signature = {
|
||||
host,
|
||||
signature: peertubeCrypto.sign(host)
|
||||
host, // Which host we pretend to be
|
||||
signature: peertubeCrypto.sign(dataToSign)
|
||||
}
|
||||
}
|
||||
|
||||
// If there are data informations
|
||||
if (params.data) {
|
||||
requestParams.json.data = params.data
|
||||
request.post(requestParams, callback)
|
||||
} else {
|
||||
// No data
|
||||
request.post(requestParams, callback)
|
||||
}
|
||||
} else {
|
||||
request.get(requestParams, callback)
|
||||
}
|
||||
|
||||
request.post(requestParams, callback)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -118,16 +118,21 @@ const REQUEST_ENDPOINTS = {
|
|||
VIDEOS: 'videos'
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const REMOTE_SCHEME = {
|
||||
HTTP: 'https',
|
||||
WS: 'wss'
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const SIGNATURE_ALGORITHM = 'RSA-SHA256'
|
||||
const SIGNATURE_ENCODING = 'hex'
|
||||
|
||||
// Password encryption
|
||||
const BCRYPT_SALT_SIZE = 10
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Express static paths (router)
|
||||
const STATIC_PATHS = {
|
||||
PREVIEWS: '/static/previews/',
|
||||
|
@ -143,6 +148,8 @@ let STATIC_MAX_AGE = '30d'
|
|||
const THUMBNAILS_SIZE = '200x110'
|
||||
const PREVIEWS_SIZE = '640x480'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const USER_ROLES = {
|
||||
ADMIN: 'admin',
|
||||
USER: 'user'
|
||||
|
@ -180,6 +187,8 @@ module.exports = {
|
|||
REQUESTS_LIMIT,
|
||||
RETRY_REQUESTS,
|
||||
SEARCHABLE_COLUMNS,
|
||||
SIGNATURE_ALGORITHM,
|
||||
SIGNATURE_ENCODING,
|
||||
SORTABLE_COLUMNS,
|
||||
STATIC_MAX_AGE,
|
||||
STATIC_PATHS,
|
||||
|
|
|
@ -23,7 +23,14 @@ function checkSignature (req, res, next) {
|
|||
|
||||
logger.debug('Checking signature from %s.', host)
|
||||
|
||||
const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, host, req.body.signature.signature)
|
||||
let signatureShouldBe
|
||||
if (req.body.data) {
|
||||
signatureShouldBe = req.body.data
|
||||
} else {
|
||||
signatureShouldBe = host
|
||||
}
|
||||
|
||||
const signatureOk = peertubeCrypto.checkSignature(pod.publicKey, signatureShouldBe, req.body.signature.signature)
|
||||
|
||||
if (signatureOk === true) {
|
||||
res.locals.secure = {
|
||||
|
|
|
@ -11,7 +11,7 @@ function signature (req, res, next) {
|
|||
req.checkBody('signature.host', 'Should have a signature host').isURL()
|
||||
req.checkBody('signature.signature', 'Should have a signature').notEmpty()
|
||||
|
||||
logger.debug('Checking signature parameters', { parameters: { signatureHost: req.body.signature.host } })
|
||||
logger.debug('Checking signature parameters', { parameters: { signature: req.body.signature } })
|
||||
|
||||
checkErrors(req, res, next)
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ function makeRequest (toPod, requestEndpoint, requestsToMake, callback) {
|
|||
'Error sending secure request to %s pod.',
|
||||
toPod.host,
|
||||
{
|
||||
error: err || new Error('Status code not 20x : ' + res.statusCode)
|
||||
error: err ? err.message : 'Status code not 20x : ' + res.statusCode
|
||||
}
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue