]>
Commit | Line | Data |
---|---|---|
9f10b292 C |
1 | 'use strict' |
2 | ||
bdfbd4f1 | 3 | const crypto = require('crypto') |
26d7d31b | 4 | const bcrypt = require('bcrypt') |
f0f5567b C |
5 | const fs = require('fs') |
6 | const openssl = require('openssl-wrapper') | |
15103f11 | 7 | const pathUtils = require('path') |
9f10b292 | 8 | |
e861452f | 9 | const constants = require('../initializers/constants') |
f0f5567b | 10 | const logger = require('./logger') |
9f10b292 | 11 | |
f0f5567b | 12 | const peertubeCrypto = { |
c4403b29 C |
13 | checkSignature, |
14 | comparePassword, | |
15 | createCertsIfNotExist, | |
16 | cryptPassword, | |
15103f11 C |
17 | getMyPrivateCert, |
18 | getMyPublicCert, | |
c4403b29 | 19 | sign |
9f10b292 C |
20 | } |
21 | ||
bdfbd4f1 C |
22 | function checkSignature (publicKey, data, hexSignature) { |
23 | const verify = crypto.createVerify(constants.SIGNATURE_ALGORITHM) | |
24 | ||
25 | let dataString | |
26 | if (typeof data === 'string') { | |
27 | dataString = data | |
28 | } else { | |
29 | try { | |
30 | dataString = JSON.stringify(data) | |
31 | } catch (err) { | |
32 | logger.error('Cannot check signature.', { error: err }) | |
33 | return false | |
34 | } | |
35 | } | |
36 | ||
37 | verify.update(dataString, 'utf8') | |
38 | ||
39 | const isValid = verify.verify(publicKey, hexSignature, constants.SIGNATURE_ENCODING) | |
bc503c2a | 40 | return isValid |
9f10b292 C |
41 | } |
42 | ||
bdfbd4f1 C |
43 | function sign (data) { |
44 | const sign = crypto.createSign(constants.SIGNATURE_ALGORITHM) | |
45 | ||
46 | let dataString | |
47 | if (typeof data === 'string') { | |
48 | dataString = data | |
49 | } else { | |
50 | try { | |
51 | dataString = JSON.stringify(data) | |
52 | } catch (err) { | |
53 | logger.error('Cannot sign data.', { error: err }) | |
54 | return '' | |
55 | } | |
56 | } | |
57 | ||
58 | sign.update(dataString, 'utf8') | |
59 | ||
60 | // TODO: make async | |
15103f11 C |
61 | const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME) |
62 | const myKey = fs.readFileSync(certPath) | |
bdfbd4f1 C |
63 | const signature = sign.sign(myKey, constants.SIGNATURE_ENCODING) |
64 | ||
65 | return signature | |
66 | } | |
67 | ||
26d7d31b C |
68 | function comparePassword (plainPassword, hashPassword, callback) { |
69 | bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) { | |
70 | if (err) return callback(err) | |
71 | ||
72 | return callback(null, isPasswordMatch) | |
73 | }) | |
74 | } | |
75 | ||
9f10b292 | 76 | function createCertsIfNotExist (callback) { |
0dd079da C |
77 | certsExist(function (err, exist) { |
78 | if (err) return callback(err) | |
79 | ||
9f10b292 C |
80 | if (exist === true) { |
81 | return callback(null) | |
82 | } | |
83 | ||
84 | createCerts(function (err) { | |
85 | return callback(err) | |
dac0a531 | 86 | }) |
9f10b292 C |
87 | }) |
88 | } | |
dac0a531 | 89 | |
26d7d31b C |
90 | function cryptPassword (password, callback) { |
91 | bcrypt.genSalt(constants.BCRYPT_SALT_SIZE, function (err, salt) { | |
92 | if (err) return callback(err) | |
93 | ||
94 | bcrypt.hash(password, salt, function (err, hash) { | |
95 | return callback(err, hash) | |
96 | }) | |
97 | }) | |
98 | } | |
99 | ||
15103f11 C |
100 | function getMyPrivateCert (callback) { |
101 | const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME) | |
102 | fs.readFile(certPath, 'utf8', callback) | |
103 | } | |
104 | ||
105 | function getMyPublicCert (callback) { | |
106 | const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PUBLIC_CERT_NAME) | |
107 | fs.readFile(certPath, 'utf8', callback) | |
108 | } | |
109 | ||
9f10b292 | 110 | // --------------------------------------------------------------------------- |
dac0a531 | 111 | |
9f10b292 | 112 | module.exports = peertubeCrypto |
dac0a531 | 113 | |
9f10b292 | 114 | // --------------------------------------------------------------------------- |
dac0a531 | 115 | |
9f10b292 | 116 | function certsExist (callback) { |
15103f11 | 117 | const certPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME) |
0dd079da C |
118 | fs.access(certPath, function (err) { |
119 | // If there is an error the certificates do not exist | |
120 | const exists = !err | |
121 | return callback(null, exists) | |
9f10b292 C |
122 | }) |
123 | } | |
124 | ||
125 | function createCerts (callback) { | |
0dd079da C |
126 | certsExist(function (err, exist) { |
127 | if (err) return callback(err) | |
128 | ||
9f10b292 | 129 | if (exist === true) { |
f0f5567b | 130 | const string = 'Certs already exist.' |
9f10b292 C |
131 | logger.warning(string) |
132 | return callback(new Error(string)) | |
133 | } | |
134 | ||
135 | logger.info('Generating a RSA key...') | |
e861452f | 136 | |
15103f11 C |
137 | const privateCertPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, constants.PRIVATE_CERT_NAME) |
138 | const genRsaOptions = { | |
139 | 'out': privateCertPath, | |
e861452f C |
140 | '2048': false |
141 | } | |
15103f11 | 142 | openssl.exec('genrsa', genRsaOptions, function (err) { |
9f10b292 C |
143 | if (err) { |
144 | logger.error('Cannot create private key on this pod.') | |
145 | return callback(err) | |
dac0a531 | 146 | } |
15103f11 | 147 | |
9f10b292 | 148 | logger.info('RSA key generated.') |
15103f11 | 149 | logger.info('Managing public key...') |
dac0a531 | 150 | |
15103f11 C |
151 | const publicCertPath = pathUtils.join(constants.CONFIG.STORAGE.CERT_DIR, 'peertube.pub') |
152 | const rsaOptions = { | |
153 | 'in': privateCertPath, | |
e861452f | 154 | 'pubout': true, |
15103f11 | 155 | 'out': publicCertPath |
e861452f | 156 | } |
15103f11 | 157 | openssl.exec('rsa', rsaOptions, function (err) { |
dac0a531 | 158 | if (err) { |
9f10b292 | 159 | logger.error('Cannot create public key on this pod.') |
dac0a531 C |
160 | return callback(err) |
161 | } | |
dac0a531 | 162 | |
9f10b292 C |
163 | logger.info('Public key managed.') |
164 | return callback(null) | |
165 | }) | |
dac0a531 | 166 | }) |
9f10b292 C |
167 | }) |
168 | } |