Fix weird bug where CPU jumps and stays to 100%
Seems related to lazy import of custom-jsonld-signature So we refactored jsonld function calls a little bit
This commit is contained in:
parent
f93bc6a8be
commit
b017d4d02f
5 changed files with 108 additions and 105 deletions
|
@ -1,6 +1,7 @@
|
|||
import { ContextType } from '@peertube/peertube-models'
|
||||
import { ACTIVITY_PUB } from '@server/initializers/constants.js'
|
||||
import { buildDigest, signJsonLDObject } from './peertube-crypto.js'
|
||||
import { buildDigest } from './peertube-crypto.js'
|
||||
import type { signJsonLDObject } from './peertube-jsonld.js'
|
||||
|
||||
export type ContextFilter = <T> (arg: T) => Promise<T>
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import httpSignature from '@peertube/http-signature'
|
||||
import { sha256 } from '@peertube/peertube-node-utils'
|
||||
import { createCipheriv, createDecipheriv, createSign, createVerify } from 'crypto'
|
||||
import { createCipheriv, createDecipheriv } from 'crypto'
|
||||
import { Request } from 'express'
|
||||
import cloneDeep from 'lodash-es/cloneDeep.js'
|
||||
import { BCRYPT_SALT_SIZE, ENCRYPTION, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants.js'
|
||||
import { MActor } from '../types/models/index.js'
|
||||
import { generateRSAKeyPairPromise, randomBytesPromise, scryptPromise } from './core-utils.js'
|
||||
import { logger } from './logger.js'
|
||||
import { assertIsInWorkerThread } from './threads.js'
|
||||
|
||||
function createPrivateAndPublicKeys () {
|
||||
logger.info('Generating a RSA key...')
|
||||
|
@ -66,66 +64,6 @@ function parseHTTPSignature (req: Request, clockSkew?: number) {
|
|||
return parsed
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// JSONLD
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function isJsonLDSignatureVerified (fromActor: MActor, signedDocument: any): Promise<boolean> {
|
||||
if (signedDocument.signature.type === 'RsaSignature2017') {
|
||||
return isJsonLDRSA2017Verified(fromActor, signedDocument)
|
||||
}
|
||||
|
||||
logger.warn('Unknown JSON LD signature %s.', signedDocument.signature.type, signedDocument)
|
||||
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
|
||||
// Backward compatibility with "other" implementations
|
||||
async function isJsonLDRSA2017Verified (fromActor: MActor, signedDocument: any) {
|
||||
const [ documentHash, optionsHash ] = await Promise.all([
|
||||
createDocWithoutSignatureHash(signedDocument),
|
||||
createSignatureHash(signedDocument.signature)
|
||||
])
|
||||
|
||||
const toVerify = optionsHash + documentHash
|
||||
|
||||
const verify = createVerify('RSA-SHA256')
|
||||
verify.update(toVerify, 'utf8')
|
||||
|
||||
return verify.verify(fromActor.publicKey, signedDocument.signature.signatureValue, 'base64')
|
||||
}
|
||||
|
||||
async function signJsonLDObject <T> (options: {
|
||||
byActor: { url: string, privateKey: string }
|
||||
data: T
|
||||
disableWorkerThreadAssertion?: boolean
|
||||
}) {
|
||||
const { byActor, data, disableWorkerThreadAssertion = false } = options
|
||||
|
||||
if (!disableWorkerThreadAssertion) assertIsInWorkerThread()
|
||||
|
||||
const signature = {
|
||||
type: 'RsaSignature2017',
|
||||
creator: byActor.url,
|
||||
created: new Date().toISOString()
|
||||
}
|
||||
|
||||
const [ documentHash, optionsHash ] = await Promise.all([
|
||||
createDocWithoutSignatureHash(data),
|
||||
createSignatureHash(signature)
|
||||
])
|
||||
|
||||
const toSign = optionsHash + documentHash
|
||||
|
||||
const sign = createSign('RSA-SHA256')
|
||||
sign.update(toSign, 'utf8')
|
||||
|
||||
const signatureValue = sign.sign(byActor.privateKey, 'base64')
|
||||
Object.assign(signature, { signatureValue })
|
||||
|
||||
return Object.assign(data, { signature })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function buildDigest (body: any) {
|
||||
|
@ -169,49 +107,10 @@ export {
|
|||
parseHTTPSignature,
|
||||
isHTTPSignatureVerified,
|
||||
buildDigest,
|
||||
isJsonLDSignatureVerified,
|
||||
comparePassword,
|
||||
createPrivateAndPublicKeys,
|
||||
cryptPassword,
|
||||
signJsonLDObject,
|
||||
|
||||
encrypt,
|
||||
decrypt
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function hashObject (obj: any): Promise<any> {
|
||||
const { jsonld } = await import('./custom-jsonld-signature.js')
|
||||
|
||||
const res = await (jsonld as any).promises.normalize(obj, {
|
||||
safe: false,
|
||||
algorithm: 'URDNA2015',
|
||||
format: 'application/n-quads'
|
||||
})
|
||||
|
||||
return sha256(res)
|
||||
}
|
||||
|
||||
function createSignatureHash (signature: any) {
|
||||
const signatureCopy = cloneDeep(signature)
|
||||
Object.assign(signatureCopy, {
|
||||
'@context': [
|
||||
'https://w3id.org/security/v1',
|
||||
{ RsaSignature2017: 'https://w3id.org/security#RsaSignature2017' }
|
||||
]
|
||||
})
|
||||
|
||||
delete signatureCopy.type
|
||||
delete signatureCopy.id
|
||||
delete signatureCopy.signatureValue
|
||||
|
||||
return hashObject(signatureCopy)
|
||||
}
|
||||
|
||||
function createDocWithoutSignatureHash (doc: any) {
|
||||
const docWithoutSignature = cloneDeep(doc)
|
||||
delete docWithoutSignature.signature
|
||||
|
||||
return hashObject(docWithoutSignature)
|
||||
}
|
||||
|
|
100
server/core/helpers/peertube-jsonld.ts
Normal file
100
server/core/helpers/peertube-jsonld.ts
Normal file
|
@ -0,0 +1,100 @@
|
|||
import { sha256 } from '@peertube/peertube-node-utils'
|
||||
import { createSign, createVerify } from 'crypto'
|
||||
import cloneDeep from 'lodash-es/cloneDeep.js'
|
||||
import { MActor } from '../types/models/index.js'
|
||||
import { logger } from './logger.js'
|
||||
import { assertIsInWorkerThread } from './threads.js'
|
||||
import { jsonld } from './custom-jsonld-signature.js'
|
||||
|
||||
export function isJsonLDSignatureVerified (fromActor: MActor, signedDocument: any): Promise<boolean> {
|
||||
if (signedDocument.signature.type === 'RsaSignature2017') {
|
||||
return isJsonLDRSA2017Verified(fromActor, signedDocument)
|
||||
}
|
||||
|
||||
logger.warn('Unknown JSON LD signature %s.', signedDocument.signature.type, signedDocument)
|
||||
|
||||
return Promise.resolve(false)
|
||||
}
|
||||
|
||||
// Backward compatibility with "other" implementations
|
||||
export async function isJsonLDRSA2017Verified (fromActor: MActor, signedDocument: any) {
|
||||
const [ documentHash, optionsHash ] = await Promise.all([
|
||||
createDocWithoutSignatureHash(signedDocument),
|
||||
createSignatureHash(signedDocument.signature)
|
||||
])
|
||||
|
||||
const toVerify = optionsHash + documentHash
|
||||
|
||||
const verify = createVerify('RSA-SHA256')
|
||||
verify.update(toVerify, 'utf8')
|
||||
|
||||
return verify.verify(fromActor.publicKey, signedDocument.signature.signatureValue, 'base64')
|
||||
}
|
||||
|
||||
export async function signJsonLDObject <T> (options: {
|
||||
byActor: { url: string, privateKey: string }
|
||||
data: T
|
||||
disableWorkerThreadAssertion?: boolean
|
||||
}) {
|
||||
const { byActor, data, disableWorkerThreadAssertion = false } = options
|
||||
|
||||
if (!disableWorkerThreadAssertion) assertIsInWorkerThread()
|
||||
|
||||
const signature = {
|
||||
type: 'RsaSignature2017',
|
||||
creator: byActor.url,
|
||||
created: new Date().toISOString()
|
||||
}
|
||||
|
||||
const [ documentHash, optionsHash ] = await Promise.all([
|
||||
createDocWithoutSignatureHash(data),
|
||||
createSignatureHash(signature)
|
||||
])
|
||||
|
||||
const toSign = optionsHash + documentHash
|
||||
|
||||
const sign = createSign('RSA-SHA256')
|
||||
sign.update(toSign, 'utf8')
|
||||
|
||||
const signatureValue = sign.sign(byActor.privateKey, 'base64')
|
||||
Object.assign(signature, { signatureValue })
|
||||
|
||||
return Object.assign(data, { signature })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function hashObject (obj: any): Promise<any> {
|
||||
const res = await (jsonld as any).promises.normalize(obj, {
|
||||
safe: false,
|
||||
algorithm: 'URDNA2015',
|
||||
format: 'application/n-quads'
|
||||
})
|
||||
|
||||
return sha256(res)
|
||||
}
|
||||
|
||||
function createSignatureHash (signature: any) {
|
||||
const signatureCopy = cloneDeep(signature)
|
||||
Object.assign(signatureCopy, {
|
||||
'@context': [
|
||||
'https://w3id.org/security/v1',
|
||||
{ RsaSignature2017: 'https://w3id.org/security#RsaSignature2017' }
|
||||
]
|
||||
})
|
||||
|
||||
delete signatureCopy.type
|
||||
delete signatureCopy.id
|
||||
delete signatureCopy.signatureValue
|
||||
|
||||
return hashObject(signatureCopy)
|
||||
}
|
||||
|
||||
function createDocWithoutSignatureHash (doc: any) {
|
||||
const docWithoutSignature = cloneDeep(doc)
|
||||
delete docWithoutSignature.signature
|
||||
|
||||
return hashObject(docWithoutSignature)
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
import { signJsonLDObject } from '@server/helpers/peertube-crypto.js'
|
||||
import { signJsonLDObject } from '@server/helpers/peertube-jsonld.js'
|
||||
|
||||
export default signJsonLDObject
|
||||
|
|
|
@ -4,7 +4,7 @@ import { getAPId } from '@server/lib/activitypub/activity.js'
|
|||
import { wrapWithSpanAndContext } from '@server/lib/opentelemetry/tracing.js'
|
||||
import { ActivityDelete, ActivityPubSignature, HttpStatusCode } from '@peertube/peertube-models'
|
||||
import { logger } from '../helpers/logger.js'
|
||||
import { isHTTPSignatureVerified, isJsonLDSignatureVerified, parseHTTPSignature } from '../helpers/peertube-crypto.js'
|
||||
import { isHTTPSignatureVerified, parseHTTPSignature } from '../helpers/peertube-crypto.js'
|
||||
import { ACCEPT_HEADERS, ACTIVITY_PUB, HTTP_SIGNATURE } from '../initializers/constants.js'
|
||||
import { getOrCreateAPActor, loadActorUrlOrGetFromWebfinger } from '../lib/activitypub/actors/index.js'
|
||||
|
||||
|
@ -122,6 +122,9 @@ async function checkHttpSignature (req: Request, res: Response) {
|
|||
}
|
||||
|
||||
async function checkJsonLDSignature (req: Request, res: Response) {
|
||||
// Lazy load the module as it's quite big with json.ld dependency
|
||||
const { isJsonLDSignatureVerified } = await import('../helpers/peertube-jsonld.js')
|
||||
|
||||
return wrapWithSpanAndContext('peertube.activitypub.JSONLDSignature', async () => {
|
||||
const signatureObject: ActivityPubSignature = req.body.signature
|
||||
|
||||
|
|
Loading…
Reference in a new issue