diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/helpers/core-utils.ts | 56 | ||||
-rw-r--r-- | server/helpers/custom-validators/activitypub/actor.ts | 4 | ||||
-rw-r--r-- | server/helpers/peertube-crypto.ts | 9 | ||||
-rw-r--r-- | server/initializers/migrations/0605-actor-missing-keys.ts | 7 |
4 files changed, 58 insertions, 18 deletions
diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index 4bbf0228d..c762f6a29 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts | |||
@@ -6,9 +6,8 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | import { exec, ExecOptions } from 'child_process' | 8 | import { exec, ExecOptions } from 'child_process' |
9 | import { randomBytes } from 'crypto' | 9 | import { ED25519KeyPairOptions, generateKeyPair, randomBytes, RSAKeyPairOptions } from 'crypto' |
10 | import { truncate } from 'lodash' | 10 | import { truncate } from 'lodash' |
11 | import { createPrivateKey as createPrivateKey_1, getPublicKey as getPublicKey_1 } from 'pem' | ||
12 | import { pipeline } from 'stream' | 11 | import { pipeline } from 'stream' |
13 | import { URL } from 'url' | 12 | import { URL } from 'url' |
14 | import { promisify } from 'util' | 13 | import { promisify } from 'util' |
@@ -242,6 +241,51 @@ function toEven (num: number) { | |||
242 | 241 | ||
243 | // --------------------------------------------------------------------------- | 242 | // --------------------------------------------------------------------------- |
244 | 243 | ||
244 | function generateRSAKeyPairPromise (size: number) { | ||
245 | return new Promise<{ publicKey: string, privateKey: string }>((res, rej) => { | ||
246 | const options: RSAKeyPairOptions<'pem', 'pem'> = { | ||
247 | modulusLength: size, | ||
248 | publicKeyEncoding: { | ||
249 | type: 'spki', | ||
250 | format: 'pem' | ||
251 | }, | ||
252 | privateKeyEncoding: { | ||
253 | type: 'pkcs1', | ||
254 | format: 'pem' | ||
255 | } | ||
256 | } | ||
257 | |||
258 | generateKeyPair('rsa', options, (err, publicKey, privateKey) => { | ||
259 | if (err) return rej(err) | ||
260 | |||
261 | return res({ publicKey, privateKey }) | ||
262 | }) | ||
263 | }) | ||
264 | } | ||
265 | |||
266 | function generateED25519KeyPairPromise () { | ||
267 | return new Promise<{ publicKey: string, privateKey: string }>((res, rej) => { | ||
268 | const options: ED25519KeyPairOptions<'pem', 'pem'> = { | ||
269 | publicKeyEncoding: { | ||
270 | type: 'spki', | ||
271 | format: 'pem' | ||
272 | }, | ||
273 | privateKeyEncoding: { | ||
274 | type: 'pkcs8', | ||
275 | format: 'pem' | ||
276 | } | ||
277 | } | ||
278 | |||
279 | generateKeyPair('ed25519', options, (err, publicKey, privateKey) => { | ||
280 | if (err) return rej(err) | ||
281 | |||
282 | return res({ publicKey, privateKey }) | ||
283 | }) | ||
284 | }) | ||
285 | } | ||
286 | |||
287 | // --------------------------------------------------------------------------- | ||
288 | |||
245 | function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> { | 289 | function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> { |
246 | return function promisified (): Promise<A> { | 290 | return function promisified (): Promise<A> { |
247 | return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => { | 291 | return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => { |
@@ -268,8 +312,6 @@ function promisify2<T, U, A> (func: (arg1: T, arg2: U, cb: (err: any, result: A) | |||
268 | } | 312 | } |
269 | 313 | ||
270 | const randomBytesPromise = promisify1<number, Buffer>(randomBytes) | 314 | const randomBytesPromise = promisify1<number, Buffer>(randomBytes) |
271 | const createPrivateKey = promisify1<number, { key: string }>(createPrivateKey_1) | ||
272 | const getPublicKey = promisify1<string, { publicKey: string }>(getPublicKey_1) | ||
273 | const execPromise2 = promisify2<string, any, string>(exec) | 315 | const execPromise2 = promisify2<string, any, string>(exec) |
274 | const execPromise = promisify1<string, string>(exec) | 316 | const execPromise = promisify1<string, string>(exec) |
275 | const pipelinePromise = promisify(pipeline) | 317 | const pipelinePromise = promisify(pipeline) |
@@ -298,8 +340,10 @@ export { | |||
298 | promisify2, | 340 | promisify2, |
299 | 341 | ||
300 | randomBytesPromise, | 342 | randomBytesPromise, |
301 | createPrivateKey, | 343 | |
302 | getPublicKey, | 344 | generateRSAKeyPairPromise, |
345 | generateED25519KeyPairPromise, | ||
346 | |||
303 | execPromise2, | 347 | execPromise2, |
304 | execPromise, | 348 | execPromise, |
305 | pipelinePromise, | 349 | pipelinePromise, |
diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index a4b152722..f43c35b23 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts | |||
@@ -41,9 +41,9 @@ function isActorPreferredUsernameValid (preferredUsername: string) { | |||
41 | function isActorPrivateKeyValid (privateKey: string) { | 41 | function isActorPrivateKeyValid (privateKey: string) { |
42 | return exists(privateKey) && | 42 | return exists(privateKey) && |
43 | typeof privateKey === 'string' && | 43 | typeof privateKey === 'string' && |
44 | privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') && | 44 | (privateKey.startsWith('-----BEGIN RSA PRIVATE KEY-----') || privateKey.startsWith('-----BEGIN PRIVATE KEY-----')) && |
45 | // Sometimes there is a \n at the end, so just assert the string contains the end mark | 45 | // Sometimes there is a \n at the end, so just assert the string contains the end mark |
46 | privateKey.includes('-----END RSA PRIVATE KEY-----') && | 46 | (privateKey.includes('-----END RSA PRIVATE KEY-----') || privateKey.includes('-----END PRIVATE KEY-----')) && |
47 | validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY) | 47 | validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY) |
48 | } | 48 | } |
49 | 49 | ||
diff --git a/server/helpers/peertube-crypto.ts b/server/helpers/peertube-crypto.ts index 1a7ee24a7..1d9cab2ce 100644 --- a/server/helpers/peertube-crypto.ts +++ b/server/helpers/peertube-crypto.ts | |||
@@ -5,7 +5,7 @@ import { cloneDeep } from 'lodash' | |||
5 | import { sha256 } from '@shared/extra-utils' | 5 | import { sha256 } from '@shared/extra-utils' |
6 | import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants' | 6 | import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants' |
7 | import { MActor } from '../types/models' | 7 | import { MActor } from '../types/models' |
8 | import { createPrivateKey, getPublicKey, promisify1, promisify2 } from './core-utils' | 8 | import { generateRSAKeyPairPromise, promisify1, promisify2 } from './core-utils' |
9 | import { jsonld } from './custom-jsonld-signature' | 9 | import { jsonld } from './custom-jsonld-signature' |
10 | import { logger } from './logger' | 10 | import { logger } from './logger' |
11 | 11 | ||
@@ -15,13 +15,10 @@ const bcryptHashPromise = promisify2<any, string | number, string>(hash) | |||
15 | 15 | ||
16 | const httpSignature = require('@peertube/http-signature') | 16 | const httpSignature = require('@peertube/http-signature') |
17 | 17 | ||
18 | async function createPrivateAndPublicKeys () { | 18 | function createPrivateAndPublicKeys () { |
19 | logger.info('Generating a RSA key...') | 19 | logger.info('Generating a RSA key...') |
20 | 20 | ||
21 | const { key } = await createPrivateKey(PRIVATE_RSA_KEY_SIZE) | 21 | return generateRSAKeyPairPromise(PRIVATE_RSA_KEY_SIZE) |
22 | const { publicKey } = await getPublicKey(key) | ||
23 | |||
24 | return { privateKey: key, publicKey } | ||
25 | } | 22 | } |
26 | 23 | ||
27 | // User password checks | 24 | // User password checks |
diff --git a/server/initializers/migrations/0605-actor-missing-keys.ts b/server/initializers/migrations/0605-actor-missing-keys.ts index 72d9b359d..aa89a500c 100644 --- a/server/initializers/migrations/0605-actor-missing-keys.ts +++ b/server/initializers/migrations/0605-actor-missing-keys.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { createPrivateKey, getPublicKey } from '../../helpers/core-utils' | 2 | import { generateRSAKeyPairPromise } from '../../helpers/core-utils' |
3 | import { PRIVATE_RSA_KEY_SIZE } from '../constants' | 3 | import { PRIVATE_RSA_KEY_SIZE } from '../constants' |
4 | 4 | ||
5 | async function up (utils: { | 5 | async function up (utils: { |
@@ -15,10 +15,9 @@ async function up (utils: { | |||
15 | const actors = await utils.sequelize.query<any>(query, options) | 15 | const actors = await utils.sequelize.query<any>(query, options) |
16 | 16 | ||
17 | for (const actor of actors) { | 17 | for (const actor of actors) { |
18 | const { key } = await createPrivateKey(PRIVATE_RSA_KEY_SIZE) | 18 | const { privateKey, publicKey } = await generateRSAKeyPairPromise(PRIVATE_RSA_KEY_SIZE) |
19 | const { publicKey } = await getPublicKey(key) | ||
20 | 19 | ||
21 | const queryUpdate = `UPDATE "actor" SET "publicKey" = '${publicKey}', "privateKey" = '${key}' WHERE id = ${actor.id}` | 20 | const queryUpdate = `UPDATE "actor" SET "publicKey" = '${publicKey}', "privateKey" = '${privateKey}' WHERE id = ${actor.id}` |
22 | await utils.sequelize.query(queryUpdate) | 21 | await utils.sequelize.query(queryUpdate) |
23 | } | 22 | } |
24 | } | 23 | } |