]>
Commit | Line | Data |
---|---|---|
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.', 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.', 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 | } |