Most of the data on the websites we use is stored on servers in plaintext, and server-side programs authenticate users’ identities and grant user access permissions. However, as business logic becomes more complex, there are always various vulnerabilities, even sensitive applications like Alipay are no exception. In addition, more and more websites are being built on public cloud platforms, a major concern is: Will the owner of the cloud platform steal my confidential data?

Therefore, it is best to encrypt data stored on the server, and the decryption key is in the user’s hands, that is, only the user can see the plaintext, and the website owner, cloud service provider, and possible server intruders can only see the ciphertext. Building web applications on top of encrypted data using Mylar, which will be published at the top conference in the network field NSDI 2014, is such a solution.

Server == Database

Traditional websites are generally “thin client” applications, that is, most of the business logic runs on the server side, and the client’s browser is only responsible for rendering the web pages sent by the server. However, with the development of front-end technologies such as JavaScript, the client has more and more code for page presentation and user interaction. The interface between client-side and server-side code has become a big trouble. Why not move the server-side business logic to the client side? First, some business logic related to “permissions” cannot be manipulated by users at will; second, transferring data to the client for processing may waste bandwidth and increase latency.

To implement a “fat client, thin server” Web application, the server side needs to provide a data model that includes permission management and fast search. Meteor is such a famous Web framework, its server side is basically a document model database (like MongoDB), and what is transmitted between the client and the server is no longer HTML but structured data. Based on the concept of reactive programming and “page elements binding data”, Meteor can not only easily implement most types of Web applications completely on the client side, but also has some cool new features:

  • When one client updates data, other client pages automatically update
  • After the client updates the data, there is no need to wait for network latency, and its own page is updated immediately
  • After the code is modified, it can be updated seamlessly without interrupting the user’s current operation

Challenges

However, it is not possible to directly use Meteor and add a password to each document submitted by the user.

  1. The invaded server may send tampered JavaScript code to the client.

  2. Each user uses a different key, and the document cannot be shared between users. Obviously, uploading the key to an untrusted server is insecure.

  3. If the document is encrypted, fast search cannot be performed on the server side. Downloading all to the client for processing is too uneconomical.
    The Mylar system solves the above challenges as follows:

  4. The website owner signs the code to ensure that the code sent to the client is not tampered with. Run client-side code in one domain and load user content in another domain, relying on the browser’s same-origin policy to ensure that client-side code is not tampered with by malicious data submitted by users.

  5. Each permission-controlled document uses a pair of public and private keys, and sharing documents is to distribute the private key of the document. Digital signatures must also be used on public keys to prevent counterfeiting.

  6. Use cryptographic methods to pre-calculate the “key difference”, and only need to submit an encrypted query request to quickly search for documents encrypted with multiple keys.
    Experiments show that these added logics only reduce the server throughput by 17%, increase the delay by 50 milliseconds, and only need to modify an average of 36 lines of code for each Meteor application to use the Mylar library. Let’s take a look at how Mylar is implemented.

System Architecture

CaptureCapture Mylar consists of the following parts:

  • Browser plugin, responsible for verifying the digital signature of the client code (similar to verifying the digital signature of HTTPS web pages)
  • Client library, encrypts data sent to the server and decrypts data received from the server. Each user has a username and a pair of public and private keys, called a principal, in each application. The private key is encrypted and stored on the server using the user’s own password, and is retrieved and decrypted from the server when logging in.
  • Server-side library, search in encrypted data (the principle will be detailed later).
  • Identity authentication service, such as OpenID, this needs to be a trusted third-party service, digitally sign the user’s username and public key.
    Since the server is untrusted, we cannot trust that the server can correctly implement access control. Therefore, each permission control unit (such as a chat room, a file) needs to be encrypted, and users who have access rights share the key. Each permission control unit has a name for identification and a pair of public and private keys, called a principal (the same data structure as the user principal).

Meteor + Mylar uses MongoDB’s document model, developers need to mark the fields (field) that need to be encrypted in the document collection (collection) and specify the name of its principal. When Alice invites Bob to join the chat room, Alice’s client code needs to sign Bob’s principal with the principal of this chat room, which is equivalent to authorizing Bob to enter the chat room.

Data Sharing

Data sharing, also known as key distribution, needs to consider two points:

  • Only authorized users can access the private key of the restricted area (access control unit). This is the Access Graph below.
  • Users should be able to authenticate the public key of the restricted area, otherwise the server may send a fake public key, tricking users into encrypting confidential content with the fake public key. This is the Certification Graph below.

Distributing Private Keys: Access Graph

As shown in the figure below, how to authorize the chat room party to Alice and Bob? Note that this “authorization” means that Alice should be able to get the private key of the chat room party, otherwise Alice cannot decrypt the content in the chat room.

CaptureCapture

