{"action":"created","comment":{"url":"https://api.github.com/repos/pyca/cryptography/pulls/comments/91001117","pull_request_review_id":11511620,"id":91001117,"diff_hunk":"@@ -0,0 +1,429 @@\n+/* osurandom engine\n+ *\n+ * Windows         CryptGenRandom()\n+ * macOS >= 10.12  getentropy()\n+ * OpenBSD 5.6+    getentropy()\n+ * other BSD       getentropy() if SYS_getentropy is defined\n+ * Linux 3.4.17+   getrandom() with fallback to /dev/urandom\n+ * other           /dev/urandom with cached fd\n+ *\n+ * The /dev/urandom, getrandom and getentropy code is derived from Python's\n+ * Python/random.c, written by Antoine Pitrou and Victor Stinner.\n+ *\n+ * Copyright 2001-2016 Python Software Foundation; All Rights Reserved.\n+ */\n+\n+static const char *Cryptography_osrandom_engine_id = \"osrandom\";\n+\n+/****************************************************************************\n+ * Windows\n+ */\n+#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM\n+static const char *Cryptography_osrandom_engine_name = \"osrandom_engine CryptGenRandom()\";\n+static HCRYPTPROV hCryptProv = 0;\n+\n+static int osrandom_init(ENGINE *e) {\n+    if (hCryptProv != 0) {\n+        return 1;\n+    }\n+    if (CryptAcquireContext(&hCryptProv, NULL, NULL,\n+                            PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {\n+        return 1;\n+    } else {\n+        return 0;\n+    }\n+}\n+\n+static int osrandom_rand_bytes(unsigned char *buffer, int size) {\n+    if (hCryptProv == 0) {\n+        return 0;\n+    }\n+\n+    if (!CryptGenRandom(hCryptProv, (DWORD)size, buffer)) {\n+        CRYPTOGRAPHY_OSRANDOM_put_error(\n+            \"osrandom_engine.py:CryptGenRandom()\");\n+        return 0;\n+    }\n+    return 1;\n+}\n+\n+static int osrandom_finish(ENGINE *e) {\n+    if (CryptReleaseContext(hCryptProv, 0)) {\n+        hCryptProv = 0;\n+        return 1;\n+    } else {\n+        return 0;\n+    }\n+}\n+\n+static int osrandom_rand_status(void) {\n+    if (hCryptProv == 0) {\n+        return 0;\n+    } else {\n+        return 1;\n+    }\n+}\n+\n+static const char* osurandom_get_implementation(void) {\n+    return \"CryptGenRandom\";\n+}\n+\n+#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM */\n+\n+/****************************************************************************\n+ * BSD getentropy\n+ */\n+#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY\n+static const char *Cryptography_osrandom_engine_name = \"osrandom_engine getentropy()\";\n+\n+static int osrandom_init(ENGINE *e) {\n+    return 1;\n+}\n+\n+static int osrandom_rand_bytes(unsigned char *buffer, int size) {\n+    int len, res;\n+    while (size > 0) {\n+        /* OpenBSD and macOS restrict maximum buffer size to 256. */\n+        len = size > 256 ? 256: size;\n+        res = getentropy(buffer, len);\n+        if (res < 0) {\n+            CRYPTOGRAPHY_OSRANDOM_put_error(\n+                \"osrandom_engine.py:getentropy()\");\n+            return 0;\n+        }\n+        buffer += len;\n+        size -= len;\n+    }\n+    return 1;\n+}\n+\n+static int osrandom_finish(ENGINE *e) {\n+    return 1;\n+}\n+\n+static int osrandom_rand_status(void) {\n+    return 1;\n+}\n+\n+static const char* osurandom_get_implementation(void) {\n+    return \"getentropy\";\n+}\n+#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY */\n+\n+/****************************************************************************\n+ * /dev/urandom helpers for all non-BSD Unix platforms\n+ */\n+#ifdef CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM\n+\n+static struct {\n+    int fd;\n+    dev_t st_dev;\n+    ino_t st_ino;\n+} urandom_cache = { -1 };\n+\n+/* return -1 on error */\n+static int dev_urandom_fd(void) {\n+    int fd, n, flags;\n+    struct stat st;\n+\n+    /* Check that fd still points to the correct device */\n+    if (urandom_cache.fd >= 0) {\n+        if (fstat(urandom_cache.fd, &st)\n+                || st.st_dev != urandom_cache.st_dev\n+                || st.st_ino != urandom_cache.st_ino) {\n+            /* Somebody replaced our FD. Invalidate our cache but don't\n+             * close the fd. */\n+            urandom_cache.fd = -1;\n+        }\n+    }\n+    if (urandom_cache.fd < 0) {\n+        fd = open(\"/dev/urandom\", O_RDONLY);\n+        if (fd < 0) {\n+            goto error;\n+        }\n+        if (fstat(fd, &st)) {\n+            goto error;\n+        }\n+        /* set CLOEXEC flag */\n+        flags = fcntl(fd, F_GETFD);\n+        if (flags == -1) {\n+            goto error;\n+        } else if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {\n+            goto error;\n+        }\n+        /* Another thread initialized the fd */\n+        if (urandom_cache.fd >= 0) {\n+            do {\n+                n = close(fd);\n+            } while (n < 0 && errno == EINTR);\n+            return urandom_cache.fd;\n+        }\n+        urandom_cache.st_dev = st.st_dev;\n+        urandom_cache.st_ino = st.st_ino;\n+        urandom_cache.fd = fd;\n+    }\n+    return urandom_cache.fd;\n+\n+  error:\n+    if (fd != -1) {\n+        do {\n+            n = close(fd);\n+        } while (n < 0 && errno == EINTR);\n+    }\n+    CRYPTOGRAPHY_OSRANDOM_put_error(\n+        \"osrandom_engine.py:dev_urandom_fd()\");\n+    return -1;\n+}\n+\n+static int dev_urandom_read(unsigned char *buffer, int size) {\n+    int fd;\n+    ssize_t n;\n+\n+    fd = dev_urandom_fd();\n+    if (fd < 0) {\n+        return 0;\n+    }\n+\n+    while (size > 0) {\n+        do {\n+            n = read(fd, buffer, (size_t)size);\n+        } while (n < 0 && errno == EINTR);\n+\n+        if (n <= 0) {\n+            CRYPTOGRAPHY_OSRANDOM_put_error(\n+                \"osrandom_engine.py:dev_urandom_read()\");\n+            return 0;\n+        }\n+        buffer += n;\n+        size -= n;\n+    }\n+    return 1;\n+}\n+\n+static void dev_urandom_close(void) {\n+    if (urandom_cache.fd >= 0) {\n+        int fd, n;\n+        struct stat st;\n+\n+        if (fstat(urandom_cache.fd, &st)\n+                && st.st_dev == urandom_cache.st_dev\n+                && st.st_ino == urandom_cache.st_ino) {\n+            fd = urandom_cache.fd;\n+            urandom_cache.fd = -1;\n+            do {\n+                n = close(fd);\n+            } while (n < 0 && errno == EINTR);\n+        }\n+    }\n+}\n+#endif /* CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM */\n+\n+/****************************************************************************\n+ * Linux getrandom engine with fallback to dev_urandom\n+ */\n+\n+#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM\n+static const char *Cryptography_osrandom_engine_name = \"osrandom_engine getrandom()\";\n+\n+static int getrandom_works = -1;\n+\n+static int osrandom_init(ENGINE *e) {\n+    /* We try to detect working getrandom until we succeed. */\n+    if (getrandom_works != 1) {\n+        long n;\n+        char dest[1];\n+        n = syscall(SYS_getrandom, dest, sizeof(dest), GRND_NONBLOCK);\n+        if (n < 0) {\n+            /* Can fail with:\n+             * - ENOSYS: Kernel does not support the syscall.\n+             * - ENOPERM: seccomp prevents syscall.\n+             * - EAGAIN: Kernel CRPNG has not been seeded yet.\n+             * EINTR cannot occur for buflen < 256.\n+             */\n+            getrandom_works = 0;\n+        } else {\n+            getrandom_works = 1;\n+        }\n+    }\n+    /* fallback to dev urandom */\n+    if (getrandom_works == 0) {\n+        int fd = dev_urandom_fd();\n+        if (fd < 0) {\n+            return 0;\n+        }\n+    }\n+    return 1;\n+}\n+\n+static int osrandom_rand_bytes(unsigned char *buffer, int size) {\n+    if (getrandom_works == 1) {\n+        long n;\n+        while (size > 0) {\n+            do {\n+                n = syscall(SYS_getrandom, buffer, size, GRND_NONBLOCK);","path":"src/_cffi_src/openssl/src/osrandom_engine.c","position":263,"original_position":263,"commit_id":"c05ea01a8d45bb3ccafbcf9cdd79ef231e50587e","original_commit_id":"c05ea01a8d45bb3ccafbcf9cdd79ef231e50587e","user":{"login":"alex","id":772,"avatar_url":"https://avatars.githubusercontent.com/u/772?v=3","gravatar_id":"","url":"https://api.github.com/users/alex","html_url":"https://github.com/alex","followers_url":"https://api.github.com/users/alex/followers","following_url":"https://api.github.com/users/alex/following{/other_user}","gists_url":"https://api.github.com/users/alex/gists{/gist_id}","starred_url":"https://api.github.com/users/alex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alex/subscriptions","organizations_url":"https://api.github.com/users/alex/orgs","repos_url":"https://api.github.com/users/alex/repos","events_url":"https://api.github.com/users/alex/events{/privacy}","received_events_url":"https://api.github.com/users/alex/received_events","type":"User","site_admin":false},"body":"What does this do on large (>256) `size`?","created_at":"2016-12-06T02:27:53Z","updated_at":"2016-12-06T02:29:17Z","html_url":"https://github.com/pyca/cryptography/pull/3229#discussion_r91001117","pull_request_url":"https://api.github.com/repos/pyca/cryptography/pulls/3229","_links":{"self":{"href":"https://api.github.com/repos/pyca/cryptography/pulls/comments/91001117"},"html":{"href":"https://github.com/pyca/cryptography/pull/3229#discussion_r91001117"},"pull_request":{"href":"https://api.github.com/repos/pyca/cryptography/pulls/3229"}}},"pull_request":{"url":"https://api.github.com/repos/pyca/cryptography/pulls/3229","id":93248469,"html_url":"https://github.com/pyca/cryptography/pull/3229","diff_url":"https://github.com/pyca/cryptography/pull/3229.diff","patch_url":"https://github.com/pyca/cryptography/pull/3229.patch","issue_url":"https://api.github.com/repos/pyca/cryptography/issues/3229","number":3229,"state":"open","locked":false,"title":"New osrandom_engine in C","user":{"login":"tiran","id":444071,"avatar_url":"https://avatars.githubusercontent.com/u/444071?v=3","gravatar_id":"","url":"https://api.github.com/users/tiran","html_url":"https://github.com/tiran","followers_url":"https://api.github.com/users/tiran/followers","following_url":"https://api.github.com/users/tiran/following{/other_user}","gists_url":"https://api.github.com/users/tiran/gists{/gist_id}","starred_url":"https://api.github.com/users/tiran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tiran/subscriptions","organizations_url":"https://api.github.com/users/tiran/orgs","repos_url":"https://api.github.com/users/tiran/repos","events_url":"https://api.github.com/users/tiran/events{/privacy}","received_events_url":"https://api.github.com/users/tiran/received_events","type":"User","site_admin":false},"body":"Inspired by Python/random.c and the old implementation. Let's ask travis if it works on all platforms.\r\n\r\nSigned-off-by: Christian Heimes <christian@python.org>\r\n\r\n- [x] Test `/dev/urandom` path\r\n- [x] Test ```getrandom()``` path\r\n- [x] Test ```getentropy()``` path\r\n- [x] Test `CryptGenRandom` path","created_at":"2016-11-10T22:59:50Z","updated_at":"2016-12-06T02:29:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"77481f7a00ed094b0df1dae13dff14a4763ffa2a","assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/pyca/cryptography/milestones/19","html_url":"https://github.com/pyca/cryptography/milestones/Seventeenth%20Release","labels_url":"https://api.github.com/repos/pyca/cryptography/milestones/19/labels","id":2150340,"number":19,"title":"Seventeenth Release","description":"","creator":{"login":"alex","id":772,"avatar_url":"https://avatars.githubusercontent.com/u/772?v=3","gravatar_id":"","url":"https://api.github.com/users/alex","html_url":"https://github.com/alex","followers_url":"https://api.github.com/users/alex/followers","following_url":"https://api.github.com/users/alex/following{/other_user}","gists_url":"https://api.github.com/users/alex/gists{/gist_id}","starred_url":"https://api.github.com/users/alex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alex/subscriptions","organizations_url":"https://api.github.com/users/alex/orgs","repos_url":"https://api.github.com/users/alex/repos","events_url":"https://api.github.com/users/alex/events{/privacy}","received_events_url":"https://api.github.com/users/alex/received_events","type":"User","site_admin":false},"open_issues":3,"closed_issues":3,"state":"open","created_at":"2016-11-22T01:09:13Z","updated_at":"2016-12-05T13:12:43Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/pyca/cryptography/pulls/3229/commits","review_comments_url":"https://api.github.com/repos/pyca/cryptography/pulls/3229/comments","review_comment_url":"https://api.github.com/repos/pyca/cryptography/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pyca/cryptography/issues/3229/comments","statuses_url":"https://api.github.com/repos/pyca/cryptography/statuses/c05ea01a8d45bb3ccafbcf9cdd79ef231e50587e","head":{"label":"tiran:new_osrandom_engine","ref":"new_osrandom_engine","sha":"c05ea01a8d45bb3ccafbcf9cdd79ef231e50587e","user":{"login":"tiran","id":444071,"avatar_url":"https://avatars.githubusercontent.com/u/444071?v=3","gravatar_id":"","url":"https://api.github.com/users/tiran","html_url":"https://github.com/tiran","followers_url":"https://api.github.com/users/tiran/followers","following_url":"https://api.github.com/users/tiran/following{/other_user}","gists_url":"https://api.github.com/users/tiran/gists{/gist_id}","starred_url":"https://api.github.com/users/tiran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tiran/subscriptions","organizations_url":"https://api.github.com/users/tiran/orgs","repos_url":"https://api.github.com/users/tiran/repos","events_url":"https://api.github.com/users/tiran/events{/privacy}","received_events_url":"https://api.github.com/users/tiran/received_events","type":"User","site_admin":false},"repo":{"id":12026946,"name":"cryptography","full_name":"tiran/cryptography","owner":{"login":"tiran","id":444071,"avatar_url":"https://avatars.githubusercontent.com/u/444071?v=3","gravatar_id":"","url":"https://api.github.com/users/tiran","html_url":"https://github.com/tiran","followers_url":"https://api.github.com/users/tiran/followers","following_url":"https://api.github.com/users/tiran/following{/other_user}","gists_url":"https://api.github.com/users/tiran/gists{/gist_id}","starred_url":"https://api.github.com/users/tiran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tiran/subscriptions","organizations_url":"https://api.github.com/users/tiran/orgs","repos_url":"https://api.github.com/users/tiran/repos","events_url":"https://api.github.com/users/tiran/events{/privacy}","received_events_url":"https://api.github.com/users/tiran/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tiran/cryptography","description":"cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.","fork":true,"url":"https://api.github.com/repos/tiran/cryptography","forks_url":"https://api.github.com/repos/tiran/cryptography/forks","keys_url":"https://api.github.com/repos/tiran/cryptography/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tiran/cryptography/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tiran/cryptography/teams","hooks_url":"https://api.github.com/repos/tiran/cryptography/hooks","issue_events_url":"https://api.github.com/repos/tiran/cryptography/issues/events{/number}","events_url":"https://api.github.com/repos/tiran/cryptography/events","assignees_url":"https://api.github.com/repos/tiran/cryptography/assignees{/user}","branches_url":"https://api.github.com/repos/tiran/cryptography/branches{/branch}","tags_url":"https://api.github.com/repos/tiran/cryptography/tags","blobs_url":"https://api.github.com/repos/tiran/cryptography/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tiran/cryptography/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tiran/cryptography/git/refs{/sha}","trees_url":"https://api.github.com/repos/tiran/cryptography/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tiran/cryptography/statuses/{sha}","languages_url":"https://api.github.com/repos/tiran/cryptography/languages","stargazers_url":"https://api.github.com/repos/tiran/cryptography/stargazers","contributors_url":"https://api.github.com/repos/tiran/cryptography/contributors","subscribers_url":"https://api.github.com/repos/tiran/cryptography/subscribers","subscription_url":"https://api.github.com/repos/tiran/cryptography/subscription","commits_url":"https://api.github.com/repos/tiran/cryptography/commits{/sha}","git_commits_url":"https://api.github.com/repos/tiran/cryptography/git/commits{/sha}","comments_url":"https://api.github.com/repos/tiran/cryptography/comments{/number}","issue_comment_url":"https://api.github.com/repos/tiran/cryptography/issues/comments{/number}","contents_url":"https://api.github.com/repos/tiran/cryptography/contents/{+path}","compare_url":"https://api.github.com/repos/tiran/cryptography/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tiran/cryptography/merges","archive_url":"https://api.github.com/repos/tiran/cryptography/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tiran/cryptography/downloads","issues_url":"https://api.github.com/repos/tiran/cryptography/issues{/number}","pulls_url":"https://api.github.com/repos/tiran/cryptography/pulls{/number}","milestones_url":"https://api.github.com/repos/tiran/cryptography/milestones{/number}","notifications_url":"https://api.github.com/repos/tiran/cryptography/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tiran/cryptography/labels{/name}","releases_url":"https://api.github.com/repos/tiran/cryptography/releases{/id}","deployments_url":"https://api.github.com/repos/tiran/cryptography/deployments","created_at":"2013-08-10T21:14:53Z","updated_at":"2015-05-10T12:09:12Z","pushed_at":"2016-11-30T14:23:09Z","git_url":"git://github.com/tiran/cryptography.git","ssh_url":"git@github.com:tiran/cryptography.git","clone_url":"https://github.com/tiran/cryptography.git","svn_url":"https://github.com/tiran/cryptography","homepage":"","size":34267,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"pyca:master","ref":"master","sha":"3a3cf1e4fdd163cc03c047f354ee51f016144eb0","user":{"login":"pyca","id":5615737,"avatar_url":"https://avatars.githubusercontent.com/u/5615737?v=3","gravatar_id":"","url":"https://api.github.com/users/pyca","html_url":"https://github.com/pyca","followers_url":"https://api.github.com/users/pyca/followers","following_url":"https://api.github.com/users/pyca/following{/other_user}","gists_url":"https://api.github.com/users/pyca/gists{/gist_id}","starred_url":"https://api.github.com/users/pyca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pyca/subscriptions","organizations_url":"https://api.github.com/users/pyca/orgs","repos_url":"https://api.github.com/users/pyca/repos","events_url":"https://api.github.com/users/pyca/events{/privacy}","received_events_url":"https://api.github.com/users/pyca/received_events","type":"Organization","site_admin":false},"repo":{"id":11939484,"name":"cryptography","full_name":"pyca/cryptography","owner":{"login":"pyca","id":5615737,"avatar_url":"https://avatars.githubusercontent.com/u/5615737?v=3","gravatar_id":"","url":"https://api.github.com/users/pyca","html_url":"https://github.com/pyca","followers_url":"https://api.github.com/users/pyca/followers","following_url":"https://api.github.com/users/pyca/following{/other_user}","gists_url":"https://api.github.com/users/pyca/gists{/gist_id}","starred_url":"https://api.github.com/users/pyca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pyca/subscriptions","organizations_url":"https://api.github.com/users/pyca/orgs","repos_url":"https://api.github.com/users/pyca/repos","events_url":"https://api.github.com/users/pyca/events{/privacy}","received_events_url":"https://api.github.com/users/pyca/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pyca/cryptography","description":"cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.","fork":false,"url":"https://api.github.com/repos/pyca/cryptography","forks_url":"https://api.github.com/repos/pyca/cryptography/forks","keys_url":"https://api.github.com/repos/pyca/cryptography/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pyca/cryptography/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pyca/cryptography/teams","hooks_url":"https://api.github.com/repos/pyca/cryptography/hooks","issue_events_url":"https://api.github.com/repos/pyca/cryptography/issues/events{/number}","events_url":"https://api.github.com/repos/pyca/cryptography/events","assignees_url":"https://api.github.com/repos/pyca/cryptography/assignees{/user}","branches_url":"https://api.github.com/repos/pyca/cryptography/branches{/branch}","tags_url":"https://api.github.com/repos/pyca/cryptography/tags","blobs_url":"https://api.github.com/repos/pyca/cryptography/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pyca/cryptography/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pyca/cryptography/git/refs{/sha}","trees_url":"https://api.github.com/repos/pyca/cryptography/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pyca/cryptography/statuses/{sha}","languages_url":"https://api.github.com/repos/pyca/cryptography/languages","stargazers_url":"https://api.github.com/repos/pyca/cryptography/stargazers","contributors_url":"https://api.github.com/repos/pyca/cryptography/contributors","subscribers_url":"https://api.github.com/repos/pyca/cryptography/subscribers","subscription_url":"https://api.github.com/repos/pyca/cryptography/subscription","commits_url":"https://api.github.com/repos/pyca/cryptography/commits{/sha}","git_commits_url":"https://api.github.com/repos/pyca/cryptography/git/commits{/sha}","comments_url":"https://api.github.com/repos/pyca/cryptography/comments{/number}","issue_comment_url":"https://api.github.com/repos/pyca/cryptography/issues/comments{/number}","contents_url":"https://api.github.com/repos/pyca/cryptography/contents/{+path}","compare_url":"https://api.github.com/repos/pyca/cryptography/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pyca/cryptography/merges","archive_url":"https://api.github.com/repos/pyca/cryptography/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pyca/cryptography/downloads","issues_url":"https://api.github.com/repos/pyca/cryptography/issues{/number}","pulls_url":"https://api.github.com/repos/pyca/cryptography/pulls{/number}","milestones_url":"https://api.github.com/repos/pyca/cryptography/milestones{/number}","notifications_url":"https://api.github.com/repos/pyca/cryptography/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pyca/cryptography/labels{/name}","releases_url":"https://api.github.com/repos/pyca/cryptography/releases{/id}","deployments_url":"https://api.github.com/repos/pyca/cryptography/deployments","created_at":"2013-08-07T02:23:38Z","updated_at":"2016-12-06T01:46:45Z","pushed_at":"2016-12-05T13:12:43Z","git_url":"git://github.com/pyca/cryptography.git","ssh_url":"git@github.com:pyca/cryptography.git","clone_url":"https://github.com/pyca/cryptography.git","svn_url":"https://github.com/pyca/cryptography","homepage":"https://cryptography.io/","size":40279,"stargazers_count":1256,"watchers_count":1256,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":323,"mirror_url":null,"open_issues_count":70,"forks":323,"open_issues":70,"watchers":1256,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pyca/cryptography/pulls/3229"},"html":{"href":"https://github.com/pyca/cryptography/pull/3229"},"issue":{"href":"https://api.github.com/repos/pyca/cryptography/issues/3229"},"comments":{"href":"https://api.github.com/repos/pyca/cryptography/issues/3229/comments"},"review_comments":{"href":"https://api.github.com/repos/pyca/cryptography/pulls/3229/comments"},"review_comment":{"href":"https://api.github.com/repos/pyca/cryptography/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pyca/cryptography/pulls/3229/commits"},"statuses":{"href":"https://api.github.com/repos/pyca/cryptography/statuses/c05ea01a8d45bb3ccafbcf9cdd79ef231e50587e"}}}}
{"actor":{"display_login":"alex"}}