Skip to content

Figuring out why encryption on S3 object storage as primary storage is not working + trying to fix it #14027

Description

@lkreher

Steps to reproduce

  1. Install NC
  2. Setup S3 Object Storage as primary storage
  3. enable Encryption
  4. upload files > 10kb
  5. try to retrieve files

Expected behaviour

Files should be retrieved

Actual behaviour

Nextcloud throws an error and files can't be retrieved

Server configuration

Operating system: Ubuntu 16.04.3 LTS

Web server: nginx

Database: MySQL 5.7

PHP version: 7.2 FPM

Nextcloud version: 15.0.2

Updated from an older Nextcloud/ownCloud or fresh install: fresh install

Where did you install Nextcloud from: Nextcloud web installer

Signing status:

Signing status
No errors have been found.

List of activated apps:

App list
Enabled:
  - accessibility: 1.1.0
  - activity: 2.8.2
  - cloud_federation_api: 0.1.0
  - comments: 1.5.0
  - dav: 1.8.1
  - encryption: 2.3.0
  - federatedfilesharing: 1.5.0
  - federation: 1.5.0
  - files: 1.10.0
  - files_pdfviewer: 1.4.0
  - files_sharing: 1.7.0
  - files_texteditor: 2.7.0
  - files_trashbin: 1.5.0
  - files_versions: 1.8.0
  - files_videoplayer: 1.4.0
  - firstrunwizard: 2.4.0
  - gallery: 18.2.0
  - logreader: 2.0.0
  - lookup_server_connector: 1.3.0
  - nextcloud_announcements: 1.4.0
  - notifications: 2.3.0
  - oauth2: 1.3.0
  - password_policy: 1.5.0
  - provisioning_api: 1.5.0
  - serverinfo: 1.5.0
  - sharebymail: 1.5.0
  - support: 1.0.0
  - survey_client: 1.3.0
  - systemtags: 1.5.0
  - theming: 1.6.0
  - twofactor_backupcodes: 1.4.1
  - updatenotification: 1.5.0
  - workflowengine: 1.5.0
Disabled:
  - admin_audit
  - files_external
  - user_ldap

Nextcloud configuration:

Config report
{
    "system": {
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "objectstore": {
            "class": "OC\\Files\\ObjectStore\\S3",
            "arguments": {
                "bucket": "bucket",
                "autocreate": true,
                "key": "key",
                "secret": "secret",
                "region": "eu-central-1",
                "use_ssl": true
            }
        },
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "xxx"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "check_data_directory_permissions": false,
        "dbtype": "mysql",
        "version": "15.0.2.0",
        "overwrite.cli.url": "xxx",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "memcache.local": "\\OC\\Memcache\\Redis",
        "memcache.distributed": "\\OC\\Memcache\\Redis",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": 6379
        },
        "maintenance": false
    }
}

Are you using external storage, if yes which one: S3 object storage

Are you using encryption: yes

Are you using an external user-backend, if yes which one: no

Client configuration

Browser: Chrome

Operating system: Windows

Logs

Nextcloud log (data/nextcloud.log)

Nextcloud log
{"reqId":"zjolUv0wdkO8YqTg4DKt","level":4,"time":"2019-02-04T11:05:56+00:00","remoteAddr":"192.168.10.1","user":"me","app":"webdav","method":"GET","url":"\/remote.php\/webdav\/Nextcloud%20Manual.pdf","message":{"Exception":"OC\\Encryption\\Exceptions\\DecryptionFailedException","Message":"Encryption library: Decryption (symmetric) of content failed: ","Code":0,"Trace":[{"file":"\/home\/vagrant\/Sites\/nextcloud\/apps\/encryption\/lib\/Crypto\/Crypt.php","line":473,"function":"decrypt","class":"OCA\\Encryption\\Crypto\\Crypt","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/apps\/encryption\/lib\/Crypto\/Encryption.php","line":379,"function":"symmetricDecryptFileContent","class":"OCA\\Encryption\\Crypto\\Crypt","type":"->","args":["*** sensitive parameter replaced ***","*** sensitive parameter replaced ***","*** sensitive parameter replaced ***",1,"*** sensitive parameter replaced ***"]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/lib\/private\/Files\/Stream\/Encryption.php","line":479,"function":"decrypt","class":"OCA\\Encryption\\Crypto\\Encryption","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/lib\/private\/Files\/Stream\/Encryption.php","line":299,"function":"readCache","class":"OC\\Files\\Stream\\Encryption","type":"->","args":[]},{"function":"stream_read","class":"OC\\Files\\Stream\\Encryption","type":"->","args":[8192]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/3rdparty\/icewind\/streams\/src\/Wrapper.php","line":91,"function":"fread","args":[null,8192]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/3rdparty\/icewind\/streams\/src\/CallbackWrapper.php","line":91,"function":"stream_read","class":"Icewind\\Streams\\Wrapper","type":"->","args":[8192]},{"function":"stream_read","class":"Icewind\\Streams\\CallbackWrapper","type":"->","args":[8192]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/3rdparty\/sabre\/http\/lib\/Sapi.php","line":80,"function":"stream_copy_to_stream","args":[null,null,"6276760"]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/3rdparty\/sabre\/dav\/lib\/DAV\/Server.php","line":498,"function":"sendResponse","class":"Sabre\\HTTP\\Sapi","type":"::","args":[{"__class__":"Sabre\\HTTP\\Response"}]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/3rdparty\/sabre\/dav\/lib\/DAV\/Server.php","line":254,"function":"invokeMethod","class":"Sabre\\DAV\\Server","type":"->","args":[{"absoluteUrl":"http:\/\/nextcloud.lars\/remote.php\/webdav\/Nextcloud%20Manual.pdf","__class__":"Sabre\\HTTP\\Request"},{"__class__":"Sabre\\HTTP\\Response"}]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/apps\/dav\/appinfo\/v1\/webdav.php","line":80,"function":"exec","class":"Sabre\\DAV\\Server","type":"->","args":[]},{"file":"\/home\/vagrant\/Sites\/nextcloud\/remote.php","line":163,"args":["\/home\/vagrant\/Sites\/nextcloud\/apps\/dav\/appinfo\/v1\/webdav.php"],"function":"require_once"}],"File":"\/home\/vagrant\/Sites\/nextcloud\/apps\/encryption\/lib\/Crypto\/Crypt.php","Line":590,"Hint":"Encryption library: Decryption (symmetric) of content failed: ","CustomMessage":"--"},"userAgent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/71.0.3578.98 Safari\/537.36","version":"15.0.2.0"}

Report

This was previously discussed for NC14 in #11826 and others. I've been trying to fix this issue, and noticed multiple problems:

  1. The IV generated to encrypt one block uses random_bytes(16) at Crypt.php#634
    When written to file, read back and evaluated, this block gets interpreted as different character encoding, so 16 characters turn into more or less than 16 bytes.
    Changing Crypt.php#634 to return substr(base64_encode(random_bytes(16)), 0, 16); makes the IV safe from character encoding issues. This way I can successfully decrypt the first and the last block of each file, which means small files can be retrieved.

  2. Blocks don't get read properly. In Encryption.php#473 less than 8192 bytes of data are returned after the first block, even when there are more than 8192 bytes remaining. Retrieving a partial block is guaranteed to result in decryption errors.
    I don't have a solution for this problem. The stream resource is being handled by a 3rdparty library which does not behave as expected.

Looking for someone with an idea how to tackle problem 2. I've been stepping through the process with xdebug for a while and can't figure out how to retrieve a full 8192 bytes at once.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions