aboutsummaryrefslogblamecommitdiffhomepage
path: root/server/helpers/peertube-crypto.ts
blob: 10a226af47b2357d2ec8e133d88fe151389a5b9c (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                









                           







                       
                                 
 
                                                                                 
                                                         







                                       
                                                  





                                   
                                                                            
                

 
                                             
                                                     
 
                        





                                       
                                            
               




                                 
                                        
                                             

 

                                                                        

 


                                         
          
   
 
                      
 
 


                                                           
                                          

 
                              
                                                                   
                                          

 
                             
                                                                  
                                          

 
                                                                              
 








                        
 
                                                                              
 
                              
                                                                   
 
                                                       






                                 
 
 






                                               
 
                                        
 

















                                                                          
 
import * as crypto from 'crypto'
import { join } from 'path'

import {
  SIGNATURE_ALGORITHM,
  SIGNATURE_ENCODING,
  PRIVATE_CERT_NAME,
  CONFIG,
  BCRYPT_SALT_SIZE,
  PUBLIC_CERT_NAME
} from '../initializers'
import {
  readFilePromise,
  bcryptComparePromise,
  bcryptGenSaltPromise,
  bcryptHashPromise,
  accessPromise,
  opensslExecPromise
} from './core-utils'
import { logger } from './logger'

function checkSignature (publicKey: string, data: string, hexSignature: string) {
  const verify = crypto.createVerify(SIGNATURE_ALGORITHM)

  let dataString
  if (typeof data === 'string') {
    dataString = data
  } else {
    try {
      dataString = JSON.stringify(data)
    } catch (err) {
      logger.error('Cannot check signature.', err)
      return false
    }
  }

  verify.update(dataString, 'utf8')

  const isValid = verify.verify(publicKey, hexSignature, SIGNATURE_ENCODING)
  return isValid
}

async function sign (data: string | Object) {
  const sign = crypto.createSign(SIGNATURE_ALGORITHM)

  let dataString: string
  if (typeof data === 'string') {
    dataString = data
  } else {
    try {
      dataString = JSON.stringify(data)
    } catch (err) {
      logger.error('Cannot sign data.', err)
      return ''
    }
  }

  sign.update(dataString, 'utf8')

  const myKey = await getMyPrivateCert()
  return sign.sign(myKey, SIGNATURE_ENCODING)
}

function comparePassword (plainPassword: string, hashPassword: string) {
  return bcryptComparePromise(plainPassword, hashPassword)
}

async function createCertsIfNotExist () {
  const exist = await certsExist()
  if (exist === true) {
    return
  }

  return createCerts()
}

async function cryptPassword (password: string) {
  const salt = await bcryptGenSaltPromise(BCRYPT_SALT_SIZE)

  return bcryptHashPromise(password, salt)
}

function getMyPrivateCert () {
  const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
  return readFilePromise(certPath, 'utf8')
}

function getMyPublicCert () {
  const certPath = join(CONFIG.STORAGE.CERT_DIR, PUBLIC_CERT_NAME)
  return readFilePromise(certPath, 'utf8')
}

// ---------------------------------------------------------------------------

export {
  checkSignature,
  comparePassword,
  createCertsIfNotExist,
  cryptPassword,
  getMyPrivateCert,
  getMyPublicCert,
  sign
}

// ---------------------------------------------------------------------------

async function certsExist () {
  const certPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)

  // If there is an error the certificates do not exist
  try {
    await accessPromise(certPath)

    return true
  } catch {
    return false
  }
}

async function createCerts () {
  const exist = await certsExist()
  if (exist === true) {
    const errorMessage = 'Certs already exist.'
    logger.warning(errorMessage)
    throw new Error(errorMessage)
  }

  logger.info('Generating a RSA key...')

  const privateCertPath = join(CONFIG.STORAGE.CERT_DIR, PRIVATE_CERT_NAME)
  const genRsaOptions = {
    'out': privateCertPath,
    '2048': false
  }

  await opensslExecPromise('genrsa', genRsaOptions)
  logger.info('RSA key generated.')
  logger.info('Managing public key...')

  const publicCertPath = join(CONFIG.STORAGE.CERT_DIR, 'peertube.pub')
  const rsaOptions = {
    'in': privateCertPath,
    'pubout': true,
    'out': publicCertPath
  }

  await opensslExecPromise('rsa', rsaOptions)
}