]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/peertube-crypto.ts
8e8001cd69bbd3563351ad025e176852a28cac1e
[github/Chocobozzz/PeerTube.git] / server / helpers / peertube-crypto.ts
1 import * as crypto from 'crypto'
2 import * as fs from 'fs'
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 ''
56 }
57 }
58
59 sign.update(dataString, 'utf8')
60
61 // TODO: make async
62 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
63 const myKey = fs.readFileSync(certPath)
64 const signature = sign.sign(myKey.toString(), SIGNATURE_ENCODING)
65
66 return signature
67 }
68
69 function comparePassword (plainPassword: string, hashPassword: string) {
70 return bcryptComparePromise(plainPassword, hashPassword)
71 }
72
73 function createCertsIfNotExist () {
74 return certsExist().then(exist => {
75 if (exist === true) {
76 return undefined
77 }
78
79 return createCerts()
80 })
81 }
82
83 function cryptPassword (password: string) {
84 return bcryptGenSaltPromise(BCRYPT_SALT_SIZE).then(salt => bcryptHashPromise(password, salt))
85 }
86
87 function getMyPrivateCert () {
88 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
89 return readFilePromise(certPath, 'utf8')
90 }
91
92 function getMyPublicCert () {
93 const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME)
94 return readFilePromise(certPath, 'utf8')
95 }
96
97 // ---------------------------------------------------------------------------
98
99 export {
100 checkSignature,
101 comparePassword,
102 createCertsIfNotExist,
103 cryptPassword,
104 getMyPrivateCert,
105 getMyPublicCert,
106 sign
107 }
108
109 // ---------------------------------------------------------------------------
110
111 function certsExist () {
112 const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
113
114 // If there is an error the certificates do not exist
115 return accessPromise(certPath)
116 .then(() => true)
117 .catch(() => false)
118 }
119
120 function createCerts () {
121 return certsExist().then(exist => {
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 return opensslExecPromise('genrsa', genRsaOptions)
136 .then(() => {
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 return opensslExecPromise('rsa', rsaOptions)
147 .then(() => logger.info('Public key managed.'))
148 .catch(err => {
149 logger.error('Cannot create public key on this pod.')
150 throw err
151 })
152 })
153 .catch(err => {
154 logger.error('Cannot create private key on this pod.')
155 throw err
156 })
157 })
158 }