Compare commits

...

2 Commits

Author SHA1 Message Date
Jeroen van Erp
fedf8c410c Merge branch 'master' into issue-588 2020-06-02 16:32:25 +02:00
Jeroen van Erp
8b0d1ca03c Introduce KeyAlgorithm to separate KeyType from Algorithm (Fixes #588) 2020-06-02 14:12:04 +02:00
27 changed files with 625 additions and 102 deletions

View File

@@ -15,6 +15,8 @@
*/ */
package com.hierynomus.sshj package com.hierynomus.sshj
import com.hierynomus.sshj.key.ECDSAKeyAlgorithm
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm
import com.hierynomus.sshj.signature.SignatureEdDSA import com.hierynomus.sshj.signature.SignatureEdDSA
import net.schmizz.sshj.DefaultConfig import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.SSHClient import net.schmizz.sshj.SSHClient
@@ -29,7 +31,7 @@ class IntegrationSpec extends IntegrationBaseSpec {
def "should accept correct key for #signatureName"() { def "should accept correct key for #signatureName"() {
given: given:
def config = new DefaultConfig() def config = new DefaultConfig()
config.setSignatureFactories(signatureFactory) config.setKeyAlgorithms(Collections.singletonList(signatureFactory))
SSHClient sshClient = new SSHClient(config) SSHClient sshClient = new SSHClient(config)
sshClient.addHostKeyVerifier(fingerprint) // test-containers/ssh_host_ecdsa_key's fingerprint sshClient.addHostKeyVerifier(fingerprint) // test-containers/ssh_host_ecdsa_key's fingerprint
@@ -40,7 +42,7 @@ class IntegrationSpec extends IntegrationBaseSpec {
sshClient.isConnected() sshClient.isConnected()
where: where:
signatureFactory << [new SignatureECDSA.Factory256(), new SignatureEdDSA.Factory()] signatureFactory << [new ECDSAKeyAlgorithm.Factory256(), new EdDSAKeyAlgorithm.Factory()]
fingerprint << ["d3:6a:a9:52:05:ab:b5:48:dd:73:60:18:0c:3a:f0:a3", "dc:68:38:ce:fc:6f:2c:d6:6d:6b:34:eb:5c:f0:41:6a"] fingerprint << ["d3:6a:a9:52:05:ab:b5:48:dd:73:60:18:0c:3a:f0:a3", "dc:68:38:ce:fc:6f:2c:d6:6d:6b:34:eb:5c:f0:41:6a"]
signatureName = signatureFactory.getName() signatureName = signatureFactory.getName()
} }

View File

@@ -0,0 +1,43 @@
/*
* 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 com.hierynomus.sshj.signature
import com.hierynomus.sshj.IntegrationBaseSpec
import com.hierynomus.sshj.key.RSAKeyAlgorithm
import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.signature.SignatureRSA
import spock.lang.Unroll
class SignatureSpec extends IntegrationBaseSpec {
@Unroll
def "should correctly connect with #sig Signature"() {
given:
def cfg = new DefaultConfig()
cfg.setKeyAlgorithms(Collections.singletonList(sigFactory))
def client = getConnectedClient(cfg)
when:
client.authPublickey(USERNAME, KEYFILE)
then:
client.authenticated
where:
sigFactory << [new RSAKeyAlgorithm.FactorySSHRSA(), new RSAKeyAlgorithm.FactoryRSASHA256(), new RSAKeyAlgorithm.FactoryRSASHA512()]
sig = sigFactory.name
}
}

View File

@@ -17,9 +17,6 @@ package com.hierynomus.sshj.transport.mac
import com.hierynomus.sshj.IntegrationBaseSpec import com.hierynomus.sshj.IntegrationBaseSpec
import net.schmizz.sshj.DefaultConfig import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.transport.mac.HMACRIPEMD160
import net.schmizz.sshj.transport.mac.HMACSHA2256
import spock.lang.AutoCleanup
import spock.lang.Unroll import spock.lang.Unroll
class MacSpec extends IntegrationBaseSpec { class MacSpec extends IntegrationBaseSpec {

View File

@@ -0,0 +1,60 @@
/*
* 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 com.hierynomus.sshj.key;
import net.schmizz.sshj.common.Buffer;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.signature.Signature;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
public abstract class AbstractKeyAlgorithm implements KeyAlgorithm {
private final String keyAlgorithm;
private final Factory.Named<Signature> signature;
private final KeyType keyFormat;
public AbstractKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
this.keyAlgorithm = keyAlgorithm;
this.signature = signature;
this.keyFormat = keyFormat;
}
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
keyFormat.putPubKeyIntoBuffer(pk, buf);
}
@Override
public PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException {
return keyFormat.readPubKeyFromBuffer(buf);
}
@Override
public String getKeyAlgorithm() {
return keyAlgorithm;
}
@Override
public KeyType getKeyFormat() {
return keyFormat;
}
@Override
public Signature newSignature() {
return this.signature.create();
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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 com.hierynomus.sshj.key;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.signature.SignatureDSA;
public class DSAKeyAlgorithm extends AbstractKeyAlgorithm {
/**
* A named factory for the SSH-DSA key algorithm.
*/
public static class FactorySSHDSA
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new DSAKeyAlgorithm(KeyType.DSA.toString(), new SignatureDSA.Factory(), KeyType.DSA);
}
@Override
public String getName() {
return KeyType.DSA.toString();
}
}
/**
* A named factory for the SSH-DSS-CERT key algorithm
*/
public static class FactorySSHDSSCert
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new DSAKeyAlgorithm(KeyType.DSA_CERT.toString(), new SignatureDSA.Factory(), KeyType.DSA_CERT);
}
@Override
public String getName() {
return KeyType.DSA_CERT.toString();
}
}
public DSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
super(keyAlgorithm, signature, KeyType.DSA);
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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 com.hierynomus.sshj.key;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.signature.SignatureECDSA;
public class ECDSAKeyAlgorithm extends AbstractKeyAlgorithm {
/** A named factory for ECDSA-256 signature */
public static class Factory256 implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new ECDSAKeyAlgorithm(KeyType.ECDSA256.toString(), new SignatureECDSA.Factory256(), KeyType.ECDSA256);
}
@Override
public String getName() {
return KeyType.ECDSA256.toString();
}
}
/** A named factory for ECDSA-384 signature */
public static class Factory384 implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new ECDSAKeyAlgorithm(KeyType.ECDSA384.toString(), new SignatureECDSA.Factory384(), KeyType.ECDSA384);
}
@Override
public String getName() {
return KeyType.ECDSA384.toString();
}
}
/** A named factory for ECDSA-521 signature */
public static class Factory521 implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new ECDSAKeyAlgorithm(KeyType.ECDSA521.toString(), new SignatureECDSA.Factory384(), KeyType.ECDSA521);
}
@Override
public String getName() {
return KeyType.ECDSA521.toString();
}
}
public ECDSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
super(keyAlgorithm, signature, keyFormat);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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 com.hierynomus.sshj.key;
import com.hierynomus.sshj.signature.SignatureEdDSA;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.signature.Signature;
public class EdDSAKeyAlgorithm extends AbstractKeyAlgorithm {
public static class Factory implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public String getName() {
return KeyType.ED25519.toString();
}
@Override
public KeyAlgorithm create() {
return new EdDSAKeyAlgorithm(KeyType.ED25519.toString(), new SignatureEdDSA.Factory(), KeyType.ED25519);
}
}
public EdDSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
super(keyAlgorithm, signature, keyFormat);
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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 com.hierynomus.sshj.key;
import net.schmizz.sshj.common.Buffer;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.signature.Signature;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
/**
* In [RFC4252], the concept "public key algorithm" is used to establish
* a relationship between one algorithm name, and:
* <p>
* A. procedures used to generate and validate a private/public
* keypair;
* B. a format used to encode a public key; and
* C. procedures used to calculate, encode, and verify a signature.
*/
public interface KeyAlgorithm {
PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException;
void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf);
String getKeyAlgorithm();
KeyType getKeyFormat();
Signature newSignature();
}

View File

@@ -0,0 +1,96 @@
/*
* 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 com.hierynomus.sshj.key;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.signature.SignatureRSA;
public class RSAKeyAlgorithm extends AbstractKeyAlgorithm {
/**
* A named factory for the SSH-RSA (SHA1) public key algorithm
*/
public static class FactorySSHRSA
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new RSAKeyAlgorithm("ssh-rsa", new SignatureRSA.FactorySSHRSA(), KeyType.RSA);
}
@Override
public String getName() {
return "ssh-rsa";
}
}
/**
* A named factory for the ssh-rsa-cert-v01@openssh.com (SHA1) public key algorithm
*/
public static class FactorySSHRSACert
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new RSAKeyAlgorithm("ssh-rsa-cert-v01@openssh.com", new SignatureRSA.FactoryCERT(), KeyType.RSA_CERT);
}
@Override
public String getName() {
return "ssh-rsa-cert-v01@openssh.com";
}
}
/**
* A named factory for the RSA-SHA2-256 public key algorithm
*/
public static class FactoryRSASHA256
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new RSAKeyAlgorithm("rsa-sha2-256", new SignatureRSA.FactoryRSASHA256(), KeyType.RSA);
}
@Override
public String getName() {
return "rsa-sha2-256";
}
}
/**
* A named factory for the RSA-SHA2-512 public key algorithm
*/
public static class FactoryRSASHA512
implements net.schmizz.sshj.common.Factory.Named<KeyAlgorithm> {
@Override
public KeyAlgorithm create() {
return new RSAKeyAlgorithm("rsa-sha2-512", new SignatureRSA.FactoryRSASHA512(), KeyType.RSA);
}
@Override
public String getName() {
return "rsa-sha2-512";
}
}
public RSAKeyAlgorithm(String keyAlgorithm, Factory.Named<Signature> signature, KeyType keyFormat) {
super(keyAlgorithm, signature, keyFormat);
}
}

View File

@@ -40,7 +40,7 @@ public class SignatureEdDSA extends AbstractSignature {
} }
SignatureEdDSA() { SignatureEdDSA() {
super(getEngine()); super(getEngine(), KeyType.ED25519.toString());
} }
private static EdDSAEngine getEngine() { private static EdDSAEngine getEngine() {

View File

@@ -15,6 +15,9 @@
*/ */
package net.schmizz.sshj; package net.schmizz.sshj;
import com.hierynomus.sshj.key.DSAKeyAlgorithm;
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm;
import com.hierynomus.sshj.key.RSAKeyAlgorithm;
import com.hierynomus.sshj.signature.SignatureEdDSA; import com.hierynomus.sshj.signature.SignatureEdDSA;
import net.schmizz.sshj.common.SecurityUtils; import net.schmizz.sshj.common.SecurityUtils;
@@ -23,6 +26,8 @@ import net.schmizz.sshj.signature.SignatureRSA;
import net.schmizz.sshj.transport.random.JCERandom; import net.schmizz.sshj.transport.random.JCERandom;
import net.schmizz.sshj.transport.random.SingletonRandomFactory; import net.schmizz.sshj.transport.random.SingletonRandomFactory;
import java.util.Arrays;
/** /**
* Registers SpongyCastle as JCE provider. * Registers SpongyCastle as JCE provider.
*/ */
@@ -33,11 +38,14 @@ public class AndroidConfig
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider"); SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
} }
// don't add ECDSA
protected void initSignatureFactories() { @Override
setSignatureFactories(new SignatureRSA.Factory(), new SignatureDSA.Factory(), protected void initKeyAlgorithms() {
// but add EdDSA setKeyAlgorithms(Arrays.asList(
new SignatureEdDSA.Factory()); new EdDSAKeyAlgorithm.Factory(),
new RSAKeyAlgorithm.FactorySSHRSA(),
new DSAKeyAlgorithm.FactorySSHDSA()
));
} }
@Override @Override

