Skip to content

Commit 09e2ca5

Browse files
authored
Add overloaded init methods that take the public key from a stream an… (#908)
* Add overloaded init methods that take the public key from a stream and properly initialize. Resolves #907. * Override public key.
1 parent 607e805 commit 09e2ca5

File tree

5 files changed

+107
-25
lines changed

5 files changed

+107
-25
lines changed

src/main/java/com/hierynomus/sshj/userauth/keyprovider/OpenSSHKeyV1KeyFile.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
2121
import com.hierynomus.sshj.transport.cipher.ChachaPolyCiphers;
2222
import com.hierynomus.sshj.transport.cipher.GcmCiphers;
23+
import com.hierynomus.sshj.userauth.keyprovider.bcrypt.BCrypt;
2324
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
2425
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
2526
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
@@ -29,24 +30,23 @@
2930
import net.schmizz.sshj.userauth.keyprovider.BaseFileKeyProvider;
3031
import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
3132
import net.schmizz.sshj.userauth.keyprovider.KeyFormat;
33+
import net.schmizz.sshj.userauth.password.PasswordFinder;
3234
import org.bouncycastle.asn1.nist.NISTNamedCurves;
3335
import org.bouncycastle.asn1.x9.X9ECParameters;
3436
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
35-
import com.hierynomus.sshj.userauth.keyprovider.bcrypt.BCrypt;
3637
import org.bouncycastle.openssl.EncryptionException;
3738
import org.slf4j.Logger;
3839
import org.slf4j.LoggerFactory;
3940

40-
import java.io.BufferedReader;
41-
import java.io.File;
42-
import java.io.FileReader;
43-
import java.io.IOException;
44-
import java.io.Reader;
41+
import java.io.*;
4542
import java.math.BigInteger;
4643
import java.nio.ByteBuffer;
4744
import java.nio.CharBuffer;
4845
import java.nio.charset.StandardCharsets;
49-
import java.security.*;
46+
import java.security.GeneralSecurityException;
47+
import java.security.KeyPair;
48+
import java.security.PrivateKey;
49+
import java.security.PublicKey;
5050
import java.security.spec.ECPrivateKeySpec;
5151
import java.security.spec.RSAPrivateCrtKeySpec;
5252
import java.util.Arrays;
@@ -83,6 +83,12 @@ public class OpenSSHKeyV1KeyFile extends BaseFileKeyProvider {
8383

8484
private PublicKey pubKey;
8585

86+
@Override
87+
public PublicKey getPublic()
88+
throws IOException {
89+
return pubKey != null ? pubKey : super.getPublic();
90+
}
91+
8692
public static class Factory
8793
implements net.schmizz.sshj.common.Factory.Named<FileKeyProvider> {
8894

@@ -100,16 +106,41 @@ public String getName() {
100106
protected final Logger log = LoggerFactory.getLogger(getClass());
101107

102108
@Override
103-
public void init(File location) {
109+
public void init(File location, PasswordFinder pwdf) {
104110
File pubKey = OpenSSHKeyFileUtil.getPublicKeyFile(location);
105-
if (pubKey != null)
111+
if (pubKey != null) {
106112
try {
107113
initPubKey(new FileReader(pubKey));
108114
} catch (IOException e) {
109115
// let super provide both public & private key
110116
log.warn("Error reading public key file: {}", e.toString());
111117
}
112-
super.init(location);
118+
}
119+
super.init(location, pwdf);
120+
}
121+
122+
@Override
123+
public void init(String privateKey, String publicKey, PasswordFinder pwdf) {
124+
if (pubKey != null) {
125+
try {
126+
initPubKey(new StringReader(publicKey));
127+
} catch (IOException e) {
128+
log.warn("Error reading public key file: {}", e.toString());
129+
}
130+
}
131+
super.init(privateKey, null, pwdf);
132+
}
133+
134+
@Override
135+
public void init(Reader privateKey, Reader publicKey, PasswordFinder pwdf) {
136+
if (pubKey != null) {
137+
try {
138+
initPubKey(publicKey);
139+
} catch (IOException e) {
140+
log.warn("Error reading public key file: {}", e.toString());
141+
}
142+
}
143+
super.init(privateKey, null, pwdf);
113144
}
114145

115146
@Override

src/main/java/net/schmizz/sshj/userauth/keyprovider/BaseFileKeyProvider.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,47 @@ public abstract class BaseFileKeyProvider implements FileKeyProvider {
3434

3535
@Override
3636
public void init(Reader location) {
37-
assert location != null;
38-
resource = new PrivateKeyReaderResource(location);
37+
this.init(location, (PasswordFinder) null);
3938
}
4039

4140
@Override
4241
public void init(Reader location, PasswordFinder pwdf) {
43-
init(location);
42+
this.init(location, null, pwdf);
43+
}
44+
45+
@Override
46+
public void init(Reader privateKey, Reader publicKey) {
47+
this.init(privateKey, publicKey, null);
48+
}
49+
50+
@Override
51+
public void init(Reader privateKey, Reader publicKey, PasswordFinder pwdf) {
52+
assert publicKey == null;
53+
this.resource = new PrivateKeyReaderResource(privateKey);
4454
this.pwdf = pwdf;
4555
}
4656

4757
@Override
4858
public void init(File location) {
49-
assert location != null;
50-
resource = new PrivateKeyFileResource(location.getAbsoluteFile());
59+
this.init(location, null);
5160
}
5261

5362
@Override
5463
public void init(File location, PasswordFinder pwdf) {
55-
init(location);
64+
this.resource = new PrivateKeyFileResource(location.getAbsoluteFile());
5665
this.pwdf = pwdf;
5766
}
5867

5968
@Override
6069
public void init(String privateKey, String publicKey) {
61-
assert privateKey != null;
62-
assert publicKey == null;
63-
resource = new PrivateKeyStringResource(privateKey);
70+
this.init(privateKey, publicKey, null);
6471
}
6572

6673
@Override
6774
public void init(String privateKey, String publicKey, PasswordFinder pwdf) {
68-
init(privateKey, publicKey);
75+
assert privateKey != null;
76+
assert publicKey == null;
77+
this.resource = new PrivateKeyStringResource(privateKey);
6978
this.pwdf = pwdf;
7079
}
7180

src/main/java/net/schmizz/sshj/userauth/keyprovider/FileKeyProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public interface FileKeyProvider
3030

3131
void init(Reader location);
3232

33+
void init(Reader privateKey, Reader publicKey);
34+
35+
void init(Reader privateKey, Reader publicKey, PasswordFinder pwdf);
36+
3337
void init(Reader location, PasswordFinder pwdf);
3438

3539
void init(String privateKey, String publicKey);

src/main/java/net/schmizz/sshj/userauth/keyprovider/OpenSSHKeyFile.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package net.schmizz.sshj.userauth.keyprovider;
1717

1818
import com.hierynomus.sshj.userauth.keyprovider.OpenSSHKeyFileUtil;
19+
import net.schmizz.sshj.userauth.password.PasswordFinder;
1920

2021
import java.io.*;
2122
import java.security.PublicKey;
@@ -54,21 +55,22 @@ public PublicKey getPublic()
5455
}
5556

5657
@Override
57-
public void init(File location) {
58+
public void init(File location, PasswordFinder pwdf) {
5859
// try cert key location first
5960
File pubKey = OpenSSHKeyFileUtil.getPublicKeyFile(location);
60-
if (pubKey != null)
61+
if (pubKey != null) {
6162
try {
6263
initPubKey(new FileReader(pubKey));
6364
} catch (IOException e) {
6465
// let super provide both public & private key
6566
log.warn("Error reading public key file: {}", e.toString());
6667
}
67-
super.init(location);
68+
}
69+
super.init(location, pwdf);
6870
}
6971

7072
@Override
71-
public void init(String privateKey, String publicKey) {
73+
public void init(String privateKey, String publicKey, PasswordFinder pwdf) {
7274
if (publicKey != null) {
7375
try {
7476
initPubKey(new StringReader(publicKey));
@@ -77,7 +79,20 @@ public void init(String privateKey, String publicKey) {
7779
log.warn("Error reading public key: {}", e.toString());
7880
}
7981
}
80-
super.init(privateKey, null);
82+
super.init(privateKey, null, pwdf);
83+
}
84+
85+
@Override
86+
public void init(Reader privateKey, Reader publicKey, PasswordFinder pwdf) {
87+
if (publicKey != null) {
88+
try {
89+
initPubKey(publicKey);
90+
} catch (IOException e) {
91+
// let super provide both public & private key
92+
log.warn("Error reading public key: {}", e.toString());
93+
}
94+
}
95+
super.init(privateKey, null, pwdf);
8196
}
8297

8398
/**

src/test/java/net/schmizz/sshj/keyprovider/OpenSSHKeyFileTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,18 @@ public void shouldSuccessfullyLoadSignedRSAPublicKey() throws IOException {
381381

382382
}
383383

384+
@Test
385+
public void shouldSuccessfullyLoadSignedRSAPublicKeyFromStream() throws IOException {
386+
FileKeyProvider keyFile = new OpenSSHKeyFile();
387+
keyFile.init(new FileReader("src/test/resources/keytypes/certificate/test_rsa"),
388+
new FileReader("src/test/resources/keytypes/certificate/test_rsa.pub"),
389+
PasswordUtils.createOneOff(correctPassphrase));
390+
assertNotNull(keyFile.getPrivate());
391+
PublicKey pubKey = keyFile.getPublic();
392+
assertNotNull(pubKey);
393+
assertEquals("RSA", pubKey.getAlgorithm());
394+
}
395+
384396
@Test
385397
public void shouldSuccessfullyLoadSignedRSAPublicKeyWithMaxDate() throws IOException {
386398
FileKeyProvider keyFile = new OpenSSHKeyFile();
@@ -422,6 +434,17 @@ public void shouldSuccessfullyLoadSignedDSAPublicKey() throws IOException {
422434
assertEquals("", certificate.getExtensions().get("permit-pty"));
423435
}
424436

437+
@Test
438+
public void shouldSuccessfullyLoadSignedDSAPublicKeyFromStream() throws IOException {
439+
FileKeyProvider keyFile = new OpenSSHKeyFile();
440+
keyFile.init(new FileReader("src/test/resources/keytypes/certificate/test_dsa"),
441+
new FileReader("src/test/resources/keytypes/certificate/test_dsa-cert.pub"),
442+
PasswordUtils.createOneOff(correctPassphrase));
443+
assertNotNull(keyFile.getPrivate());
444+
PublicKey pubKey = keyFile.getPublic();
445+
assertEquals("DSA", pubKey.getAlgorithm());
446+
}
447+
425448
/**
426449
* Sometimes users copy-pastes private and public keys in text editors. It leads to redundant
427450
* spaces and newlines. OpenSSH can easily read such keys, so users expect from SSHJ the same.

0 commit comments

Comments
 (0)