If the private key of the chat room is stored in plaintext on the server, it is obviously insecure. Mylar encrypts the private key of the chat room (as data) with the public keys of Alice and Bob respectively, and stores these two encrypted private keys on the server. The more people have the right to access an area, the more the area has to encrypt its own private key with the public keys of these people and save it on the server. When Alice needs to access the chat room, she retrieves the chat room private key encrypted with Alice’s public key, decrypts it with her private key, and gets the private key of the chat room.

Authorization is transitive, that is, if A authorizes B to access, and B authorizes C to access, then C has the right to access A. Therefore, this authorization relationship forms a graph, called the Access Graph.

Authenticating Public Keys: Certification Graph

Continuing the example from the last section, if Bob joins the chat room party at Alice’s invitation, how can he verify that this chat room is indeed created by Alice? After all, another person (such as Boss) may pretend to be Alice, trick Bob into joining his chat room and say things he doesn’t want the boss to know. This is where digital signatures come into play.

First case: The chat rooms are all created by the administrator. The application developer creates a pair of public and private keys hard-coded in the program code (the private key is encrypted with the administrator’s password and stored). When the administrator creates a chat room, he needs to specify a unique name and automatically generate a pair of public and private keys for the chat room. The administrator enters the password, decrypts the hard-coded private key, and then signs the chat room name and chat room public key with it. Since the application code is unalterable (see the next section for the principle), this forms a complete trust chain. Users can confirm that they have entered a trusted chat room through the name of the chat room.

Second case: Anyone can create a chat room. When Alice creates a chat room, she needs to use her own private key to sign the public key of the chat room. This signature can be verified with Alice’s public key. Assuming that anyone can trustingly obtain Alice’s public key, the application program can verify the public key of the chat room and mark “Chat room created by Alice” on the chat room window. Others cannot forge this mark.

To verify Alice’s public key, another trusted institution needs to sign Alice’s public key.

  • If it is an internal application of the company, that is, all users are created by the administrator, this trusted institution can be the application itself. Since the administrator has the password of the hard-coded private key, he can get the private key and use it to sign the newly created user.
  • If it is a public application where users can register at will, this trusted institution can be a third-party OpenID service. Note that the third-party service signs its username and public key, without needing to get the user’s private key. The public keys of these trusted institutions are either signed by higher-level trusted institutions or pre-installed in browsers or operating systems. In fact, the current HTTPS digital signature system works in this way.

Code Verification

Friends familiar with HTTPS should know that HTML, CSS, JS and other files loaded using HTTPS are trustworthy because they have been signed by the server. In Mylar, since the server is no longer trusted, HTTPS that signs the server is no longer available. But application developers can sign the code on their own computers and then upload it to the server. The server provides signed static code and resource files to users each time, and users install plugins on their browsers to verify the signatures on these files.

The issuance and trust mechanism of the signature is no different from the SSL certificate system that HTTPS relies on. We can obtain a certificate that can be used for re-signing (i.e., code-signing certificate) from a trusted certificate issuing authority. Each time the code is modified, use this certificate to sign each code file and resource file separately.

The rich text information submitted by users may embed JavaScript code, thereby tampering with the signed application code. This is not a problem unique to Mylar, but a common Web attack, known as Cross-Site Scripting (XSS). Mylar’s approach is:

  1. The code on the homepage of the website should have a version number.
  2. Website developers need to sign the website homepage.
  3. All content loaded by the website homepage must use another domain. This can prevent the content submitted by users from tampering with the application code in the website homepage.
  4. All URLs must include the version number as a parameter, and the HTTP response should also include this version number. The client will check the consistency of the version number. This can prevent the man-in-the-middle from returning old content, unless the man-in-the-middle returns the old version of the website homepage from the beginning.

First of all, to allow encrypted documents to be searched on the server side (without having to transfer all data to the client), you need to index the documents according to words. Since the server is not allowed to see plaintext, each word needs to be encrypted. That is, the query words sent by the user and the words in the document are encrypted according to the same encryption algorithm and key. In this way, the same words get the same ciphertext, and you can quickly search within the document.

However, if the documents in Mylar are in different access control units, they will be encrypted with different keys. If the user sends a query request to each access control unit separately, the overhead is too high. It is best for the user to send an encrypted query request with a certain key, and the server automatically converts this encrypted query request into an encrypted query request with other keys, which can reduce the communication between the client and the server. Of course, the server cannot decrypt the query request in this process, let alone get any of the user’s keys. Is this possible?

Based on elliptic curve cryptography, Mylar has proposed a reliable solution.

CaptureCapture

Continuing the previous example, when Bob is authorized to access the chat room party, Bob can calculate the difference between Bob’s private key and the private key of the chat room party, and store this difference in the chat room party. When Bob is authorized to access the chat room work, Bob can store the difference between his private key and the private key of the chat room work in the chat room work.

When Bob needs to search in all chat rooms, he only needs to encrypt the word to be searched with his own private key and send it to the server. The server will use the previously stored “private key difference” to calculate the results of the word to be searched encrypted with the party and work private keys respectively, and then use the indexes already existing in the party and chat chat rooms to find the documents containing the word to be searched in a short time. If the index is built with a hash table, assuming the time complexity is constant, then the time required for the entire query is proportional to the number of chat rooms Bob joined. (As shown in the actual test results below, the server-side multi-key search proposed in the paper is much faster than the client downloading and then searching)