View File

@@ -15,6 +15,7 @@
*/ */
package net.schmizz.sshj; package net.schmizz.sshj;
import com.hierynomus.sshj.key.KeyAlgorithm;
import net.schmizz.keepalive.KeepAliveProvider; import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory; import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.LoggerFactory; import net.schmizz.sshj.common.LoggerFactory;
@@ -77,11 +78,11 @@ public interface Config {
Factory<Random> getRandomFactory(); Factory<Random> getRandomFactory();
/** /**
* Retrieve the list of named factories for {@link Signature} * Retrieve the list of named factories for {@link com.hierynomus.sshj.key.KeyAlgorithm}
* *
* @return a list of named {@link Signature} factories * @return a list of named {@link com.hierynomus.sshj.key.KeyAlgorithm} factories
*/ */
List<Factory.Named<Signature>> getSignatureFactories(); List<Factory.Named<KeyAlgorithm>> getKeyAlgorithms();
/** /**
* Returns the software version information for identification during SSH connection initialization. For example, * Returns the software version information for identification during SSH connection initialization. For example,
@@ -132,11 +133,11 @@ public interface Config {
void setRandomFactory(Factory<Random> randomFactory); void setRandomFactory(Factory<Random> randomFactory);
/** /**
* Set the named factories for {@link Signature}. * Set the named factories for {@link KeyAlgorithm}.
* *
* @param signatureFactories a list of named factories * @param keyAlgorithms a list of named factories
*/ */
void setSignatureFactories(List<Factory.Named<Signature>> signatureFactories); void setKeyAlgorithms(List<Factory.Named<KeyAlgorithm>> keyAlgorithms);
/** /**
* Set the software version information for identification during SSH connection initialization. For example, {@code * Set the software version information for identification during SSH connection initialization. For example, {@code

View File

@@ -15,10 +15,10 @@
*/ */
package net.schmizz.sshj; package net.schmizz.sshj;
import com.hierynomus.sshj.key.KeyAlgorithm;
import net.schmizz.keepalive.KeepAliveProvider; import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory; import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.LoggerFactory; import net.schmizz.sshj.common.LoggerFactory;
import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.transport.cipher.Cipher; import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.transport.compression.Compression; import net.schmizz.sshj.transport.compression.Compression;
import net.schmizz.sshj.transport.kex.KeyExchange; import net.schmizz.sshj.transport.kex.KeyExchange;
@@ -42,7 +42,7 @@ public class ConfigImpl
private List<Factory.Named<Cipher>> cipherFactories; private List<Factory.Named<Cipher>> cipherFactories;
private List<Factory.Named<Compression>> compressionFactories; private List<Factory.Named<Compression>> compressionFactories;
private List<Factory.Named<MAC>> macFactories; private List<Factory.Named<MAC>> macFactories;
private List<Factory.Named<Signature>> signatureFactories; private List<Factory.Named<KeyAlgorithm>> keyAlgorithms;
private List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories; private List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories;
private boolean waitForServerIdentBeforeSendingClientIdent = false; private boolean waitForServerIdentBeforeSendingClientIdent = false;
@@ -78,11 +78,6 @@ public class ConfigImpl
return randomFactory; return randomFactory;
} }
@Override
public List<Factory.Named<Signature>> getSignatureFactories() {
return signatureFactories;
}
@Override @Override
public String getVersion() { public String getVersion() {
return version; return version;
@@ -138,15 +133,6 @@ public class ConfigImpl
this.randomFactory = randomFactory; this.randomFactory = randomFactory;
} }
public void setSignatureFactories(Factory.Named<Signature>... signatureFactories) {
setSignatureFactories(Arrays.asList(signatureFactories));
}
@Override
public void setSignatureFactories(List<Factory.Named<Signature>> signatureFactories) {
this.signatureFactories = signatureFactories;
}
@Override @Override
public void setVersion(String version) { public void setVersion(String version) {
this.version = version; this.version = version;
@@ -172,6 +158,16 @@ public class ConfigImpl
this.waitForServerIdentBeforeSendingClientIdent = waitForServerIdentBeforeSendingClientIdent; this.waitForServerIdentBeforeSendingClientIdent = waitForServerIdentBeforeSendingClientIdent;
} }
@Override
public List<Factory.Named<KeyAlgorithm>> getKeyAlgorithms() {
return keyAlgorithms;
}
@Override
public void setKeyAlgorithms(List<Factory.Named<KeyAlgorithm>> keyAlgorithms) {
this.keyAlgorithms = keyAlgorithms;
}
@Override @Override
public LoggerFactory getLoggerFactory() { public LoggerFactory getLoggerFactory() {
return loggerFactory; return loggerFactory;

View File

@@ -15,7 +15,10 @@
*/ */
package net.schmizz.sshj; package net.schmizz.sshj;
import com.hierynomus.sshj.signature.SignatureEdDSA; import com.hierynomus.sshj.key.DSAKeyAlgorithm;
import com.hierynomus.sshj.key.ECDSAKeyAlgorithm;
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm;
import com.hierynomus.sshj.key.RSAKeyAlgorithm;
import com.hierynomus.sshj.transport.cipher.BlockCiphers; import com.hierynomus.sshj.transport.cipher.BlockCiphers;
import com.hierynomus.sshj.transport.cipher.StreamCiphers; import com.hierynomus.sshj.transport.cipher.StreamCiphers;
import com.hierynomus.sshj.transport.kex.DHGroups; import com.hierynomus.sshj.transport.kex.DHGroups;
@@ -26,10 +29,7 @@ import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory; import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.LoggerFactory; import net.schmizz.sshj.common.LoggerFactory;
import net.schmizz.sshj.common.SecurityUtils; import net.schmizz.sshj.common.SecurityUtils;
import net.schmizz.sshj.signature.SignatureDSA; import net.schmizz.sshj.transport.cipher.Cipher;
import net.schmizz.sshj.signature.SignatureECDSA;
import net.schmizz.sshj.signature.SignatureRSA;
import net.schmizz.sshj.transport.cipher.*;
import net.schmizz.sshj.transport.compression.NoneCompression; import net.schmizz.sshj.transport.compression.NoneCompression;
import net.schmizz.sshj.transport.kex.Curve25519SHA256; import net.schmizz.sshj.transport.kex.Curve25519SHA256;
import net.schmizz.sshj.transport.kex.DHGexSHA1; import net.schmizz.sshj.transport.kex.DHGexSHA1;
@@ -56,7 +56,7 @@ import java.util.*;
* <li>{@link net.schmizz.sshj.ConfigImpl#setMACFactories MAC}: {@link net.schmizz.sshj.transport.mac.HMACSHA1}, {@link net.schmizz.sshj.transport.mac.HMACSHA196}, {@link net.schmizz.sshj.transport.mac.HMACMD5}, {@link * <li>{@link net.schmizz.sshj.ConfigImpl#setMACFactories MAC}: {@link net.schmizz.sshj.transport.mac.HMACSHA1}, {@link net.schmizz.sshj.transport.mac.HMACSHA196}, {@link net.schmizz.sshj.transport.mac.HMACMD5}, {@link
* net.schmizz.sshj.transport.mac.HMACMD596}</li> * net.schmizz.sshj.transport.mac.HMACMD596}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setCompressionFactories Compression}: {@link net.schmizz.sshj.transport.compression.NoneCompression}</li> * <li>{@link net.schmizz.sshj.ConfigImpl#setCompressionFactories Compression}: {@link net.schmizz.sshj.transport.compression.NoneCompression}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setSignatureFactories Signature}: {@link net.schmizz.sshj.signature.SignatureRSA}, {@link net.schmizz.sshj.signature.SignatureDSA}</li> * <li>{@link net.schmizz.sshj.ConfigImpl#setKeyAlgorithms KeyAlgorithm}: {@link net.schmizz.sshj.signature.SignatureRSA}, {@link net.schmizz.sshj.signature.SignatureDSA}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setRandomFactory PRNG}: {@link net.schmizz.sshj.transport.random.BouncyCastleRandom}* or {@link net.schmizz.sshj.transport.random.JCERandom}</li> * <li>{@link net.schmizz.sshj.ConfigImpl#setRandomFactory PRNG}: {@link net.schmizz.sshj.transport.random.BouncyCastleRandom}* or {@link net.schmizz.sshj.transport.random.JCERandom}</li>
* <li>{@link net.schmizz.sshj.ConfigImpl#setFileKeyProviderFactories Key file support}: {@link net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile}*, {@link * <li>{@link net.schmizz.sshj.ConfigImpl#setFileKeyProviderFactories Key file support}: {@link net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile}*, {@link
* net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile}*</li> * net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile}*</li>
@@ -76,12 +76,12 @@ public class DefaultConfig
setVersion(readVersionFromProperties()); setVersion(readVersionFromProperties());
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered(); final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
initKeyExchangeFactories(bouncyCastleRegistered); initKeyExchangeFactories(bouncyCastleRegistered);
initKeyAlgorithms();
initRandomFactory(bouncyCastleRegistered); initRandomFactory(bouncyCastleRegistered);
initFileKeyProviderFactories(bouncyCastleRegistered); initFileKeyProviderFactories(bouncyCastleRegistered);
initCipherFactories(); initCipherFactories();
initCompressionFactories(); initCompressionFactories();
initMACFactories(); initMACFactories();
initSignatureFactories();
setKeepAliveProvider(KeepAliveProvider.HEARTBEAT); setKeepAliveProvider(KeepAliveProvider.HEARTBEAT);
} }
@@ -133,6 +133,20 @@ public class DefaultConfig
} }
} }
protected void initKeyAlgorithms() {
setKeyAlgorithms(Arrays.asList(
new EdDSAKeyAlgorithm.Factory(),
new ECDSAKeyAlgorithm.Factory521(),
new ECDSAKeyAlgorithm.Factory384(),
new ECDSAKeyAlgorithm.Factory256(),
new RSAKeyAlgorithm.FactoryRSASHA512(),
new RSAKeyAlgorithm.FactoryRSASHA256(),
new RSAKeyAlgorithm.FactorySSHRSACert(),
new DSAKeyAlgorithm.FactorySSHDSSCert(),
new RSAKeyAlgorithm.FactorySSHRSA(),
new DSAKeyAlgorithm.FactorySSHDSA()));
}
protected void initRandomFactory(boolean bouncyCastleRegistered) { protected void initRandomFactory(boolean bouncyCastleRegistered) {
setRandomFactory(new SingletonRandomFactory(bouncyCastleRegistered setRandomFactory(new SingletonRandomFactory(bouncyCastleRegistered
? new BouncyCastleRandom.Factory() : new JCERandom.Factory())); ? new BouncyCastleRandom.Factory() : new JCERandom.Factory()));
@@ -207,18 +221,6 @@ public class DefaultConfig
log.debug("Available cipher factories: {}", avail); log.debug("Available cipher factories: {}", avail);
} }
protected void initSignatureFactories() {
setSignatureFactories(
new SignatureEdDSA.Factory(),
new SignatureECDSA.Factory256(),
new SignatureECDSA.Factory384(),
new SignatureECDSA.Factory521(),
new SignatureRSA.Factory(),
new SignatureRSA.FactoryCERT(),
new SignatureDSA.Factory()
);
}
protected void initMACFactories() { protected void initMACFactories() {
setMACFactories( setMACFactories(
Macs.HMACSHA1(), Macs.HMACSHA1(),

View File

@@ -29,18 +29,26 @@ public abstract class AbstractSignature
@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName") @SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
protected final java.security.Signature signature; protected final java.security.Signature signature;
private final String signatureName;
protected AbstractSignature(String algorithm) { protected AbstractSignature(String algorithm, String signatureName) {
try { try {
this.signature = SecurityUtils.getSignature(algorithm); this.signature = SecurityUtils.getSignature(algorithm);
this.signatureName = signatureName;
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new SSHRuntimeException(e); throw new SSHRuntimeException(e);
} }
} }
protected AbstractSignature(@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName") protected AbstractSignature(@SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
java.security.Signature signatureEngine) { java.security.Signature signatureEngine, String signatureName) {
this.signature = signatureEngine; this.signature = signatureEngine;
this.signatureName = signatureName;
}
@Override
public String getSignatureName() {
return signatureName;
} }
@Override @Override

View File

@@ -21,6 +21,8 @@ import java.security.PublicKey;
/** Signature interface for SSH used to sign or verify data. Usually wraps a {@code javax.crypto.Signature} object. */ /** Signature interface for SSH used to sign or verify data. Usually wraps a {@code javax.crypto.Signature} object. */
public interface Signature { public interface Signature {
String getSignatureName();
/** /**
* Initialize this signature with the given public key for signature verification. * Initialize this signature with the given public key for signature verification.
* *

View File

@@ -50,7 +50,7 @@ public class SignatureDSA
} }
public SignatureDSA() { public SignatureDSA() {
super("SHA1withDSA"); super("SHA1withDSA", KeyType.DSA.toString());
} }
@Override @Override
@@ -72,8 +72,8 @@ public class SignatureDSA
// result must be 40 bytes, but length of r and s may not be 20 bytes // result must be 40 bytes, but length of r and s may not be 20 bytes
int r_copylen = (r.length < 20) ? r.length : 20; int r_copylen = Math.min(r.length, 20);
int s_copylen = (s.length < 20) ? s.length : 20; int s_copylen = Math.min(s.length, 20);
System.arraycopy(r, r.length - r_copylen, result, 20 - r_copylen, r_copylen); System.arraycopy(r, r.length - r_copylen, result, 20 - r_copylen, r_copylen);
System.arraycopy(s, s.length - s_copylen, result, 40 - s_copylen, s_copylen); System.arraycopy(s, s.length - s_copylen, result, 40 - s_copylen, s_copylen);

View File

@@ -79,7 +79,7 @@ public class SignatureECDSA extends AbstractSignature {
private String keyTypeName; private String keyTypeName;
public SignatureECDSA(String algorithm, String keyTypeName) { public SignatureECDSA(String algorithm, String keyTypeName) {
super(algorithm); super(algorithm, keyTypeName);
this.keyTypeName = keyTypeName; this.keyTypeName = keyTypeName;
} }

View File

@@ -22,26 +22,53 @@ import net.schmizz.sshj.common.SSHRuntimeException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.SignatureException; import java.security.SignatureException;
import java.util.Date;
/** RSA {@link Signature} */ /** RSA {@link Signature} */
public class SignatureRSA public class SignatureRSA
extends AbstractSignature { extends AbstractSignature {
/** A named factory for RSA {@link Signature} */ /** A named factory for RSA {@link Signature} */
public static class Factory public static class FactorySSHRSA
implements net.schmizz.sshj.common.Factory.Named<Signature> { implements net.schmizz.sshj.common.Factory.Named<Signature> {
@Override @Override
public Signature create() { public Signature create() {
return new SignatureRSA(KeyType.RSA.toString()); return new SignatureRSA("SHA1withRSA", KeyType.RSA, KeyType.RSA.toString());
} }
@Override @Override
public String getName() { public String getName() {
return KeyType.RSA.toString(); return KeyType.RSA.toString();
} }
}
/** A named factory for RSA {@link Signature} */
public static class FactoryRSASHA256
implements net.schmizz.sshj.common.Factory.Named<Signature> {
@Override
public Signature create() {
return new SignatureRSA("SHA256withRSA", KeyType.RSA, "rsa-sha2-256");
}
@Override
public String getName() {
return "rsa-sha2-256";
}
}
/** A named factory for RSA {@link Signature} */
public static class FactoryRSASHA512
implements net.schmizz.sshj.common.Factory.Named<Signature> {
@Override
public Signature create() {
return new SignatureRSA("SHA512withRSA", KeyType.RSA, "rsa-sha2-512");
}
@Override
public String getName() {
return "rsa-sha2-512";
}
} }
/** A named factory for RSA {@link Signature} */ /** A named factory for RSA {@link Signature} */
@@ -50,7 +77,7 @@ public class SignatureRSA
@Override @Override
public Signature create() { public Signature create() {
return new SignatureRSA(KeyType.RSA_CERT.toString()); return new SignatureRSA("SHA1withRSA", KeyType.RSA_CERT, KeyType.RSA.toString());
} }
@Override @Override
@@ -60,19 +87,19 @@ public class SignatureRSA
} }
private String keyTypeName; private KeyType keyType;
public SignatureRSA(String keyTypeName) { public SignatureRSA(String algorithm, KeyType keyType, String name) {
super("SHA1withRSA"); super(algorithm, name);
this.keyTypeName = keyTypeName; this.keyType = keyType;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void initVerify(PublicKey publicKey) { public void initVerify(PublicKey publicKey) {
try { try {
if (this.keyTypeName.equals(KeyType.RSA_CERT.toString()) && publicKey instanceof Certificate) { if (this.keyType.equals(KeyType.RSA_CERT) && publicKey instanceof Certificate) {
signature.initVerify(((Certificate<PublicKey>) publicKey).getKey()); signature.initVerify(((Certificate<PublicKey>) publicKey).getKey());
} else { } else {
signature.initVerify(publicKey); signature.initVerify(publicKey);
@@ -89,7 +116,7 @@ public class SignatureRSA
@Override @Override
public boolean verify(byte[] sig) { public boolean verify(byte[] sig) {
sig = extractSig(sig, KeyType.RSA.toString()); sig = extractSig(sig, getSignatureName());
try { try {
return signature.verify(sig); return signature.verify(sig);
} catch (SignatureException e) { } catch (SignatureException e) {

View File

@@ -15,6 +15,7 @@
*/ */
package net.schmizz.sshj.transport; package net.schmizz.sshj.transport;
import com.hierynomus.sshj.key.KeyAlgorithm;
import net.schmizz.concurrent.ErrorDeliveryUtil; import net.schmizz.concurrent.ErrorDeliveryUtil;
import net.schmizz.concurrent.Event; import net.schmizz.concurrent.Event;
import net.schmizz.sshj.common.*; import net.schmizz.sshj.common.*;
@@ -30,9 +31,7 @@ import org.slf4j.Logger;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Arrays; import java.util.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -232,6 +231,13 @@ final class KeyExchanger
} }
kex = Factory.Named.Util.create(transport.getConfig().getKeyExchangeFactories(), kex = Factory.Named.Util.create(transport.getConfig().getKeyExchangeFactories(),
negotiatedAlgs.getKeyExchangeAlgorithm()); negotiatedAlgs.getKeyExchangeAlgorithm());
List<KeyAlgorithm> keyAlgorithms = new ArrayList<KeyAlgorithm>();
for (String signatureAlgorithm : negotiatedAlgs.getSignatureAlgorithms()) {
keyAlgorithms.add(Factory.Named.Util.create(transport.getConfig().getKeyAlgorithms(), signatureAlgorithm));
}
transport.setKeyAlgorithms(keyAlgorithms);
try { try {
kex.init(transport, kex.init(transport,
transport.getServerID(), transport.getClientID(), transport.getServerID(), transport.getClientID(),

View File

@@ -15,10 +15,12 @@
*/ */
package net.schmizz.sshj.transport; package net.schmizz.sshj.transport;
import java.util.List;
public final class NegotiatedAlgorithms { public final class NegotiatedAlgorithms {
private final String kex; private final String kex;
private final String sig; private final List<String> availableSigs;
private final String c2sCipher; private final String c2sCipher;
private final String s2cCipher; private final String s2cCipher;
private final String c2sMAC; private final String c2sMAC;
@@ -26,10 +28,10 @@ public final class NegotiatedAlgorithms {
private final String c2sComp; private final String c2sComp;
private final String s2cComp; private final String s2cComp;
NegotiatedAlgorithms(String kex, String sig, String c2sCipher, String s2cCipher, String c2sMAC, String s2cMAC, NegotiatedAlgorithms(String kex, List<String> availableSigs, String c2sCipher, String s2cCipher, String c2sMAC, String s2cMAC,
String c2sComp, String s2cComp) { String c2sComp, String s2cComp) {
this.kex = kex; this.kex = kex;
this.sig = sig; this.availableSigs = availableSigs;
this.c2sCipher = c2sCipher; this.c2sCipher = c2sCipher;
this.s2cCipher = s2cCipher; this.s2cCipher = s2cCipher;
this.c2sMAC = c2sMAC; this.c2sMAC = c2sMAC;
@@ -42,8 +44,8 @@ public final class NegotiatedAlgorithms {
return kex; return kex;
} }
public String getSignatureAlgorithm() { public List<String> getSignatureAlgorithms() {
return sig; return availableSigs;
} }
public String getClient2ServerCipherAlgorithm() { public String getClient2ServerCipherAlgorithm() {
@@ -74,7 +76,7 @@ public final class NegotiatedAlgorithms {
public String toString() { public String toString() {
return ("[ " + return ("[ " +
"kex=" + kex + "; " + "kex=" + kex + "; " +
"sig=" + sig + "; " + "availableSigs=" + availableSigs + "; " +
"c2sCipher=" + c2sCipher + "; " + "c2sCipher=" + c2sCipher + "; " +
"s2cCipher=" + s2cCipher + "; " + "s2cCipher=" + s2cCipher + "; " +
"c2sMAC=" + c2sMAC + "; " + "c2sMAC=" + c2sMAC + "; " +

View File

@@ -21,6 +21,7 @@ import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.Message; import net.schmizz.sshj.common.Message;
import net.schmizz.sshj.common.SSHPacket; import net.schmizz.sshj.common.SSHPacket;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -38,7 +39,7 @@ class Proposal {
public Proposal(Config config) { public Proposal(Config config) {
kex = Factory.Named.Util.getNames(config.getKeyExchangeFactories()); kex = Factory.Named.Util.getNames(config.getKeyExchangeFactories());
sig = Factory.Named.Util.getNames(config.getSignatureFactories()); sig = Factory.Named.Util.getNames(config.getKeyAlgorithms());
c2sCipher = s2cCipher = Factory.Named.Util.getNames(config.getCipherFactories()); c2sCipher = s2cCipher = Factory.Named.Util.getNames(config.getCipherFactories());
c2sMAC = s2cMAC = Factory.Named.Util.getNames(config.getMACFactories()); c2sMAC = s2cMAC = Factory.Named.Util.getNames(config.getMACFactories());
c2sComp = s2cComp = Factory.Named.Util.getNames(config.getCompressionFactories()); c2sComp = s2cComp = Factory.Named.Util.getNames(config.getCompressionFactories());
@@ -126,7 +127,7 @@ class Proposal {
throws TransportException { throws TransportException {
return new NegotiatedAlgorithms( return new NegotiatedAlgorithms(
firstMatch(this.getKeyExchangeAlgorithms(), other.getKeyExchangeAlgorithms()), firstMatch(this.getKeyExchangeAlgorithms(), other.getKeyExchangeAlgorithms()),
firstMatch(this.getSignatureAlgorithms(), other.getSignatureAlgorithms()), allMatch(this.getSignatureAlgorithms(), other.getSignatureAlgorithms()),
firstMatch(this.getClient2ServerCipherAlgorithms(), other.getClient2ServerCipherAlgorithms()), firstMatch(this.getClient2ServerCipherAlgorithms(), other.getClient2ServerCipherAlgorithms()),
firstMatch(this.getServer2ClientCipherAlgorithms(), other.getServer2ClientCipherAlgorithms()), firstMatch(this.getServer2ClientCipherAlgorithms(), other.getServer2ClientCipherAlgorithms()),
firstMatch(this.getClient2ServerMACAlgorithms(), other.getClient2ServerMACAlgorithms()), firstMatch(this.getClient2ServerMACAlgorithms(), other.getClient2ServerMACAlgorithms()),
@@ -138,19 +139,36 @@ class Proposal {
private static String firstMatch(List<String> a, List<String> b) private static String firstMatch(List<String> a, List<String> b)
throws TransportException { throws TransportException {
for (String aa : a) for (String aa : a) {
for (String bb : b) if (b.contains(aa)) {
if (aa.equals(bb))
return aa; return aa;
}
}
throw new TransportException("Unable to reach a settlement: " + a + " and " + b); throw new TransportException("Unable to reach a settlement: " + a + " and " + b);
} }
private static List<String> allMatch(List<String> a, List<String> b) throws TransportException {
List<String> res = new ArrayList<String>();
for (String aa : a) {
if (b.contains(aa)) {
res.add(aa);
}
}
if (res.isEmpty()) {
throw new TransportException("Unable to reach a settlement: " + a + " and " + b);
}
return res;
}
private static String toCommaString(List<String> sl) { private static String toCommaString(List<String> sl) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int i = 0; int i = 0;
for (String s : sl) { for (String s : sl) {
if (i++ != 0) if (i++ != 0) {
sb.append(","); sb.append(",");
}
sb.append(s); sb.append(s);
} }
return sb.toString(); return sb.toString();

View File

@@ -15,9 +15,11 @@
*/ */
package net.schmizz.sshj.transport; package net.schmizz.sshj.transport;
import com.hierynomus.sshj.key.KeyAlgorithm;
import net.schmizz.sshj.Config; import net.schmizz.sshj.Config;
import net.schmizz.sshj.Service; import net.schmizz.sshj.Service;
import net.schmizz.sshj.common.DisconnectReason; import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.common.SSHPacket; import net.schmizz.sshj.common.SSHPacket;
import net.schmizz.sshj.common.SSHPacketHandler; import net.schmizz.sshj.common.SSHPacketHandler;
import net.schmizz.sshj.transport.verification.AlgorithmsVerifier; import net.schmizz.sshj.transport.verification.AlgorithmsVerifier;
@@ -235,4 +237,6 @@ public interface Transport
* @param e The exception that occurred. * @param e The exception that occurred.
*/ */
void die(Exception e); void die(Exception e);
KeyAlgorithm getKeyAlgorithm(KeyType keyType) throws TransportException;
} }

View File

@@ -15,6 +15,7 @@
*/ */
package net.schmizz.sshj.transport; package net.schmizz.sshj.transport;
import com.hierynomus.sshj.key.KeyAlgorithm;
import com.hierynomus.sshj.transport.IdentificationStringParser; import com.hierynomus.sshj.transport.IdentificationStringParser;
import net.schmizz.concurrent.ErrorDeliveryUtil; import net.schmizz.concurrent.ErrorDeliveryUtil;
import net.schmizz.concurrent.Event; import net.schmizz.concurrent.Event;
@@ -30,6 +31,7 @@ import org.slf4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@@ -39,6 +41,7 @@ import java.util.concurrent.locks.ReentrantLock;
public final class TransportImpl public final class TransportImpl
implements Transport, DisconnectListener { implements Transport, DisconnectListener {
private static final class NullService private static final class NullService
extends AbstractService { extends AbstractService {
@@ -86,6 +89,8 @@ public final class TransportImpl
private final Decoder decoder; private final Decoder decoder;
private List<KeyAlgorithm> keyAlgorithms;
private final Event<TransportException> serviceAccept; private final Event<TransportException> serviceAccept;
private final Event<TransportException> close; private final Event<TransportException> close;
@@ -649,4 +654,18 @@ public final class TransportImpl
return connInfo; return connInfo;
} }
@Override
public KeyAlgorithm getKeyAlgorithm(KeyType keyType) throws TransportException {
for (KeyAlgorithm ka : keyAlgorithms) {
if (ka.getKeyFormat().equals(keyType)) {
return ka;
}
}
throw new TransportException("Cannot find an available KeyAlgorithm for type " + keyType);
}
public void setKeyAlgorithms(List<KeyAlgorithm> keyAlgorithms) {
this.keyAlgorithms = keyAlgorithms;
}
} }

View File

@@ -78,8 +78,8 @@ public abstract class AbstractDHG extends AbstractDH
digest.update(buf.array(), buf.rpos(), buf.available()); digest.update(buf.array(), buf.rpos(), buf.available());
H = digest.digest(); H = digest.digest();
Signature signature = Factory.Named.Util.create(trans.getConfig().getSignatureFactories(),
KeyType.fromKey(hostKey).toString()); Signature signature = trans.getKeyAlgorithm(KeyType.fromKey(hostKey)).newSignature();
signature.initVerify(hostKey); signature.initVerify(hostKey);
signature.update(H, 0, H.length); signature.update(H, 0, H.length);
if (!signature.verify(sig)) if (!signature.verify(sig))

View File

@@ -15,6 +15,7 @@
*/ */
package net.schmizz.sshj.transport.kex; package net.schmizz.sshj.transport.kex;
import com.hierynomus.sshj.key.KeyAlgorithm;
import net.schmizz.sshj.common.*; import net.schmizz.sshj.common.*;
import net.schmizz.sshj.signature.Signature; import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.transport.Transport; import net.schmizz.sshj.transport.Transport;
@@ -30,9 +31,9 @@ import java.security.GeneralSecurityException;
public abstract class AbstractDHGex extends AbstractDH { public abstract class AbstractDHGex extends AbstractDH {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private int minBits = 1024; private final int minBits = 1024;
private int maxBits = 8192; private final int maxBits = 8192;
private int preferredBits = 2048; private final int preferredBits = 2048;
public AbstractDHGex(Digest digest) { public AbstractDHGex(Digest digest) {
super(new DH(), digest); super(new DH(), digest);
@@ -84,8 +85,8 @@ public abstract class AbstractDHGex extends AbstractDH {
.putMPInt(k); .putMPInt(k);
digest.update(buf.array(), buf.rpos(), buf.available()); digest.update(buf.array(), buf.rpos(), buf.available());
H = digest.digest(); H = digest.digest();
Signature signature = Factory.Named.Util.create(trans.getConfig().getSignatureFactories(), KeyAlgorithm keyAlgorithm = trans.getKeyAlgorithm(KeyType.fromKey(hostKey));
KeyType.fromKey(hostKey).toString()); Signature signature = keyAlgorithm.newSignature();
signature.initVerify(hostKey); signature.initVerify(hostKey);
signature.update(H, 0, H.length); signature.update(H, 0, H.length);
if (!signature.verify(sig)) if (!signature.verify(sig))

View File

@@ -15,11 +15,12 @@
*/ */
package net.schmizz.sshj.userauth.method; package net.schmizz.sshj.userauth.method;
import com.hierynomus.sshj.key.KeyAlgorithm;
import net.schmizz.sshj.common.Buffer; import net.schmizz.sshj.common.Buffer;
import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.KeyType; import net.schmizz.sshj.common.KeyType;
import net.schmizz.sshj.common.SSHPacket; import net.schmizz.sshj.common.SSHPacket;
import net.schmizz.sshj.signature.Signature; import net.schmizz.sshj.signature.Signature;
import net.schmizz.sshj.transport.TransportException;
import net.schmizz.sshj.userauth.UserAuthException; import net.schmizz.sshj.userauth.UserAuthException;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider; import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
@@ -47,9 +48,15 @@ public abstract class KeyedAuthMethod
} }
// public key as 2 strings: [ key type | key blob ] // public key as 2 strings: [ key type | key blob ]
reqBuf.putString(KeyType.fromKey(key).toString()) KeyType keyType = KeyType.fromKey(key);
try {
KeyAlgorithm ka = params.getTransport().getKeyAlgorithm(keyType);
reqBuf.putString(ka.getKeyAlgorithm())
.putString(new Buffer.PlainBuffer().putPublicKey(key).getCompactData()); .putString(new Buffer.PlainBuffer().putPublicKey(key).getCompactData());
return reqBuf; return reqBuf;
} catch (IOException ioe) {
throw new UserAuthException("No KeyAlgorithm configured for key " + keyType);
}
} }
protected SSHPacket putSig(SSHPacket reqBuf) protected SSHPacket putSig(SSHPacket reqBuf)
@@ -61,17 +68,20 @@ public abstract class KeyedAuthMethod
throw new UserAuthException("Problem getting private key from " + kProv, ioe); throw new UserAuthException("Problem getting private key from " + kProv, ioe);
} }
final String kt = KeyType.fromKey(key).toString(); final KeyType kt = KeyType.fromKey(key);
Signature signature = Factory.Named.Util.create(params.getTransport().getConfig().getSignatureFactories(), kt); Signature signature;
if (signature == null) try {
throw new UserAuthException("Could not create signature instance for " + kt + " key"); signature = params.getTransport().getKeyAlgorithm(kt).newSignature();
} catch (TransportException e) {
throw new UserAuthException("No KeyAlgorithm configured for key " + kt);
}
signature.initSign(key); signature.initSign(key);
signature.update(new Buffer.PlainBuffer() signature.update(new Buffer.PlainBuffer()
.putString(params.getTransport().getSessionID()) .putString(params.getTransport().getSessionID())
.putBuffer(reqBuf) // & rest of the data for sig .putBuffer(reqBuf) // & rest of the data for sig
.getCompactData()); .getCompactData());
reqBuf.putSignature(kt, signature.encode(signature.sign())); reqBuf.putSignature(signature.getSignatureName(), signature.encode(signature.sign()));
return reqBuf; return reqBuf;
} }