]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/peertube-crypto.ts
Async signature and various fixes
[github/Chocobozzz/PeerTube.git] / server / helpers / peertube-crypto.ts
1 import * as crypto from 'crypto'
2 import * as Promise from 'bluebird'
3 import { join } from 'path'
4
5 import {
6 SIGNATURE_ALGORITHM,
7 SIGNATURE_ENCODING,
8 PRIVATE_CERT_NAME,
9 CONFIG,
10 BCRYPT_SALT_SIZE,
11 PUBLIC_CERT_NAME
12 } from '../initializers'
13 import {
14 readFilePromise,
15 bcryptComparePromise,
16 bcryptGenSaltPromise,
17 bcryptHashPromise,
18 accessPromise,
19 opensslExecPromise
20 } from './core-utils'
21 import { logger } from './logger'
22
23 function checkSignature (publicKey: string, data: string, hexSignature: string) {
24 const verify = crypto.createVerify(SIGNATURE_ALGORITHM)
25
26 let dataString
27 if (typeof data === 'string') {
28 dataString = data
29 } else {
30 try {
31 dataString = JSON.stringify(data)
32 } catch (err) {
33 logger.error('Cannot check signature.', { error: err })
34 return false
35 }
36 }
37
38 verify.update(dataString, 'utf8')
39
40 const isValid = verify.verify(publicKey, hexSignature, SIGNATURE_ENCODING)
41 return isValid
42 }
43
44 function sign (data: string|Object) {
45 const sign = crypto.createSign(SIGNATURE_ALGORITHM)
46
47 let dataString: string
48 if (typeof data === 'string') {
49 dataString = data
50 } else {
51 try {
52 dataString = JSON.stringify(data)
53 } catch (err) {
54 logger.error('Cannot sign data.', { error: err })
55 return Promise.resolve('')
56 }
57 }
58
59 sign.update(dataString, 'utf8')
60
61 return getMyPrivateCert().then(myKey => {
62 return sign.sign(myKey, SIGNATURE_ENCODING)
63 })
64 }
65
66 function comparePassword (plainPassword: string, hashPassword: string) {
67 return bcryptComparePromise(plainPassword, hashPassword)
68 }
69
70 function createCertsIfNotExist () {
71 return certsExist().then(exist => {
72 if (exist === true) {
73 return undefined
74 }
75
76 return createCerts()
77 })
78 }
79
80 function cryptPassword (password: string) {
81 return bcryptGenSaltPromise(BCRYPT_SALT_SIZE).then(salt => bcryptHashPromise(password, salt))
82 }
83
84 function getMyPrivateCert () {
85 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
86 return readFilePromise(certPath, 'utf8')
87 }
88
89 function getMyPublicCert () {
90 const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME)
91 return readFilePromise(certPath, 'utf8')
92 }
93
94 // ---------------------------------------------------------------------------
95
96 export {
97 checkSignature,
98 comparePassword,
99 createCertsIfNotExist,
100 cryptPassword,
101 getMyPrivateCert,
102 getMyPublicCert,
103 sign
104 }
105
106 // ---------------------------------------------------------------------------
107
108 function certsExist () {
109 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
110
111 // If there is an error the certificates do not exist
112 return accessPromise(certPath)
113 .then(() => true)
114 .catch(() => false)
115 }
116
117 function createCerts () {
118 return certsExist().then(exist => {
119 if (exist === true) {
120 const errorMessage = 'Certs already exist.'
121 logger.warning(errorMessage)
122 throw new Error(errorMessage)
123 }
124
125 logger.info('Generating a RSA key...')
126
127 const privateCertPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
128 const genRsaOptions = {
129 'out': privateCertPath,
130 '2048': false
131 }
132 return opensslExecPromise('genrsa', genRsaOptions)
133 .then(() => {
134 logger.info('RSA key generated.')
135 logger.info('Managing public key...')
136
137 const publicCertPath = join(CONFIG.STORAGE.CERT_DIR, 'peertube.pub')
138 const rsaOptions = {
139 'in': privateCertPath,
140 'pubout': true,
141 'out': publicCertPath
142 }
143 return opensslExecPromise('rsa', rsaOptions)
144 .then(() => logger.info('Public key managed.'))
145 .catch(err => {
146 logger.error('Cannot create public key on this pod.')
147 throw err
148 })
149 })
150 .catch(err => {
151 logger.error('Cannot create private key on this pod.')
152 throw err
153 })
154 })
155 }