From f932bf318475e610fe98e7456c5f0e251228af1b Mon Sep 17 00:00:00 2001 From: jmxnzo Date: Sun, 13 Aug 2023 21:25:19 +0200 Subject: [PATCH 1/5] feat: Add equals and hashCode to SshPublicKeys and subclasses --- .../core/crypto/keys/CustomDsaPrivateKey.java | 17 ++++++++++++++++ .../core/crypto/keys/CustomDsaPublicKey.java | 17 ++++++++++++++++ .../core/crypto/keys/CustomEcPrivateKey.java | 14 +++++++++++++ .../core/crypto/keys/CustomEcPublicKey.java | 14 +++++++++++++ .../core/crypto/keys/CustomRsaPrivateKey.java | 15 ++++++++++++++ .../core/crypto/keys/CustomRsaPublicKey.java | 15 ++++++++++++++ .../core/crypto/keys/SshPublicKey.java | 20 +++++++++++++++++++ .../core/crypto/keys/XCurveEcPrivateKey.java | 17 ++++++++++++++++ .../core/crypto/keys/XCurveEcPublicKey.java | 17 ++++++++++++++++ 9 files changed, 146 insertions(+) diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPrivateKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPrivateKey.java index e4a17d84b..6a4250c36 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPrivateKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPrivateKey.java @@ -14,6 +14,7 @@ import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPrivateKey; import java.security.spec.DSAParameterSpec; +import java.util.Objects; /** A serializable DSA private key used in the DSA signature algorithm. */ @XmlRootElement @@ -83,4 +84,20 @@ public String getAlgorithm() { public DSAParams getParams() { return new DSAParameterSpec(p, q, g); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomDsaPrivateKey that = (CustomDsaPrivateKey) o; + return Objects.equals(p, that.p) + && Objects.equals(q, that.q) + && Objects.equals(g, that.g) + && Objects.equals(x, that.x); + } + + @Override + public int hashCode() { + return Objects.hash(p, q, g, x); + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPublicKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPublicKey.java index 124756e4a..66906b5a3 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPublicKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomDsaPublicKey.java @@ -14,6 +14,7 @@ import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.spec.DSAParameterSpec; +import java.util.Objects; /** A serializable DSA public key used in the DSA signature algorithm. */ @XmlRootElement @@ -83,4 +84,20 @@ public DSAParams getParams() { public String getAlgorithm() { return "DSA"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomDsaPublicKey that = (CustomDsaPublicKey) o; + return Objects.equals(p, that.p) + && Objects.equals(q, that.q) + && Objects.equals(g, that.g) + && Objects.equals(y, that.y); + } + + @Override + public int hashCode() { + return Objects.hash(p, q, g, y); + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPrivateKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPrivateKey.java index 908834ed1..500dea86a 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPrivateKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPrivateKey.java @@ -19,6 +19,7 @@ import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.InvalidParameterSpecException; +import java.util.Objects; /** * A serializable elliptic curve private key used in various EC-based algorithms like ECDH and @@ -97,4 +98,17 @@ public String getFormat() { public byte[] getEncoded() { return ArrayConverter.bigIntegerToByteArray(privateKey); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomEcPrivateKey that = (CustomEcPrivateKey) o; + return group == that.group && Objects.equals(privateKey, that.privateKey); + } + + @Override + public int hashCode() { + return Objects.hash(group, privateKey); + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPublicKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPublicKey.java index 4f3e7aace..384c86dba 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPublicKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomEcPublicKey.java @@ -21,6 +21,7 @@ import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.InvalidParameterSpecException; +import java.util.Objects; /** * A serializable elliptic curve public key used in various EC-based algorithms like ECDH and ECDSA. @@ -98,4 +99,17 @@ public ECParameterSpec getParams() { public static CustomEcPublicKey parse(byte[] encoded, NamedEcGroup group) { return new CustomEcPublicKey(PointFormatter.formatFromByteArray(group, encoded), group); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomEcPublicKey that = (CustomEcPublicKey) o; + return Objects.equals(publicKey, that.publicKey) && group == that.group; + } + + @Override + public int hashCode() { + return Objects.hash(publicKey, group); + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPrivateKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPrivateKey.java index 7a0a1f8af..d99f9f144 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPrivateKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPrivateKey.java @@ -12,6 +12,7 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.math.BigInteger; import java.security.interfaces.RSAPrivateKey; +import java.util.Objects; /** A serializable RSA private key used in RSA encryption and signatures. */ @XmlRootElement @@ -60,4 +61,18 @@ public void setPrivateExponent(BigInteger privateExponent) { public String getAlgorithm() { return "RSA"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomRsaPrivateKey that = (CustomRsaPrivateKey) o; + return Objects.equals(modulus, that.modulus) + && Objects.equals(privateExponent, that.privateExponent); + } + + @Override + public int hashCode() { + return Objects.hash(modulus, privateExponent); + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPublicKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPublicKey.java index dad0bc260..0dfd51b62 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPublicKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/CustomRsaPublicKey.java @@ -12,6 +12,7 @@ import jakarta.xml.bind.annotation.XmlRootElement; import java.math.BigInteger; import java.security.interfaces.RSAPublicKey; +import java.util.Objects; /** A serializable RSA public key used in RSA encryption and signatures. */ @XmlRootElement @@ -60,4 +61,18 @@ public void setPublicExponent(BigInteger publicExponent) { public String getAlgorithm() { return "RSA"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomRsaPublicKey that = (CustomRsaPublicKey) o; + return Objects.equals(modulus, that.modulus) + && Objects.equals(publicExponent, that.publicExponent); + } + + @Override + public int hashCode() { + return Objects.hash(modulus, publicExponent); + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/SshPublicKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/SshPublicKey.java index 8b62ac187..55db5f798 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/SshPublicKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/SshPublicKey.java @@ -15,6 +15,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; +import java.util.Objects; import java.util.Optional; /** @@ -132,12 +133,31 @@ public Optional getPrivateKey() { return Optional.ofNullable(privateKey); } + public void setPrivateKey(PRIVATE privateKey) { + this.privateKey = privateKey; + } + public String toString() { return String.format( "SshPublicKey[%s,%s]", publicKeyFormat.toString(), getPrivateKey().map(key -> "private").orElse("public")); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SshPublicKey that = (SshPublicKey) o; + return publicKeyFormat == that.publicKeyFormat + && Objects.equals(publicKey, that.publicKey) + && Objects.equals(privateKey, that.privateKey); + } + + @Override + public int hashCode() { + return Objects.hash(publicKeyFormat, publicKey, privateKey); + } + public enum FingerprintType { SHA1, SHA256 diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPrivateKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPrivateKey.java index d74f874dd..a67be1d8b 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPrivateKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPrivateKey.java @@ -20,6 +20,8 @@ import java.security.PrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Objects; import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.edec.EdECObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; @@ -114,4 +116,19 @@ public String getFormat() { public byte[] getEncoded() { return scalar; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + XCurveEcPrivateKey that = (XCurveEcPrivateKey) o; + return group == that.group && Arrays.equals(scalar, that.scalar); + } + + @Override + public int hashCode() { + int result = Objects.hash(group); + result = 31 * result + Arrays.hashCode(scalar); + return result; + } } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPublicKey.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPublicKey.java index b6ba9d310..5c2dbeafa 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPublicKey.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/crypto/keys/XCurveEcPublicKey.java @@ -20,6 +20,8 @@ import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; +import java.util.Objects; import org.bouncycastle.asn1.edec.EdECObjectIdentifiers; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; @@ -112,4 +114,19 @@ public String getFormat() { public byte[] getEncoded() { return coordinate; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + XCurveEcPublicKey that = (XCurveEcPublicKey) o; + return group == that.group && Arrays.equals(coordinate, that.coordinate); + } + + @Override + public int hashCode() { + int result = Objects.hash(group); + result = 31 * result + Arrays.hashCode(coordinate); + return result; + } } From 2e69db0d5a138f51e405a8bf5430994741c77a59 Mon Sep 17 00:00:00 2001 From: jmxnzo Date: Sun, 13 Aug 2023 21:27:40 +0200 Subject: [PATCH 2/5] feat: Add KeyParser, keys + testing --- .../nds/sshattacker/core/util/KeyParser.java | 364 ++++++++++++++++++ SSH-Core/src/main/resources/keys/id_dsa | 21 + SSH-Core/src/main/resources/keys/id_dsa.pub | 1 + SSH-Core/src/main/resources/keys/id_ecdsa | 9 + SSH-Core/src/main/resources/keys/id_ecdsa.pub | 1 + SSH-Core/src/main/resources/keys/id_ed25519 | 7 + .../src/main/resources/keys/id_ed25519.pub | 1 + SSH-Core/src/main/resources/keys/id_rsa | 27 ++ SSH-Core/src/main/resources/keys/id_rsa.pub | 1 + .../sshattacker/core/util/KeyParserTest.java | 183 +++++++++ 10 files changed, 615 insertions(+) create mode 100644 SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java create mode 100644 SSH-Core/src/main/resources/keys/id_dsa create mode 100644 SSH-Core/src/main/resources/keys/id_dsa.pub create mode 100644 SSH-Core/src/main/resources/keys/id_ecdsa create mode 100644 SSH-Core/src/main/resources/keys/id_ecdsa.pub create mode 100644 SSH-Core/src/main/resources/keys/id_ed25519 create mode 100644 SSH-Core/src/main/resources/keys/id_ed25519.pub create mode 100644 SSH-Core/src/main/resources/keys/id_rsa create mode 100644 SSH-Core/src/main/resources/keys/id_rsa.pub create mode 100644 SSH-Core/src/test/java/de/rub/nds/sshattacker/core/util/KeyParserTest.java diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java new file mode 100644 index 000000000..ee1c0aab0 --- /dev/null +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java @@ -0,0 +1,364 @@ +/* + * SSH-Attacker - A Modular Penetration Testing Framework for SSH + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.sshattacker.core.util; + +import de.rub.nds.sshattacker.core.constants.DataFormatConstants; +import de.rub.nds.sshattacker.core.constants.NamedEcGroup; +import de.rub.nds.sshattacker.core.constants.PublicKeyFormat; +import de.rub.nds.sshattacker.core.crypto.keys.*; +import de.rub.nds.sshattacker.core.crypto.util.PublicKeyHelper; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.security.*; +import java.security.spec.*; +import java.util.Arrays; +import java.util.Base64; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public final class KeyParser { + + private static final Logger LOGGER = LogManager.getLogger(); + + public KeyParser() {} + + public static SshPublicKey readPublicKeyFromBytes(String path) { + InputStream inputStream = KeyParser.class.getClassLoader().getResourceAsStream(path); + byte[] publicKeyBytes = new byte[0]; + try { + publicKeyBytes = inputStream.readAllBytes(); + } catch (IOException e) { + LOGGER.error( + "Error occured reading user key:" + path + ", continue without adding key!"); + return null; + } + int offset = 0; + byte[] keyBytes = unwrapPublicKeyBytes(publicKeyBytes); + return PublicKeyHelper.parse(Arrays.copyOfRange(keyBytes, offset, keyBytes.length)); + } + + public static SshPublicKey readKeyPairFromBytes(String path) { + InputStream inputStream = KeyParser.class.getClassLoader().getResourceAsStream(path); + byte[] privateKeyBytes = new byte[0]; + try { + privateKeyBytes = inputStream.readAllBytes(); + } catch (IOException e) { + LOGGER.error( + "Error occured reading user key: " + path + ", continue without adding key!"); + return null; + } + byte[] keyBytes = new byte[0]; + try { + keyBytes = unwrapPrivateKeyBytes(privateKeyBytes); + } catch (IllegalArgumentException e) { + LOGGER.error( + "Wrong key format provided: " + + path + + "please check to provide ssh private key to readKeyPairFromFile()"); + return null; + } + if (keyBytes.length == 0) { + LOGGER.error("Provided keyfiles was empty, please recheck " + path); + return null; + } + int offset = 0; + String fixedString = new String(Arrays.copyOfRange(keyBytes, offset, offset = offset + 14)); + // if the keybytes are starting with this string, we have to deal with a open-ssh key file, + // containing private and public key specs + if (!fixedString.equals("openssh-key-v1")) { + LOGGER.error( + "Currently only support for open-ssh keys is supported, failed to read key from " + + path); + return null; + } + + // 32-bit length, "none" # ciphername length and string + // 32-bit length, "none" # kdfname length and string + // 32-bit length, nil # kdf (0 length, no kdf) + // 32-bit 0x01 # number of keys, hard-coded to 1 (no length) + // 32-bit length, sshpub # public key in ssh format + // 32-bit length, keytype + // 32-bit length, pub0 + // 32-bit length, pub1 + // in this case we need to add +1 on the parser, because the string is finished with a + // null-byte, but would be interpreted wrong by Java + + offset = offset + 1; + BigInteger lengthCipherName = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + String ciphername = + new String( + Arrays.copyOfRange( + keyBytes, offset, offset = offset + lengthCipherName.intValue())); + BigInteger lengthKdfName = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + String kdfname = + new String( + Arrays.copyOfRange( + keyBytes, offset, offset = offset + lengthKdfName.intValue())); + + BigInteger lengthKdf = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + if (lengthKdf.intValue() != 0) {} + BigInteger numberOfKeys = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger pubkeyLength = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + + SshPublicKey sshPublicKey = + PublicKeyHelper.parse( + Arrays.copyOfRange( + keyBytes, offset, offset = offset + pubkeyLength.intValue())); + BigInteger privKeyLength = + new BigInteger( + Arrays.copyOfRange( + keyBytes, offset, offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + + sshPublicKey.setPrivateKey( + parsePrivateKey( + Arrays.copyOfRange(keyBytes, offset, offset + privKeyLength.intValue()))); + return sshPublicKey; + } + + public static CustomPrivateKey parsePrivateKey(byte[] keyBytes) { + int offset = 0; + offset = offset + 12; + BigInteger lengthPubKeyAlg = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + String pubKeyAlg = + new String( + Arrays.copyOfRange( + keyBytes, offset, offset = offset + lengthPubKeyAlg.intValue())); + + // 32-bit length for rnd+prv+comment+pad + // 64-bit dummy checksum? # a random 32-bit int, repeated + // 32-bit length, keytype # the private key (including public) + // 32-bit length, pub0 # Public Key parts + // 32-bit length, pub1 + // 32-bit length, prv0 # Private Key parts + // ... # (number varies by type) + // 32-bit length, comment # comment string + // padding bytes 0x010203 + switch (pubKeyAlg) { + case "ssh-rsa": + return readRsaPrivateKey(Arrays.copyOfRange(keyBytes, offset, keyBytes.length)); + case "ecdsa-sha2-nistp256": + case "ecdsa-sha2-nistp384": + case "ecdsa-sha2-nistp521": + return readEcdsaPrivateKey(Arrays.copyOfRange(keyBytes, offset, keyBytes.length)); + case "ssh-ed25519": + return readEd25519PrivateKey(Arrays.copyOfRange(keyBytes, offset, keyBytes.length)); + case "ssh-dss": + return readDsaPrivateKey(Arrays.copyOfRange(keyBytes, offset, keyBytes.length)); + default: + LOGGER.error(""); + return null; + } + } + + public static CustomRsaPrivateKey readRsaPrivateKey(byte[] keyBytes) { + int offset = 0; + BigInteger lengthN = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger n = + new BigInteger( + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthN.intValue())); + BigInteger lengthE = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + offset = offset + lengthE.intValue(); // because the coordinates have already been read from + // the pubkey, this step can be skipped right here + BigInteger lengthD = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger d = + new BigInteger( + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthD.intValue())); + // we don't need to read any further for now, but performance-wise it might be needed + // someday + return new CustomRsaPrivateKey(d, n); + } + + public static CustomEcPrivateKey readEcdsaPrivateKey(byte[] keyBytes) { + int offset = 0; + BigInteger curveSpeclength = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + String curveSpec = + new String( + Arrays.copyOfRange( + keyBytes, offset, offset = offset + curveSpeclength.intValue())); + BigInteger lengthCoordinates = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + offset = + offset + + lengthCoordinates + .intValue(); // because the coordinates have already been read from + // the pubkey, this step can be skipped right here + BigInteger lengthScalar = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger privateKey = + new BigInteger( + Arrays.copyOfRange( + keyBytes, offset, offset = offset + lengthScalar.intValue())); + return new CustomEcPrivateKey(privateKey, NamedEcGroup.fromIdentifier(curveSpec)); + } + + public static XCurveEcPrivateKey readEd25519PrivateKey(byte[] keyBytes) { + int offset = 0; + BigInteger lengthCoordinate = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + offset = + offset + + lengthCoordinate + .intValue(); // because the coordinates have already been read from + // the pubkey, this step can be skipped right here + BigInteger lengthScalar = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + byte[] scalar = + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthScalar.intValue() / 2); + return new XCurveEcPrivateKey(scalar, NamedEcGroup.CURVE25519); + } + + public static CustomDsaPrivateKey readDsaPrivateKey(byte[] keyBytes) { + int offset = 0; + BigInteger lengthP = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger p = + new BigInteger( + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthP.intValue())); + BigInteger lengthQ = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger q = + new BigInteger( + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthQ.intValue())); + BigInteger lengthG = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger g = + new BigInteger( + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthG.intValue())); + BigInteger lengthY = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + offset = offset + lengthY.intValue(); + BigInteger lengthX = + new BigInteger( + Arrays.copyOfRange( + keyBytes, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + BigInteger x = + new BigInteger( + Arrays.copyOfRange(keyBytes, offset, offset = offset + lengthX.intValue())); + return new CustomDsaPrivateKey(p, q, g, x); + } + + public static byte[] unwrapPublicKeyBytes(byte[] publicKeyBytes) { + // pubkey structure ssh-rsa AAAAB3NzaC1yc2E...Q02P1Eamz/nT4I3 root@localhost thus we want to + // cut the last part of the pubkey holding the ownership + String unwrappedKey = new String(publicKeyBytes, Charset.defaultCharset()).split(" ")[1]; + // replacements for public keyfile + for (PublicKeyFormat keyformat : PublicKeyFormat.values()) { + // we can replace the key type right here because it is kept in the key data anyways + unwrappedKey = unwrappedKey.replace(keyformat.getName(), ""); + } + // == are not accepted as Base64 Java encoding so we need to cut them off too + unwrappedKey = + unwrappedKey + .replace(" ", "") + .replace("=", "") + .replaceAll(System.lineSeparator(), ""); + byte[] keyBytes = Base64.getDecoder().decode(unwrappedKey); + return keyBytes; + } + + private static byte[] unwrapPrivateKeyBytes(byte[] privateKeyBytes) { + // replacements for private key + // == are not accepted as Base64 Java encoding so we need to cut them off too + String unwrappedKey = + new String(privateKeyBytes, Charset.defaultCharset()) + .replace("-----BEGIN OPENSSH PRIVATE KEY-----", "") + .replace("-----BEGIN RSA PRIVATE KEY-----", "") + .replaceAll(System.lineSeparator(), "") + .replace("-----END OPENSSH PRIVATE KEY-----", "") + .replace("-----END RSA PRIVATE KEY-----", "") + .replace("=", ""); + byte[] keyBytes = Base64.getDecoder().decode(unwrappedKey); + return keyBytes; + } +} diff --git a/SSH-Core/src/main/resources/keys/id_dsa b/SSH-Core/src/main/resources/keys/id_dsa new file mode 100644 index 000000000..5f56df5c6 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_dsa @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdzc2gtZH +NzAAAAgQDTTtJdNSNuWj78rjTDDwb0RNH76F3CnXHa1ajv1e1FYJ9OKUhN9eIduZJmZClu ++RCqmCL+zdl1FEedwoxpq0JKEteS47ONVsLeZo2niChuUTaKwbg3x8kotbWmonfs6pQ2+v +fL8nnNEDaVt67Ja075daIYSDu3Ff4M/ue+ngffpQAAABUA2PPaxr+qLOr8vw4kndB1CROl +v+kAAACAQrTZyYOUGt/aDm2cRYP2+pZBcBeziddQz9cXxZH9EpMRZ9EsluM0Xnm2IlNgSF +/y6DnKnDjUQ6SuLxPWWT/2lgWGasStHNZ3RB/Q1u0V/2NtgjETDMB7iqbx31SmUXmDaV4+ +X/o7/5owtEQj2FBM8HSK+Zynm2qFmXWefG27tdwAAACAaIAUNbKiYPd4UgvSPJ6/OK9SPL +gdZMVvh0GJCxIGyi4XXulL/yyEYB81f7W2BxqyJA1yWNHt49i8wvbnjepdy7W8MVuFih3Y +M2B+BDPN4v0kJA3S0cRflQj7ol3I5vQNm8WLbTJGhlAn6bXkj0EOCEtSoa6Z0pZlQyQ3ZE +NnV/YAAAHoFoHDIxaBwyMAAAAHc3NoLWRzcwAAAIEA007SXTUjblo+/K40ww8G9ETR++hd +wp1x2tWo79XtRWCfTilITfXiHbmSZmQpbvkQqpgi/s3ZdRRHncKMaatCShLXkuOzjVbC3m +aNp4goblE2isG4N8fJKLW1pqJ37OqUNvr3y/J5zRA2lbeuyWtO+XWiGEg7txX+DP7nvp4H +36UAAAAVANjz2sa/qizq/L8OJJ3QdQkTpb/pAAAAgEK02cmDlBrf2g5tnEWD9vqWQXAXs4 +nXUM/XF8WR/RKTEWfRLJbjNF55tiJTYEhf8ug5ypw41EOkri8T1lk/9pYFhmrErRzWd0Qf +0NbtFf9jbYIxEwzAe4qm8d9UplF5g2lePl/6O/+aMLREI9hQTPB0ivmcp5tqhZl1nnxtu7 +XcAAAAgGiAFDWyomD3eFIL0jyevzivUjy4HWTFb4dBiQsSBsouF17pS/8shGAfNX+1tgca +siQNcljR7ePYvML2543qXcu1vDFbhYod2DNgfgQzzeL9JCQN0tHEX5UI+6JdyOb0DZvFi2 +0yRoZQJ+m15I9BDghLUqGumdKWZUMkN2RDZ1f2AAAAFGYWVWRC9rjx6otfo6k7tjjVVzfY +AAAAEHNzaGF0dGFja0Bkb2NrZXIBAgM= +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/id_dsa.pub b/SSH-Core/src/main/resources/keys/id_dsa.pub new file mode 100644 index 000000000..2a873acd1 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBANNO0l01I25aPvyuNMMPBvRE0fvoXcKdcdrVqO/V7UVgn04pSE314h25kmZkKW75EKqYIv7N2XUUR53CjGmrQkoS15Ljs41Wwt5mjaeIKG5RNorBuDfHySi1taaid+zqlDb698vyec0QNpW3rslrTvl1ohhIO7cV/gz+576eB9+lAAAAFQDY89rGv6os6vy/DiSd0HUJE6W/6QAAAIBCtNnJg5Qa39oObZxFg/b6lkFwF7OJ11DP1xfFkf0SkxFn0SyW4zReebYiU2BIX/LoOcqcONRDpK4vE9ZZP/aWBYZqxK0c1ndEH9DW7RX/Y22CMRMMwHuKpvHfVKZReYNpXj5f+jv/mjC0RCPYUEzwdIr5nKebaoWZdZ58bbu13AAAAIBogBQ1sqJg93hSC9I8nr84r1I8uB1kxW+HQYkLEgbKLhde6Uv/LIRgHzV/tbYHGrIkDXJY0e3j2LzC9ueN6l3LtbwxW4WKHdgzYH4EM83i/SQkDdLRxF+VCPuiXcjm9A2bxYttMkaGUCfpteSPQQ4IS1KhrpnSlmVDJDdkQ2dX9g== sshattacker@docker diff --git a/SSH-Core/src/main/resources/keys/id_ecdsa b/SSH-Core/src/main/resources/keys/id_ecdsa new file mode 100644 index 000000000..0e0ccbb22 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_ecdsa @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQRdoWi9i+lSIqdSVYhzDZ/SI4AvmrCE +yKuCPcyVvb7gA4Bvjf1Bo2q14uNvJRcaXAy69EjZfqjrjQinAnQXX2UNAAAAqN0Nb8TdDW +/EAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBF2haL2L6VIip1JV +iHMNn9IjgC+asITIq4I9zJW9vuADgG+N/UGjarXi428lFxpcDLr0SNl+qOuNCKcCdBdfZQ +0AAAAgNBKsB8DzVfUt8GPW4UZNDJYkxdbB4PwU0aaot5lV+MsAAAAQc3NoYXR0YWNrQGRv +Y2tlcg== +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/id_ecdsa.pub b/SSH-Core/src/main/resources/keys/id_ecdsa.pub new file mode 100644 index 000000000..9e1871dc7 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBF2haL2L6VIip1JViHMNn9IjgC+asITIq4I9zJW9vuADgG+N/UGjarXi428lFxpcDLr0SNl+qOuNCKcCdBdfZQ0= sshattacker@docker diff --git a/SSH-Core/src/main/resources/keys/id_ed25519 b/SSH-Core/src/main/resources/keys/id_ed25519 new file mode 100644 index 000000000..b06909468 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCZr1RtMN0XcMwnoaHOetHOxymCNSdSk1IUHon380IPLAAAAJjIReRKyEXk +SgAAAAtzc2gtZWQyNTUxOQAAACCZr1RtMN0XcMwnoaHOetHOxymCNSdSk1IUHon380IPLA +AAAEBtNwOHbtAgdRAvdn4uqWnjEbd3b3FjC3wd8+VcmNZkG5mvVG0w3RdwzCehoc560c7H +KYI1J1KTUhQeiffzQg8sAAAAD2phbkBqYW4tZGVza3RvcAECAwQFBg== +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/id_ed25519.pub b/SSH-Core/src/main/resources/keys/id_ed25519.pub new file mode 100644 index 000000000..4c6051a2d --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJmvVG0w3RdwzCehoc560c7HKYI1J1KTUhQeiffzQg8s sshattacker@docker diff --git a/SSH-Core/src/main/resources/keys/id_rsa b/SSH-Core/src/main/resources/keys/id_rsa new file mode 100644 index 000000000..f81159ba1 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAnfDHBjhEiv71eZvHwWHVvChrrrik3HD/77L0gTqBB0fTy/zR +yanOdicnMe0eLAumT+ua9jSujk32mbLTtSr032FsqAA1AuOLgb+mgBFIx7qxhwpp +S0TYL/CYYz7bCb+6tSs+dJjOGCaBPaAQAA98RYh3+Fn0ZEIIUyINYy2dH8ET6IXm +MfFd/PH926kMDFqlILxqVaVqGynq1Ukvg/5+a5SUr74WYV2qRGwpCcIY3NdQrkqa +nGnHTXSOkEuo4s4oEtHOPE7RL9gsyn/oH4iCOQdnAmVu8dP5PkcqrlCaCuXiQcT9 +m2YfTMb/sC1BanJUaeUeJyBLPbPyiWHiRKnmwwIDAQABAoIBAQCHAevO+Eg3HIwP +QMd3Gb9PUKoDt5hNS1aruihhUvY6l/6G730QylNPElbhyZQyCF9JD9ftv8i6ohA6 +/+8SfT7GuAvebBbkekelSIL2FFBHUuIv0gmBqr619A7/PxqTcc4S0X1Yw8ngQQHX +ALzMoHAVK/uJUrOjBAMDtScGcVZPbidT4F5BOTHiKmsRX9MmT9bkwly5AczdAG2b +V4U3n3y8wbvRSa/aa1H+E0MPtcoZ2llK/M0r2ZRzAB6ZUDMRbUjTKdQiVe8O7BGm +0jEOuXkS1xm3t110aWYT4hMF2mcVhGvwTE52BG+/hqeT2WwP5wJjhpbu1LdIjBgj +Pbh55wFJAoGBAPmhmpfFM/GmKy/QCpRYe4vPEdfOf924DxLSG19Cw/QkKYBEGxpR +dsZtoqUtjERty5c8/HcNkevrN8D3iqxTaDYLYBHwbvXsyIjGHUL5j7aDl9SfIeA8 +QoELKwjNYa4k+fhIbUX62n+NsrtpYnHlMvyNpS8jVF6eKhF4fMXf3D3PAoGBAKH4 +UksdFB+4sxqPx70l4HSF8VK0oZgJRtHoiElm4BXnzv1IrRCUZA/Ol66Ew8/NPUE+ +bPOmkynks0Ut+Wg3F2i+YEl476Nz406o8QULT0mjtrOS6Eknln51eHkWYPRVjYPp +Iycon3LRL+Y4aU1tqa3cJQ1wJWhvEN63M4T1rxjNAoGBAJPpXWBwSMb2XsCF1L7x +bsL4fuoQQVNuq//K3s0jElim1LBbqnN9sZMBg028H1CsfeWvDSi9sajIRtDf3Bsf +kK/1LYdzn0u4cVoZiV0V4kGS13P0lm33RrCPnYApsact4a9rutOsP6s0mqLRXrN9 +yyg6BZZYqLUnomWXrtbQPf+hAoGAKJfcwBiMl5qpwKlyTNR2WZ3MKoc8zKbeifM2 +XPcciEDtnosdXL9kCJYla8a4cJcml/h2Q+ZmkaRQzbDFBjpwcn7sEN3vaU69FFTA ++xunhnQycPULpHH4hL8aL3bNW88pRXsjpUfIFnWZBKD0u0QVt44p9yE5LuBPIRJX +JiaQ+K0CgYEA7rAPinHSdPweHzFU8tg57ai4BRRWWROF6W6NynOc5vKDswAAGn9u +bxFwHAE7633+HH19BjG7dukgU9/XoKT6Rp5q0za+YLT4xFP4HuXeHr48z4tHoRd9 +gc1imWyzmsXT4b8nws8/NzqMQyR50bVuIgy3jDH/+Hy39hmAcZ9wEcw= +-----END RSA PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/id_rsa.pub b/SSH-Core/src/main/resources/keys/id_rsa.pub new file mode 100644 index 000000000..9f6fd9742 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCd8McGOESK/vV5m8fBYdW8KGuuuKTccP/vsvSBOoEHR9PL/NHJqc52Jycx7R4sC6ZP65r2NK6OTfaZstO1KvTfYWyoADUC44uBv6aAEUjHurGHCmlLRNgv8JhjPtsJv7q1Kz50mM4YJoE9oBAAD3xFiHf4WfRkQghTIg1jLZ0fwRPoheYx8V388f3bqQwMWqUgvGpVpWobKerVSS+D/n5rlJSvvhZhXapEbCkJwhjc11CuSpqcacdNdI6QS6jizigS0c48TtEv2CzKf+gfiII5B2cCZW7x0/k+RyquUJoK5eJBxP2bZh9Mxv+wLUFqclRp5R4nIEs9s/KJYeJEqebD sshattacker@docker diff --git a/SSH-Core/src/test/java/de/rub/nds/sshattacker/core/util/KeyParserTest.java b/SSH-Core/src/test/java/de/rub/nds/sshattacker/core/util/KeyParserTest.java new file mode 100644 index 000000000..f63123c51 --- /dev/null +++ b/SSH-Core/src/test/java/de/rub/nds/sshattacker/core/util/KeyParserTest.java @@ -0,0 +1,183 @@ +/* + * SSH-Attacker - A Modular Penetration Testing Framework for SSH + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.sshattacker.core.util; + +import static org.junit.jupiter.api.Assertions.*; + +import de.rub.nds.modifiablevariable.util.ArrayConverter; +import de.rub.nds.sshattacker.core.constants.NamedEcGroup; +import de.rub.nds.sshattacker.core.constants.PublicKeyFormat; +import de.rub.nds.sshattacker.core.crypto.ec.PointFormatter; +import de.rub.nds.sshattacker.core.crypto.keys.*; +import java.io.InputStream; +import java.math.BigInteger; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.Test; + +public class KeyParserTest { + private static final Logger LOGGER = LogManager.getLogger(); + + // sshkey generated with "openssl ecparam -name secp521r1 -genkey -out key.pem" + // pubkey for authorized_keys file on host generated with "ssh-keygen -y -f + // key.pem > + // key.pub" + private List> userKeys = + List.of( + new SshPublicKey<>( + PublicKeyFormat.SSH_RSA, + new CustomRsaPublicKey( + new BigInteger("10001", 16), + new BigInteger( + "009df0c70638448afef5799bc7c161d5bc286baeb8a4dc70ffefb2f4813a" + + "810747d3cbfcd1c9a9ce76272731ed1e2c0ba64feb9af634ae8e4df699b2" + + "d3b52af4df616ca8003502e38b81bfa6801148c7bab1870a694b44d82ff0" + + "98633edb09bfbab52b3e7498ce1826813da010000f7c458877f859f46442" + + "0853220d632d9d1fc113e885e631f15dfcf1fddba90c0c5aa520bc6a55a5" + + "6a1b29ead5492f83fe7e6b9494afbe16615daa446c2909c218dcd750ae4a" + + "9a9c69c74d748e904ba8e2ce2812d1ce3c4ed12fd82cca7fe81f88823907" + + "6702656ef1d3f93e472aae509a0ae5e241c4fd9b661f4cc6ffb02d416a72" + + "5469e51e27204b3db3f28961e244a9e6c3", + 16)), + new CustomRsaPrivateKey( + new BigInteger( + "008701ebcef848371c8c0f40c77719bf4f50aa03b7984d4b56abba286152" + + "f63a97fe86ef7d10ca534f1256e1c99432085f490fd7edbfc8baa2103aff" + + "ef127d3ec6b80bde6c16e47a47a54882f614504752e22fd20981aabeb5f4" + + "0eff3f1a9371ce12d17d58c3c9e04101d700bccca070152bfb8952b3a304" + + "0303b5270671564f6e2753e05e413931e22a6b115fd3264fd6e4c25cb901" + + "ccdd006d9b5785379f7cbcc1bbd149afda6b51fe13430fb5ca19da594afc" + + "cd2bd99473001e995033116d48d329d42255ef0eec11a6d2310eb97912d7" + + "19b7b75d74696613e21305da6715846bf04c4e76046fbf86a793d96c0fe7" + + "02638696eed4b7488c18233db879e70149", + 16), + new BigInteger( + "009df0c70638448afef5799bc7c161d5bc286baeb8a4dc70ffefb2f4813a" + + "810747d3cbfcd1c9a9ce76272731ed1e2c0ba64feb9af634ae8e4df699b2" + + "d3b52af4df616ca8003502e38b81bfa6801148c7bab1870a694b44d82ff0" + + "98633edb09bfbab52b3e7498ce1826813da010000f7c458877f859f46442" + + "0853220d632d9d1fc113e885e631f15dfcf1fddba90c0c5aa520bc6a55a5" + + "6a1b29ead5492f83fe7e6b9494afbe16615daa446c2909c218dcd750ae4a" + + "9a9c69c74d748e904ba8e2ce2812d1ce3c4ed12fd82cca7fe81f88823907" + + "6702656ef1d3f93e472aae509a0ae5e241c4fd9b661f4cc6ffb02d416a72" + + "5469e51e27204b3db3f28961e244a9e6c3", + 16))), + new SshPublicKey<>( + PublicKeyFormat.ECDSA_SHA2_NISTP256, + new CustomEcPublicKey( + PointFormatter.formatFromByteArray( + NamedEcGroup.SECP256R1, + ArrayConverter.hexStringToByteArray( + "045da168bd8be95222a7525588730d9fd223802f9ab084c8ab" + + "823dcc95bdbee003806f8dfd41a36ab5e2e36f25171a5c0c" + + "baf448d97ea8eb8d08a70274175f650d")), + NamedEcGroup.SECP256R1), + new CustomEcPrivateKey( + new BigInteger( + "3412ac07c0f355f52df063d6e1464d0c9624c5d6c1e0fc14" + + "d1a6a8b79955f8cb", + 16), + NamedEcGroup.SECP256R1)), + new SshPublicKey<>( + PublicKeyFormat.SSH_ED25519, + new XCurveEcPublicKey( + ArrayConverter.hexStringToByteArray( + "99AF546D30DD1770CC27A1A1CE7AD1CEC729823527529352141E89F7F3420F2C"), + NamedEcGroup.CURVE25519), + new XCurveEcPrivateKey( + ArrayConverter.hexStringToByteArray( + "6D3703876ED02075102F767E2EA969E311B7776F71630B7C1DF3E55C98D6641B"), + NamedEcGroup.CURVE25519)), + new SshPublicKey<>( + PublicKeyFormat.SSH_DSS, + new CustomDsaPublicKey( + new BigInteger( + "00D34ED25D35236E5A3EFCAE34C30F06F444D1FBE85DC29D71DAD5" + + "A8EFD5ED45609F4E29484DF5E21DB9926664296EF910AA9822FECDD" + + "97514479DC28C69AB424A12D792E3B38D56C2DE668DA788286E5136" + + "8AC1B837C7C928B5B5A6A277ECEA9436FAF7CBF279CD103695B7AEC" + + "96B4EF975A218483BB715FE0CFEE7BE9E07DFA5", + 16), + new BigInteger( + "00D8F3DAC6BFAA2CEAFCBF0E249DD0750913A5BFE9", 16), + new BigInteger( + "42B4D9C983941ADFDA0E6D9C4583F6FA96417017B389D750CFD717C" + + "591FD12931167D12C96E3345E79B6225360485FF2E839CA9C38" + + "D443A4AE2F13D6593FF69605866AC4AD1CD677441FD0D6ED15F" + + "F636D8231130CC07B8AA6F1DF54A6517983695E3E5FFA3BFF9A" + + "30B44423D8504CF0748AF99CA79B6A8599759E7C6DBBB5DC", + 16), + new BigInteger( + "68801435B2A260F778520BD23C9EBF38AF523CB81D64C56F8741890B" + + "1206CA2E175EE94BFF2C84601F357FB5B6071AB2240D7258D1EDE3D8B" + + "CC2F6E78DEA5DCBB5BC315B858A1DD833607E0433CDE2FD24240DD2D1" + + "C45F9508FBA25DC8E6F40D9BC58B6D3246865027E9B5E48F410E084B5" + + "2A1AE99D2966543243764436757F6", + 16)), + new CustomDsaPrivateKey( + new BigInteger( + "00D34ED25D35236E5A3EFCAE34C30F06F444D1FBE85DC29D71DAD5A8EFD5" + + "ED45609F4E29484DF5E21DB9926664296EF910AA9822FECDD97514479D" + + "C28C69AB424A12D792E3B38D56C2DE668DA788286E51368AC1B837C7C9" + + "28B5B5A6A277ECEA9436FAF7CBF279CD103695B7AEC96B4EF975A21848" + + "3BB715FE0CFEE7BE9E07DFA5", + 16), + new BigInteger( + "00D8F3DAC6BFAA2CEAFCBF0E249DD0750913A5BFE9", 16), + new BigInteger( + "42B4D9C983941ADFDA0E6D9C4583F6FA96417017B389D750CFD717C591FD" + + "12931167D12C96E3345E79B6225360485FF2E839CA9C38D443A4AE2F13D6" + + "593FF69605866AC4AD1CD677441FD0D6ED15FF636D8231130CC07B8AA6F1" + + "DF54A6517983695E3E5FFA3BFF9A30B44423D8504CF0748AF99CA79B6A85" + + "99759E7C6DBBB5DC", + 16), + new BigInteger( + "6616556442F6B8F1EA8B5FA3A93BB638D55737D8", 16)))); + + InputStream id_rsa = KeyParser.class.getClassLoader().getResourceAsStream("keys/id_rsa-new1"); + + InputStream id_dsa = KeyParser.class.getClassLoader().getResourceAsStream("keys/id_dsa"); + + InputStream id_ecdsa = KeyParser.class.getClassLoader().getResourceAsStream("keys/id_ecdsa"); + + InputStream id_ed25519 = + KeyParser.class.getClassLoader().getResourceAsStream("keys/id_ed25519"); + + @Test + public void testRsaKeyParsing() { + SshPublicKey rsaKey; + rsaKey = KeyParser.readKeyPairFromBytes("keys/id_rsa"); + SshPublicKey check = userKeys.get(0); + assertTrue(check.equals(rsaKey)); + assertEquals(rsaKey, userKeys.get(0)); + } + + @Test + public void testDsaKeyParsing() { + SshPublicKey dsaKey = null; + dsaKey = KeyParser.readKeyPairFromBytes("keys/id_dsa"); + assertEquals(dsaKey, userKeys.get(3)); + } + + @Test + public void testEcdsaKeyParsing() { + SshPublicKey ecdsaKey; + ecdsaKey = KeyParser.readKeyPairFromBytes("keys/id_ecdsa"); + + assertTrue(ecdsaKey.equals(userKeys.get(1))); + } + + @Test + public void testEd25519KeyParsing() { + SshPublicKey ed25519Key; + ed25519Key = KeyParser.readKeyPairFromBytes("keys/id_ed25519"); + + assertEquals(ed25519Key, userKeys.get(2)); + } +} From 9d002df65731b9a9aad2cee0daba5cf17582bb34 Mon Sep 17 00:00:00 2001 From: jmxnzo Date: Sun, 13 Aug 2023 21:28:01 +0200 Subject: [PATCH 3/5] feat: Change userKeys in Config --- .../nds/sshattacker/core/config/Config.java | 133 ++---------------- 1 file changed, 12 insertions(+), 121 deletions(-) diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java index abf676f89..a4e0fddee 100755 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java @@ -19,6 +19,7 @@ import de.rub.nds.sshattacker.core.protocol.transport.message.extension.AbstractExtension; import de.rub.nds.sshattacker.core.protocol.transport.message.extension.DelayCompressionExtension; import de.rub.nds.sshattacker.core.protocol.transport.message.extension.ServerSigAlgsExtension; +import de.rub.nds.sshattacker.core.util.KeyParser; import de.rub.nds.sshattacker.core.workflow.action.executor.WorkflowExecutorType; import de.rub.nds.sshattacker.core.workflow.factory.WorkflowTraceType; import de.rub.nds.sshattacker.core.workflow.filter.FilterType; @@ -309,7 +310,7 @@ public class Config implements Serializable { /** The List of user keys for public key authentication */ @XmlElement(name = "userKey") @XmlElementWrapper - private List> userKeys; + private List> userKeys = new ArrayList<>(); // endregion // region Channel @@ -858,126 +859,7 @@ public Config() { AuthenticationResponse preConfiguredAuthResponse2 = new AuthenticationResponse(); preConfiguredAuthResponse2.add(new AuthenticationResponse.ResponseEntry(false)); preConfiguredAuthResponses.add(preConfiguredAuthResponse2); - - // sshkey generated with "openssl ecparam -name secp521r1 -genkey -out key.pem" - // pubkey for authorized_keys file on host generated with "ssh-keygen -y -f - // key.pem > - // key.pub" - userKeys = - List.of( - new SshPublicKey<>( - PublicKeyFormat.SSH_RSA, - new CustomRsaPublicKey( - new BigInteger("10001", 16), - new BigInteger( - "009df0c70638448afef5799bc7c161d5bc286baeb8a4dc70ffefb2f4813a" - + "810747d3cbfcd1c9a9ce76272731ed1e2c0ba64feb9af634ae8e4df699b2" - + "d3b52af4df616ca8003502e38b81bfa6801148c7bab1870a694b44d82ff0" - + "98633edb09bfbab52b3e7498ce1826813da010000f7c458877f859f46442" - + "0853220d632d9d1fc113e885e631f15dfcf1fddba90c0c5aa520bc6a55a5" - + "6a1b29ead5492f83fe7e6b9494afbe16615daa446c2909c218dcd750ae4a" - + "9a9c69c74d748e904ba8e2ce2812d1ce3c4ed12fd82cca7fe81f88823907" - + "6702656ef1d3f93e472aae509a0ae5e241c4fd9b661f4cc6ffb02d416a72" - + "5469e51e27204b3db3f28961e244a9e6c3", - 16)), - new CustomRsaPrivateKey( - new BigInteger( - "008701ebcef848371c8c0f40c77719bf4f50aa03b7984d4b56abba286152" - + "f63a97fe86ef7d10ca534f1256e1c99432085f490fd7edbfc8baa2103aff" - + "ef127d3ec6b80bde6c16e47a47a54882f614504752e22fd20981aabeb5f4" - + "0eff3f1a9371ce12d17d58c3c9e04101d700bccca070152bfb8952b3a304" - + "0303b5270671564f6e2753e05e413931e22a6b115fd3264fd6e4c25cb901" - + "ccdd006d9b5785379f7cbcc1bbd149afda6b51fe13430fb5ca19da594afc" - + "cd2bd99473001e995033116d48d329d42255ef0eec11a6d2310eb97912d7" - + "19b7b75d74696613e21305da6715846bf04c4e76046fbf86a793d96c0fe7" - + "02638696eed4b7488c18233db879e70149", - 16), - new BigInteger( - "009df0c70638448afef5799bc7c161d5bc286baeb8a4dc70ffefb2f4813a" - + "810747d3cbfcd1c9a9ce76272731ed1e2c0ba64feb9af634ae8e4df699b2" - + "d3b52af4df616ca8003502e38b81bfa6801148c7bab1870a694b44d82ff0" - + "98633edb09bfbab52b3e7498ce1826813da010000f7c458877f859f46442" - + "0853220d632d9d1fc113e885e631f15dfcf1fddba90c0c5aa520bc6a55a5" - + "6a1b29ead5492f83fe7e6b9494afbe16615daa446c2909c218dcd750ae4a" - + "9a9c69c74d748e904ba8e2ce2812d1ce3c4ed12fd82cca7fe81f88823907" - + "6702656ef1d3f93e472aae509a0ae5e241c4fd9b661f4cc6ffb02d416a72" - + "5469e51e27204b3db3f28961e244a9e6c3", - 16))), - new SshPublicKey<>( - PublicKeyFormat.ECDSA_SHA2_NISTP521, - new CustomEcPublicKey( - PointFormatter.formatFromByteArray( - NamedEcGroup.SECP521R1, - ArrayConverter.hexStringToByteArray( - "0400c94546ca3a758e2be7700c6710dbc193db62b511b51c" - + "2e5ae09e92723527078bfc97d7cfe0b30adec350905d4c3b" - + "2f798b88d57ca1a4cc8600ffa9568b50b8553400ce85433f" - + "fb71641153d690d1c253c8ca395daa9100a547f42a0ca8ae" - + "e4711bcc750294fd6719bb6348d0b92c51d00b7a12ba0646" - + "433d2f56677b4540ddf89a5da5")), - NamedEcGroup.SECP521R1), - new CustomEcPrivateKey( - new BigInteger( - "000bf5ef2fdec03bfa6cf0e2c5ee58c8bcfe0d1b41920792151f2c" - + "51b0aa621743b613056155bd51bde866f92b3e9bcfed230381" - + "b3dab5100a03c5965538c6f1c30a9", - 16), - NamedEcGroup.SECP521R1)), - new SshPublicKey<>( - PublicKeyFormat.SSH_ED25519, - new XCurveEcPublicKey( - ArrayConverter.hexStringToByteArray( - "99AF546D30DD1770CC27A1A1CE7AD1CEC729823527529352141E89F7F3420F2C"), - NamedEcGroup.CURVE25519), - new XCurveEcPrivateKey( - ArrayConverter.hexStringToByteArray( - "6D3703876ED02075102F767E2EA969E311B7776F71630B7C1DF3E55C98D6641B"), - NamedEcGroup.CURVE25519)), - new SshPublicKey<>( - PublicKeyFormat.SSH_DSS, - new CustomDsaPublicKey( - new BigInteger( - "00D34ED25D35236E5A3EFCAE34C30F06F444D1FBE85DC29D71DAD5" - + "A8EFD5ED45609F4E29484DF5E21DB9926664296EF910AA9822FECDD" - + "97514479DC28C69AB424A12D792E3B38D56C2DE668DA788286E5136" - + "8AC1B837C7C928B5B5A6A277ECEA9436FAF7CBF279CD103695B7AEC" - + "96B4EF975A218483BB715FE0CFEE7BE9E07DFA5", - 16), - new BigInteger( - "00D8F3DAC6BFAA2CEAFCBF0E249DD0750913A5BFE9", 16), - new BigInteger( - "42B4D9C983941ADFDA0E6D9C4583F6FA96417017B389D750CFD717C" - + "591FD12931167D12C96E3345E79B6225360485FF2E839CA9C38" - + "D443A4AE2F13D6593FF69605866AC4AD1CD677441FD0D6ED15F" - + "F636D8231130CC07B8AA6F1DF54A6517983695E3E5FFA3BFF9A" - + "30B44423D8504CF0748AF99CA79B6A8599759E7C6DBBB5DC", - 16), - new BigInteger( - "68801435B2A260F778520BD23C9EBF38AF523CB81D64C56F8741890B" - + "1206CA2E175EE94BFF2C84601F357FB5B6071AB2240D7258D1EDE3D8B" - + "CC2F6E78DEA5DCBB5BC315B858A1DD833607E0433CDE2FD24240DD2D1" - + "C45F9508FBA25DC8E6F40D9BC58B6D3246865027E9B5E48F410E084B5" - + "2A1AE99D2966543243764436757F6", - 16)), - new CustomDsaPrivateKey( - new BigInteger( - "00D34ED25D35236E5A3EFCAE34C30F06F444D1FBE85DC29D71DAD5A8EFD5" - + "ED45609F4E29484DF5E21DB9926664296EF910AA9822FECDD97514479D" - + "C28C69AB424A12D792E3B38D56C2DE668DA788286E51368AC1B837C7C9" - + "28B5B5A6A277ECEA9436FAF7CBF279CD103695B7AEC96B4EF975A21848" - + "3BB715FE0CFEE7BE9E07DFA5", - 16), - new BigInteger( - "00D8F3DAC6BFAA2CEAFCBF0E249DD0750913A5BFE9", 16), - new BigInteger( - "42B4D9C983941ADFDA0E6D9C4583F6FA96417017B389D750CFD717C591FD" - + "12931167D12C96E3345E79B6225360485FF2E839CA9C38D443A4AE2F13D6" - + "593FF69605866AC4AD1CD677441FD0D6ED15FF636D8231130CC07B8AA6F1" - + "DF54A6517983695E3E5FFA3BFF9A30B44423D8504CF0748AF99CA79B6A85" - + "99759E7C6DBBB5DC", - 16), - new BigInteger( - "6616556442F6B8F1EA8B5FA3A93BB638D55737D8", 16)))); + addUserKeys("keys/id_ecdsa", "keys/id_rsa", "keys/id_dsa", "keys/id_ed25519"); // endregion // region Channel initialization @@ -1575,6 +1457,15 @@ public List getPreConfiguredAuthResponses() { public List> getUserKeys() { return userKeys; } + + public void addUserKeys(String... pathlist) { + SshPublicKey userKey; + for (String path : pathlist) { + if ((userKey = KeyParser.readKeyPairFromBytes(path)) != null) { + this.userKeys.add(userKey); + } + } + } // endregion // region Setters for authentication public void setAuthenticationMethod(AuthenticationMethod authenticationMethod) { From 62fe404a4c2a4d43a0d09ab235b7ef0d9e81aceb Mon Sep 17 00:00:00 2001 From: jmxnzo Date: Mon, 14 Aug 2023 00:22:55 +0200 Subject: [PATCH 4/5] feat: KeyParser and add support for hostkeys-00@openssh.com parsing --- ...lRequestOpenSshHostKeysMessageHandler.java | 6 +- .../sshattacker/core/state/SshContext.java | 10 ++ .../nds/sshattacker/core/util/KeyParser.java | 124 +++++++++++++++--- 3 files changed, 120 insertions(+), 20 deletions(-) diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/protocol/connection/handler/GlobalRequestOpenSshHostKeysMessageHandler.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/protocol/connection/handler/GlobalRequestOpenSshHostKeysMessageHandler.java index 3b4179852..aafe7cce9 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/protocol/connection/handler/GlobalRequestOpenSshHostKeysMessageHandler.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/protocol/connection/handler/GlobalRequestOpenSshHostKeysMessageHandler.java @@ -13,6 +13,7 @@ import de.rub.nds.sshattacker.core.protocol.connection.preparator.GlobalRequestOpenSshHostKeysMessagePreparator; import de.rub.nds.sshattacker.core.protocol.connection.serializer.GlobalRequestOpenSshHostKeysMessageSerializer; import de.rub.nds.sshattacker.core.state.SshContext; +import de.rub.nds.sshattacker.core.util.KeyParser; public class GlobalRequestOpenSshHostKeysMessageHandler extends SshMessageHandler { @@ -27,7 +28,10 @@ public GlobalRequestOpenSshHostKeysMessageHandler( } @Override - public void adjustContext() {} + public void adjustContext() { + // this parses the hostkeyblob and sets the hostkeys in the context + context.setServerHostKeys(KeyParser.parseHostkeyBlob(message.getHostKeys().getValue())); + } @Override public SshMessageParser getParser(byte[] array) { diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/state/SshContext.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/state/SshContext.java index 78d812895..135dc69fa 100755 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/state/SshContext.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/state/SshContext.java @@ -197,6 +197,8 @@ public class SshContext { private Integer maximalDhGroupSize; /** Host key */ private SshPublicKey hostKey; + /** Server host keys, sent by hostkey00 message */ + private List> serverHostKeys; /** Signature generated by the server over the exchange hash to authenticate the key exchange */ private byte[] serverExchangeHashSignature; /** Flag indicating whether the server exchange hash signature is valid */ @@ -869,6 +871,10 @@ public Optional getMaximalDhGroupSize() { return Optional.ofNullable(hostKey); } + public List> getServerHostKeys() { + return serverHostKeys; + } + public Optional getServerExchangeHashSignature() { return Optional.ofNullable(serverExchangeHashSignature); } @@ -919,6 +925,10 @@ public void setHostKey(SshPublicKey hostKey) { this.hostKey = hostKey; } + public void setServerHostKeys(List> serverHostKeys) { + this.serverHostKeys = serverHostKeys; + } + public void setServerExchangeHashSignature(byte[] serverExchangeHashSignature) { this.serverExchangeHashSignature = serverExchangeHashSignature; } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java index ee1c0aab0..c80d781c6 100644 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/util/KeyParser.java @@ -18,8 +18,10 @@ import java.nio.charset.Charset; import java.security.*; import java.security.spec.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -27,13 +29,27 @@ public final class KeyParser { private static final Logger LOGGER = LogManager.getLogger(); - public KeyParser() {} + private KeyParser() {} - public static SshPublicKey readPublicKeyFromBytes(String path) { + /** + * Reads a private key from a file and returns it as an SshPublicKey, only containing the public + * component of the key + * + * @param path path to the file containing the public key + * @return + */ + public static SshPublicKey readPublicKeyFromBytes(String path) { InputStream inputStream = KeyParser.class.getClassLoader().getResourceAsStream(path); - byte[] publicKeyBytes = new byte[0]; + byte[] publicKeyBytes; try { publicKeyBytes = inputStream.readAllBytes(); + if (publicKeyBytes == null) { + LOGGER.error( + "Error occured reading user key:" + + path + + ", continue without adding key!"); + return null; + } } catch (IOException e) { LOGGER.error( "Error occured reading user key:" + path + ", continue without adding key!"); @@ -44,17 +60,31 @@ public static SshPublicKey readPublicKeyFromBytes(String path) { return PublicKeyHelper.parse(Arrays.copyOfRange(keyBytes, offset, keyBytes.length)); } - public static SshPublicKey readKeyPairFromBytes(String path) { + /** + * Reads a private key from a file and returns it as an SshPrivateKey, containing both key + * components + * + * @param path path to the file containing the private key + * @return + */ + public static SshPublicKey readKeyPairFromBytes(String path) { InputStream inputStream = KeyParser.class.getClassLoader().getResourceAsStream(path); - byte[] privateKeyBytes = new byte[0]; + byte[] privateKeyBytes; try { privateKeyBytes = inputStream.readAllBytes(); + if (privateKeyBytes == null) { + LOGGER.error( + "Error occured reading user key:" + + path + + ", continue without adding key!"); + return null; + } } catch (IOException e) { LOGGER.error( "Error occured reading user key: " + path + ", continue without adding key!"); return null; } - byte[] keyBytes = new byte[0]; + byte[] keyBytes; try { keyBytes = unwrapPrivateKeyBytes(privateKeyBytes); } catch (IllegalArgumentException e) { @@ -78,18 +108,8 @@ public static SshPublicKey readKeyPairFromBytes(String path) { + path); return null; } - - // 32-bit length, "none" # ciphername length and string - // 32-bit length, "none" # kdfname length and string - // 32-bit length, nil # kdf (0 length, no kdf) - // 32-bit 0x01 # number of keys, hard-coded to 1 (no length) - // 32-bit length, sshpub # public key in ssh format - // 32-bit length, keytype - // 32-bit length, pub0 - // 32-bit length, pub1 // in this case we need to add +1 on the parser, because the string is finished with a // null-byte, but would be interpreted wrong by Java - offset = offset + 1; BigInteger lengthCipherName = new BigInteger( @@ -118,7 +138,8 @@ public static SshPublicKey readKeyPairFromBytes(String path) { keyBytes, offset, offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); - if (lengthKdf.intValue() != 0) {} + if (lengthKdf.intValue() != 0) { // ToDo + } BigInteger numberOfKeys = new BigInteger( Arrays.copyOfRange( @@ -147,6 +168,12 @@ public static SshPublicKey readKeyPairFromBytes(String path) { return sshPublicKey; } + /** + * Parses a private key, first analysing which pubkey type needs to be parsed + * + * @param keyBytes the key bytes to parse + * @return a CustomPrivateKey containing the parsed key + */ public static CustomPrivateKey parsePrivateKey(byte[] keyBytes) { int offset = 0; offset = offset + 12; @@ -187,6 +214,12 @@ public static CustomPrivateKey parsePrivateKey(byte[] keyBytes) { } } + /** + * Reads a RSA private key from the given key bytes + * + * @param keyBytes the key bytes to read + * @return a CustomRsaPrivateKey containing the parsed key + */ public static CustomRsaPrivateKey readRsaPrivateKey(byte[] keyBytes) { int offset = 0; BigInteger lengthN = @@ -220,6 +253,12 @@ public static CustomRsaPrivateKey readRsaPrivateKey(byte[] keyBytes) { return new CustomRsaPrivateKey(d, n); } + /** + * Reads a ECDSA private key from the given key bytes + * + * @param keyBytes the key bytes to read + * @return a CustomEcPrivateKey containing the parsed key + */ public static CustomEcPrivateKey readEcdsaPrivateKey(byte[] keyBytes) { int offset = 0; BigInteger curveSpeclength = @@ -256,6 +295,12 @@ public static CustomEcPrivateKey readEcdsaPrivateKey(byte[] keyBytes) { return new CustomEcPrivateKey(privateKey, NamedEcGroup.fromIdentifier(curveSpec)); } + /** + * Reads a Ed25519 private key from the given key bytes + * + * @param keyBytes the key bytes to read + * @return a XCurveEcPrivateKey containing the parsed key + */ public static XCurveEcPrivateKey readEd25519PrivateKey(byte[] keyBytes) { int offset = 0; BigInteger lengthCoordinate = @@ -280,6 +325,12 @@ public static XCurveEcPrivateKey readEd25519PrivateKey(byte[] keyBytes) { return new XCurveEcPrivateKey(scalar, NamedEcGroup.CURVE25519); } + /** + * Reads a DSA private key from the given key bytes + * + * @param keyBytes the key bytes to read + * @return a CustomDsaPrivateKey containing the parsed key + */ public static CustomDsaPrivateKey readDsaPrivateKey(byte[] keyBytes) { int offset = 0; BigInteger lengthP = @@ -328,6 +379,12 @@ public static CustomDsaPrivateKey readDsaPrivateKey(byte[] keyBytes) { return new CustomDsaPrivateKey(p, q, g, x); } + /** + * Unwraps the public key bytes from the public key file + * + * @param publicKeyBytes the public key bytes + * @return + */ public static byte[] unwrapPublicKeyBytes(byte[] publicKeyBytes) { // pubkey structure ssh-rsa AAAAB3NzaC1yc2E...Q02P1Eamz/nT4I3 root@localhost thus we want to // cut the last part of the pubkey holding the ownership @@ -343,10 +400,15 @@ public static byte[] unwrapPublicKeyBytes(byte[] publicKeyBytes) { .replace(" ", "") .replace("=", "") .replaceAll(System.lineSeparator(), ""); - byte[] keyBytes = Base64.getDecoder().decode(unwrappedKey); - return keyBytes; + return Base64.getDecoder().decode(unwrappedKey); } + /** + * Unwraps the private key bytes from the keyfile + * + * @param privateKeyBytes the private key bytes + * @return + */ private static byte[] unwrapPrivateKeyBytes(byte[] privateKeyBytes) { // replacements for private key // == are not accepted as Base64 Java encoding so we need to cut them off too @@ -361,4 +423,28 @@ private static byte[] unwrapPrivateKeyBytes(byte[] privateKeyBytes) { byte[] keyBytes = Base64.getDecoder().decode(unwrappedKey); return keyBytes; } + + /** + * Parses the hostkey blob into a list of hostkeys + * + * @param hostkeyBlob the hostkey blob + * @return + */ + public static List> parseHostkeyBlob(byte[] hostkeyBlob) { + int offset = 0; + List> hostKeyList = new ArrayList<>(); + while (offset < hostkeyBlob.length) { + BigInteger lengthKey = + new BigInteger( + Arrays.copyOfRange( + hostkeyBlob, + offset, + offset = offset + DataFormatConstants.MPINT_SIZE_LENGTH)); + hostKeyList.add( + PublicKeyHelper.parse( + Arrays.copyOfRange( + hostkeyBlob, offset, offset = offset + lengthKey.intValue()))); + } + return hostKeyList; + } } From 74872380b1486f02a55c27cdcd69b8579988e3ea Mon Sep 17 00:00:00 2001 From: jmxnzo Date: Mon, 14 Aug 2023 02:13:58 +0200 Subject: [PATCH 5/5] feat: Add CLI path support for host and user keys --- .../client/config/ClientCommandConfig.java | 7 + .../nds/sshattacker/core/config/Config.java | 280 +++++------------- .../config/delegate/HostKeysPathDelegate.java | 40 +++ .../config/delegate/UserKeysPathDelegate.java | 40 +++ .../fallbackRsaTransientPublicKey | 49 +++ .../fallbackRsaTransientPublicKey.pub | 1 + .../main/resources/keys/hostkeys/hostkey_dsa | 21 ++ .../resources/keys/hostkeys/hostkey_dsa.pub | 1 + .../resources/keys/hostkeys/hostkey_ecdsa256 | 9 + .../keys/hostkeys/hostkey_ecdsa256.pub | 1 + .../resources/keys/hostkeys/hostkey_ecdsa384 | 11 + .../keys/hostkeys/hostkey_ecdsa384.pub | 1 + .../resources/keys/hostkeys/hostkey_ecdsa521 | 12 + .../keys/hostkeys/hostkey_ecdsa521.pub | 1 + .../resources/keys/hostkeys/hostkey_ed25519 | 8 + .../keys/hostkeys/hostkey_ed25519.pub | 1 + .../main/resources/keys/hostkeys/hostkey_rsa | 49 +++ .../resources/keys/hostkeys/hostkey_rsa.pub | 1 + .../main/resources/keys/{ => userkeys}/id_dsa | 0 .../resources/keys/{ => userkeys}/id_dsa.pub | 0 .../resources/keys/{ => userkeys}/id_ecdsa | 0 .../keys/{ => userkeys}/id_ecdsa.pub | 0 .../resources/keys/{ => userkeys}/id_ed25519 | 0 .../keys/{ => userkeys}/id_ed25519.pub | 0 .../main/resources/keys/{ => userkeys}/id_rsa | 0 .../resources/keys/{ => userkeys}/id_rsa.pub | 0 .../mitm/config/MitmCommandConfig.java | 6 + .../server/config/ServerCommandConfig.java | 3 + 28 files changed, 340 insertions(+), 202 deletions(-) create mode 100644 SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/HostKeysPathDelegate.java create mode 100644 SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/UserKeysPathDelegate.java create mode 100644 SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey create mode 100644 SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey.pub create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa.pub create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256 create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256.pub create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384 create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384.pub create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521 create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521.pub create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519 create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519.pub create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa create mode 100644 SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa.pub rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_dsa (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_dsa.pub (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_ecdsa (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_ecdsa.pub (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_ed25519 (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_ed25519.pub (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_rsa (100%) rename SSH-Core/src/main/resources/keys/{ => userkeys}/id_rsa.pub (100%) diff --git a/SSH-Client/src/main/java/de/rub/nds/sshattacker/client/config/ClientCommandConfig.java b/SSH-Client/src/main/java/de/rub/nds/sshattacker/client/config/ClientCommandConfig.java index e81d54c3e..635654e54 100755 --- a/SSH-Client/src/main/java/de/rub/nds/sshattacker/client/config/ClientCommandConfig.java +++ b/SSH-Client/src/main/java/de/rub/nds/sshattacker/client/config/ClientCommandConfig.java @@ -22,6 +22,9 @@ public class ClientCommandConfig extends SshDelegateConfig { @ParametersDelegate private final WorkflowOutputDelegate workflowOutputDelegate; @ParametersDelegate private final WorkflowTypeDelegate workflowTypeDelegate; + @ParametersDelegate private final UserKeysPathDelegate userKeysPathDelegate; + @ParametersDelegate private final HostKeysPathDelegate hostKeysPathDelegate; + public ClientCommandConfig(GeneralDelegate delegate) { super(delegate); clientDelegate = new ClientDelegate(); @@ -30,12 +33,16 @@ public ClientCommandConfig(GeneralDelegate delegate) { workflowInputDelegate = new WorkflowInputDelegate(); workflowOutputDelegate = new WorkflowOutputDelegate(); workflowTypeDelegate = new WorkflowTypeDelegate(); + userKeysPathDelegate = new UserKeysPathDelegate(); + hostKeysPathDelegate = new HostKeysPathDelegate(); addDelegate(clientDelegate); addDelegate(configOutputDelegate); addDelegate(timeoutDelegate); addDelegate(workflowInputDelegate); addDelegate(workflowOutputDelegate); addDelegate(workflowTypeDelegate); + addDelegate(userKeysPathDelegate); + addDelegate(hostKeysPathDelegate); } @Override diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java index a4e0fddee..d76c340a0 100755 --- a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/Config.java @@ -12,7 +12,6 @@ import de.rub.nds.sshattacker.core.connection.InboundConnection; import de.rub.nds.sshattacker.core.connection.OutboundConnection; import de.rub.nds.sshattacker.core.constants.*; -import de.rub.nds.sshattacker.core.crypto.ec.PointFormatter; import de.rub.nds.sshattacker.core.crypto.keys.*; import de.rub.nds.sshattacker.core.protocol.authentication.AuthenticationResponse; import de.rub.nds.sshattacker.core.protocol.connection.ChannelDefaults; @@ -30,7 +29,6 @@ import java.io.InputStream; import java.io.Serializable; import java.lang.reflect.Field; -import java.math.BigInteger; import java.security.Security; import java.util.*; import java.util.stream.Collectors; @@ -259,7 +257,11 @@ public class Config implements Serializable { @XmlElement(name = "hostKey") @XmlElementWrapper private List> hostKeys; - + /** + * String list of hostkey path, to load default hostkeys. Will be overwritten when parsing paths + * by CLI + */ + private List hostKeyPaths; /** * RSA transient key used to encrypt the shared secret K. This may be a transient key generated * solely for this SSH connection, or it may be re-used for several connections. @@ -310,7 +312,13 @@ public class Config implements Serializable { /** The List of user keys for public key authentication */ @XmlElement(name = "userKey") @XmlElementWrapper - private List> userKeys = new ArrayList<>(); + private List> userKeys; + + /** + * String list of user keys path, to load default userkeys. Will be overwritten when parsing + * paths by CLI + */ + private List userKeyPaths; // endregion // region Channel @@ -653,197 +661,19 @@ public Config() { defaultEcdhKeyExchangeAlgorithm = KeyExchangeAlgorithm.ECDH_SHA2_NISTP256; defaultRsaKeyExchangeAlgorithm = KeyExchangeAlgorithm.RSA2048_SHA256; defaultHybridKeyExchangeAlgorithm = KeyExchangeAlgorithm.SNTRUP761_X25519; - - // An OpenSSL generated 2048 bit RSA keypair is currently being used as the - // default host key - // TODO: Load host keys from file to reduce length of Config class - hostKeys = - List.of( - new SshPublicKey<>( - PublicKeyFormat.SSH_RSA, - new CustomRsaPublicKey( - new BigInteger("010001", 16), - new BigInteger( - "00D9F6BFFAB8BC79C6E9AB6C3D4593F561CC93B41A70B9A750045ED0AC09" - + "6EF4A6A8C7B2AAA4F44459481319AE956934BF9D5C5AD7C004ADE0B81E43" - + "75FD1DF8797DF6F3CA130ED8A2A9B6E94467A05D97A0F8380A4CBB75FC5E" - + "5C303433B61750063D3801D5C90658ACAEE140B09F95A0FD8886EFAE16EA" - + "B779DF82E6A12C1BE011FECB417C788B72C42948AB54CCE1E8119CFB78E1" - + "3B06090CEBF6D3806854FE09F03B20BA92505058EC64C44F0B4DA0BAE71D" - + "52EDA11AB67F4B54D9FCEFE1FACEB520D595FFA33502FB91423EBD972F26" - + "150715CB0E648F715E6E5E8FC9D8FA55E9DE0652CF85D7928B235486F54A" - + "3F3EE64B04888B898864B08200A9E22909", - 16)), - new CustomRsaPrivateKey( - new BigInteger( - "7AAB5898AEE7C451A2A90B9DE04EC947656FAB69460FF68E1E278EA1841D" - + "A22B39CA4A4FA7CEA1B8EDCB7224C38A1659D1226D2E07AF9A7C62A305AC" - + "9DEC042FBC290443B23E24C64765DE1AD58777A522BF102B1BCC5536D794" - + "62BCBE6DB8E91CD9CF6F98F62E5031BFAA9E51C93ED900579A39C26CBB64" - + "CF7E6F998513E20B4B2A4DD36D4F6F074A0FDB04232FA6EDAB89A1B32BA5" - + "2214696BDA66C4518A73F92807DD088AB11263519885A0CD6A42B6D9EAE9" - + "EBD13241EDC4EB7205AE838A5EF7AE280D36410057B38ED05CEBA75F92AC" - + "DF40226164BB3A0C4312B65A8C2FBA85CDB7CC5F77F53C45F64409AFC460" - + "210C8EE4DAB818F009172387ED00E141", - 16), - new BigInteger( - "00D9F6BFFAB8BC79C6E9AB6C3D4593F561CC93B41A70B9A750045ED0AC09" - + "6EF4A6A8C7B2AAA4F44459481319AE956934BF9D5C5AD7C004ADE0B81E43" - + "75FD1DF8797DF6F3CA130ED8A2A9B6E94467A05D97A0F8380A4CBB75FC5E" - + "5C303433B61750063D3801D5C90658ACAEE140B09F95A0FD8886EFAE16EA" - + "B779DF82E6A12C1BE011FECB417C788B72C42948AB54CCE1E8119CFB78E1" - + "3B06090CEBF6D3806854FE09F03B20BA92505058EC64C44F0B4DA0BAE71D" - + "52EDA11AB67F4B54D9FCEFE1FACEB520D595FFA33502FB91423EBD972F26" - + "150715CB0E648F715E6E5E8FC9D8FA55E9DE0652CF85D7928B235486F54A" - + "3F3EE64B04888B898864B08200A9E22909", - 16))), - // SSH enforces the use of 1024 / 160 bit DSA keys as per RFC 4253 Sec. 6.6 - new SshPublicKey<>( - PublicKeyFormat.SSH_DSS, - new CustomDsaPublicKey( - new BigInteger( - "008BD081A858028A729F0C04E0788C06BC5B2EA8B880A203986C90E92D20" - + "322670248A305A3217737BF0256EFFD53CC512993F137A4F64162AF4F3E6" - + "AA64D348343C86D1B3D18CAE017A48FD2FFA56A9DFC70D18BE8958938768" - + "995AFD952719DE2066B0A7E3D90948D4E0437BD1A5C94F1A1FBBADDCEA3A" - + "338E96A4CACCF4A855", - 16), - new BigInteger( - "00B971EBD0321EEC38C15E01FD9C773CCA23E66879", 16), - new BigInteger( - "259DC09E04AD1818271F3E676B17A98B6F7B1D08B43B51FAEF06D2C9F921" - + "0667ED3C14ABEBEE372D1F325C11C0304AE8B9BAC8914619CA05165BAE2B" - + "E49BAD5DD8ECB8129CDDD2941D6DDF53C7D53A5FB9D88B58F362034CA6A1" - + "3929D28942D0054FFA4166D3DDDE0B2FE2E4A0342A827DEF6B6FECDB0614" - + "8ED403D3FC9C4C79", - 16), - new BigInteger( - "1433495B5BB346BEB6A783DA2ADF1C5CFE946146E4A461B2A658CEC29DA2" - + "1496A6D69119026059D0C2557D535E664A0F10B4DB006601D8848EA6B92F" - + "C6313B03103C9C3C6F0ED55CB46EEC8B0FE0007D2411F46676A8761DADAA" - + "171351322D29487E9AE8738C354DD04FFEACA50503AFEC8F0610A679FF81" - + "6EFD9B162F152BDA", - 16)), - new CustomDsaPrivateKey( - new BigInteger( - "008BD081A858028A729F0C04E0788C06BC5B2EA8B880A203986C90E92D20" - + "322670248A305A3217737BF0256EFFD53CC512993F137A4F64162AF4F3E6" - + "AA64D348343C86D1B3D18CAE017A48FD2FFA56A9DFC70D18BE8958938768" - + "995AFD952719DE2066B0A7E3D90948D4E0437BD1A5C94F1A1FBBADDCEA3A" - + "338E96A4CACCF4A855", - 16), - new BigInteger( - "00B971EBD0321EEC38C15E01FD9C773CCA23E66879", 16), - new BigInteger( - "259DC09E04AD1818271F3E676B17A98B6F7B1D08B43B51FAEF06D2C9F921" - + "0667ED3C14ABEBEE372D1F325C11C0304AE8B9BAC8914619CA05165BAE2B" - + "E49BAD5DD8ECB8129CDDD2941D6DDF53C7D53A5FB9D88B58F362034CA6A1" - + "3929D28942D0054FFA4166D3DDDE0B2FE2E4A0342A827DEF6B6FECDB0614" - + "8ED403D3FC9C4C79", - 16), - new BigInteger( - "7C6B4E2B32192EFC09B7CB12D85CBB4141EF7348", 16))), - new SshPublicKey<>( - PublicKeyFormat.ECDSA_SHA2_NISTP256, - new CustomEcPublicKey( - PointFormatter.formatFromByteArray( - NamedEcGroup.SECP256R1, - ArrayConverter.hexStringToByteArray( - "0492A8D4E6EECBED47D0AACD15D714FB619D6F3941028874B99117CF8EAE" - + "BBCDF7CC981DE460635590F3AB5AE6F7DF0A12E6E0DE951DEAE3D2C48EC3" - + "4C237C61E7")), - NamedEcGroup.SECP256R1), - new CustomEcPrivateKey( - new BigInteger( - "8DD62AA24F982B18446E3ECC7E50F8EB976610750242BA637C949F4C8FD6A1CF", - 16), - NamedEcGroup.SECP256R1)), - new SshPublicKey<>( - PublicKeyFormat.ECDSA_SHA2_NISTP384, - new CustomEcPublicKey( - PointFormatter.formatFromByteArray( - NamedEcGroup.SECP384R1, - ArrayConverter.hexStringToByteArray( - "04650469DB4E282660E0DCB23197D10EE935BA038B8B62890EB098420211" - + "C38D5E4E737FF2A0DC53E1B8A55C65B2BD85673EFEEEE9CE4727374D2E2D" - + "E8EEA6B8AB146245C8627E2346C76944AEB1C0BDCE1B267773F6ED08473A" - + "DE8B6F5687A2B6")), - NamedEcGroup.SECP384R1), - new CustomEcPrivateKey( - new BigInteger( - "EA39EE919D73A1FE8F8FBFC8807E7ED36BE3D89FBC1F35619B04E825E8E8" - + "07E994348EE8095467499AE15F73FE0FD298", - 16), - NamedEcGroup.SECP384R1)), - new SshPublicKey<>( - PublicKeyFormat.ECDSA_SHA2_NISTP521, - new CustomEcPublicKey( - PointFormatter.formatFromByteArray( - NamedEcGroup.SECP521R1, - ArrayConverter.hexStringToByteArray( - "0400A97EC5412F12C6CCAEDF2F288041146015FBCE1B939F017039D63280" - + "9B170C1E51B5AFE19127F97146C0556A70E44D179B76DA98C39ACF418F98" - + "95F7E8483665A800AF936C1864E14340ABE09860281D9A015E0C78A540F1" - + "6CB36DD0275C9AF61A2A41F6AE6447ECCFCA1788878B7A249B195424BED8" - + "CD881C0C3C5CEB051D64366DE5")), - NamedEcGroup.SECP521R1), - new CustomEcPrivateKey( - new BigInteger( - "015B220911DD64BD8793BC5429093B7AE8E2B4F462751D553CE48E09D72E" - + "9981F4EF80334B981D6558C6498BFB4B6E1973BF60BF568C624934F1EF2B" - + "8561C67B2AD2", - 16), - NamedEcGroup.SECP521R1)), - new SshPublicKey<>( - PublicKeyFormat.SSH_ED25519, - new XCurveEcPublicKey( - ArrayConverter.hexStringToByteArray( - "13E3591CC0D1BAE515EC44FD3FA01784E2103165ECCFE939D91A619F46DBED70"), - NamedEcGroup.CURVE25519), - new XCurveEcPrivateKey( - ArrayConverter.hexStringToByteArray( - "092E829DE536BE8F7D74E7A3C6CD90EA6EADDDEEB2E50D8617EBDD132B53669B"), - NamedEcGroup.CURVE25519))); - fallbackRsaTransientPublicKey = - new SshPublicKey<>( - PublicKeyFormat.SSH_RSA, - new CustomRsaPublicKey( - new BigInteger("10001", 16), - new BigInteger( - "00EB617D71223FF5D286DBC136905B348783D4B540EFA9E00C7B1F605049" - + "7C6739FBAB3F5D5F2C9A86682D148701E9E04D58D31716C9C88BC0DD85BC" - + "170969A27709AF332C79453FC5B99231C3D6410B0A6119EAEE6D09AB59CF" - + "4EC425BE8A86C10BBA30902B7916D2E51AE5C2CA66E9650431DD3B98878E" - + "EA8A207F4336005157021F7FA4D6DBD54D64B5B974CE3FA4D135C5FD7893" - + "B8A6EAC0C1AC9D98144947C22E7D0E7E18F4F02C0E448D1AE9596BCE0A2E" - + "F417F693C914FAF24F716D0567ED48BAA5161727743A8431EB4E3CB65417" - + "B835926AC528BAA02343B0E784C297E0C19C17FB9E8A778F9EC805AC4AAC" - + "AA24AE34B96A3189D83FB6EC38C1D3EBFB", - 16)), - new CustomRsaPrivateKey( - new BigInteger( - "00C15941BBCF108F1332680D9C8E93FCE05C703BBB6DA33341CD5986BA2C" - + "C31DE04954F025F8EA20BCCB924C4C624C054E43EA920ACC120A8A90ED2C" - + "06185B477354E72FB8169DC5B6DBAAB56A52F2F6E8BDBE9676E7E68B74A8" - + "8FE11BC81AEE7A60F1BEB68E9F571A41CC08742BE2C15193528A924BC6FE" - + "A4B675DF540C65D2697D31E533007B310D7E728D2E6DB06256A93F178200" - + "CED6AD5A59B40224A3373C3875539368971A32D27B48697D4FFE61ED7084" - + "7CA1D935392EA540C938072667BA9C9737A695C20CFCF578A1FF61DD9C43" - + "7666D97D5A986A3E786601498C3342A7C7307F7D8E6300436A7681AA9558" - + "9DF5A4479FAF232B83B9A19CB59833ECC1", - 16), - new BigInteger( - "00EB617D71223FF5D286DBC136905B348783D4B540EFA9E00C7B1F605049" - + "7C6739FBAB3F5D5F2C9A86682D148701E9E04D58D31716C9C88BC0DD85BC" - + "170969A27709AF332C79453FC5B99231C3D6410B0A6119EAEE6D09AB59CF" - + "4EC425BE8A86C10BBA30902B7916D2E51AE5C2CA66E9650431DD3B98878E" - + "EA8A207F4336005157021F7FA4D6DBD54D64B5B974CE3FA4D135C5FD7893" - + "B8A6EAC0C1AC9D98144947C22E7D0E7E18F4F02C0E448D1AE9596BCE0A2E" - + "F417F693C914FAF24F716D0567ED48BAA5161727743A8431EB4E3CB65417" - + "B835926AC528BAA02343B0E784C297E0C19C17FB9E8A778F9EC805AC4AAC" - + "AA24AE34B96A3189D83FB6EC38C1D3EBFB", - 16))); + (SshPublicKey) + KeyParser.readKeyPairFromBytes( + "keys/fallbackkeys/fallbackRsaTransientPublicKey"); + hostKeyPaths = + List.of( + "keys/hostkeys/hostkey_rsa", + "keys/hostkeys/hostkey_dsa", + "keys/hostkeys/hostkey_ecdsa256", + "keys/hostkeys/hostkey_ecdsa384", + "keys/hostkeys/hostkey_ecdsa521", + "keys/hostkeys/hostkey_ed25519"); + loadHostKeys(); // endregion // region Authentication initialization @@ -859,7 +689,13 @@ public Config() { AuthenticationResponse preConfiguredAuthResponse2 = new AuthenticationResponse(); preConfiguredAuthResponse2.add(new AuthenticationResponse.ResponseEntry(false)); preConfiguredAuthResponses.add(preConfiguredAuthResponse2); - addUserKeys("keys/id_ecdsa", "keys/id_rsa", "keys/id_dsa", "keys/id_ed25519"); + userKeyPaths = + List.of( + "keys/userkeys/id_ecdsa", + "keys/userkeys/id_rsa", + "keys/userkeys/id_dsa", + "keys/userkeys/id_ed25519"); + loadUserKeys(); // endregion // region Channel initialization @@ -1382,6 +1218,10 @@ public Boolean getEnforceSettings() { return hostKeys; } + public List getHostKeyPaths() { + return hostKeyPaths; + } + // endregion // region Setters for KeyExchange public void setDhGexMinimalGroupSize(Integer dhGexMinimalGroupSize) { @@ -1431,6 +1271,11 @@ public void setEnforceSettings(Boolean enforceSettings) { public void setHostKeys(List> hostKeys) { this.hostKeys = Objects.requireNonNull(hostKeys); } + + public void setHostKeyPaths(List hostKeyPaths) { + this.hostKeyPaths = hostKeyPaths; + } + // endregion // region Getters for authentication @@ -1458,14 +1303,10 @@ public List getPreConfiguredAuthResponses() { return userKeys; } - public void addUserKeys(String... pathlist) { - SshPublicKey userKey; - for (String path : pathlist) { - if ((userKey = KeyParser.readKeyPairFromBytes(path)) != null) { - this.userKeys.add(userKey); - } - } + public List getUserKeyPaths() { + return userKeyPaths; } + // endregion // region Setters for authentication public void setAuthenticationMethod(AuthenticationMethod authenticationMethod) { @@ -1492,6 +1333,11 @@ public void setPreConfiguredAuthResponses( public void setUserKeys(List> userKeys) { this.userKeys = Objects.requireNonNull(userKeys); } + + public void setUserKeyPaths(List userKeyPaths) { + this.userKeyPaths = userKeyPaths; + } + // endregion // region Getters for Channel @@ -1756,6 +1602,36 @@ public void setStopReceivingAfterDisconnect(boolean stopReceivingAfterDisconnect } // endregion + public void loadUserKeys() { + // create a new user key list, because default values will already be written into user keys + // at time of delegating + List> tempUserKeys = new ArrayList<>(); + SshPublicKey userKey; + for (String path : userKeyPaths) { + if ((userKey = KeyParser.readKeyPairFromBytes(path)) != null) { + tempUserKeys.add(userKey); + } + } + if (!tempUserKeys.isEmpty()) { + this.setUserKeys(tempUserKeys); + } + } + + public void loadHostKeys() { + // create a new host key list, because default values will already be written into host keys + // at time of delegating + List> tempHostKeys = new ArrayList<>(); + SshPublicKey hostKey; + for (String path : hostKeyPaths) { + if ((hostKey = KeyParser.readKeyPairFromBytes(path)) != null) { + tempHostKeys.add(hostKey); + } + } + if (!tempHostKeys.isEmpty()) { + this.setHostKeys(tempHostKeys); + } + } + public String getConfigOutput() { return configOutput; } diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/HostKeysPathDelegate.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/HostKeysPathDelegate.java new file mode 100644 index 000000000..68e021d5a --- /dev/null +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/HostKeysPathDelegate.java @@ -0,0 +1,40 @@ +/* + * SSH-Attacker - A Modular Penetration Testing Framework for SSH + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.sshattacker.core.config.delegate; + +import com.beust.jcommander.Parameter; +import de.rub.nds.sshattacker.core.config.Config; +import java.util.ArrayList; +import java.util.List; + +public class HostKeysPathDelegate extends Delegate { + + @Parameter( + names = "-host_keys", + description = + "Comma seperated list of paths to host keys (no white-space). " + + "If no host keys are provided, the default host keys will be used.") + private List paths = new ArrayList<>(); + + public List getHostKeyPaths() { + return paths; + } + + public void setHostKeyPaths(List paths) { + this.paths = paths; + } + + @Override + public void applyDelegate(Config config) { + if (paths != null && !paths.isEmpty()) { + config.setHostKeyPaths(paths); + // after overwriting the list of paths, we need to load the host keys again + config.loadHostKeys(); + } + } +} diff --git a/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/UserKeysPathDelegate.java b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/UserKeysPathDelegate.java new file mode 100644 index 000000000..b593cd933 --- /dev/null +++ b/SSH-Core/src/main/java/de/rub/nds/sshattacker/core/config/delegate/UserKeysPathDelegate.java @@ -0,0 +1,40 @@ +/* + * SSH-Attacker - A Modular Penetration Testing Framework for SSH + * + * Copyright 2014-2023 Ruhr University Bochum, Paderborn University, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.sshattacker.core.config.delegate; + +import com.beust.jcommander.Parameter; +import de.rub.nds.sshattacker.core.config.Config; +import java.util.ArrayList; +import java.util.List; + +public class UserKeysPathDelegate extends Delegate { + + @Parameter( + names = "-user_keys", + description = + "Comma seperated list of paths to user keys (no white-space). " + + "If no user keys are provided, the default user keys will be used.") + private List paths = new ArrayList<>(); + + public List getUserKeyPaths() { + return paths; + } + + public void setUserKeyPaths(List paths) { + this.paths = paths; + } + + @Override + public void applyDelegate(Config config) { + if (paths != null && !paths.isEmpty()) { + config.setUserKeyPaths(paths); + // after overwriting the list of paths, we need to load the user keys again + config.loadUserKeys(); + } + } +} diff --git a/SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey b/SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey new file mode 100644 index 000000000..0e6b62be4 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey @@ -0,0 +1,49 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +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 +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey.pub b/SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey.pub new file mode 100644 index 000000000..13740ecce --- /dev/null +++ b/SSH-Core/src/main/resources/keys/fallbackkeys/fallbackRsaTransientPublicKey.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCSbItfjTThByLS//m+mHNlktOJEWW7TEYTIGuuQ+KccClGIdxsUIytJEBkm4Bk+TaL9ZpdBTKleSZGEV7LOMdIEAF3ThFhAvwA4PUwoMSRB4/Oz3MqMG7U+WWOmmAAcihpiDyPn4nU/ZMYscTjfj2gb6elguDWjAM6KotySARVE8KdAxPm17ZBY+QXzdeY/5/pjTzKYPHM3He8/ZC/2mzUSol9LLVRIHIYl/bC1blVhrWDcRoBPD/2sJA/5YsmQjiJ+cBl6gVunSfTgDf9R4V/Asp3CX8N5iuvZsAMd7fv0Py7tf6oZqL4c9O5cRekW/6F5Ya1HK3YLCFYU1qVRuofevQOVlaQjKfB5yVhWNd5QOWHCMuBQj6B56F4G+m8g8O9glnphEn2tmGqMteogFDfAGYYx73JvVR0Qig/rFPlTFlviUwoVBgkX5ra4Nvo+rD2qPta8Lvo/rWyBsk6LLd4OmCE9Lxja8cMwhWYwpUrg2v2doi1uualzNCCOpmTKCjNm64eFHYmPouOALjTLALcIttI27NnmT22v5XMnPQbnRv6lvj7GhvaOMz4wwWlS4pHNhj6/9CRuRKNp12Tbw7DXYG6ITurjrlnE2TnuzfORY7YHsp+JvYRo/OSbr4XVomFuARLe1fX4j+RFiPanZJI9Zv6ANP/YdmBZhUTSxStcQ== jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa new file mode 100644 index 000000000..51f9c60e1 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH +NzAAAAgQDvQgBuMxCW/OYwBzs6gBn8R6diFldiaEBU8uUM0VadUVW8TKSspNLqK+ORs6bs +vlRQOwrpcIPlVuXIskJOxpdPwdbwfGuJx9e72j2YDQow365En6TdZneJvP++xWPHkbkIDH +L8+EWbqYGsvU0zBynH0HrnV+BrJ0fXb6tOmzXxoQAAABUAuwvNRIZjk5wS6wTmN9aIl01L +598AAACBALI0BLR/Ct0S5SDn9B5bC6OQzRRQvXkROG7rDDCDxtmNc5gIyq2hmoeXbUy2wI +0V/BFapSXLrRyeviz4DbNwEuMt77eYkM+yPSkvgAUvrODGt3HvAQSdfNfVNknLKzkrMVI/ +2Carb6QdZjRYYpeqNFiUA6N6PpmbxVePH/DqUJPQAAAAgDtT+Duc4uY99u/wV3B9W98IL+ +Kx2JPTT8kBWziZfdIBolGhdSE5+hDyN0Ba6hp7gFOVqzZIGa4mwPhRGg00ZXcImwa5BrQD +ZehpDDsMp8tMvFV61ONIdXt+99RsJ9E9BUHJ5ZSgELOJCrAr0RnAcKRD6SHgd9hoEAjkQu +kyG3RxAAAB+EeL8eRHi/HkAAAAB3NzaC1kc3MAAACBAO9CAG4zEJb85jAHOzqAGfxHp2IW +V2JoQFTy5QzRVp1RVbxMpKyk0uor45Gzpuy+VFA7Culwg+VW5ciyQk7Gl0/B1vB8a4nH17 +vaPZgNCjDfrkSfpN1md4m8/77FY8eRuQgMcvz4RZupgay9TTMHKcfQeudX4GsnR9dvq06b +NfGhAAAAFQC7C81EhmOTnBLrBOY31oiXTUvn3wAAAIEAsjQEtH8K3RLlIOf0HlsLo5DNFF +C9eRE4busMMIPG2Y1zmAjKraGah5dtTLbAjRX8EVqlJcutHJ6+LPgNs3AS4y3vt5iQz7I9 +KS+ABS+s4Ma3ce8BBJ1819U2ScsrOSsxUj/YJqtvpB1mNFhil6o0WJQDo3o+mZvFV48f8O +pQk9AAAACAO1P4O5zi5j327/BXcH1b3wgv4rHYk9NPyQFbOJl90gGiUaF1ITn6EPI3QFrq +GnuAU5WrNkgZribA+FEaDTRldwibBrkGtANl6GkMOwyny0y8VXrU40h1e3731Gwn0T0FQc +nllKAQs4kKsCvRGcBwpEPpIeB32GgQCORC6TIbdHEAAAAUDlTFBdDSSB3LbN/5Jq8cQ8GN +2ooAAAAham14bnpvQGpteG56by1UaGlua1BhZC1UNDcwLVcxMERHAQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa.pub b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa.pub new file mode 100644 index 000000000..b085abc15 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAO9CAG4zEJb85jAHOzqAGfxHp2IWV2JoQFTy5QzRVp1RVbxMpKyk0uor45Gzpuy+VFA7Culwg+VW5ciyQk7Gl0/B1vB8a4nH17vaPZgNCjDfrkSfpN1md4m8/77FY8eRuQgMcvz4RZupgay9TTMHKcfQeudX4GsnR9dvq06bNfGhAAAAFQC7C81EhmOTnBLrBOY31oiXTUvn3wAAAIEAsjQEtH8K3RLlIOf0HlsLo5DNFFC9eRE4busMMIPG2Y1zmAjKraGah5dtTLbAjRX8EVqlJcutHJ6+LPgNs3AS4y3vt5iQz7I9KS+ABS+s4Ma3ce8BBJ1819U2ScsrOSsxUj/YJqtvpB1mNFhil6o0WJQDo3o+mZvFV48f8OpQk9AAAACAO1P4O5zi5j327/BXcH1b3wgv4rHYk9NPyQFbOJl90gGiUaF1ITn6EPI3QFrqGnuAU5WrNkgZribA+FEaDTRldwibBrkGtANl6GkMOwyny0y8VXrU40h1e3731Gwn0T0FQcnllKAQs4kKsCvRGcBwpEPpIeB32GgQCORC6TIbdHE= jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256 b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256 new file mode 100644 index 000000000..7f4376edf --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256 @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTtJ/M1JICQx4dfsrBwcirT375rKUDg +Wu6uM3JSwqfvbHmEwaw80i3inydOaP+68dZSv58cr3BEHeg5T+EaSJr1AAAAwDrQHj860B +4/AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBO0n8zUkgJDHh1+y +sHByKtPfvmspQOBa7q4zclLCp+9seYTBrDzSLeKfJ05o/7rx1lK/nxyvcEQd6DlP4RpImv +UAAAAgB0a/O8Hf8VeeS0wra9wrW0nfDDJOgVgwYSJVoDnMpJwAAAAham14bnpvQGpteG56 +by1UaGlua1BhZC1UNDcwLVcxMERHAQIDBAUGBw== +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256.pub b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256.pub new file mode 100644 index 000000000..f658ca11c --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa256.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBO0n8zUkgJDHh1+ysHByKtPfvmspQOBa7q4zclLCp+9seYTBrDzSLeKfJ05o/7rx1lK/nxyvcEQd6DlP4RpImvU= jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384 b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384 new file mode 100644 index 000000000..75ca001ce --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384 @@ -0,0 +1,11 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS +1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQRXq9QVhF5zUrrO33gAAS5hXdXnWrT7 +wz5Ne29x7KOiv9Dd9aUN/rnCBcbd8cpsmPhaQbYDIt1NnW/nWAFfJlXqDPGq64gQHLnegg +44E0ZAGbFVaWNJIHqUiOPHovmTzaQAAADwE610lROtdJUAAAATZWNkc2Etc2hhMi1uaXN0 +cDM4NAAAAAhuaXN0cDM4NAAAAGEEV6vUFYRec1K6zt94AAEuYV3V51q0+8M+TXtvceyjor +/Q3fWlDf65wgXG3fHKbJj4WkG2AyLdTZ1v51gBXyZV6gzxquuIEBy53oIOOBNGQBmxVWlj +SSB6lIjjx6L5k82kAAAAMQC/MuY9JoDn4ah3BmYHJ+90vUskkR7GfRXD2V/iYoQDrg+LWQ +dCsHZTOrqZRl6+FVMAAAAham14bnpvQGpteG56by1UaGlua1BhZC1UNDcwLVcxMERHAQID +BAUG +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384.pub b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384.pub new file mode 100644 index 000000000..baded63f0 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa384.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBFer1BWEXnNSus7feAABLmFd1edatPvDPk17b3Hso6K/0N31pQ3+ucIFxt3xymyY+FpBtgMi3U2db+dYAV8mVeoM8arriBAcud6CDjgTRkAZsVVpY0kgepSI48ei+ZPNpA== jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521 b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521 new file mode 100644 index 000000000..c1b84b316 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521 @@ -0,0 +1,12 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS +1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBBMQoYHqJzZKXH0WDGdYhANnI17gA +zJmHFCJ5FRyi5O7bvKVkiOKmrUPq9CXu4jJ4wdPnf2fdzovX+VYCjQ+rPpgAVTLNSwjbZf +kQoE6QqEkEHfjt+m+5XolbFw/TEb7N6OAMuJRhEdNRl0qg3ptVRhhmHuX+v872j0d50GSz +7z4URDkAAAEgGgu2KRoLtikAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ +AAAIUEAQTEKGB6ic2Slx9FgxnWIQDZyNe4AMyZhxQieRUcouTu27ylZIjipq1D6vQl7uIy +eMHT539n3c6L1/lWAo0Pqz6YAFUyzUsI22X5EKBOkKhJBB347fpvuV6JWxcP0xG+zejgDL +iUYRHTUZdKoN6bVUYYZh7l/r/O9o9HedBks+8+FEQ5AAAAQgFwwHpy4FNx/KCoy89VW8OQ +ZLGyz9s9WK6zE1Rp9eUyM5ArpgNUxyeOFTJJycSRDw6pKYaucvgo2dWf2GDDUasNSQAAAC +FqbXhuem9Aam14bnpvLVRoaW5rUGFkLVQ0NzAtVzEwREcB +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521.pub b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521.pub new file mode 100644 index 000000000..b96dc09ec --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ecdsa521.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAEExChgeonNkpcfRYMZ1iEA2cjXuADMmYcUInkVHKLk7tu8pWSI4qatQ+r0Je7iMnjB0+d/Z93Oi9f5VgKND6s+mABVMs1LCNtl+RCgTpCoSQQd+O36b7leiVsXD9MRvs3o4Ay4lGER01GXSqDem1VGGGYe5f6/zvaPR3nQZLPvPhREOQ== jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519 b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519 new file mode 100644 index 000000000..5066d8871 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519 @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACA/EG5R4D91zX3PfV/bmcbrxlWUQZAU8XukDqHJr08oCAAAAKjfKis13yor +NQAAAAtzc2gtZWQyNTUxOQAAACA/EG5R4D91zX3PfV/bmcbrxlWUQZAU8XukDqHJr08oCA +AAAEACjg61AuOB7lMmv9tSSFC6CKDS4RSvswC4eBtezRFxkj8QblHgP3XNfc99X9uZxuvG +VZRBkBTxe6QOocmvTygIAAAAIWpteG56b0BqbXhuem8tVGhpbmtQYWQtVDQ3MC1XMTBERw +ECAwQ= +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519.pub b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519.pub new file mode 100644 index 000000000..74de7b631 --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID8QblHgP3XNfc99X9uZxuvGVZRBkBTxe6QOocmvTygI jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa new file mode 100644 index 000000000..30412037f --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa @@ -0,0 +1,49 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +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 +-----END OPENSSH PRIVATE KEY----- diff --git a/SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa.pub b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa.pub new file mode 100644 index 000000000..f7603aa5e --- /dev/null +++ b/SSH-Core/src/main/resources/keys/hostkeys/hostkey_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3K2jtC95T9mEc/cQ6fc+c1zNFVsOfMQ77lyDl+Dsv4Cld1WAhn1JZrHrbL68S2Wih/lPTcoNyS0pVFIre6CO/ORVpHSvehzxMAdzIHKLll9hzi/3zZ2ZnUhCxJH2TDP1IXqypS7NJYlvvymN7zq7HGPRZTIv335uM0XjmbQFFHfi8xxFSYe0G7qdCjlNT9JiFWYh4INOtZecaFx/lVZ2mf7vV04iOOzqOntGafvhp73TjoNNFoewbBUxovnvJkLzlPq+vNlr7QywjASncYx6Wx1nVLtDrhxM51hInsaVfNJasu7uc096rrHviEkiI30qiq8WYLWTH3+TxvRuGmw43Fd+aXuOo0htpHHRDXtJ7kF7gCWLdx/55BlFN/h7BPs4pJUoXhJuCNbiLZoo3Gx9Wv6HDX3c52BC+4GIDEF5IQm+ReBV3JSJk0s/XFzodtXyPtM4z2gdb8jLEqXSzXfgBatfErL+xWsB/EBs1m0ewkONUosPyYH6r0R7dUIK+BVGeNv/38cMGwFheSWYsHOiFvAG6pmgVL3T7KtAM327tlqce9V8DLncWLpzEnaXNhQyGLy9I55B1t8JedAUSrfn2SwL4rFOOtOtZdzdsPNGbXm5tUXXCANnEpU8+DWKmK+up68obuplO0GVfUaghOtTvDCuoT2ZjhIJvEbZ/nsP0Aw== jmxnzo@jmxnzo-ThinkPad-T470-W10DG diff --git a/SSH-Core/src/main/resources/keys/id_dsa b/SSH-Core/src/main/resources/keys/userkeys/id_dsa similarity index 100% rename from SSH-Core/src/main/resources/keys/id_dsa rename to SSH-Core/src/main/resources/keys/userkeys/id_dsa diff --git a/SSH-Core/src/main/resources/keys/id_dsa.pub b/SSH-Core/src/main/resources/keys/userkeys/id_dsa.pub similarity index 100% rename from SSH-Core/src/main/resources/keys/id_dsa.pub rename to SSH-Core/src/main/resources/keys/userkeys/id_dsa.pub diff --git a/SSH-Core/src/main/resources/keys/id_ecdsa b/SSH-Core/src/main/resources/keys/userkeys/id_ecdsa similarity index 100% rename from SSH-Core/src/main/resources/keys/id_ecdsa rename to SSH-Core/src/main/resources/keys/userkeys/id_ecdsa diff --git a/SSH-Core/src/main/resources/keys/id_ecdsa.pub b/SSH-Core/src/main/resources/keys/userkeys/id_ecdsa.pub similarity index 100% rename from SSH-Core/src/main/resources/keys/id_ecdsa.pub rename to SSH-Core/src/main/resources/keys/userkeys/id_ecdsa.pub diff --git a/SSH-Core/src/main/resources/keys/id_ed25519 b/SSH-Core/src/main/resources/keys/userkeys/id_ed25519 similarity index 100% rename from SSH-Core/src/main/resources/keys/id_ed25519 rename to SSH-Core/src/main/resources/keys/userkeys/id_ed25519 diff --git a/SSH-Core/src/main/resources/keys/id_ed25519.pub b/SSH-Core/src/main/resources/keys/userkeys/id_ed25519.pub similarity index 100% rename from SSH-Core/src/main/resources/keys/id_ed25519.pub rename to SSH-Core/src/main/resources/keys/userkeys/id_ed25519.pub diff --git a/SSH-Core/src/main/resources/keys/id_rsa b/SSH-Core/src/main/resources/keys/userkeys/id_rsa similarity index 100% rename from SSH-Core/src/main/resources/keys/id_rsa rename to SSH-Core/src/main/resources/keys/userkeys/id_rsa diff --git a/SSH-Core/src/main/resources/keys/id_rsa.pub b/SSH-Core/src/main/resources/keys/userkeys/id_rsa.pub similarity index 100% rename from SSH-Core/src/main/resources/keys/id_rsa.pub rename to SSH-Core/src/main/resources/keys/userkeys/id_rsa.pub diff --git a/SSH-Mitm/src/main/java/de/rub/nds/sshattacker/mitm/config/MitmCommandConfig.java b/SSH-Mitm/src/main/java/de/rub/nds/sshattacker/mitm/config/MitmCommandConfig.java index c4980c3de..6fb99b06a 100644 --- a/SSH-Mitm/src/main/java/de/rub/nds/sshattacker/mitm/config/MitmCommandConfig.java +++ b/SSH-Mitm/src/main/java/de/rub/nds/sshattacker/mitm/config/MitmCommandConfig.java @@ -21,6 +21,8 @@ public class MitmCommandConfig extends SshDelegateConfig { @ParametersDelegate private final WorkflowOutputDelegate workflowOutputDelegate; @ParametersDelegate private final WorkflowTypeDelegate workflowTypeDelegate; @ParametersDelegate private final MitmDelegate mitmDelegate; + @ParametersDelegate private final UserKeysPathDelegate userKeysPathDelegate; + @ParametersDelegate private final HostKeysPathDelegate hostKeysPathDelegate; public MitmCommandConfig(GeneralDelegate delegate) { super(delegate); @@ -30,12 +32,16 @@ public MitmCommandConfig(GeneralDelegate delegate) { workflowOutputDelegate = new WorkflowOutputDelegate(); workflowTypeDelegate = new WorkflowTypeDelegate(); mitmDelegate = new MitmDelegate(); + userKeysPathDelegate = new UserKeysPathDelegate(); + hostKeysPathDelegate = new HostKeysPathDelegate(); addDelegate(configOutputDelegate); addDelegate(timeoutDelegate); addDelegate(workflowInputDelegate); addDelegate(workflowOutputDelegate); addDelegate(workflowTypeDelegate); addDelegate(mitmDelegate); + addDelegate(userKeysPathDelegate); + addDelegate(hostKeysPathDelegate); } public String getWorkflowInput() { diff --git a/SSH-Server/src/main/java/de/rub/nds/sshattacker/server/config/ServerCommandConfig.java b/SSH-Server/src/main/java/de/rub/nds/sshattacker/server/config/ServerCommandConfig.java index 1d16e0fff..4c823540d 100644 --- a/SSH-Server/src/main/java/de/rub/nds/sshattacker/server/config/ServerCommandConfig.java +++ b/SSH-Server/src/main/java/de/rub/nds/sshattacker/server/config/ServerCommandConfig.java @@ -21,6 +21,7 @@ public class ServerCommandConfig extends SshDelegateConfig { @ParametersDelegate private final WorkflowInputDelegate workflowInputDelegate; @ParametersDelegate private final WorkflowOutputDelegate workflowOutputDelegate; @ParametersDelegate private final WorkflowTypeDelegate workflowTypeDelegate; + @ParametersDelegate private final HostKeysPathDelegate hostKeysPathDelegate; public ServerCommandConfig(GeneralDelegate delegate) { super(delegate); @@ -30,12 +31,14 @@ public ServerCommandConfig(GeneralDelegate delegate) { workflowInputDelegate = new WorkflowInputDelegate(); workflowOutputDelegate = new WorkflowOutputDelegate(); workflowTypeDelegate = new WorkflowTypeDelegate(); + hostKeysPathDelegate = new HostKeysPathDelegate(); addDelegate(serverDelegate); addDelegate(configOutputDelegate); addDelegate(timeoutDelegate); addDelegate(workflowInputDelegate); addDelegate(workflowOutputDelegate); addDelegate(workflowTypeDelegate); + addDelegate(hostKeysPathDelegate); } @Override