mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2025-10-03 01:39:31 +02:00
Add generating dh keys
This commit is contained in:
parent
1414e41672
commit
f725a7bda3
23 changed files with 659 additions and 5 deletions
|
@ -49,6 +49,9 @@
|
|||
},
|
||||
"kr": {
|
||||
"type": "number"
|
||||
},
|
||||
"dh": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
|
@ -216,6 +216,8 @@
|
|||
|
||||
* [ServerDeviceList](./serverdatastatus-definitions-serverdevicelist.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceList`
|
||||
|
||||
* [ServerDhKey](./serverdatastatus-definitions-serverdhkey.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey`
|
||||
|
||||
* [ServerExtendedDeviceData](./serverdatastatus-definitions-serverextendeddevicedata.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerExtendedDeviceData`
|
||||
|
||||
* [ServerInstalledAppsData](./serverdatastatus-definitions-serverinstalledappsdata.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData`
|
||||
|
|
|
@ -67,6 +67,9 @@
|
|||
"$ref": "#/definitions/ServerKeyResponse"
|
||||
}
|
||||
},
|
||||
"dh": {
|
||||
"$ref": "#/definitions/ServerDhKey"
|
||||
},
|
||||
"fullVersion": {
|
||||
"type": "number"
|
||||
},
|
||||
|
@ -913,6 +916,23 @@
|
|||
"tempKey"
|
||||
],
|
||||
"title": "ServerKeyResponse"
|
||||
},
|
||||
"ServerDhKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "string"
|
||||
},
|
||||
"k": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"k",
|
||||
"v"
|
||||
],
|
||||
"title": "ServerDhKey"
|
||||
}
|
||||
},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Untitled string in ClientPullChangesRequest Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/dh
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [ClientPullChangesRequest.schema.json\*](ClientPullChangesRequest.schema.json "open original schema") |
|
||||
|
||||
## dh Type
|
||||
|
||||
`string`
|
|
@ -26,6 +26,7 @@ https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus
|
|||
| [devicesDetail](#devicesdetail) | `object` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-devicesdetail.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/devicesDetail") |
|
||||
| [kri](#kri) | `number` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-kri.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/kri") |
|
||||
| [kr](#kr) | `number` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-kr.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/kr") |
|
||||
| [dh](#dh) | `string` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-dh.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/dh") |
|
||||
|
||||
## devices
|
||||
|
||||
|
@ -170,3 +171,21 @@ https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus
|
|||
### kr Type
|
||||
|
||||
`number`
|
||||
|
||||
## dh
|
||||
|
||||
|
||||
|
||||
`dh`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-dh.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/dh")
|
||||
|
||||
### dh Type
|
||||
|
||||
`string`
|
||||
|
|
|
@ -77,6 +77,7 @@ Reference this group by using
|
|||
| [devicesDetail](#devicesdetail) | `object` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-devicesdetail.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/devicesDetail") |
|
||||
| [kri](#kri) | `number` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-kri.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/kri") |
|
||||
| [kr](#kr) | `number` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-kr.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/kr") |
|
||||
| [dh](#dh) | `string` | Optional | cannot be null | [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-dh.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/dh") |
|
||||
|
||||
### devices
|
||||
|
||||
|
@ -222,6 +223,24 @@ Reference this group by using
|
|||
|
||||
`number`
|
||||
|
||||
### dh
|
||||
|
||||
|
||||
|
||||
`dh`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ClientPullChangesRequest](clientpullchangesrequest-definitions-clientdatastatus-properties-dh.md "https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/dh")
|
||||
|
||||
#### dh Type
|
||||
|
||||
`string`
|
||||
|
||||
## Definitions group CategoryDataStatus
|
||||
|
||||
Reference this group by using
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/k
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## k Type
|
||||
|
||||
`string`
|
|
@ -0,0 +1,15 @@
|
|||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/v
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## v Type
|
||||
|
||||
`string`
|
58
docs/schema/serverdatastatus-definitions-serverdhkey.md
Normal file
58
docs/schema/serverdatastatus-definitions-serverdhkey.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# ServerDhKey Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :----------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | No | Forbidden | Forbidden | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## ServerDhKey Type
|
||||
|
||||
`object` ([ServerDhKey](serverdatastatus-definitions-serverdhkey.md))
|
||||
|
||||
# ServerDhKey Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :------- | :------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [v](#v) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-v.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/v") |
|
||||
| [k](#k) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-k.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/k") |
|
||||
|
||||
## v
|
||||
|
||||
|
||||
|
||||
`v`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-v.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/v")
|
||||
|
||||
### v Type
|
||||
|
||||
`string`
|
||||
|
||||
## k
|
||||
|
||||
|
||||
|
||||
`k`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-k.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/k")
|
||||
|
||||
### k Type
|
||||
|
||||
`string`
|
15
docs/schema/serverdatastatus-properties-dh-properties-k.md
Normal file
15
docs/schema/serverdatastatus-properties-dh-properties-k.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/properties/dh/properties/k
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## k Type
|
||||
|
||||
`string`
|
15
docs/schema/serverdatastatus-properties-dh-properties-v.md
Normal file
15
docs/schema/serverdatastatus-properties-dh-properties-v.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/properties/dh/properties/v
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## v Type
|
||||
|
||||
`string`
|
58
docs/schema/serverdatastatus-properties-dh.md
Normal file
58
docs/schema/serverdatastatus-properties-dh.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Untitled object in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/properties/dh
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :----------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | No | Forbidden | Forbidden | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## dh Type
|
||||
|
||||
`object` ([Details](serverdatastatus-properties-dh.md))
|
||||
|
||||
# dh Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [v](#v) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-properties-dh-properties-v.md "https://timelimit.io/ServerDataStatus#/properties/dh/properties/v") |
|
||||
| [k](#k) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-properties-dh-properties-k.md "https://timelimit.io/ServerDataStatus#/properties/dh/properties/k") |
|
||||
|
||||
## v
|
||||
|
||||
|
||||
|
||||
`v`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-properties-dh-properties-v.md "https://timelimit.io/ServerDataStatus#/properties/dh/properties/v")
|
||||
|
||||
### v Type
|
||||
|
||||
`string`
|
||||
|
||||
## k
|
||||
|
||||
|
||||
|
||||
`k`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-properties-dh-properties-k.md "https://timelimit.io/ServerDataStatus#/properties/dh/properties/k")
|
||||
|
||||
### k Type
|
||||
|
||||
`string`
|
|
@ -30,6 +30,7 @@ https://timelimit.io/ServerDataStatus
|
|||
| [users](#users) | `object` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserlist.md "https://timelimit.io/ServerDataStatus#/properties/users") |
|
||||
| [krq](#krq) | `array` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-properties-krq.md "https://timelimit.io/ServerDataStatus#/properties/krq") |
|
||||
| [kr](#kr) | `array` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-properties-kr.md "https://timelimit.io/ServerDataStatus#/properties/kr") |
|
||||
| [dh](#dh) | `object` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdhkey.md "https://timelimit.io/ServerDataStatus#/properties/dh") |
|
||||
| [fullVersion](#fullversion) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-properties-fullversion.md "https://timelimit.io/ServerDataStatus#/properties/fullVersion") |
|
||||
| [message](#message) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-properties-message.md "https://timelimit.io/ServerDataStatus#/properties/message") |
|
||||
| [apiLevel](#apilevel) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-properties-apilevel.md "https://timelimit.io/ServerDataStatus#/properties/apiLevel") |
|
||||
|
@ -250,6 +251,24 @@ https://timelimit.io/ServerDataStatus
|
|||
|
||||
`object[]` ([ServerKeyResponse](serverdatastatus-definitions-serverkeyresponse.md))
|
||||
|
||||
## dh
|
||||
|
||||
|
||||
|
||||
`dh`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `object` ([ServerDhKey](serverdatastatus-definitions-serverdhkey.md))
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdhkey.md "https://timelimit.io/ServerDataStatus#/properties/dh")
|
||||
|
||||
### dh Type
|
||||
|
||||
`object` ([ServerDhKey](serverdatastatus-definitions-serverdhkey.md))
|
||||
|
||||
## fullVersion
|
||||
|
||||
|
||||
|
@ -3372,3 +3391,52 @@ Reference this group by using
|
|||
#### signature Type
|
||||
|
||||
`string`
|
||||
|
||||
## Definitions group ServerDhKey
|
||||
|
||||
Reference this group by using
|
||||
|
||||
```json
|
||||
{"$ref":"https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey"}
|
||||
```
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :------- | :------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [v](#v) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-v.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/v") |
|
||||
| [k](#k) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-k.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/k") |
|
||||
|
||||
### v
|
||||
|
||||
|
||||
|
||||
`v`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-v.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/v")
|
||||
|
||||
#### v Type
|
||||
|
||||
`string`
|
||||
|
||||
### k
|
||||
|
||||
|
||||
|
||||
`k`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdhkey-properties-k.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDhKey/properties/k")
|
||||
|
||||
#### k Type
|
||||
|
||||
`string`
|
||||
|
|
|
@ -117,7 +117,8 @@ export const createSyncRouter = ({ database, websocket, connectedDevicesManager,
|
|||
familyId,
|
||||
deviceId,
|
||||
clientStatus: body.status,
|
||||
transaction
|
||||
transaction,
|
||||
eventHandler
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -128,6 +129,9 @@ export const createSyncRouter = ({ database, websocket, connectedDevicesManager,
|
|||
if (serverStatus.usedTimes) { eventHandler.countEvent('pullStatusRequest usedTimes') }
|
||||
if (serverStatus.rules) { eventHandler.countEvent('pullStatusRequest rules') }
|
||||
if (serverStatus.users) { eventHandler.countEvent('pullStatusRequest users') }
|
||||
if (serverStatus.krq) { eventHandler.countEvent('pullStatusRequest pendingKeyRequests') }
|
||||
if (serverStatus.kr) { eventHandler.countEvent('pullStatusRequest keyResponses') }
|
||||
if (serverStatus.dh) { eventHandler.countEvent('pullStatusRequest dh') }
|
||||
|
||||
res.json(serverStatus)
|
||||
} catch (ex) {
|
||||
|
|
|
@ -72,6 +72,9 @@ const definitions = {
|
|||
},
|
||||
"kr": {
|
||||
"type": "number"
|
||||
},
|
||||
"dh": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
@ -2705,6 +2708,22 @@ const definitions = {
|
|||
"srvSeq",
|
||||
"tempKey"
|
||||
]
|
||||
},
|
||||
"ServerDhKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "string"
|
||||
},
|
||||
"k": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"k",
|
||||
"v"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
81
src/database/devicedhkey.ts
Normal file
81
src/database/devicedhkey.ts
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { familyIdColumn, idWithinFamilyColumn, versionColumn, timestampColumn } from './columns'
|
||||
import { SequelizeAttributes } from './types'
|
||||
|
||||
export const config = {
|
||||
generateNewKeyAfterAge: 1000 * 60 * 60 * 24,
|
||||
generationTimeRounding: 1000 * 60 * 60,
|
||||
expireDelay: 1000 * 60 * 60 * 2,
|
||||
expireTimeRounding: 1000 * 60 * 15
|
||||
}
|
||||
|
||||
export function calculateExpireTime(now: bigint): BigInt {
|
||||
const expireBaseTime = now + BigInt(config.expireDelay)
|
||||
const expireTime = expireBaseTime - expireBaseTime % BigInt(config.expireTimeRounding) + BigInt(config.expireTimeRounding)
|
||||
|
||||
return expireTime
|
||||
}
|
||||
|
||||
export interface DeviceDhKeyAttributes {
|
||||
familyId: string
|
||||
deviceId: string
|
||||
version: string
|
||||
createdAt: string
|
||||
expireAt: string | null
|
||||
publicKey: Buffer
|
||||
privateKey: Buffer
|
||||
}
|
||||
|
||||
export type DeviceDhKeyModel = Sequelize.Model<DeviceDhKeyAttributes> & DeviceDhKeyAttributes
|
||||
export type DeviceDhKeyModelStatic = typeof Sequelize.Model & {
|
||||
new (values?: object, options?: Sequelize.BuildOptions): DeviceDhKeyModel;
|
||||
}
|
||||
|
||||
export const attributes: SequelizeAttributes<DeviceDhKeyAttributes> = {
|
||||
familyId: {
|
||||
...familyIdColumn,
|
||||
primaryKey: true
|
||||
},
|
||||
deviceId: {
|
||||
...idWithinFamilyColumn,
|
||||
primaryKey: true
|
||||
},
|
||||
version: {
|
||||
...versionColumn,
|
||||
primaryKey: true
|
||||
},
|
||||
createdAt: {
|
||||
...timestampColumn
|
||||
},
|
||||
expireAt: {
|
||||
...timestampColumn,
|
||||
allowNull: true
|
||||
},
|
||||
publicKey: {
|
||||
type: Sequelize.BLOB,
|
||||
allowNull: false
|
||||
},
|
||||
privateKey: {
|
||||
type: Sequelize.BLOB,
|
||||
allowNull: false
|
||||
}
|
||||
}
|
||||
|
||||
export const createDeviceDhKey = (sequelize: Sequelize.Sequelize): DeviceDhKeyModelStatic => sequelize.define('DeviceDhKey', attributes) as DeviceDhKeyModelStatic
|
|
@ -27,6 +27,7 @@ import { CategoryTimeWarningModelStatic, createCategoryTimeWarningModel } from '
|
|||
import { ChildTaskModelStatic, createChildTaskModel } from './childtask'
|
||||
import { ConfigModelStatic, createConfigModel } from './config'
|
||||
import { createDeviceModel, DeviceModelStatic } from './device'
|
||||
import { createDeviceDhKey, DeviceDhKeyModelStatic } from './devicedhkey'
|
||||
import { createEncryptedAppListModel, EncryptedAppListModelStatic } from './encryptedapplist'
|
||||
import { createFamilyModel, FamilyModelStatic } from './family'
|
||||
import { createKeyRequestModel, KeyRequestModelStatic } from './keyrequest'
|
||||
|
@ -55,6 +56,7 @@ export interface Database {
|
|||
childTask: ChildTaskModelStatic
|
||||
config: ConfigModelStatic
|
||||
device: DeviceModelStatic
|
||||
deviceDhKey: DeviceDhKeyModelStatic
|
||||
encryptedAppList: EncryptedAppListModelStatic
|
||||
family: FamilyModelStatic
|
||||
keyRequest: KeyRequestModelStatic
|
||||
|
@ -83,6 +85,7 @@ const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
|||
categoryTimeWarning: createCategoryTimeWarningModel(sequelize),
|
||||
config: createConfigModel(sequelize),
|
||||
device: createDeviceModel(sequelize),
|
||||
deviceDhKey: createDeviceDhKey(sequelize),
|
||||
encryptedAppList: createEncryptedAppListModel(sequelize),
|
||||
family: createFamilyModel(sequelize),
|
||||
keyRequest: createKeyRequestModel(sequelize),
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { QueryInterface, Sequelize, Transaction } from 'sequelize'
|
||||
|
||||
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
const dialect = sequelize.getDialect()
|
||||
const isMysql = dialect === 'mysql' || dialect === 'mariadb'
|
||||
const isPosgresql = dialect === 'postgres'
|
||||
|
||||
if (isMysql) {
|
||||
await sequelize.query(
|
||||
'CREATE TABLE `DeviceDhKeys` ' +
|
||||
'(`familyId` VARCHAR(10) NOT NULL,' +
|
||||
'`deviceId` VARCHAR(6) NOT NULL,' +
|
||||
'`version` VARCHAR(4) NOT NULL,' +
|
||||
'`createdAt` BIGINT NOT NULL, ' +
|
||||
'`expireAt` BIGINT NULL, ' +
|
||||
'`publicKey` BLOB NOT NULL, ' +
|
||||
'`privateKey` BLOB NOT NULL, ' +
|
||||
'PRIMARY KEY (`familyId`, `deviceId`, `version`),' +
|
||||
'FOREIGN KEY (`familyId`, `deviceId`) REFERENCES `Devices` (`familyId`, `deviceId`) ON UPDATE CASCADE ON DELETE CASCADE' +
|
||||
')',
|
||||
{ transaction }
|
||||
)
|
||||
} else {
|
||||
await sequelize.query(
|
||||
'CREATE TABLE "DeviceDhKeys" ' +
|
||||
'("familyId" VARCHAR(10) NOT NULL,' +
|
||||
'"deviceId" VARCHAR(6) NOT NULL,' +
|
||||
'"version" VARCHAR(4) NOT NULL,' +
|
||||
'"createdAt" ' + (isPosgresql ? 'BIGINT' : 'LONG') + ' NOT NULL, ' +
|
||||
'"expireAt" ' + (isPosgresql ? 'BIGINT' : 'LONG') + ' NULL, ' +
|
||||
'"publicKey" ' + (isPosgresql ? 'BYTEA' : 'BLOB') + ' NOT NULL, ' +
|
||||
'"privateKey" ' + (isPosgresql ? 'BYTEA' : 'BLOB') + ' NOT NULL, ' +
|
||||
'PRIMARY KEY ("familyId", "deviceId", "version"),' +
|
||||
'FOREIGN KEY ("familyId", "deviceId") REFERENCES "Devices" ("familyId", "deviceId") ON UPDATE CASCADE ON DELETE CASCADE' +
|
||||
')',
|
||||
{ transaction }
|
||||
)
|
||||
}
|
||||
|
||||
await queryInterface.addIndex('DeviceDhKeys', ['expireAt'], { transaction })
|
||||
})
|
||||
}
|
||||
|
||||
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.dropTable('DeviceDhKeys', { transaction })
|
||||
})
|
||||
}
|
123
src/function/sync/get-server-data-status/dh-keys.ts
Normal file
123
src/function/sync/get-server-data-status/dh-keys.ts
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { Database } from '../../../database'
|
||||
import { config, calculateExpireTime } from '../../../database/devicedhkey'
|
||||
import { ServerDhKey } from '../../../object/serverdatastatus'
|
||||
import { generateVersionId } from '../../../util/token'
|
||||
import { EventHandler } from '../../../monitoring/eventhandler'
|
||||
import { FamilyEntry } from './family-entry'
|
||||
import { generateKeyPair } from 'crypto'
|
||||
import { promisify } from 'util'
|
||||
|
||||
const generateKeyPairAsync = promisify(generateKeyPair)
|
||||
|
||||
export async function getDeviceDhKeys ({
|
||||
database, transaction, familyEntry, deviceId, lastVersionId, eventHandler
|
||||
}: {
|
||||
database: Database
|
||||
transaction: Sequelize.Transaction
|
||||
familyEntry: FamilyEntry
|
||||
deviceId: string
|
||||
lastVersionId: string | null
|
||||
eventHandler: EventHandler
|
||||
}): Promise<ServerDhKey | null> {
|
||||
const savedData = await database.deviceDhKey.findAll({
|
||||
where: {
|
||||
familyId: familyEntry.familyId,
|
||||
deviceId
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
const now = BigInt(Date.now())
|
||||
const oldCurrentKey = savedData.find((item) => item.expireAt === null)
|
||||
const needsNewKey =
|
||||
oldCurrentKey === undefined ||
|
||||
BigInt(oldCurrentKey.createdAt) + BigInt(config.generateNewKeyAfterAge) <= now ||
|
||||
BigInt(oldCurrentKey.createdAt) > now
|
||||
|
||||
if (needsNewKey) {
|
||||
eventHandler.countEvent('getDeviceDhKeys:needsNewKey')
|
||||
|
||||
const newVersion = generateVersionId()
|
||||
const newKeypair = await generateKeyPairAsync(
|
||||
'ec',
|
||||
{
|
||||
namedCurve: 'prime256v1',
|
||||
publicKeyEncoding: {
|
||||
type: 'spki',
|
||||
format: 'der'
|
||||
},
|
||||
privateKeyEncoding: {
|
||||
type: 'pkcs8',
|
||||
format: 'der'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (savedData.length >= 8) {
|
||||
eventHandler.countEvent('getDeviceDhKeys:gc')
|
||||
|
||||
const minCreatedAtValue = savedData.map((item) => BigInt(item.createdAt)).sort()[0]
|
||||
|
||||
await database.deviceDhKey.destroy({
|
||||
where: {
|
||||
familyId: familyEntry.familyId,
|
||||
deviceId,
|
||||
createdAt: {
|
||||
[Sequelize.Op.lte]: minCreatedAtValue.toString(10)
|
||||
}
|
||||
},
|
||||
transaction
|
||||
})
|
||||
}
|
||||
|
||||
await database.deviceDhKey.update({
|
||||
expireAt: calculateExpireTime(now).toString(10)
|
||||
}, {
|
||||
where: {
|
||||
familyId: familyEntry.familyId,
|
||||
deviceId,
|
||||
expireAt: null
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
await database.deviceDhKey.create({
|
||||
familyId: familyEntry.familyId,
|
||||
deviceId,
|
||||
version: newVersion,
|
||||
createdAt: (now - now % BigInt(config.generationTimeRounding)).toString(10),
|
||||
expireAt: null,
|
||||
publicKey: newKeypair.publicKey,
|
||||
privateKey: newKeypair.privateKey
|
||||
}, { transaction })
|
||||
|
||||
return {
|
||||
k: newKeypair.publicKey.toString('base64'),
|
||||
v: newVersion
|
||||
}
|
||||
} else {
|
||||
if (lastVersionId === oldCurrentKey.version) return null
|
||||
else return {
|
||||
k: oldCurrentKey.publicKey.toString('base64'),
|
||||
v: oldCurrentKey.version
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import { Database } from '../../../database'
|
|||
import { getStatusMessage } from '../../../function/statusmessage'
|
||||
import { ClientDataStatus } from '../../../object/clientdatastatus'
|
||||
import { ServerDataStatus } from '../../../object/serverdatastatus'
|
||||
import { EventHandler } from '../../../monitoring/eventhandler'
|
||||
import { getAppList } from './app-list'
|
||||
import {
|
||||
getCategoryAssignedApps, getCategoryBaseDatas, getCategoryDataToSync,
|
||||
|
@ -28,23 +29,28 @@ import {
|
|||
} from './category'
|
||||
import { getDeviceDetailList } from './device-detail'
|
||||
import { getDeviceList } from './device-list'
|
||||
import { getDeviceDhKeys } from './dh-keys'
|
||||
import { getFamilyEntry } from './family-entry'
|
||||
import { getUserList } from './user-list'
|
||||
import { getKeyRequests } from './key-requests'
|
||||
import { getKeyResponses } from './key-responses'
|
||||
|
||||
export const generateServerDataStatus = async ({
|
||||
database, clientStatus, familyId, deviceId, transaction
|
||||
database, clientStatus, familyId, deviceId, transaction, eventHandler
|
||||
}: {
|
||||
database: Database
|
||||
clientStatus: ClientDataStatus
|
||||
familyId: string
|
||||
deviceId: string
|
||||
transaction: Sequelize.Transaction
|
||||
eventHandler: EventHandler
|
||||
}): Promise<ServerDataStatus> => {
|
||||
const clientLevel = clientStatus.clientLevel || 0
|
||||
|
||||
const familyEntry = await getFamilyEntry({ database, familyId, transaction })
|
||||
const doesClientSupportTasks = clientStatus.clientLevel !== undefined && clientStatus.clientLevel >= 3
|
||||
const doesClientSupportCryptoApps = clientStatus.clientLevel !== undefined && clientStatus.clientLevel >= 4
|
||||
const doesClientSupportTasks = clientLevel >= 3
|
||||
const doesClientSupportCryptoApps = clientLevel >= 4
|
||||
const doesClientSupportDh = clientLevel >= 5
|
||||
|
||||
const result: ServerDataStatus = {
|
||||
fullVersion: config.alwaysPro ? 1 : (
|
||||
|
@ -135,5 +141,16 @@ export const generateServerDataStatus = async ({
|
|||
}) || undefined
|
||||
}
|
||||
|
||||
if (doesClientSupportDh) {
|
||||
result.dh = await getDeviceDhKeys({
|
||||
database,
|
||||
transaction,
|
||||
familyEntry,
|
||||
deviceId,
|
||||
lastVersionId: clientStatus.dh || null,
|
||||
eventHandler
|
||||
}) || undefined
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ export interface ClientDataStatus {
|
|||
devicesDetail?: ClientDataStatusDevicesExtended
|
||||
kri?: number // last key request index
|
||||
kr?: number // last key response index
|
||||
dh?: string // last Diffie Hellman key version
|
||||
}
|
||||
|
||||
export type ClientDataStatusApps = {[key: string]: string} // installedAppsVersionsByDeviceId
|
||||
|
|
|
@ -34,6 +34,7 @@ export interface ServerDataStatus {
|
|||
users?: ServerUserList // newUserList
|
||||
krq?: Array<ServerKeyRequest> // pendingKeyRequests
|
||||
kr?: Array<ServerKeyResponse> // keyResponses
|
||||
dh?: ServerDhKey // Diffie Hellman
|
||||
fullVersion: number // fullVersionUntil
|
||||
message?: string
|
||||
apiLevel: number
|
||||
|
@ -252,3 +253,8 @@ export interface ServerKeyResponse {
|
|||
cryptKey: string,
|
||||
signature: string
|
||||
}
|
||||
|
||||
export interface ServerDhKey {
|
||||
v: string // version
|
||||
k: string // key, base64
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2021 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
|
@ -71,4 +71,12 @@ async function deleteOldTokens ({ database }: {
|
|||
transaction
|
||||
})
|
||||
})
|
||||
|
||||
await database.deviceDhKey.destroy({
|
||||
where: {
|
||||
expireAt: {
|
||||
[Sequelize.Op.lt]: Date.now().toString()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue