Skip to content

Commit

Permalink
Introduce KeyAlgorithm to separate KeyType from Algorithm (Fixes #588)
Browse files Browse the repository at this point in the history
  • Loading branch information
hierynomus committed Jun 2, 2020
1 parent 4e802ce commit 8b0d1ca
Show file tree
Hide file tree
Showing 27 changed files with 625 additions and 102 deletions.
6 changes: 4 additions & 2 deletions src/itest/groovy/com/hierynomus/sshj/IntegrationSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.hierynomus.sshj

import com.hierynomus.sshj.key.ECDSAKeyAlgorithm
import com.hierynomus.sshj.key.EdDSAKeyAlgorithm
import com.hierynomus.sshj.signature.SignatureEdDSA
import net.schmizz.sshj.DefaultConfig
import net.schmizz.sshj.SSHClient
Expand All @@ -29,7 +31,7 @@ class IntegrationSpec extends IntegrationBaseSpec {
def "should accept correct key for #signatureName"() {
given:
def config = new DefaultConfig()
config.setSignatureFactories(signatureFactory)
config.setKeyAlgorithms(Collections.singletonList(signatureFactory))
SSHClient sshClient = new SSHClient(config)
sshClient.addHostKeyVerifier(fingerprint) // test-containers/ssh_host_ecdsa_key's fingerprint

Expand All @@ -40,7 +42,7 @@ class IntegrationSpec extends IntegrationBaseSpec {
sshClient.isConnected()

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"]
signatureName = signatureFactory.getName()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ package com.hierynomus.sshj.transport.mac

import com.hierynomus.sshj.IntegrationBaseSpec
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

class MacSpec extends IntegrationBaseSpec {
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/com/hierynomus/sshj/key/AbstractKeyAlgorithm.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
65 changes: 65 additions & 0 deletions src/main/java/com/hierynomus/sshj/key/DSAKeyAlgorithm.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
72 changes: 72 additions & 0 deletions src/main/java/com/hierynomus/sshj/key/ECDSAKeyAlgorithm.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
39 changes: 39 additions & 0 deletions src/main/java/com/hierynomus/sshj/key/EdDSAKeyAlgorithm.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
45 changes: 45 additions & 0 deletions src/main/java/com/hierynomus/sshj/key/KeyAlgorithm.java
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit 8b0d1ca

Please sign in to comment.