{"action":"created","comment":{"url":"https://api.github.com/repos/hierynomus/sshj/pulls/comments/85533351","pull_request_review_id":6245370,"id":85533351,"diff_hunk":"@@ -0,0 +1,160 @@\n+/*\n+ * Copyright (C)2009 - SSHJ Contributors\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package com.hierynomus.sshj.userauth.keyprovider;\n+\n+import java.io.BufferedReader;\n+import java.io.IOException;\n+import java.security.GeneralSecurityException;\n+import java.security.KeyPair;\n+import java.security.PublicKey;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+import net.i2p.crypto.eddsa.EdDSAPrivateKey;\n+import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;\n+import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;\n+import net.schmizz.sshj.common.*;\n+import net.schmizz.sshj.common.Buffer.PlainBuffer;\n+import net.schmizz.sshj.userauth.keyprovider.BaseFileKeyProvider;\n+import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;\n+import net.schmizz.sshj.userauth.keyprovider.KeyFormat;\n+\n+import static net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable.CURVE_ED25519_SHA512;\n+\n+/**\n+ * Reads a key file in the new OpenSSH format.\n+ * The format is described in the following document: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key\n+ */\n+public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {\n+    private static final Logger logger = LoggerFactory.getLogger(OpenSSHKeyV1KeyFile.class);\n+    private static final String BEGIN = \"-----BEGIN \";\n+    private static final String END = \"-----END \";\n+    private static final byte[] AUTH_MAGIC = \"openssh-key-v1\\0\".getBytes();\n+    public static final String OPENSSH_PRIVATE_KEY = \"OPENSSH PRIVATE KEY-----\";\n+\n+    public static class Factory\n+            implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {\n+\n+        @Override\n+        public FileKeyProvider create() {\n+            return new OpenSSHKeyV1KeyFile();\n+        }\n+\n+        @Override\n+        public String getName() {\n+            return KeyFormat.OpenSSHv1.name();\n+        }\n+    }\n+\n+    @Override\n+    protected KeyPair readKeyPair() throws IOException {\n+        BufferedReader reader = new BufferedReader(resource.getReader());\n+        try {\n+            if (!checkHeader(reader)) {\n+                throw new IOException(\"This key is not in 'openssh-key-v1' format\");\n+            }\n+\n+            String keyFile = readKeyFile(reader);\n+            byte[] decode = Base64.decode(keyFile);\n+            PlainBuffer keyBuffer = new PlainBuffer(decode);\n+            return readDecodedKeyPair(keyBuffer);\n+\n+        } catch (GeneralSecurityException e) {\n+            throw new SSHRuntimeException(e);\n+        } finally {\n+            IOUtils.closeQuietly(reader);\n+        }\n+    }\n+\n+    private KeyPair readDecodedKeyPair(final PlainBuffer keyBuffer) throws IOException, GeneralSecurityException {\n+        byte[] bytes = new byte[AUTH_MAGIC.length];\n+        keyBuffer.readRawBytes(bytes); // byte[] AUTH_MAGIC\n+        if (!ByteArrayUtils.equals(bytes, 0, AUTH_MAGIC, 0, AUTH_MAGIC.length)) {\n+            throw new IOException(\"This key does not contain the 'openssh-key-v1' format magic header\");\n+        }\n+\n+        String cipherName = keyBuffer.readString(); // string ciphername\n+        String kdfName = keyBuffer.readString(); // string kdfname\n+        String kdfOptions = keyBuffer.readString(); // string kdfoptions\n+\n+        int nrKeys = keyBuffer.readUInt32AsInt(); // int number of keys N; Should be 1\n+        if (nrKeys != 1) {\n+            throw new IOException(\"We don't support having more than 1 key in the file (yet).\");\n+        }\n+        PublicKey publicKey = readPublicKey(new PlainBuffer(keyBuffer.readBytes())); // string publickey1\n+        PlainBuffer privateKeyBuffer = new PlainBuffer(keyBuffer.readBytes()); // string (possibly) encrypted, padded list of private keys\n+        if (\"none\".equals(cipherName)) {\n+            logger.debug(\"Reading unencrypted keypair\");\n+            return readUnencrypted(privateKeyBuffer, publicKey);\n+        } else {\n+            logger.info(\"Keypair is encrypted with: \" + cipherName + \", \" + kdfName + \", \" + kdfOptions);\n+            throw new IOException(\"Cannot read encrypted keypair with \" + cipherName + \" yet..\");","path":"src/main/java/com/hierynomus/sshj/userauth/keyprovider/OpenSSHKeyV1KeyFile.java","position":104,"original_position":104,"commit_id":"179b30ef4eee4144b25d3facf314ba233410f337","original_commit_id":"179b30ef4eee4144b25d3facf314ba233410f337","user":{"login":"hierynomus","id":117667,"avatar_url":"https://avatars.githubusercontent.com/u/117667?v=3","gravatar_id":"","url":"https://api.github.com/users/hierynomus","html_url":"https://github.com/hierynomus","followers_url":"https://api.github.com/users/hierynomus/followers","following_url":"https://api.github.com/users/hierynomus/following{/other_user}","gists_url":"https://api.github.com/users/hierynomus/gists{/gist_id}","starred_url":"https://api.github.com/users/hierynomus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hierynomus/subscriptions","organizations_url":"https://api.github.com/users/hierynomus/orgs","repos_url":"https://api.github.com/users/hierynomus/repos","events_url":"https://api.github.com/users/hierynomus/events{/privacy}","received_events_url":"https://api.github.com/users/hierynomus/received_events","type":"User","site_admin":false},"body":"I have to figure out how the 'altered' bcrypt implementation works... i.e. seems non-trivial at the moment.","created_at":"2016-10-28T13:50:25Z","updated_at":"2016-10-28T13:50:25Z","html_url":"https://github.com/hierynomus/sshj/pull/279#discussion_r85533351","pull_request_url":"https://api.github.com/repos/hierynomus/sshj/pulls/279","_links":{"self":{"href":"https://api.github.com/repos/hierynomus/sshj/pulls/comments/85533351"},"html":{"href":"https://github.com/hierynomus/sshj/pull/279#discussion_r85533351"},"pull_request":{"href":"https://api.github.com/repos/hierynomus/sshj/pulls/279"}}},"pull_request":{"url":"https://api.github.com/repos/hierynomus/sshj/pulls/279","id":91375424,"html_url":"https://github.com/hierynomus/sshj/pull/279","diff_url":"https://github.com/hierynomus/sshj/pull/279.diff","patch_url":"https://github.com/hierynomus/sshj/pull/279.patch","issue_url":"https://api.github.com/repos/hierynomus/sshj/issues/279","number":279,"state":"open","locked":false,"title":"Support for OpenSSH new key file format ","user":{"login":"hierynomus","id":117667,"avatar_url":"https://avatars.githubusercontent.com/u/117667?v=3","gravatar_id":"","url":"https://api.github.com/users/hierynomus","html_url":"https://github.com/hierynomus","followers_url":"https://api.github.com/users/hierynomus/followers","following_url":"https://api.github.com/users/hierynomus/following{/other_user}","gists_url":"https://api.github.com/users/hierynomus/gists{/gist_id}","starred_url":"https://api.github.com/users/hierynomus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hierynomus/subscriptions","organizations_url":"https://api.github.com/users/hierynomus/orgs","repos_url":"https://api.github.com/users/hierynomus/repos","events_url":"https://api.github.com/users/hierynomus/events{/privacy}","received_events_url":"https://api.github.com/users/hierynomus/received_events","type":"User","site_admin":false},"body":"The new format is used for ed-25519 keys.\r\n\r\nOnly support for non-encrypted keys currently.","created_at":"2016-10-28T12:46:43Z","updated_at":"2016-10-28T13:50:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1fe2e58dfd85829d959d3a0fdfeb3e5e2a1e030a","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/hierynomus/sshj/pulls/279/commits","review_comments_url":"https://api.github.com/repos/hierynomus/sshj/pulls/279/comments","review_comment_url":"https://api.github.com/repos/hierynomus/sshj/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hierynomus/sshj/issues/279/comments","statuses_url":"https://api.github.com/repos/hierynomus/sshj/statuses/179b30ef4eee4144b25d3facf314ba233410f337","head":{"label":"hierynomus:issue-276","ref":"issue-276","sha":"179b30ef4eee4144b25d3facf314ba233410f337","user":{"login":"hierynomus","id":117667,"avatar_url":"https://avatars.githubusercontent.com/u/117667?v=3","gravatar_id":"","url":"https://api.github.com/users/hierynomus","html_url":"https://github.com/hierynomus","followers_url":"https://api.github.com/users/hierynomus/followers","following_url":"https://api.github.com/users/hierynomus/following{/other_user}","gists_url":"https://api.github.com/users/hierynomus/gists{/gist_id}","starred_url":"https://api.github.com/users/hierynomus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hierynomus/subscriptions","organizations_url":"https://api.github.com/users/hierynomus/orgs","repos_url":"https://api.github.com/users/hierynomus/repos","events_url":"https://api.github.com/users/hierynomus/events{/privacy}","received_events_url":"https://api.github.com/users/hierynomus/received_events","type":"User","site_admin":false},"repo":{"id":538681,"name":"sshj","full_name":"hierynomus/sshj","owner":{"login":"hierynomus","id":117667,"avatar_url":"https://avatars.githubusercontent.com/u/117667?v=3","gravatar_id":"","url":"https://api.github.com/users/hierynomus","html_url":"https://github.com/hierynomus","followers_url":"https://api.github.com/users/hierynomus/followers","following_url":"https://api.github.com/users/hierynomus/following{/other_user}","gists_url":"https://api.github.com/users/hierynomus/gists{/gist_id}","starred_url":"https://api.github.com/users/hierynomus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hierynomus/subscriptions","organizations_url":"https://api.github.com/users/hierynomus/orgs","repos_url":"https://api.github.com/users/hierynomus/repos","events_url":"https://api.github.com/users/hierynomus/events{/privacy}","received_events_url":"https://api.github.com/users/hierynomus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/hierynomus/sshj","description":"ssh, scp and sftp for java","fork":false,"url":"https://api.github.com/repos/hierynomus/sshj","forks_url":"https://api.github.com/repos/hierynomus/sshj/forks","keys_url":"https://api.github.com/repos/hierynomus/sshj/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hierynomus/sshj/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hierynomus/sshj/teams","hooks_url":"https://api.github.com/repos/hierynomus/sshj/hooks","issue_events_url":"https://api.github.com/repos/hierynomus/sshj/issues/events{/number}","events_url":"https://api.github.com/repos/hierynomus/sshj/events","assignees_url":"https://api.github.com/repos/hierynomus/sshj/assignees{/user}","branches_url":"https://api.github.com/repos/hierynomus/sshj/branches{/branch}","tags_url":"https://api.github.com/repos/hierynomus/sshj/tags","blobs_url":"https://api.github.com/repos/hierynomus/sshj/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hierynomus/sshj/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hierynomus/sshj/git/refs{/sha}","trees_url":"https://api.github.com/repos/hierynomus/sshj/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hierynomus/sshj/statuses/{sha}","languages_url":"https://api.github.com/repos/hierynomus/sshj/languages","stargazers_url":"https://api.github.com/repos/hierynomus/sshj/stargazers","contributors_url":"https://api.github.com/repos/hierynomus/sshj/contributors","subscribers_url":"https://api.github.com/repos/hierynomus/sshj/subscribers","subscription_url":"https://api.github.com/repos/hierynomus/sshj/subscription","commits_url":"https://api.github.com/repos/hierynomus/sshj/commits{/sha}","git_commits_url":"https://api.github.com/repos/hierynomus/sshj/git/commits{/sha}","comments_url":"https://api.github.com/repos/hierynomus/sshj/comments{/number}","issue_comment_url":"https://api.github.com/repos/hierynomus/sshj/issues/comments{/number}","contents_url":"https://api.github.com/repos/hierynomus/sshj/contents/{+path}","compare_url":"https://api.github.com/repos/hierynomus/sshj/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hierynomus/sshj/merges","archive_url":"https://api.github.com/repos/hierynomus/sshj/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hierynomus/sshj/downloads","issues_url":"https://api.github.com/repos/hierynomus/sshj/issues{/number}","pulls_url":"https://api.github.com/repos/hierynomus/sshj/pulls{/number}","milestones_url":"https://api.github.com/repos/hierynomus/sshj/milestones{/number}","notifications_url":"https://api.github.com/repos/hierynomus/sshj/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hierynomus/sshj/labels{/name}","releases_url":"https://api.github.com/repos/hierynomus/sshj/releases{/id}","deployments_url":"https://api.github.com/repos/hierynomus/sshj/deployments","created_at":"2010-02-27T14:34:40Z","updated_at":"2016-10-27T17:28:03Z","pushed_at":"2016-10-28T12:50:42Z","git_url":"git://github.com/hierynomus/sshj.git","ssh_url":"git@github.com:hierynomus/sshj.git","clone_url":"https://github.com/hierynomus/sshj.git","svn_url":"https://github.com/hierynomus/sshj","homepage":"","size":7746,"stargazers_count":742,"watchers_count":742,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":214,"mirror_url":null,"open_issues_count":42,"forks":214,"open_issues":42,"watchers":742,"default_branch":"master"}},"base":{"label":"hierynomus:master","ref":"master","sha":"63927a3e2bce9e97f538e6be284ac2f94d720c65","user":{"login":"hierynomus","id":117667,"avatar_url":"https://avatars.githubusercontent.com/u/117667?v=3","gravatar_id":"","url":"https://api.github.com/users/hierynomus","html_url":"https://github.com/hierynomus","followers_url":"https://api.github.com/users/hierynomus/followers","following_url":"https://api.github.com/users/hierynomus/following{/other_user}","gists_url":"https://api.github.com/users/hierynomus/gists{/gist_id}","starred_url":"https://api.github.com/users/hierynomus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hierynomus/subscriptions","organizations_url":"https://api.github.com/users/hierynomus/orgs","repos_url":"https://api.github.com/users/hierynomus/repos","events_url":"https://api.github.com/users/hierynomus/events{/privacy}","received_events_url":"https://api.github.com/users/hierynomus/received_events","type":"User","site_admin":false},"repo":{"id":538681,"name":"sshj","full_name":"hierynomus/sshj","owner":{"login":"hierynomus","id":117667,"avatar_url":"https://avatars.githubusercontent.com/u/117667?v=3","gravatar_id":"","url":"https://api.github.com/users/hierynomus","html_url":"https://github.com/hierynomus","followers_url":"https://api.github.com/users/hierynomus/followers","following_url":"https://api.github.com/users/hierynomus/following{/other_user}","gists_url":"https://api.github.com/users/hierynomus/gists{/gist_id}","starred_url":"https://api.github.com/users/hierynomus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hierynomus/subscriptions","organizations_url":"https://api.github.com/users/hierynomus/orgs","repos_url":"https://api.github.com/users/hierynomus/repos","events_url":"https://api.github.com/users/hierynomus/events{/privacy}","received_events_url":"https://api.github.com/users/hierynomus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/hierynomus/sshj","description":"ssh, scp and sftp for java","fork":false,"url":"https://api.github.com/repos/hierynomus/sshj","forks_url":"https://api.github.com/repos/hierynomus/sshj/forks","keys_url":"https://api.github.com/repos/hierynomus/sshj/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hierynomus/sshj/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hierynomus/sshj/teams","hooks_url":"https://api.github.com/repos/hierynomus/sshj/hooks","issue_events_url":"https://api.github.com/repos/hierynomus/sshj/issues/events{/number}","events_url":"https://api.github.com/repos/hierynomus/sshj/events","assignees_url":"https://api.github.com/repos/hierynomus/sshj/assignees{/user}","branches_url":"https://api.github.com/repos/hierynomus/sshj/branches{/branch}","tags_url":"https://api.github.com/repos/hierynomus/sshj/tags","blobs_url":"https://api.github.com/repos/hierynomus/sshj/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hierynomus/sshj/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hierynomus/sshj/git/refs{/sha}","trees_url":"https://api.github.com/repos/hierynomus/sshj/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hierynomus/sshj/statuses/{sha}","languages_url":"https://api.github.com/repos/hierynomus/sshj/languages","stargazers_url":"https://api.github.com/repos/hierynomus/sshj/stargazers","contributors_url":"https://api.github.com/repos/hierynomus/sshj/contributors","subscribers_url":"https://api.github.com/repos/hierynomus/sshj/subscribers","subscription_url":"https://api.github.com/repos/hierynomus/sshj/subscription","commits_url":"https://api.github.com/repos/hierynomus/sshj/commits{/sha}","git_commits_url":"https://api.github.com/repos/hierynomus/sshj/git/commits{/sha}","comments_url":"https://api.github.com/repos/hierynomus/sshj/comments{/number}","issue_comment_url":"https://api.github.com/repos/hierynomus/sshj/issues/comments{/number}","contents_url":"https://api.github.com/repos/hierynomus/sshj/contents/{+path}","compare_url":"https://api.github.com/repos/hierynomus/sshj/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hierynomus/sshj/merges","archive_url":"https://api.github.com/repos/hierynomus/sshj/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hierynomus/sshj/downloads","issues_url":"https://api.github.com/repos/hierynomus/sshj/issues{/number}","pulls_url":"https://api.github.com/repos/hierynomus/sshj/pulls{/number}","milestones_url":"https://api.github.com/repos/hierynomus/sshj/milestones{/number}","notifications_url":"https://api.github.com/repos/hierynomus/sshj/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hierynomus/sshj/labels{/name}","releases_url":"https://api.github.com/repos/hierynomus/sshj/releases{/id}","deployments_url":"https://api.github.com/repos/hierynomus/sshj/deployments","created_at":"2010-02-27T14:34:40Z","updated_at":"2016-10-27T17:28:03Z","pushed_at":"2016-10-28T12:50:42Z","git_url":"git://github.com/hierynomus/sshj.git","ssh_url":"git@github.com:hierynomus/sshj.git","clone_url":"https://github.com/hierynomus/sshj.git","svn_url":"https://github.com/hierynomus/sshj","homepage":"","size":7746,"stargazers_count":742,"watchers_count":742,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":214,"mirror_url":null,"open_issues_count":42,"forks":214,"open_issues":42,"watchers":742,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hierynomus/sshj/pulls/279"},"html":{"href":"https://github.com/hierynomus/sshj/pull/279"},"issue":{"href":"https://api.github.com/repos/hierynomus/sshj/issues/279"},"comments":{"href":"https://api.github.com/repos/hierynomus/sshj/issues/279/comments"},"review_comments":{"href":"https://api.github.com/repos/hierynomus/sshj/pulls/279/comments"},"review_comment":{"href":"https://api.github.com/repos/hierynomus/sshj/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hierynomus/sshj/pulls/279/commits"},"statuses":{"href":"https://api.github.com/repos/hierynomus/sshj/statuses/179b30ef4eee4144b25d3facf314ba233410f337"}}}}
{"actor":{"display_login":"hierynomus"}}