Security

Encryption At-Rest / TDE

It goes without saying that if you are storing ScreenJSON documents in a database or local UI, you should ensure the entire file is encrypted. It is entirely possible for a hard drive or SD card to be removed, or RAM scraped, to discover its contents, outside of the host application environment.

The feature of a database to encrypt its disk content whilst serving content to an authorised application is called Transparent Data Encryption (TDE).

Providers which support some kind of encryption at rest include:

  • SQL Server
  • MySQL
  • DB2
  • Oracle

See: https://securityfirstcorp.com/what-is-data-encryption-at-rest/

Access Control

ScreenJSON allows a host to store the identities of permitted roles/groups in its file structure, but does not define an authorisation protocol. The host application or GUI is required to implement the identification of the viewer accessing the document, the validation of their authorisation, and their access privileges.

Defining Roles & Groups

Access control is extremely simplistic. The names of roles or groups are provided as a list the host application should check, for which it has an external reference. It is assumed an application could be as likely to store screenplays as static files on a cloud drive, as it could within a database.

  "access" : ['role-name', 'another-role', 'group-name']

For production purposes, it might look like:

  "access" : ['producers', 'director', 'actors', 'editor', 'john-doe']

In most scenarios, providing a simple lookup table with a user’s identifier and the raw file name is usually enough. However, it is possibly to provide a further step by checking what the file itself requires.

Example: Server-Side Web Application (Database Storage)

Generally speaking, a user is authenticated when they log in and are granted a session by the web server or host technology. On each HTTP request, a session cookie is sent for future requests to remember the browser. Upon attempting to access a part of an application, the server-side business logic re-identifies the session user and checks their group, role, or permissions to do so. If they are authorised, the resource is served to them, and recorded.

In this scenario, the names of the groups or roles the user belongs to - contained in the database - would be imprinted in the ScreenJSON file, and synchronised between the two. Upon the middleware server logic loading the file, the permitted groups and roles specified in the file would be checked against those of the session user’s.

Example: Cloud Drive + Network Directory (File Storage)

On a Windows office network, users receive their access credentials and policy controls from a centralized directory server (e.g. Microsoft ActiveDirectory, OpenLDAP etc). In the same way, the server re-identifies the network user and checks their group, role, or permissions to do as they are asking. If they are authorised, the resource is served to them, and recorded.

In this scenario, the names of the groups or roles the user belongs to - configured in the directory server - would be imprinted in the ScreenJSON file, and synchronised between the two. Upon loading a raw file from a network or cloud drive, the permitted groups and roles specified in the file would be checked against those of the session user’s.

Important: Access control is only effective when a server-side process or host application acts as a gateway to a ScreenJSON file. If a viewer has access to the raw document itself, it is entirely meaningless.


Content Encryption

ScreenJSON allows a host to store scrambled content but does not define an encryption protocol. The host application or GUI is required to implement their own encryption methodology and authentication/authorisation routine (including the creation and safekeeping of a decryption secret).

Encryption can be technically be applied to any JSON value containing text. Each user may have their own specific private key, or password. GUI display should auto-detect an encrypted paragraph element, and attempt to decode it with a password already stored for that user.

The beauty of this approach is that no data or handshake needs to be conducted with the back-end server. An author encrypting the element can set a password in their client program, and give it to a collaborator personally, without sending it over the wire. An author can choose to hide any number of text elements to provide different selective views for different readers.

Encryption is generally used at an Element level. Structures such as Action, Dialogue, and Transition must include an Encryption object specifying how the host application should decrypt their content. This is the most flexible and granular way to maintain the document’s integrity.

Important: ScreenJSON does not store decryption information. The host application must perform the decryption in its own UI. If that information is lost, so is all the data in the document itself.

Example client-side AES encryption with Node

In this example, we are in a Node client like Electron or Ionic. The reader GUI is able to encrypt text, or decrypt it, by providing a specified password.

We want to hide the line of dialogue from everyone except Above-The-Line, the Director, the DoP, and the actor who is going to be saying it. Everyone gets a copy of the script, but those who are not included in the access policy, or without the specific password, see a redacted block.

var crypto = require('crypto'), algorithm = 'aes-256-ctr', password = 'password_for_specific_individual';

function encrypt(text){
  var cipher = crypto.createCipher(algorithm,password)
  var crypted = cipher.update(text,'utf8','hex')
  crypted += cipher.final('hex');
  return crypted;
}

function decrypt(text){
  var decipher = crypto.createDecipher(algorithm,password)
  var dec = decipher.update(text,'hex','utf8')
  dec += decipher.final('utf8');
  return dec;
}

var dialogue_element = encrypt("I'm going to make him an offer he can't refuse.")
console.log(decrypt(dialogue_element));

Encrypted output (when using Base64, not Hex):

U2FsdGVkX19voPV6ClqPfhSFJFMEALJeZSmAVl/dukvbxtfFOondqaZLVdRg0/HxBV8g8B9iZYzYY2Aa/cH7Kw==

The dialogue data element would then be expressed as:

{
  "id" : "6e27748b-b5d9-4da5-8e53-c2766a1c074b",
  "parent" : "81fcebe1-a2ae-4d49-91ac-b544d9a7cad6",
  "scene" : "271ee0f5-8ce8-46e6-919f-87b9ace58496",
  "access" : ["ABL", "director", "cinematography", "actor-corleone"],
  "type": "dialogue",
  "charset": "utf8",
  "dir": "ltr",
  "encryption" : {
    "cipher" : "aes-256-ctr",
    "hash" : "sha256",
    "encoding" : "base64"
  },
  "content": {
    "en": "U2FsdGVkX19voPV6ClqPfhSFJFMEALJeZSmAVl/dukvbxtfFOondqaZLVdRg0/HxBV8g8B9iZYzYY2Aa/cH7Kw=="
  },
  "annotations" : [
    {
      "highlight": [
        [3,6],
        [7,9]
      ],
      "contributor": "8e0cd67f-f9da-46b8-98b9-16169893b439",
      "created" : "2004-02-12T15:19:21+00:00",
      "content" : {
        "en" : "I can't read this. Can someone send me the password?"
      },
      "meta" : {
        "property": "value"
      }
    }
  ],
  "revisions": [
    {
      "id": "c34bc1a7-fa99-4e3c-8d91-14498cdae5c0",
      "parent" : "6e27748b-b5d9-4da5-8e53-c2766a1c074b",
      "index": 0,
      "authors": [
        "01979fca-6ac3-479e-9f33-d89498836eb1"
      ],
      "version": "draft",
      "created": "2004-02-12T15:19:21+00:00"
    }
  ]
}