CaptureCapture

Next, we use non-strict elementary mathematics to describe the general idea of “key difference”. Encrypted is the encrypted word, and token is the encrypted word to be searched. Please note the difference between the two.

CaptureCapture

Knowing the word to be searched after encryption with a key, and the “difference” between two keys, you can find out the word to be searched after encryption with another key.

CaptureCapture

In order to avoid malicious people stealing plaintext by statistical word frequency or dictionary attack methods, you need to hash the word before encryption, add salt (random string) to the encrypted result, and then hash it. The salt is stored in the access control unit in plaintext. “Salting” is a common method to avoid hash attacks such as rainbow tables. In current websites, user passwords are generally first hashed, then salted and hashed before being stored in the database.

CaptureCapture

Careful readers may have noticed that the query word conversion through “private key difference” can only be performed once, because the result after conversion is an encrypted word and no longer a token. If the Access Graph has more than two levels, the application code has to decide which level is the most economical to do the private key conversion.

For example, in the medical record database, all doctors have access to an access control unit called “staff”, and “staff” has access to all patient access control units. The server can store the “private key difference” between the “staff” private key and each patient’s private key. Every time a doctor searches, he obtains the private key of the “staff” access control unit and decrypts it, uses the “staff” private key to encrypt the query word, sends it to the server, and the server then converts it into the encrypted result of each patient, and queries in each patient’s access control unit.

Implementation Details

Mylar provides the following APIs to developers (unless otherwise specified, APIs are called by the client):

  • User control:

    • idp_config(url, pubkey): Retrieve the user’s principal from a third-party OpenID service (IDP).
    • create_user(uname, password, auth_princ): Create user uname, whose password is password, and the public and private keys are auth_princ.
    • login(uname, password): User login.
    • logout(): The current user logs out.
  • Data operation:

    • collection.encrypted([field: princ_field], …): Specify which fields in a document collection need to be encrypted and what keys are used for encryption respectively.
    • collection.auth_set([princ_field, fields], …): Authenticate the consistency of several fields in a document collection with the given key, that is, the checksum of these fields as a whole is correct. This is to prevent malicious servers from replacing the X field of document A with the X field value of document B, destroying data integrity.
    • collection.searchable(field): Called by the server. Mark a field in the document collection as searchable to build an index and improve search efficiency.
    • collection.search(word, field, princ, filter, proj): Search for documents in the document collection where the field value equals word, use princ to generate encrypted search keywords; filter the search results and output the fields specified by proj.
  • Key Management:

    • princ_create(name, creator_princ): Create a pair of public and private keys, sign it with the creator’s key, and authorize the creator to access this pair of keys.
    • princ_create_static(name, password): Called by the server side. Create a pair of public and private keys hardcoded in the application, and encrypt the private key with the password.
    • princ_static(name, password): Returns the public key hardcoded in the application. If the password is correct, the private key is also returned.
    • princ_current(): Get the current user’s public and private keys.
    • princ_lookup(name1, …, namek, root): Check the key chain starting from the root key (such as a third-party OpenID) root, namek, …, name1.
    • granter.add_access(grantee): Grant grantee access to the granter’s key.
    • grantee.allow_search(granter): Grant grantee the permission to search the granter’s content.

Taking the chat room application as an example, the code framework is:

CaptureCapture

As you can see, transforming an application into a Mylar application does not require too many changes. The paper also describes some other types of applications, and the amount of code modification is not large:

CaptureCapture

After adding the encryption process, will the server performance significantly decrease? The answer is no.

CaptureCapture

For more evaluation results, please see the original paper. Mylar is an open source project, its homepage is http://css.csail.mit.edu/mylar/

Summary

Meteor + Mylar truly hands over the ownership of data to users, achieving “end-to-end” (client A to client B) security without significantly increasing the burden on application developers and servers.

For the sake of security, Mylar has to make some sacrifices in some aspects:

  • Once permissions are granted, they cannot be revoked. This is a common weakness of the digital signature mechanism, unless a “certificate revocation list” is introduced.
  • It is impossible to separately grant read and write permissions.
  • The server side cannot perform counting, sorting, etc. on encrypted data.
  • The process of exchanging keys and encryption and decryption increases the user’s access delay.
  • The encrypted private key and the “key difference” used for searching need to be saved in multiple copies, occupying more storage space.
    Whether it’s personal data or enterprise applications, the trend is to move to the cloud, but few people completely trust the security of data in the cloud. Under the Meteor + Mylar architecture, the cloud becomes an encrypted database, and server “defection” is no longer a privacy nightmare. Although this security comes at the cost of performance, with the improvement of web frameworks represented by Mylar and the improvement of network conditions, it is believed that more and more applications will start to adopt the “end-to-end” security model.

Comments