]>
Commit | Line | Data |
---|---|---|
9f10b292 C |
1 | 'use strict' |
2 | ||
f0f5567b C |
3 | const crypto = require('crypto') |
4 | const fs = require('fs') | |
5 | const openssl = require('openssl-wrapper') | |
f0f5567b | 6 | const ursa = require('ursa') |
9f10b292 | 7 | |
e861452f | 8 | const constants = require('../initializers/constants') |
f0f5567b | 9 | const logger = require('./logger') |
9f10b292 | 10 | |
f0f5567b | 11 | const algorithm = 'aes-256-ctr' |
9f10b292 | 12 | |
f0f5567b | 13 | const peertubeCrypto = { |
9f10b292 C |
14 | checkSignature: checkSignature, |
15 | createCertsIfNotExist: createCertsIfNotExist, | |
16 | decrypt: decrypt, | |
17 | encrypt: encrypt, | |
9f10b292 C |
18 | sign: sign |
19 | } | |
20 | ||
bc503c2a C |
21 | function checkSignature (publicKey, rawData, hexSignature) { |
22 | const crt = ursa.createPublicKey(publicKey) | |
23 | const isValid = crt.hashAndVerify('sha256', new Buffer(rawData).toString('hex'), hexSignature, 'hex') | |
24 | return isValid | |
9f10b292 C |
25 | } |
26 | ||
27 | function createCertsIfNotExist (callback) { | |
28 | certsExist(function (exist) { | |
29 | if (exist === true) { | |
30 | return callback(null) | |
31 | } | |
32 | ||
33 | createCerts(function (err) { | |
34 | return callback(err) | |
dac0a531 | 35 | }) |
9f10b292 C |
36 | }) |
37 | } | |
dac0a531 | 38 | |
9f10b292 | 39 | function decrypt (key, data, callback) { |
e861452f | 40 | fs.readFile(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem', function (err, file) { |
9f10b292 | 41 | if (err) return callback(err) |
dac0a531 | 42 | |
bc503c2a C |
43 | const myPrivateKey = ursa.createPrivateKey(file) |
44 | const decryptedKey = myPrivateKey.decrypt(key, 'hex', 'utf8') | |
45 | const decryptedData = symetricDecrypt(data, decryptedKey) | |
dac0a531 | 46 | |
bc503c2a | 47 | return callback(null, decryptedData) |
9f10b292 C |
48 | }) |
49 | } | |
dac0a531 | 50 | |
bc503c2a C |
51 | function encrypt (publicKey, data, callback) { |
52 | const crt = ursa.createPublicKey(publicKey) | |
dac0a531 | 53 | |
9f10b292 C |
54 | symetricEncrypt(data, function (err, dataEncrypted) { |
55 | if (err) return callback(err) | |
dac0a531 | 56 | |
f0f5567b C |
57 | const key = crt.encrypt(dataEncrypted.password, 'utf8', 'hex') |
58 | const encrypted = { | |
9f10b292 C |
59 | data: dataEncrypted.crypted, |
60 | key: key | |
61 | } | |
dac0a531 | 62 | |
9f10b292 C |
63 | callback(null, encrypted) |
64 | }) | |
65 | } | |
dac0a531 | 66 | |
9f10b292 | 67 | function sign (data) { |
e861452f | 68 | const myKey = ursa.createPrivateKey(fs.readFileSync(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem')) |
f0f5567b | 69 | const signature = myKey.hashAndSign('sha256', data, 'utf8', 'hex') |
dac0a531 | 70 | |
9f10b292 C |
71 | return signature |
72 | } | |
dac0a531 | 73 | |
9f10b292 | 74 | // --------------------------------------------------------------------------- |
dac0a531 | 75 | |
9f10b292 | 76 | module.exports = peertubeCrypto |
dac0a531 | 77 | |
9f10b292 | 78 | // --------------------------------------------------------------------------- |
dac0a531 | 79 | |
9f10b292 | 80 | function certsExist (callback) { |
e861452f | 81 | fs.exists(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem', function (exists) { |
9f10b292 C |
82 | return callback(exists) |
83 | }) | |
84 | } | |
85 | ||
86 | function createCerts (callback) { | |
87 | certsExist(function (exist) { | |
88 | if (exist === true) { | |
f0f5567b | 89 | const string = 'Certs already exist.' |
9f10b292 C |
90 | logger.warning(string) |
91 | return callback(new Error(string)) | |
92 | } | |
93 | ||
94 | logger.info('Generating a RSA key...') | |
e861452f C |
95 | |
96 | let options = { | |
97 | 'out': constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem', | |
98 | '2048': false | |
99 | } | |
100 | openssl.exec('genrsa', options, function (err) { | |
9f10b292 C |
101 | if (err) { |
102 | logger.error('Cannot create private key on this pod.') | |
103 | return callback(err) | |
dac0a531 | 104 | } |
9f10b292 | 105 | logger.info('RSA key generated.') |
dac0a531 | 106 | |
e861452f C |
107 | options = { |
108 | 'in': constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem', | |
109 | 'pubout': true, | |
110 | 'out': constants.CONFIG.STORAGE.CERT_DIR + 'peertube.pub' | |
111 | } | |
9f10b292 | 112 | logger.info('Manage public key...') |
e861452f | 113 | openssl.exec('rsa', options, function (err) { |
dac0a531 | 114 | if (err) { |
9f10b292 | 115 | logger.error('Cannot create public key on this pod.') |
dac0a531 C |
116 | return callback(err) |
117 | } | |
dac0a531 | 118 | |
9f10b292 C |
119 | logger.info('Public key managed.') |
120 | return callback(null) | |
121 | }) | |
dac0a531 | 122 | }) |
9f10b292 C |
123 | }) |
124 | } | |
125 | ||
126 | function generatePassword (callback) { | |
127 | crypto.randomBytes(32, function (err, buf) { | |
128 | if (err) return callback(err) | |
129 | ||
130 | callback(null, buf.toString('utf8')) | |
131 | }) | |
132 | } | |
133 | ||
134 | function symetricDecrypt (text, password) { | |
f0f5567b C |
135 | const decipher = crypto.createDecipher(algorithm, password) |
136 | let dec = decipher.update(text, 'hex', 'utf8') | |
9f10b292 C |
137 | dec += decipher.final('utf8') |
138 | return dec | |
139 | } | |
140 | ||
141 | function symetricEncrypt (text, callback) { | |
142 | generatePassword(function (err, password) { | |
143 | if (err) return callback(err) | |
144 | ||
f0f5567b C |
145 | const cipher = crypto.createCipher(algorithm, password) |
146 | let crypted = cipher.update(text, 'utf8', 'hex') | |
9f10b292 C |
147 | crypted += cipher.final('hex') |
148 | callback(null, { crypted: crypted, password: password }) | |
149 | }) | |
150 | } |