mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
All: Encryption setup on apps
This commit is contained in:
parent
5951ed3f55
commit
ee02f8255e
@ -1,26 +1,27 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
// Loading time: 20170803: 1.5s with no commands
|
// Make it possible to require("/lib/...") without specifying full path
|
||||||
|
|
||||||
require('app-module-path').addPath(__dirname);
|
require('app-module-path').addPath(__dirname);
|
||||||
|
|
||||||
const { app } = require('./app.js');
|
const { app } = require('./app.js');
|
||||||
const { BaseModel } = require('lib/base-model.js');
|
|
||||||
const { Folder } = require('lib/models/folder.js');
|
const { Folder } = require('lib/models/folder.js');
|
||||||
const { Resource } = require('lib/models/resource.js');
|
const { Resource } = require('lib/models/resource.js');
|
||||||
const { BaseItem } = require('lib/models/base-item.js');
|
const { BaseItem } = require('lib/models/base-item.js');
|
||||||
const { Note } = require('lib/models/note.js');
|
const { Note } = require('lib/models/note.js');
|
||||||
const { Tag } = require('lib/models/tag.js');
|
const { Tag } = require('lib/models/tag.js');
|
||||||
const { NoteTag } = require('lib/models/note-tag.js');
|
const { NoteTag } = require('lib/models/note-tag.js');
|
||||||
|
const MasterKey = require('lib/models/MasterKey');
|
||||||
const { Setting } = require('lib/models/setting.js');
|
const { Setting } = require('lib/models/setting.js');
|
||||||
const { Logger } = require('lib/logger.js');
|
const { Logger } = require('lib/logger.js');
|
||||||
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
||||||
const { shimInit } = require('lib/shim-init-node.js');
|
const { shimInit } = require('lib/shim-init-node.js');
|
||||||
const { _ } = require('lib/locale.js');
|
const { _ } = require('lib/locale.js');
|
||||||
|
const EncryptionService = require('lib/services/EncryptionService');
|
||||||
|
|
||||||
const fsDriver = new FsDriverNode();
|
const fsDriver = new FsDriverNode();
|
||||||
Logger.fsDriver_ = fsDriver;
|
Logger.fsDriver_ = fsDriver;
|
||||||
Resource.fsDriver_ = fsDriver;
|
Resource.fsDriver_ = fsDriver;
|
||||||
|
EncryptionService.fsDriver_ = fsDriver;
|
||||||
|
|
||||||
// That's not good, but it's to avoid circular dependency issues
|
// That's not good, but it's to avoid circular dependency issues
|
||||||
// in the BaseItem class.
|
// in the BaseItem class.
|
||||||
@ -29,6 +30,7 @@ BaseItem.loadClass('Folder', Folder);
|
|||||||
BaseItem.loadClass('Resource', Resource);
|
BaseItem.loadClass('Resource', Resource);
|
||||||
BaseItem.loadClass('Tag', Tag);
|
BaseItem.loadClass('Tag', Tag);
|
||||||
BaseItem.loadClass('NoteTag', NoteTag);
|
BaseItem.loadClass('NoteTag', NoteTag);
|
||||||
|
BaseItem.loadClass('MasterKey', MasterKey);
|
||||||
|
|
||||||
Setting.setConstant('appId', 'net.cozic.joplin-cli');
|
Setting.setConstant('appId', 'net.cozic.joplin-cli');
|
||||||
Setting.setConstant('appType', 'cli');
|
Setting.setConstant('appType', 'cli');
|
||||||
|
@ -10,15 +10,18 @@ const { BaseItem } = require('lib/models/base-item.js');
|
|||||||
const { Note } = require('lib/models/note.js');
|
const { Note } = require('lib/models/note.js');
|
||||||
const { Tag } = require('lib/models/tag.js');
|
const { Tag } = require('lib/models/tag.js');
|
||||||
const { NoteTag } = require('lib/models/note-tag.js');
|
const { NoteTag } = require('lib/models/note-tag.js');
|
||||||
|
const MasterKey = require('lib/models/MasterKey');
|
||||||
const { Setting } = require('lib/models/setting.js');
|
const { Setting } = require('lib/models/setting.js');
|
||||||
const { Logger } = require('lib/logger.js');
|
const { Logger } = require('lib/logger.js');
|
||||||
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
||||||
const { shimInit } = require('lib/shim-init-node.js');
|
const { shimInit } = require('lib/shim-init-node.js');
|
||||||
|
const EncryptionService = require('lib/services/EncryptionService');
|
||||||
const { bridge } = require('electron').remote.require('./bridge');
|
const { bridge } = require('electron').remote.require('./bridge');
|
||||||
|
|
||||||
const fsDriver = new FsDriverNode();
|
const fsDriver = new FsDriverNode();
|
||||||
Logger.fsDriver_ = fsDriver;
|
Logger.fsDriver_ = fsDriver;
|
||||||
Resource.fsDriver_ = fsDriver;
|
Resource.fsDriver_ = fsDriver;
|
||||||
|
EncryptionService.fsDriver_ = fsDriver;
|
||||||
|
|
||||||
// That's not good, but it's to avoid circular dependency issues
|
// That's not good, but it's to avoid circular dependency issues
|
||||||
// in the BaseItem class.
|
// in the BaseItem class.
|
||||||
@ -27,6 +30,7 @@ BaseItem.loadClass('Folder', Folder);
|
|||||||
BaseItem.loadClass('Resource', Resource);
|
BaseItem.loadClass('Resource', Resource);
|
||||||
BaseItem.loadClass('Tag', Tag);
|
BaseItem.loadClass('Tag', Tag);
|
||||||
BaseItem.loadClass('NoteTag', NoteTag);
|
BaseItem.loadClass('NoteTag', NoteTag);
|
||||||
|
BaseItem.loadClass('MasterKey', MasterKey);
|
||||||
|
|
||||||
Setting.setConstant('appId', 'net.cozic.joplin-desktop');
|
Setting.setConstant('appId', 'net.cozic.joplin-desktop');
|
||||||
Setting.setConstant('appType', 'desktop');
|
Setting.setConstant('appType', 'desktop');
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Encrypted data is encoded to ASCII because encryption/decryption functions in React Native can only deal with strings. So for compatibility with all the apps we need to use the lowest common denominator.
|
Encrypted data is encoded to ASCII because encryption/decryption functions in React Native can only deal with strings. So for compatibility with all the apps we need to use the lowest common denominator.
|
||||||
|
|
||||||
## Encrypted file format
|
## Encrypted data format
|
||||||
|
|
||||||
### Header
|
### Header
|
||||||
|
|
||||||
@ -10,14 +10,29 @@ Name | Size
|
|||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
Version number | 2 chars (Hexa string)
|
Version number | 2 chars (Hexa string)
|
||||||
Encryption method | 2 chars (Hexa string)
|
Encryption method | 2 chars (Hexa string)
|
||||||
|
Master key ID | 32 chars (Hexa string)
|
||||||
|
|
||||||
See lib/services/EncryptionService.js for the list of available encryption methods.
|
See lib/services/EncryptionService.js for the list of available encryption methods.
|
||||||
|
|
||||||
### Data
|
### Data chunk
|
||||||
|
|
||||||
The data is encoded in one or more chuncks for performance reasons. That way it is possible to take a block of data from one file and encrypt it to another block in another file. Encrypting/decrypting the whole file in one go would not work (on mobile especially).
|
The data is encoded in one or more chuncks for performance reasons. That way it is possible to take a block of data from one file and encrypt it to another block in another file. Encrypting/decrypting the whole file in one go would not work (on mobile especially).
|
||||||
|
|
||||||
Name | Size
|
Name | Size
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
Length | 6 chars (Hexa string)
|
Length | 6 chars (Hexa string)
|
||||||
Data | ("Length" bytes)
|
Data | ("Length" bytes) (ASCII)
|
||||||
|
|
||||||
|
## Master Keys
|
||||||
|
|
||||||
|
The master keys are used to encrypt and decrypt data. They can be generated from the Encryption Service, and are saved to the database. They are themselves encrypted via a user password.
|
||||||
|
|
||||||
|
These encrypted master keys are transmitted with the sync data so that they can be available to each clients. Each client will need to supply the user password to decrypt each keys.
|
||||||
|
|
||||||
|
The application supports multiple master keys in order to handle cases where one offline client starts encrypting notes, then another offline client starts encrypting notes too, and later both sync. Both master keys will have to be decrypted separately with the user password.
|
||||||
|
|
||||||
|
Only one master key can be active for encryption purposes. For decryption, the algorithm will check the Master Key ID in the header, then check if it's available to the current app and, if so, use this for decryption.
|
||||||
|
|
||||||
|
## Encryption Service
|
||||||
|
|
||||||
|
The applications make use of the EncryptionService class to handle encryption and decryption. Before it can be used, a least one master key must be loaded into it and marked as "active".
|
Loading…
Reference in New Issue
Block a user