mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 15:20:54 +03:00
Reading first part of the new openssh key format
This commit is contained in:
@@ -33,6 +33,7 @@ import net.schmizz.sshj.transport.random.BouncyCastleRandom;
|
||||
import net.schmizz.sshj.transport.random.JCERandom;
|
||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
|
||||
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
|
||||
import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile;
|
||||
import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
|
||||
import org.slf4j.Logger;
|
||||
@@ -113,7 +114,7 @@ public class DefaultConfig
|
||||
|
||||
protected void initFileKeyProviderFactories(boolean bouncyCastleRegistered) {
|
||||
if (bouncyCastleRegistered) {
|
||||
setFileKeyProviderFactories(new PKCS8KeyFile.Factory(), new OpenSSHKeyFile.Factory(), new PuTTYKeyFile.Factory());
|
||||
setFileKeyProviderFactories(new OpenSSHKeyV1KeyFile.Factory(), new PKCS8KeyFile.Factory(), new OpenSSHKeyFile.Factory(), new PuTTYKeyFile.Factory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package net.schmizz.sshj.userauth.keyprovider;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyPair;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.schmizz.sshj.common.Base64;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.ByteArrayUtils;
|
||||
import net.schmizz.sshj.common.IOUtils;
|
||||
|
||||
public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OpenSSHKeyV1KeyFile.class);
|
||||
private static final String BEGIN = "-----BEGIN ";
|
||||
private static final String END = "-----END ";
|
||||
private static final byte[] AUTH_MAGIC = "openssh-key-v1\0".getBytes();
|
||||
|
||||
public static class Factory
|
||||
implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
|
||||
|
||||
@Override
|
||||
public FileKeyProvider create() {
|
||||
return new OpenSSHKeyV1KeyFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "openssh-key-v1";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeyPair readKeyPair() throws IOException {
|
||||
BufferedReader reader = new BufferedReader(resource.getReader());
|
||||
try {
|
||||
String line = reader.readLine();
|
||||
while (line != null && !line.startsWith(BEGIN)) {
|
||||
line = reader.readLine();
|
||||
}
|
||||
line = line.substring(BEGIN.length());
|
||||
if (!line.startsWith("OPENSSH PRIVATE KEY-----")) {
|
||||
throw new IOException("This key is not in 'openssh-key-v1' format");
|
||||
}
|
||||
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
line = reader.readLine();
|
||||
while (!line.startsWith(END)) {
|
||||
stringBuffer.append(line);
|
||||
line = reader.readLine();
|
||||
}
|
||||
byte[] decode = Base64.decode(stringBuffer.toString());
|
||||
System.out.println(ByteArrayUtils.printHex(decode, 0, decode.length));
|
||||
Buffer.PlainBuffer keyBuffer = new Buffer.PlainBuffer(decode);
|
||||
byte[] bytes = new byte[AUTH_MAGIC.length];
|
||||
keyBuffer.readRawBytes(bytes);
|
||||
if (!ByteArrayUtils.equals(bytes, 0, AUTH_MAGIC, 0, AUTH_MAGIC.length)) {
|
||||
throw new IOException("This key does not contain the 'openssh-key-v1' format header");
|
||||
}
|
||||
|
||||
String cipherName = keyBuffer.readString();
|
||||
String kdfName = keyBuffer.readString();
|
||||
String kdfOptions = keyBuffer.readString();
|
||||
|
||||
if ("none".equals(cipherName)) {
|
||||
return readUnencrypted(keyBuffer);
|
||||
} else {
|
||||
logger.debug("Reading encrypted openssh-key-v1 file with cipher: " + cipherName);
|
||||
|
||||
System.out.println(cipherName + " " + kdfName + " " + kdfOptions);
|
||||
}
|
||||
|
||||
} finally {
|
||||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private KeyPair readUnencrypted(final Buffer.PlainBuffer keyBuffer) throws IOException {
|
||||
int i = keyBuffer.readUInt32AsInt();
|
||||
if (i != 1) {
|
||||
throw new IOException("We don't support having more than 1 key in the file (yet).");
|
||||
}
|
||||
logger.info("reading {} keys", i);
|
||||
byte[] pubKey = keyBuffer.readBytes();
|
||||
logger.info("read key: {}", ByteArrayUtils.printHex(pubKey, 0, pubKey.length));
|
||||
int privKeyListSize = keyBuffer.readUInt32AsInt();
|
||||
if (privKeyListSize % 8 != 0) {
|
||||
throw new IOException("The private key section must be a multiple of the block size (8)");
|
||||
}
|
||||
int checkInt1 = keyBuffer.readUInt32AsInt();
|
||||
int checkInt2 = keyBuffer.readUInt32AsInt();
|
||||
logger.info("Read checkInts: {}, {}", checkInt1, checkInt2);
|
||||
byte[] privKey = keyBuffer.readBytes();
|
||||
logger.info("read key: {}", ByteArrayUtils.printHex(privKey, 0, privKey.length));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package net.schmizz.sshj.keyprovider;
|
||||
import net.schmizz.sshj.common.KeyType;
|
||||
import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
|
||||
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
|
||||
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyV1KeyFile;
|
||||
import net.schmizz.sshj.userauth.password.PasswordFinder;
|
||||
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
||||
import net.schmizz.sshj.userauth.password.Resource;
|
||||
@@ -30,11 +31,13 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Arrays;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -142,7 +145,7 @@ public class OpenSSHKeyFileTest {
|
||||
|
||||
@Test
|
||||
public void shouldHaveCorrectFingerprintForED25519() throws IOException {
|
||||
OpenSSHKeyFile keyFile = new OpenSSHKeyFile();
|
||||
OpenSSHKeyV1KeyFile keyFile = new OpenSSHKeyV1KeyFile();
|
||||
keyFile.init(new File("src/test/resources/keytypes/test_ed25519"));
|
||||
String expected = "256 MD5:d3:5e:40:72:db:08:f1:6d:0c:d7:6d:35:0d:ba:7c:32 root@sshj (ED25519)\n";
|
||||
PublicKey aPublic = keyFile.getPublic();
|
||||
@@ -150,6 +153,15 @@ public class OpenSSHKeyFileTest {
|
||||
assertThat(expected, containsString(sshjFingerprintSshjKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldLoadED25519PrivateKey() throws IOException {
|
||||
OpenSSHKeyV1KeyFile keyFile = new OpenSSHKeyV1KeyFile();
|
||||
keyFile.init(new File("src/test/resources/keytypes/test_ed25519"));
|
||||
String expected = "256 MD5:d3:5e:40:72:db:08:f1:6d:0c:d7:6d:35:0d:ba:7c:32 root@sshj (ED25519)\n";
|
||||
PrivateKey aPrivate = keyFile.getPrivate();
|
||||
assertThat(aPrivate.getAlgorithm(), equalTo("ed-25519"));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
@@ -171,4 +183,4 @@ public class OpenSSHKeyFileTest {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user