Merge pull request #487 from shocknet/bug/deprecate-rsa-encryption
Deprecate RSA Encryption
This commit is contained in:
commit
9bbd2a14fe
6 changed files with 45 additions and 370 deletions
127
src/routes.js
127
src/routes.js
|
|
@ -20,7 +20,6 @@ const path = require('path')
|
||||||
const getListPage = require('../utils/paginate')
|
const getListPage = require('../utils/paginate')
|
||||||
const auth = require('../services/auth/auth')
|
const auth = require('../services/auth/auth')
|
||||||
const FS = require('../utils/fs')
|
const FS = require('../utils/fs')
|
||||||
const Encryption = require('../utils/encryptionStore')
|
|
||||||
const ECC = require('../utils/ECC')
|
const ECC = require('../utils/ECC')
|
||||||
const LightningServices = require('../utils/lightningServices')
|
const LightningServices = require('../utils/lightningServices')
|
||||||
const lndErrorManager = require('../utils/lightningServices/errors')
|
const lndErrorManager = require('../utils/lightningServices/errors')
|
||||||
|
|
@ -215,98 +214,12 @@ module.exports = async (
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
const legacyDeviceId = req.headers['x-shockwallet-device-id']
|
|
||||||
const deviceId = req.headers['encryption-device-id']
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
nonEncryptedRoutes.includes(req.path) ||
|
|
||||||
process.env.DISABLE_SHOCK_ENCRYPTION === 'true' ||
|
|
||||||
(deviceId && !legacyDeviceId)
|
|
||||||
) {
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!legacyDeviceId) {
|
|
||||||
const error = {
|
|
||||||
field: 'deviceId',
|
|
||||||
message: 'Please specify a device ID'
|
|
||||||
}
|
|
||||||
logger.error('Please specify a device ID')
|
|
||||||
return res.status(401).json(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Encryption.isAuthorizedDevice({ deviceId: legacyDeviceId })) {
|
|
||||||
const error = {
|
|
||||||
field: 'deviceId',
|
|
||||||
message: 'Please specify a device ID'
|
|
||||||
}
|
|
||||||
logger.error('Unknown Device')
|
|
||||||
return res.status(401).json(error)
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!req.body.encryptionKey &&
|
|
||||||
!req.body.iv &&
|
|
||||||
!req.headers['x-shock-encryption-token']
|
|
||||||
) {
|
|
||||||
return next()
|
|
||||||
}
|
|
||||||
let reqData = null
|
|
||||||
let IV = null
|
|
||||||
let encryptedKey = null
|
|
||||||
let encryptedToken = null
|
|
||||||
if (req.method === 'GET' || req.method === 'DELETE') {
|
|
||||||
if (req.headers['x-shock-encryption-token']) {
|
|
||||||
encryptedToken = req.headers['x-shock-encryption-token']
|
|
||||||
encryptedKey = req.headers['x-shock-encryption-key']
|
|
||||||
IV = req.headers['x-shock-encryption-iv']
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
encryptedToken = req.body.token
|
|
||||||
encryptedKey = req.body.encryptionKey || req.body.encryptedKey
|
|
||||||
IV = req.body.iv
|
|
||||||
reqData = req.body.data || req.body.encryptedData
|
|
||||||
}
|
|
||||||
const decryptedKey = Encryption.decryptKey({
|
|
||||||
deviceId: legacyDeviceId,
|
|
||||||
message: encryptedKey
|
|
||||||
})
|
|
||||||
if (reqData) {
|
|
||||||
const decryptedMessage = Encryption.decryptMessage({
|
|
||||||
message: reqData,
|
|
||||||
key: decryptedKey,
|
|
||||||
iv: IV
|
|
||||||
})
|
|
||||||
req.body = JSON.parse(decryptedMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
const decryptedToken = encryptedToken
|
|
||||||
? Encryption.decryptMessage({
|
|
||||||
message: encryptedToken,
|
|
||||||
key: decryptedKey,
|
|
||||||
iv: IV
|
|
||||||
})
|
|
||||||
: null
|
|
||||||
|
|
||||||
if (decryptedToken) {
|
|
||||||
req.headers.authorization = decryptedToken
|
|
||||||
}
|
|
||||||
|
|
||||||
return next()
|
|
||||||
} catch (err) {
|
|
||||||
logger.error(err)
|
|
||||||
return res.status(401).json(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.use(async (req, res, next) => {
|
app.use(async (req, res, next) => {
|
||||||
const legacyDeviceId = req.headers['x-shockwallet-device-id']
|
|
||||||
const deviceId = req.headers['encryption-device-id']
|
const deviceId = req.headers['encryption-device-id']
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
nonEncryptedRoutes.includes(req.path) ||
|
nonEncryptedRoutes.includes(req.path) ||
|
||||||
process.env.DISABLE_SHOCK_ENCRYPTION === 'true' ||
|
process.env.DISABLE_SHOCK_ENCRYPTION === 'true'
|
||||||
(legacyDeviceId && !deviceId)
|
|
||||||
) {
|
) {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
@ -514,44 +427,6 @@ module.exports = async (
|
||||||
res.json({ msg: 'OK' })
|
res.json({ msg: 'OK' })
|
||||||
})
|
})
|
||||||
|
|
||||||
app.post('/api/security/exchangeKeys', async (req, res) => {
|
|
||||||
try {
|
|
||||||
const { publicKey, deviceId } = req.body
|
|
||||||
|
|
||||||
if (!publicKey) {
|
|
||||||
return res.status(400).json({
|
|
||||||
field: 'publicKey',
|
|
||||||
message: 'Please provide a valid public key'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!deviceId ||
|
|
||||||
!/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/iu.test(
|
|
||||||
deviceId
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return res.status(400).json({
|
|
||||||
field: 'deviceId',
|
|
||||||
message: 'Please provide a valid device ID'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const authorizedDevice = await Encryption.authorizeDevice({
|
|
||||||
deviceId,
|
|
||||||
publicKey
|
|
||||||
})
|
|
||||||
logger.info(authorizedDevice)
|
|
||||||
return res.json(authorizedDevice)
|
|
||||||
} catch (err) {
|
|
||||||
logger.error(err)
|
|
||||||
return res.status(401).json({
|
|
||||||
field: 'unknown',
|
|
||||||
message: err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.post('/api/encryption/exchange', async (req, res) => {
|
app.post('/api/encryption/exchange', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { publicKey, deviceId } = req.body
|
const { publicKey, deviceId } = req.body
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
const { generateRandomString } = require('../utils/encryptionStore')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @prettier
|
* @prettier
|
||||||
*/
|
*/
|
||||||
|
|
@ -22,7 +20,6 @@ const server = program => {
|
||||||
|
|
||||||
const ECC = require('../utils/ECC')
|
const ECC = require('../utils/ECC')
|
||||||
const LightningServices = require('../utils/lightningServices')
|
const LightningServices = require('../utils/lightningServices')
|
||||||
const Encryption = require('../utils/encryptionStore')
|
|
||||||
const app = Express()
|
const app = Express()
|
||||||
|
|
||||||
const compression = require('compression')
|
const compression = require('compression')
|
||||||
|
|
@ -124,7 +121,6 @@ const server = program => {
|
||||||
* @param {(() => void)} next
|
* @param {(() => void)} next
|
||||||
*/
|
*/
|
||||||
const modifyResponseBody = (req, res, next) => {
|
const modifyResponseBody = (req, res, next) => {
|
||||||
const legacyDeviceId = req.headers['x-shockwallet-device-id']
|
|
||||||
const deviceId = req.headers['encryption-device-id']
|
const deviceId = req.headers['encryption-device-id']
|
||||||
const oldSend = res.send
|
const oldSend = res.send
|
||||||
|
|
||||||
|
|
@ -136,66 +132,32 @@ const server = program => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (legacyDeviceId) {
|
res.send = (...args) => {
|
||||||
res.send = (...args) => {
|
if (args[0] && args[0].ciphertext && args[0].iv) {
|
||||||
if (args[0] && args[0].encryptedData && args[0].encryptionKey) {
|
logger.warn('Response loop detected!')
|
||||||
logger.warn('Response loop detected!')
|
|
||||||
oldSend.apply(res, args)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const { cached, hash } = cacheCheck({ req, res, args, send: oldSend })
|
|
||||||
|
|
||||||
if (cached) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// arguments[0] (or `data`) contains the response body
|
|
||||||
const authorized = Encryption.isAuthorizedDevice({
|
|
||||||
deviceId: legacyDeviceId
|
|
||||||
})
|
|
||||||
const encryptedMessage = authorized
|
|
||||||
? Encryption.encryptMessage({
|
|
||||||
message: args[0] ? args[0] : {},
|
|
||||||
deviceId: legacyDeviceId,
|
|
||||||
metadata: {
|
|
||||||
hash
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: args[0]
|
|
||||||
args[0] = JSON.stringify(encryptedMessage)
|
|
||||||
oldSend.apply(res, args)
|
oldSend.apply(res, args)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceId) {
|
const authorized = ECC.isAuthorizedDevice({
|
||||||
res.send = (...args) => {
|
deviceId
|
||||||
if (args[0] && args[0].ciphertext && args[0].iv) {
|
})
|
||||||
logger.warn('Response loop detected!')
|
|
||||||
|
// Using classic promises syntax to avoid
|
||||||
|
// modifying res.send's return type
|
||||||
|
if (authorized && process.env.SHOCK_ENCRYPTION_ECC !== 'false') {
|
||||||
|
ECC.encryptMessage({
|
||||||
|
deviceId,
|
||||||
|
message: args[0]
|
||||||
|
}).then(encryptedMessage => {
|
||||||
|
args[0] = JSON.stringify(encryptedMessage)
|
||||||
oldSend.apply(res, args)
|
oldSend.apply(res, args)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const authorized = ECC.isAuthorizedDevice({
|
|
||||||
deviceId
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Using classic promises syntax to avoid
|
if (!authorized || process.env.SHOCK_ENCRYPTION_ECC === 'false') {
|
||||||
// modifying res.send's return type
|
args[0] = JSON.stringify(args[0])
|
||||||
if (authorized && process.env.SHOCK_ENCRYPTION_ECC !== 'false') {
|
oldSend.apply(res, args)
|
||||||
ECC.encryptMessage({
|
|
||||||
deviceId,
|
|
||||||
message: args[0]
|
|
||||||
}).then(encryptedMessage => {
|
|
||||||
args[0] = JSON.stringify(encryptedMessage)
|
|
||||||
oldSend.apply(res, args)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!authorized || process.env.SHOCK_ENCRYPTION_ECC === 'false') {
|
|
||||||
args[0] = JSON.stringify(args[0])
|
|
||||||
oldSend.apply(res, args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,7 +250,7 @@ const server = program => {
|
||||||
return randomField
|
return randomField
|
||||||
}
|
}
|
||||||
|
|
||||||
const newValue = await Encryption.generateRandomString(length)
|
const newValue = await ECC.generateRandomString(length)
|
||||||
await Storage.setItem(fieldName, newValue)
|
await Storage.setItem(fieldName, newValue)
|
||||||
return newValue
|
return newValue
|
||||||
}
|
}
|
||||||
|
|
@ -440,10 +402,11 @@ const server = program => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if(process.env.ALLOW_UNLOCKED_LND === 'true'){
|
if(process.env.ALLOW_UNLOCKED_LND === 'true'){
|
||||||
const codes = await Storage.valuesWithKeyMatch(/^UnlockedAccessSecrets\//u)
|
const codes = await Storage.valuesWithKeyMatch(/^UnlockedAccessSecrets\//u)
|
||||||
if(codes.length === 0){
|
if(codes.length === 0){
|
||||||
const code = await generateRandomString(12)
|
const code = ECC.generateRandomString(12)
|
||||||
await Storage.setItem(`UnlockedAccessSecrets/${code}`, false)
|
await Storage.setItem(`UnlockedAccessSecrets/${code}`, false)
|
||||||
await Storage.setItem(`FirstAccessSecret`, code)
|
await Storage.setItem(`FirstAccessSecret`, code)
|
||||||
logger.info("the access code is:"+code)
|
logger.info("the access code is:"+code)
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
|
||||||
|
|
@ -60,5 +60,6 @@
|
||||||
/* Experimental Options */
|
/* Experimental Options */
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
|
"useUnknownInCatchVariables": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
const { Buffer } = require("buffer");
|
const { Buffer } = require("buffer");
|
||||||
|
const Crypto = require("crypto");
|
||||||
const FieldError = require("../fieldError")
|
const FieldError = require("../fieldError")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,6 +18,19 @@ const FieldError = require("../fieldError")
|
||||||
* @prop {string} ephemPublicKey
|
* @prop {string} ephemPublicKey
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const generateRandomString = (length = 16) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
Crypto.randomBytes(length, (err, buffer) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = buffer.toString('hex')
|
||||||
|
resolve(token)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} value
|
* @param {string} value
|
||||||
*/
|
*/
|
||||||
|
|
@ -101,10 +115,11 @@ const convertToEncryptedMessage = (encryptedMessage) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
generateRandomString,
|
||||||
convertUTF8ToBuffer,
|
convertUTF8ToBuffer,
|
||||||
convertBase64ToBuffer,
|
convertBase64ToBuffer,
|
||||||
convertBufferToBase64,
|
convertBufferToBase64,
|
||||||
convertToEncryptedMessage,
|
convertToEncryptedMessage,
|
||||||
convertToEncryptedMessageResponse,
|
convertToEncryptedMessageResponse,
|
||||||
processKey
|
processKey,
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ const Storage = require('node-persist')
|
||||||
const FieldError = require('../fieldError')
|
const FieldError = require('../fieldError')
|
||||||
const logger = require('../../config/log')
|
const logger = require('../../config/log')
|
||||||
const {
|
const {
|
||||||
|
generateRandomString,
|
||||||
convertBufferToBase64,
|
convertBufferToBase64,
|
||||||
processKey,
|
processKey,
|
||||||
convertToEncryptedMessageResponse,
|
convertToEncryptedMessageResponse,
|
||||||
|
|
@ -182,5 +183,6 @@ module.exports = {
|
||||||
generateKeyPair,
|
generateKeyPair,
|
||||||
encryptMessage,
|
encryptMessage,
|
||||||
decryptMessage,
|
decryptMessage,
|
||||||
authorizeDevice
|
authorizeDevice,
|
||||||
|
generateRandomString
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,181 +0,0 @@
|
||||||
/**
|
|
||||||
* @prettier
|
|
||||||
*/
|
|
||||||
const Crypto = require('crypto')
|
|
||||||
const { Buffer } = require('buffer')
|
|
||||||
const logger = require('../config/log')
|
|
||||||
|
|
||||||
const APIKeyPair = new Map()
|
|
||||||
const authorizedDevices = new Map()
|
|
||||||
|
|
||||||
const nonEncryptedEvents = [
|
|
||||||
'ping',
|
|
||||||
'disconnect',
|
|
||||||
'IS_GUN_AUTH',
|
|
||||||
'SET_LAST_SEEN_APP'
|
|
||||||
]
|
|
||||||
|
|
||||||
const Encryption = {
|
|
||||||
/**
|
|
||||||
* @param {string} event
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
isNonEncrypted: event => nonEncryptedEvents.includes(event),
|
|
||||||
/**
|
|
||||||
* @param {{ deviceId: string , message: string }} arg0
|
|
||||||
*/
|
|
||||||
encryptKey: ({ deviceId, message }) => {
|
|
||||||
if (!authorizedDevices.has(deviceId)) {
|
|
||||||
throw { field: 'deviceId', message: 'Unknown Device ID' }
|
|
||||||
}
|
|
||||||
|
|
||||||
const devicePublicKey = authorizedDevices.get(deviceId)
|
|
||||||
const data = Buffer.from(message)
|
|
||||||
const encryptedData = Crypto.publicEncrypt(
|
|
||||||
{
|
|
||||||
key: devicePublicKey,
|
|
||||||
padding: Crypto.constants.RSA_PKCS1_PADDING
|
|
||||||
},
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
return encryptedData.toString('base64')
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @param {{ deviceId: string , message: string }} arg0
|
|
||||||
*/
|
|
||||||
decryptKey: ({ deviceId, message }) => {
|
|
||||||
if (!authorizedDevices.has(deviceId)) {
|
|
||||||
throw { field: 'deviceId', message: 'Unknown Device ID' }
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = Buffer.from(message, 'base64')
|
|
||||||
const encryptedData = Crypto.privateDecrypt(
|
|
||||||
{
|
|
||||||
key: APIKeyPair.get(deviceId).privateKey,
|
|
||||||
padding: Crypto.constants.RSA_PKCS1_PADDING
|
|
||||||
},
|
|
||||||
data
|
|
||||||
)
|
|
||||||
|
|
||||||
return encryptedData.toString()
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @param {{ deviceId: string , message: any , metadata?: any}} arg0
|
|
||||||
*/
|
|
||||||
encryptMessage: ({ deviceId, message, metadata = {} }) => {
|
|
||||||
const parsedMessage =
|
|
||||||
typeof message === 'object' ? JSON.stringify(message) : message
|
|
||||||
const data = Buffer.from(parsedMessage)
|
|
||||||
const key = Crypto.randomBytes(32)
|
|
||||||
const iv = Crypto.randomBytes(16)
|
|
||||||
const encryptedKey = Encryption.encryptKey({
|
|
||||||
deviceId,
|
|
||||||
message: key.toString('hex')
|
|
||||||
})
|
|
||||||
const cipher = Crypto.createCipheriv('aes-256-cbc', key, iv)
|
|
||||||
const encryptedCipher = cipher.update(data)
|
|
||||||
const encryptedBuffer = Buffer.concat([
|
|
||||||
Buffer.from(encryptedCipher),
|
|
||||||
Buffer.from(cipher.final())
|
|
||||||
])
|
|
||||||
const encryptedData = encryptedBuffer.toString('base64')
|
|
||||||
const encryptedMessage = {
|
|
||||||
encryptedData,
|
|
||||||
encryptedKey,
|
|
||||||
iv: iv.toString('hex'),
|
|
||||||
metadata
|
|
||||||
}
|
|
||||||
|
|
||||||
return encryptedMessage
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @param {{ message: string , key: string , iv: string }} arg0
|
|
||||||
*/
|
|
||||||
decryptMessage: ({ message, key, iv }) => {
|
|
||||||
const data = Buffer.from(message, 'base64')
|
|
||||||
const cipher = Crypto.createDecipheriv(
|
|
||||||
'aes-256-cbc',
|
|
||||||
Buffer.from(key, 'hex'),
|
|
||||||
Buffer.from(iv, 'hex')
|
|
||||||
)
|
|
||||||
const decryptedCipher = cipher.update(data)
|
|
||||||
const decryptedBuffer = Buffer.concat([
|
|
||||||
Buffer.from(decryptedCipher),
|
|
||||||
Buffer.from(cipher.final())
|
|
||||||
])
|
|
||||||
const decryptedData = decryptedBuffer.toString()
|
|
||||||
|
|
||||||
return decryptedData.toString()
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @param {{ deviceId: string }} arg0
|
|
||||||
*/
|
|
||||||
isAuthorizedDevice: ({ deviceId }) => {
|
|
||||||
if (authorizedDevices.has(deviceId)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @param {{ deviceId: string , publicKey: string }} arg0
|
|
||||||
*/
|
|
||||||
authorizeDevice: ({ deviceId, publicKey }) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
authorizedDevices.set(deviceId, publicKey)
|
|
||||||
Crypto.generateKeyPair(
|
|
||||||
'rsa',
|
|
||||||
{
|
|
||||||
modulusLength: 2048,
|
|
||||||
privateKeyEncoding: {
|
|
||||||
type: 'pkcs1',
|
|
||||||
format: 'pem'
|
|
||||||
},
|
|
||||||
publicKeyEncoding: {
|
|
||||||
type: 'pkcs1',
|
|
||||||
format: 'pem'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err, publicKey, privateKey) => {
|
|
||||||
if (err) {
|
|
||||||
// @ts-ignore
|
|
||||||
logger.error(err)
|
|
||||||
reject(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const exportedKey = {
|
|
||||||
publicKey,
|
|
||||||
privateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
APIKeyPair.set(deviceId, exportedKey)
|
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
APIPublicKey: exportedKey.publicKey
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
/**
|
|
||||||
* @param {{ deviceId: string }} arg0
|
|
||||||
*/
|
|
||||||
unAuthorizeDevice: ({ deviceId }) => {
|
|
||||||
authorizedDevices.delete(deviceId)
|
|
||||||
},
|
|
||||||
generateRandomString: (length = 16) =>
|
|
||||||
new Promise((resolve, reject) => {
|
|
||||||
Crypto.randomBytes(length, (err, buffer) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const token = buffer.toString('hex')
|
|
||||||
resolve(token)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Encryption
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue