Skip blank lines when detecting key formats

Some private keys found in the wild start with a blank line, which
breaks SSHJ. OpenSSH utilities worked as expected with these key files.

Also add some basic tests for key formats.
This commit is contained in:
Billy Keyes
2015-08-17 15:05:02 -07:00
committed by Jeroen van Erp
parent 1c749da957
commit c98ad22a7a
7 changed files with 140 additions and 24 deletions

View File

@@ -51,8 +51,7 @@ public class KeyProviderUtil {
* @return name of the key file format
* @throws java.io.IOException
*/
public static KeyFormat detectKeyFileFormat(String privateKey,
boolean separatePubKey)
public static KeyFormat detectKeyFileFormat(String privateKey, boolean separatePubKey)
throws IOException {
return detectKeyFileFormat(new StringReader(privateKey), separatePubKey);
}
@@ -67,35 +66,44 @@ public class KeyProviderUtil {
* @return name of the key file format
* @throws java.io.IOException
*/
public static KeyFormat detectKeyFileFormat(Reader privateKey,
boolean separatePubKey)
public static KeyFormat detectKeyFileFormat(Reader privateKey, boolean separatePubKey)
throws IOException {
BufferedReader br = new BufferedReader(privateKey);
final String firstLine;
try {
firstLine = br.readLine();
}
finally {
IOUtils.closeQuietly(br);
}
if(firstLine == null) {
String header = readHeader(privateKey);
if (header == null) {
throw new IOException("Empty file");
}
if(firstLine.startsWith("-----BEGIN") && firstLine.endsWith("PRIVATE KEY-----")) {
if(separatePubKey)
// Can delay asking for password since have unencrypted pubkey
{
return KeyFormat.OpenSSH;
return keyFormatFromHeader(header, separatePubKey);
}
private static String readHeader(Reader privateKey) throws IOException {
BufferedReader br = new BufferedReader(privateKey);
try {
String header;
while ((header = br.readLine()) != null) {
header = header.trim();
if (!header.isEmpty()) {
break;
}
}
else
// More general
{
return header;
} finally {
IOUtils.closeQuietly(br);
}
}
private static KeyFormat keyFormatFromHeader(String header, boolean separatePubKey) {
if (header.startsWith("-----BEGIN") && header.endsWith("PRIVATE KEY-----")) {
if (separatePubKey) {
// Can delay asking for password since have unencrypted pubkey
return KeyFormat.OpenSSH;
} else {
// More general
return KeyFormat.PKCS8;
}
}
if(firstLine.startsWith("PuTTY-User-Key-File-")) {
} else if (header.startsWith("PuTTY-User-Key-File-")) {
return KeyFormat.PuTTY;
} else {
return KeyFormat.Unknown;
}
return KeyFormat.Unknown;
}
}

View File

@@ -0,0 +1,40 @@
package net.schmizz.sshj.keyprovider;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
import net.schmizz.sshj.userauth.keyprovider.KeyFormat;
import net.schmizz.sshj.userauth.keyprovider.KeyProviderUtil;
public class KeyProviderUtilTest {
private static final File ROOT = new File("src/test/resources/keyformats");
@Test
public void testOpenSsh() throws IOException {
KeyFormat format = KeyProviderUtil.detectKeyFileFormat(new File(ROOT, "openssh"));
assertEquals(KeyFormat.OpenSSH, format);
}
@Test
public void testPkcs8() throws IOException {
KeyFormat format = KeyProviderUtil.detectKeyFileFormat(new File(ROOT, "pkcs8"));
assertEquals(KeyFormat.PKCS8, format);
}
@Test
public void testPutty() throws IOException {
KeyFormat format = KeyProviderUtil.detectKeyFileFormat(new File(ROOT, "putty"));
assertEquals(KeyFormat.PuTTY, format);
}
@Test
public void testSkipsBlankLines() throws IOException {
KeyFormat format = KeyProviderUtil.detectKeyFileFormat(new File(ROOT, "pkcs8-blanks"));
assertEquals(KeyFormat.PKCS8, format);
}
}

View File

@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qt
TcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQK
oL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cwIDAQAB
AoGAHQ7cOyuLSnT3RISRX8eyLkBxLffUX8HRcQzbI+2PGTSnpuQHk6NWn/Xv87pr
+LKABBr3zjOFgrX81p2QwEz3jDxNXzbOeZzhuvGXCX5GocuEO4n5EhDvXRDF4uht
uvVV5FsQv/sTOR0PNo1nELiAA8k3NYDxraB83q7wtsmErtECQQDYWMnq8mwRe49d
jIXNKJeNiuLUYxO3CLI/vx279gDKlKrt677trr1e7JZqm/DapEWG511tw3cW63gQ
+qxtgkw1AkEAxW0UeaNaJd7DApqwGAcS1JkygCKwzQ4ns/Co15qUgMkqCkmQU9AU
/zQpt2+BjdYVe50r/nr8K1KYwrBsyndrBwJBALe90N+FvFqswfoFmq2/R9eimTsg
WmIdNKYHPs2gBNQIp5MhoSpkOdkgvi8U+d33nkUQwryyQbZpjbN98mufOfECQEML
eBiW0NZrf+4yefqu7EYmgG/jWAdK91C0OaJ+bFAQAKbdtJXB5F+GZ2RUCbsRKNqB
1Z7mRRyxQA9dupRHWaECQQCM9bbCtfGesgvZlhBavlWavu8iCvJlAbGdf5QMlFQE
kABmZg84Fy3NUFCD+RXCuatb4Oo9P/WPIbjYiC4p0hLJ
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qtTcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQKoL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cw==

View File

@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qt
TcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQK
oL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cwIDAQAB
AoGAHQ7cOyuLSnT3RISRX8eyLkBxLffUX8HRcQzbI+2PGTSnpuQHk6NWn/Xv87pr
+LKABBr3zjOFgrX81p2QwEz3jDxNXzbOeZzhuvGXCX5GocuEO4n5EhDvXRDF4uht
uvVV5FsQv/sTOR0PNo1nELiAA8k3NYDxraB83q7wtsmErtECQQDYWMnq8mwRe49d
jIXNKJeNiuLUYxO3CLI/vx279gDKlKrt677trr1e7JZqm/DapEWG511tw3cW63gQ
+qxtgkw1AkEAxW0UeaNaJd7DApqwGAcS1JkygCKwzQ4ns/Co15qUgMkqCkmQU9AU
/zQpt2+BjdYVe50r/nr8K1KYwrBsyndrBwJBALe90N+FvFqswfoFmq2/R9eimTsg
WmIdNKYHPs2gBNQIp5MhoSpkOdkgvi8U+d33nkUQwryyQbZpjbN98mufOfECQEML
eBiW0NZrf+4yefqu7EYmgG/jWAdK91C0OaJ+bFAQAKbdtJXB5F+GZ2RUCbsRKNqB
1Z7mRRyxQA9dupRHWaECQQCM9bbCtfGesgvZlhBavlWavu8iCvJlAbGdf5QMlFQE
kABmZg84Fy3NUFCD+RXCuatb4Oo9P/WPIbjYiC4p0hLJ
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,18 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCm2IJ9gWDkPTlQ37NNUB0za5mCsQ8bi++8fyEqw7wl8ZNBh3qt
TcnL+m+NZfQjUC0BXic7PcMLVm4A3ID2IAZQM+axfq9aL4huWerm4ua6tvdt4gQK
oL1+8JFmdFvFw5pWW/NZHtkIprbVf7KtYrU27WmMhXruN071UzqLsw08cwIDAQAB
AoGAHQ7cOyuLSnT3RISRX8eyLkBxLffUX8HRcQzbI+2PGTSnpuQHk6NWn/Xv87pr
+LKABBr3zjOFgrX81p2QwEz3jDxNXzbOeZzhuvGXCX5GocuEO4n5EhDvXRDF4uht
uvVV5FsQv/sTOR0PNo1nELiAA8k3NYDxraB83q7wtsmErtECQQDYWMnq8mwRe49d
jIXNKJeNiuLUYxO3CLI/vx279gDKlKrt677trr1e7JZqm/DapEWG511tw3cW63gQ
+qxtgkw1AkEAxW0UeaNaJd7DApqwGAcS1JkygCKwzQ4ns/Co15qUgMkqCkmQU9AU
/zQpt2+BjdYVe50r/nr8K1KYwrBsyndrBwJBALe90N+FvFqswfoFmq2/R9eimTsg
WmIdNKYHPs2gBNQIp5MhoSpkOdkgvi8U+d33nkUQwryyQbZpjbN98mufOfECQEML
eBiW0NZrf+4yefqu7EYmgG/jWAdK91C0OaJ+bFAQAKbdtJXB5F+GZ2RUCbsRKNqB
1Z7mRRyxQA9dupRHWaECQQCM9bbCtfGesgvZlhBavlWavu8iCvJlAbGdf5QMlFQE
kABmZg84Fy3NUFCD+RXCuatb4Oo9P/WPIbjYiC4p0hLJ
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,19 @@
PuTTY-User-Key-File-2: ssh-rsa
Encryption: none
Comment: rsa-key-20150817
Public-Lines: 4
AAAAB3NzaC1yc2EAAAABJQAAAIEAhoCAakZdrCNrHNpJHRIED4movsposAlk4ZPz
n/IFGkiIZOWRF/p4Sq+CaLigamwpe3f2/vYxCwtF3oCcJMQdn6CLYytHgrC2pRWa
bNBBClSO4jzWMlBRBZnzXBHKJ04kviqIybEvrN2weg5ArSOK7297DU2id+kDxSJz
QleZ+9c=
Private-Lines: 8
AAAAgBItCm858PuWFWTDjVb0mMPUVRLdFRDerMSJnXZ6pr5c1ClPdHjcqHjLnABQ
TQd2Znh3/siCIk2ZvVVrU17qEdcZyivntbi8NuehqcVQr2ny8pc+sXvxXv2inoA3
4mIVqjhIoljYf1VWgDXUxUsGU6QZdMfkDCEuoxL9QM7RdFXNAAAAQQDk01miHj3M
LozpMovCU2oKDFLsmOrXe7jroff2sM4BX5Iwym4N197O7ZIs5E52K0bWIDH9SouX
RTseqiHsPxexAAAAQQCWeZFwG7qm8cyAGSzsDsN35cmzgkvlFl4uIuJ9jh0S2Yt5
2couD/AoQVmHqGaxwYPc+q24yvbFbjCxtlkqMTYHAAAAQQCcpItltKrhNW2svG2P
NuOi0TQmMZQigMOYQx4wd/8G2n+nr0Qsi4wuq/qccgKViVRyobB7nxQqoJdGAI90
ECNG
Private-MAC: 4f200e5f5b766351b996d92f3b733b671b9ff957