{"action":"opened","number":162,"pull_request":{"url":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/162","id":37255750,"html_url":"https://github.com/cloudant/CDTDatastore/pull/162","diff_url":"https://github.com/cloudant/CDTDatastore/pull/162.diff","patch_url":"https://github.com/cloudant/CDTDatastore/pull/162.patch","issue_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues/162","number":162,"state":"open","locked":false,"title":"47559 Fixing sha1 naming","user":{"login":"indisoluble","id":472832,"avatar_url":"https://avatars.githubusercontent.com/u/472832?v=3","gravatar_id":"","url":"https://api.github.com/users/indisoluble","html_url":"https://github.com/indisoluble","followers_url":"https://api.github.com/users/indisoluble/followers","following_url":"https://api.github.com/users/indisoluble/following{/other_user}","gists_url":"https://api.github.com/users/indisoluble/gists{/gist_id}","starred_url":"https://api.github.com/users/indisoluble/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/indisoluble/subscriptions","organizations_url":"https://api.github.com/users/indisoluble/orgs","repos_url":"https://api.github.com/users/indisoluble/repos","events_url":"https://api.github.com/users/indisoluble/events{/privacy}","received_events_url":"https://api.github.com/users/indisoluble/received_events","type":"User","site_admin":false},"body":"*What:*\r\nSave attachments to disk with a random-generated filename.\r\n\r\n*Why:*\r\nTo save an attachment to disk, we were using the SHA1 digest of the plain data to generate its filename. This is not a problem as long as the datastore is not encrypted but if it is and the attachment has a well-known content, an attacker can simply generate the SHA1 values for all well-known content and discover the content of any attachment without decrypting the file.\r\n\r\n*How:*\r\n1. Add a new table to the database to relate keys (SHA1 digest of the plain data) with filenames.\r\n2. Populate the new table with the current content in the database:\r\n    1. Get the keys in the attachment table\r\n    2. For each key, generate a filename equal to: <key>.blob\r\n    3. Insert keys and filenames in the new table\r\n3. Modify methods in `TDBlobStore` to receive a `FMDatabase` instance. These methods need access to the database to get the filename for a key or insert a key and a filename when an attachment is saved to disk.\r\n4. Instead of generating the filename based on the plain content of the attachment, use a random function to generate the filename.\r\n\r\n*Tests:*\r\n* Create table if the database version is less than or equal to 100\r\n* The new table is populated with the current attachments\r\n* The same key can not be inserted twice in the database\r\n* However, if an user tries to save the same attachment twice (with the same key), the operation succeeds and returns the filename generated the first time. But no file is saved to disk and the db is not updated.\r\n* Check that a migrated key (moved to the new table) can be retrieved as any other key.\r\n* Check that we are still able to delete attachment from disk and also from db.\r\n\r\nreviewer @mikerhodes \r\nreviewer @rhyshort \r\n","created_at":"2015-06-09T13:57:55Z","updated_at":"2015-06-09T13:57:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"42c339c41180a844b4a5cc278c9f6ff69baa5b40","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/162/commits","review_comments_url":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/162/comments","review_comment_url":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues/162/comments","statuses_url":"https://api.github.com/repos/cloudant/CDTDatastore/statuses/b7a6503606c25f22fe222cfe5ef3135012d3b307","head":{"label":"cloudant:47559-fixing-SHA1-naming","ref":"47559-fixing-SHA1-naming","sha":"b7a6503606c25f22fe222cfe5ef3135012d3b307","user":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"repo":{"id":15022868,"name":"CDTDatastore","full_name":"cloudant/CDTDatastore","owner":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cloudant/CDTDatastore","description":"Cloudant Sync iOS datastore library.","fork":false,"url":"https://api.github.com/repos/cloudant/CDTDatastore","forks_url":"https://api.github.com/repos/cloudant/CDTDatastore/forks","keys_url":"https://api.github.com/repos/cloudant/CDTDatastore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cloudant/CDTDatastore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cloudant/CDTDatastore/teams","hooks_url":"https://api.github.com/repos/cloudant/CDTDatastore/hooks","issue_events_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues/events{/number}","events_url":"https://api.github.com/repos/cloudant/CDTDatastore/events","assignees_url":"https://api.github.com/repos/cloudant/CDTDatastore/assignees{/user}","branches_url":"https://api.github.com/repos/cloudant/CDTDatastore/branches{/branch}","tags_url":"https://api.github.com/repos/cloudant/CDTDatastore/tags","blobs_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/refs{/sha}","trees_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cloudant/CDTDatastore/statuses/{sha}","languages_url":"https://api.github.com/repos/cloudant/CDTDatastore/languages","stargazers_url":"https://api.github.com/repos/cloudant/CDTDatastore/stargazers","contributors_url":"https://api.github.com/repos/cloudant/CDTDatastore/contributors","subscribers_url":"https://api.github.com/repos/cloudant/CDTDatastore/subscribers","subscription_url":"https://api.github.com/repos/cloudant/CDTDatastore/subscription","commits_url":"https://api.github.com/repos/cloudant/CDTDatastore/commits{/sha}","git_commits_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/commits{/sha}","comments_url":"https://api.github.com/repos/cloudant/CDTDatastore/comments{/number}","issue_comment_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues/comments{/number}","contents_url":"https://api.github.com/repos/cloudant/CDTDatastore/contents/{+path}","compare_url":"https://api.github.com/repos/cloudant/CDTDatastore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cloudant/CDTDatastore/merges","archive_url":"https://api.github.com/repos/cloudant/CDTDatastore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cloudant/CDTDatastore/downloads","issues_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues{/number}","pulls_url":"https://api.github.com/repos/cloudant/CDTDatastore/pulls{/number}","milestones_url":"https://api.github.com/repos/cloudant/CDTDatastore/milestones{/number}","notifications_url":"https://api.github.com/repos/cloudant/CDTDatastore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cloudant/CDTDatastore/labels{/name}","releases_url":"https://api.github.com/repos/cloudant/CDTDatastore/releases{/id}","created_at":"2013-12-08T11:59:05Z","updated_at":"2015-06-08T06:13:21Z","pushed_at":"2015-06-09T13:57:55Z","git_url":"git://github.com/cloudant/CDTDatastore.git","ssh_url":"git@github.com:cloudant/CDTDatastore.git","clone_url":"https://github.com/cloudant/CDTDatastore.git","svn_url":"https://github.com/cloudant/CDTDatastore","homepage":null,"size":8635,"stargazers_count":71,"watchers_count":71,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":6,"forks":13,"open_issues":6,"watchers":71,"default_branch":"master"}},"base":{"label":"cloudant:feature-encryption","ref":"feature-encryption","sha":"59fb9f5937d73f0a7afab7fb2d4d8e6212b26e26","user":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"repo":{"id":15022868,"name":"CDTDatastore","full_name":"cloudant/CDTDatastore","owner":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cloudant/CDTDatastore","description":"Cloudant Sync iOS datastore library.","fork":false,"url":"https://api.github.com/repos/cloudant/CDTDatastore","forks_url":"https://api.github.com/repos/cloudant/CDTDatastore/forks","keys_url":"https://api.github.com/repos/cloudant/CDTDatastore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cloudant/CDTDatastore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cloudant/CDTDatastore/teams","hooks_url":"https://api.github.com/repos/cloudant/CDTDatastore/hooks","issue_events_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues/events{/number}","events_url":"https://api.github.com/repos/cloudant/CDTDatastore/events","assignees_url":"https://api.github.com/repos/cloudant/CDTDatastore/assignees{/user}","branches_url":"https://api.github.com/repos/cloudant/CDTDatastore/branches{/branch}","tags_url":"https://api.github.com/repos/cloudant/CDTDatastore/tags","blobs_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/refs{/sha}","trees_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cloudant/CDTDatastore/statuses/{sha}","languages_url":"https://api.github.com/repos/cloudant/CDTDatastore/languages","stargazers_url":"https://api.github.com/repos/cloudant/CDTDatastore/stargazers","contributors_url":"https://api.github.com/repos/cloudant/CDTDatastore/contributors","subscribers_url":"https://api.github.com/repos/cloudant/CDTDatastore/subscribers","subscription_url":"https://api.github.com/repos/cloudant/CDTDatastore/subscription","commits_url":"https://api.github.com/repos/cloudant/CDTDatastore/commits{/sha}","git_commits_url":"https://api.github.com/repos/cloudant/CDTDatastore/git/commits{/sha}","comments_url":"https://api.github.com/repos/cloudant/CDTDatastore/comments{/number}","issue_comment_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues/comments{/number}","contents_url":"https://api.github.com/repos/cloudant/CDTDatastore/contents/{+path}","compare_url":"https://api.github.com/repos/cloudant/CDTDatastore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cloudant/CDTDatastore/merges","archive_url":"https://api.github.com/repos/cloudant/CDTDatastore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cloudant/CDTDatastore/downloads","issues_url":"https://api.github.com/repos/cloudant/CDTDatastore/issues{/number}","pulls_url":"https://api.github.com/repos/cloudant/CDTDatastore/pulls{/number}","milestones_url":"https://api.github.com/repos/cloudant/CDTDatastore/milestones{/number}","notifications_url":"https://api.github.com/repos/cloudant/CDTDatastore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cloudant/CDTDatastore/labels{/name}","releases_url":"https://api.github.com/repos/cloudant/CDTDatastore/releases{/id}","created_at":"2013-12-08T11:59:05Z","updated_at":"2015-06-08T06:13:21Z","pushed_at":"2015-06-09T13:57:55Z","git_url":"git://github.com/cloudant/CDTDatastore.git","ssh_url":"git@github.com:cloudant/CDTDatastore.git","clone_url":"https://github.com/cloudant/CDTDatastore.git","svn_url":"https://github.com/cloudant/CDTDatastore","homepage":null,"size":8635,"stargazers_count":71,"watchers_count":71,"language":"Objective-C","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":6,"forks":13,"open_issues":6,"watchers":71,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/162"},"html":{"href":"https://github.com/cloudant/CDTDatastore/pull/162"},"issue":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/issues/162"},"comments":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/issues/162/comments"},"review_comments":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/162/comments"},"review_comment":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/pulls/162/commits"},"statuses":{"href":"https://api.github.com/repos/cloudant/CDTDatastore/statuses/b7a6503606c25f22fe222cfe5ef3135012d3b307"}},"merged":false,"mergeable":true,"mergeable_state":"clean","merged_by":null,"comments":0,"review_comments":0,"commits":7,"additions":1555,"deletions":258,"changed_files":24}}