Skip to content

Client side Encryption

Tomas Celaya edited this page Dec 29, 2017 · 2 revisions

A user-specified key ID is required to allow identification of which key was used to encrypt an object. Performing encryption within the client grants users of java-manta the ability to prevent access to application data in situations where manta itself might be compromised. At the same time, this means that there is no server-side assistance for performing encryption and it is entirely up to the user of java-manta to manage their encryption secrets.

Enabling encryption

In order to enable client side encryption for downloading and decrypting encrypted files, please set the following parameters:

  • manta.client_encryption/MANTA_CLIENT_ENCRYPTION - set to true
  • manta.encryption_key_id to a meaningful identifier for the key being used
  • manta.encryption_algorithm the Java Cipher name of the algorithm to use when encrypting. See the table below for potential values and their respective features.
  • The key itself, specified through one of the following parameters:
    • manta.encryption_key_bytes - raw byte[] representation of the key. Can only be specified through a setter, the system property name is used only for reference.
    • manta.encryption_key_bytes_base64/MANTA_ENCRYPTION_KEY_BYTES - a base64 representation of the secret key

An example ConfigContext with encryption enabled:

ConfigContext config = new ChainedConfigContext(
    new DefaultsConfigContext(),
    new EnvVarConfigContext(),
    new SystemSettingsConfigContext())

    /* Standard credentials */
    .setMantaUser(mantaUserName)
    .setMantaKeyId(publicKeyId)
    .setMantaKeyPath(privateKeyPath)

    /* Encryption settings */
    .setClientEncryptionEnabled(true)
    .setEncryptionAlgorithm("AES256/CTR/NoPadding")
    .setEncryptionKeyId("personal-256")
    .setEncryptionPrivateKeyBytes(Base64.getDecoder().decode("RkZGRkZGRkJEOTY3ODNDNkM5MUUyMjIyMTExMTIyMjI="));

    /*
      Alternatively, provide the path to a file generated by java-manta-cli generate-key:

        .setEncryptionPrivateKeyPath("/path/to/generate-key/output")
    */

Additional encryption settings

To protect against the modification of ciphertext, all encryption modes support either built-in authenticated encryption (known as AEAD ciphers) or fall back to calculating a digest for cipher modes which do not include ciphertext authentication.

When a file is downloaded the client will check metadata in the headers to determine whether or not is should be decrypted. Assuming the ciphertext has not been modified a client should be able to compute the same digest over the downloaded ciphertext. The manta.encryption_authentication_mode parameter indicates whether or not to compute a digest of the downloaded file. Setting this to Optional is should only be done in one of the following two scenarios:

  • Performing range requests within encrypted objects. It is generally not possible to only fetch a subset of the object content and still verify the ciphertext has not been modified.
  • Partial decryption of object content is desired. This may be necessary in situations where data integrity is suspect and retrieving as much of the file as possible is a priority.
    .setEncryptionAuthenticationMode(EncryptionAuthenticationMode.Mandatory)

    /*
      Performing range requests or encountering `MantaClientEncryptionCiphertextAuthenticationException`?
      Setting this to `Optional` will prevent exceptions that would otherwise prevent the client
      from downloading an encrypted object without fully authenticating it's ciphertext:

        .setEncryptionAuthenticationMode(EncryptionAuthenticationMode.Optional)
    */

Finally, a client can be configured to use encryption but also fetch objects which are not encrypted. This behavior is not allowed by default but can be enabled by setting manta.permit_unencrypted_downloads to true.

    /*
      Attempting to download an object which was not encrypted will throw an error unless this
      parameter is explicitly set to allow it.

        .setPermitUnencryptedDownloads(true)
    */

Obtaining encryption keys

Generating an encryption key (or secret key) can be done using the java-manta-cli module's generate-key command to generate a file with the key content. Alternatively, use the SecretKeyUtils or javax.crypto.KeyGenerator classes to generate the secret key yourself. Let's say we wanted to generate a new encryption key for the above configuration (key strength of 256 bits), the following methods can be used to generate a new key.

byte[] encryptionKeyContent = SecretKeyUtils.generate(AesCtrCipherDetails.INSTANCE_192_BIT);

String base64Encoded = Base64.getEncoder().encodeToString(encryptionKeyContent);

Cipher modes

Below is a table of each of the supported encryption algorithms and the features they provide. Additional information about how these encryption modes differ is available here and here.

Algorithm Range Requests Authenticated Encryption
AES128/GCM/NoPadding No Yes
AES192/GCM/NoPadding No Yes
AES256/GCM/NoPadding No Yes
AES128/CTR/NoPadding Yes No
AES192/CTR/NoPadding Yes No
AES256/CTR/NoPadding Yes No
AES128/CBC/PKCS5Padding No No
AES192/CBC/PKCS5Padding No No
AES256/CBC/PKCS5Padding No No

All algorithms will honor the manta.encryption_auth_mode setting. This setting can be used to ensure that all files downloaded using a client with encryption enabled will be authenticated by the client. Algorithms which do not support authenticated encryption will include an HMAC at the end of the object payload. The calculated HMAC is used to verify that the bytes which were downloaded match the bytes the user intended to send.

Changing encryption settings

In order to simplify certain operations within the client, toggling encryption and/or changing the algorithm after client instatiation is not supported. To modify encryption settings, please close the existing client instance and create a new one or maintain one client for each cipher being used.

Appendix