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