You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/09/06 16:03:42 UTC
[32/51] [abbrv] mina-sshd git commit: [SSHD-842] Split common
utilities code from sshd-core into sshd-common (new artifact)
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java
new file mode 100644
index 0000000..48f7ec4
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsCloneTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.config.keys;
+
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sshd.common.cipher.ECCurves;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class KeyUtilsCloneTest extends JUnitTestSupport {
+ private final String keyType;
+ private final int keySize;
+
+ public KeyUtilsCloneTest(String keyType, int keySize) {
+ this.keyType = ValidateUtils.checkNotNullAndNotEmpty(keyType, "No key type specified");
+ this.keySize = keySize;
+ }
+
+ @Parameters(name = "type={0}, size={1}")
+ public static List<Object[]> parameters() {
+ List<Object[]> list = new ArrayList<>();
+ addTests(list, KeyPairProvider.SSH_DSS, DSS_SIZES);
+ addTests(list, KeyPairProvider.SSH_RSA, RSA_SIZES);
+ if (SecurityUtils.isECCSupported()) {
+ for (ECCurves curve : ECCurves.VALUES) {
+ if (!curve.isSupported()) {
+ continue;
+ }
+ addTests(list, curve.getKeyType(), Collections.singletonList(curve.getKeySize()));
+ }
+ }
+ if (SecurityUtils.isEDDSACurveSupported()) {
+ addTests(list, KeyPairProvider.SSH_ED25519, ED25519_SIZES);
+ }
+ return Collections.unmodifiableList(list);
+ }
+
+ private static void addTests(List<Object[]> list, String keyType, Collection<Integer> sizes) {
+ for (Integer keySize : sizes) {
+ list.add(new Object[]{keyType, keySize});
+ }
+ }
+
+ @Test
+ @SuppressWarnings("checkstyle:avoidnestedblocks")
+ public void testKeyPairCloning() throws GeneralSecurityException {
+ outputDebugMessage("generateKeyPair(%s)[%d]", keyType, keySize);
+ KeyPair original = KeyUtils.generateKeyPair(keyType, keySize);
+
+ outputDebugMessage("cloneKeyPair(%s)[%d]", keyType, keySize);
+ KeyPair cloned = KeyUtils.cloneKeyPair(keyType, original);
+
+ String prefix = keyType + "[" + keySize + "]";
+ assertNotSame(prefix + ": Key pair not cloned", original, cloned);
+ assertTrue(prefix + ": Cloned pair not equals", KeyUtils.compareKeyPairs(original, cloned));
+
+ {
+ PublicKey k1 = original.getPublic();
+ PublicKey k2 = cloned.getPublic();
+ assertNotSame(prefix + ": Public key not cloned", k1, k2);
+ assertTrue(prefix + ": Cloned public key not equals", KeyUtils.compareKeys(k1, k2));
+
+ String f1 = KeyUtils.getFingerPrint(k1);
+ String f2 = KeyUtils.getFingerPrint(k2);
+ assertEquals(prefix + ": Mismatched fingerprints", f1, f2);
+ }
+
+ {
+ PrivateKey k1 = original.getPrivate();
+ PrivateKey k2 = cloned.getPrivate();
+ assertNotSame(prefix + ": Private key not cloned", k1, k2);
+ assertTrue(prefix + ": Cloned private key not equals", KeyUtils.compareKeys(k1, k2));
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintCaseSensitivityTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintCaseSensitivityTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintCaseSensitivityTest.java
new file mode 100644
index 0000000..ae0b86d
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintCaseSensitivityTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.config.keys;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class KeyUtilsFingerprintCaseSensitivityTest extends JUnitTestSupport {
+
+ // CHECKSTYLE:OFF
+ private static final String KEY_STRING = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxr3N5fkt966xJINl0hH7Q6lLDRR1D0yMjcXCE5roE9VFut2ctGFuo90TCOxkPOMnwzwConeyScVF4ConZeWsxbG9VtRh61IeZ6R5P5ZTvE9xPdZBgIEWvU1bRfrrOfSMihqF98pODspE6NoTtND2eglwSGwxcYFmpdTAmu+8qgxgGxlEaaCjqwdiNPZhygrH81Mv2ruolNeZkn4Bj+wFFmZTD/waN1pQaMf+SO1+kEYIYFNl5+8JRGuUcr8MhHHJB+gwqMTF2BSBVITJzZUiQR0TMtkK6Vbs7yt1F9hhzDzAFDwhV+rsfNQaOHpl3zP07qH+/99A0XG1CVcEdHqVMw== lgoldstein@LGOLDSTEIN-WIN7";
+ // CHECKSTYLE:ON
+ private static final String MD5_PREFIX = "MD5:";
+ private static final String MD5 = "24:32:3c:80:01:b3:e1:fa:7c:53:ca:e3:e8:4e:c6:8e";
+ private static final String MD5_FULL = MD5_PREFIX + MD5;
+ private static final String SHA1_PREFIX = "SHA1:";
+ private static final String SHA1 = "ZNLzC6u+F37oq8BpEAwP69EQtoA";
+ private static final String SHA1_FULL = SHA1_PREFIX + SHA1;
+
+ private static PublicKey key;
+
+ private String expected;
+ private String test;
+
+ public KeyUtilsFingerprintCaseSensitivityTest(String expected, String test) {
+ this.expected = expected;
+ this.test = test;
+ }
+
+ @BeforeClass
+ public static void beforeClass() throws GeneralSecurityException, IOException {
+ key = PublicKeyEntry.parsePublicKeyEntry(KEY_STRING).resolvePublicKey(PublicKeyEntryResolver.FAILING);
+ }
+
+ @Parameters(name = "expected={0}, test={1}")
+ public static Collection<Object[]> parameters() {
+ return Arrays.asList(
+ new Object[] {MD5_FULL, MD5_FULL},
+ new Object[] {MD5_FULL, MD5_FULL.toUpperCase()},
+ new Object[] {MD5_FULL, MD5_FULL.toLowerCase()},
+ new Object[] {MD5_FULL, MD5_PREFIX.toUpperCase() + MD5},
+ new Object[] {MD5_FULL, MD5_PREFIX.toLowerCase() + MD5},
+ new Object[] {MD5_FULL, MD5.toLowerCase()},
+ new Object[] {MD5_FULL, MD5.toUpperCase()},
+ new Object[] {SHA1_FULL, SHA1_FULL},
+ new Object[] {SHA1_FULL, SHA1_PREFIX.toUpperCase() + SHA1},
+ new Object[] {SHA1_FULL, SHA1_PREFIX.toLowerCase() + SHA1}
+ );
+ }
+
+ @Test
+ public void testCase() throws Exception {
+ assertEquals("Check failed", new SimpleImmutableEntry<>(true, expected), KeyUtils.checkFingerPrint(test, key));
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintGenerationTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintGenerationTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintGenerationTest.java
new file mode 100644
index 0000000..9a8fb7a
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsFingerprintGenerationTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.config.keys;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sshd.common.digest.BuiltinDigests;
+import org.apache.sshd.common.digest.DigestFactory;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class KeyUtilsFingerprintGenerationTest extends JUnitTestSupport {
+ private final PublicKey key;
+ private final DigestFactory digestFactory;
+ private final String expected;
+
+ public KeyUtilsFingerprintGenerationTest(PublicKey key, DigestFactory digestFactory, String expected) {
+ this.key = key;
+ this.digestFactory = digestFactory;
+ this.expected = expected;
+ }
+
+ @Parameters(name = "key={0}, digestFactory={1}, expected={2}")
+ public static Collection<Object[]> parameters() throws IOException, GeneralSecurityException {
+ List<? extends Map.Entry<String, List<? extends Map.Entry<DigestFactory, String>>>> keyEntries =
+ Collections.unmodifiableList(Arrays.asList(
+ new SimpleImmutableEntry<>(
+ // CHECKSTYLE:OFF
+ "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAxr3N5fkt966xJINl0hH7Q6lLDRR1D0yMjcXCE5roE9VFut2ctGFuo90TCOxkPOMnwzwConeyScVF4ConZeWsxbG9VtRh61IeZ6R5P5ZTvE9xPdZBgIEWvU1bRfrrOfSMihqF98pODspE6NoTtND2eglwSGwxcYFmpdTAmu+8qgxgGxlEaaCjqwdiNPZhygrH81Mv2ruolNeZkn4Bj+wFFmZTD/waN1pQaMf+SO1+kEYIYFNl5+8JRGuUcr8MhHHJB+gwqMTF2BSBVITJzZUiQR0TMtkK6Vbs7yt1F9hhzDzAFDwhV+rsfNQaOHpl3zP07qH+/99A0XG1CVcEdHqVMw== lgoldstein@LGOLDSTEIN-WIN7",
+ // CHECKSTYLE:ON
+ Arrays.asList(
+ new SimpleImmutableEntry<>(
+ BuiltinDigests.md5,
+ "MD5:24:32:3c:80:01:b3:e1:fa:7c:53:ca:e3:e8:4e:c6:8e"
+ ),
+ new SimpleImmutableEntry<>(
+ BuiltinDigests.sha256,
+ "SHA256:1wNOZO+/XgNGJMx8UUJst33V+bBMTz5EcL0B6y2iRv0"
+ )
+ )
+ ),
+ new SimpleImmutableEntry<>(
+ // CHECKSTYLE:OFF
+ "ssh-dss AAAAB3NzaC1kc3MAAACBAMg/IxsG5BxnF5gM7IKqqR0rftxZC+n5GlbO+J4H+iIb/KR8NBehkxG3CrBZMF96M2K1sEGYLob+3k4r71oWaPul8n5rt9kpd+JSq4iD2ygOyg6Kd1/YDBHoxneizy6I/bGsLwhAAKWcRNrXmYVKGzhrhvZWN12AJDq2mGdj3szLAAAAFQD7a2MltdUSF7FU3//SpW4WGjZbeQAAAIBf0nNsfKQL/TEMo7IpTrEMg5V0RnSigCX0+yUERS42GW/ZeCZBJw7oL2XZbuBtu63vMjDgVpnb92BdrcPgjJ7EFW6DlcyeuywStmg1ygXmDR2AQCxv0eX2CQgrdUczmRa155SDVUTvTQlO1IyKx0vwKAh1H7E3yJUfkTAJstbGYQAAAIEAtv+cdRfNevYFkp55jVqazc8zRLvfb64jzgc5oSJVc64kFs4yx+abYpGX9WxNxDlG6g2WiY8voDBB0YnUJsn0kVRjBKX9OceROxrfT4K4dVbQZsdt+SLaXWL4lGJFrFZL3LZqvySvq6xfhJfakQDDivW4hUOhFPXPHrE5/Ia3T7A= dsa-key-20130709",
+ // CHECKSTYLE:ON
+ Arrays.asList(
+ new SimpleImmutableEntry<>(
+ BuiltinDigests.md5,
+ "MD5:fb:29:14:8d:94:f9:1d:cf:6b:0e:a4:35:1d:83:44:2f"
+ ),
+ new SimpleImmutableEntry<>(
+ BuiltinDigests.sha256,
+ "SHA256:grxw4KhY1cK6eOczBWs7tDVvo9V0PQw4E1wN1gJvHlw"
+ )
+ )
+ ),
+ new SimpleImmutableEntry<>(
+ // CHECKSTYLE:OFF
+ "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBFImZtcTj842stlcVHLFBFxTEx7lu3jW9aZCvd0r9fUNKZ6LbRPh6l1oJ4ozArnw7XreQBUc5oNd9HB5RNJ8jl1nWXY5cXBA7McZrKZrYmk+zxNhH6UL+kMLaJkyngJHQw== root@osv-linux",
+ // CHECKSTYLE:ON
+ Arrays.asList(
+ new SimpleImmutableEntry<>(
+ BuiltinDigests.md5,
+ "MD5:e6:dc:a2:4f:5b:11:b2:3c:0f:e8:f6:d8:d1:01:e9:d3"
+ ),
+ new SimpleImmutableEntry<>(
+ BuiltinDigests.sha512,
+ "SHA512:4w6ZB78tmFWhpN2J50Ok6WeMJhZp1X0xN0EKWxZmRLcYDbCWhyJDe8lgrQKWqdTCMZ5aNEBl9xQUklcC5Gt2jg"
+ )
+ )
+ )
+ ));
+
+ List<Object[]> ret = new ArrayList<>();
+ for (Map.Entry<String, ? extends Collection<? extends Map.Entry<DigestFactory, String>>> kentry : keyEntries) {
+ String keyValue = kentry.getKey();
+ try {
+ PublicKey key = PublicKeyEntry.parsePublicKeyEntry(keyValue).resolvePublicKey(PublicKeyEntryResolver.FAILING);
+ for (Map.Entry<DigestFactory, String> dentry : kentry.getValue()) {
+ DigestFactory factory = dentry.getKey();
+ String fingerprint = dentry.getValue();
+ if (!factory.isSupported()) {
+ System.out.println("Skip unsupported digest: " + fingerprint);
+ continue;
+ }
+
+ ret.add(new Object[]{key, factory, fingerprint});
+ }
+ } catch (InvalidKeySpecException e) {
+ System.out.println("Skip unsupported key: " + keyValue);
+ }
+ }
+
+ return ret;
+ }
+
+ @Test
+ public void testFingerprint() throws Exception {
+ String name = digestFactory.getName();
+ assertEquals(
+ String.format("Fingerprint does not match for digest %s", name),
+ expected,
+ KeyUtils.getFingerPrint(digestFactory, key)
+ );
+ assertEquals(
+ String.format("Fingerprint check failed for digest %s", name),
+ new SimpleImmutableEntry<>(true, expected),
+ KeyUtils.checkFingerPrint(expected, digestFactory, key)
+ );
+ assertEquals(
+ String.format("Fingerprint check succeeded for invalid digest %s", name),
+ new SimpleImmutableEntry<>(false, expected),
+ KeyUtils.checkFingerPrint(expected + "A", digestFactory, key)
+ );
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
new file mode 100644
index 0000000..00b273f
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/KeyUtilsTest.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.config.keys;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFilePermission;
+import java.security.DigestException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
+
+import org.apache.sshd.common.digest.BaseDigest;
+import org.apache.sshd.common.digest.BuiltinDigests;
+import org.apache.sshd.common.digest.Digest;
+import org.apache.sshd.common.digest.DigestFactory;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.OsUtils;
+import org.apache.sshd.common.util.io.IoUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class KeyUtilsTest extends JUnitTestSupport {
+ public KeyUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testGenerateFingerPrintOnException() {
+ for (DigestFactory info : BuiltinDigests.VALUES) {
+ if (!info.isSupported()) {
+ System.out.println("Skip unsupported digest: " + info.getAlgorithm());
+ continue;
+ }
+
+ Exception thrown = new DigestException(info.getAlgorithm() + ":" + info.getBlockSize());
+ Digest digest = new BaseDigest(info.getAlgorithm(), info.getBlockSize()) {
+ @Override
+ public byte[] digest() throws Exception {
+ throw thrown;
+ }
+ };
+ String actual = KeyUtils.getFingerPrint(new DigestFactory() {
+ @Override
+ public String getName() {
+ return getCurrentTestName();
+ }
+
+ @Override
+ public String getAlgorithm() {
+ return digest.getAlgorithm();
+ }
+
+ @Override
+ public boolean isSupported() {
+ return info.isSupported();
+ }
+
+ @Override
+ public int getBlockSize() {
+ return info.getBlockSize();
+ }
+
+ @Override
+ public Digest create() {
+ return digest;
+ }
+ }, getCurrentTestName());
+ String expected = thrown.getClass().getSimpleName();
+ assertEquals("Mismatched fingerprint for " + thrown.getMessage(), expected, actual);
+ }
+ }
+
+ @Test
+ public void testGenerateDefaultFingerprintDigest() {
+ DigestFactory defaultValue = KeyUtils.getDefaultFingerPrintFactory();
+ assertNotNull("No current default fingerprint digest factory", defaultValue);
+ try {
+ for (DigestFactory f : BuiltinDigests.VALUES) {
+ if (!f.isSupported()) {
+ System.out.println("Skip unsupported digest=" + f.getAlgorithm());
+ continue;
+ }
+
+ KeyUtils.setDefaultFingerPrintFactory(f);
+
+ String data = getClass().getName() + "#" + getCurrentTestName() + "(" + f.getName() + ")";
+ String expected = KeyUtils.getFingerPrint(f, data);
+ String actual = KeyUtils.getFingerPrint(data);
+ assertEquals("Mismatched fingerprint for digest=" + f.getName(), expected, actual);
+ }
+ } finally {
+ KeyUtils.setDefaultFingerPrintFactory(defaultValue); // restore the original
+ }
+ }
+
+ @Test // see SSHD-606
+ public void testValidateStrictKeyFilePermissions() throws IOException {
+ Path file = getTempTargetRelativeFile(getClass().getSimpleName(), getCurrentTestName());
+ outputDebugMessage("%s deletion result=%s", file, Files.deleteIfExists(file));
+ assertNull("Unexpected violation for non-existent file: " + file, KeyUtils.validateStrictKeyFilePermissions(file));
+
+ assertHierarchyTargetFolderExists(file.getParent());
+ try (OutputStream output = Files.newOutputStream(file)) {
+ output.write((getClass().getName() + "#" + getCurrentTestName() + "@" + new Date(System.currentTimeMillis())).getBytes(StandardCharsets.UTF_8));
+ }
+
+ Collection<PosixFilePermission> perms = IoUtils.getPermissions(file);
+ if (GenericUtils.isEmpty(perms)) {
+ assertNull("Unexpected violation for no permissions file: " + file, KeyUtils.validateStrictKeyFilePermissions(file));
+ } else if (OsUtils.isUNIX()) {
+ Map.Entry<String, Object> violation = null;
+ for (PosixFilePermission p : KeyUtils.STRICTLY_PROHIBITED_FILE_PERMISSION) {
+ if (perms.contains(p)) {
+ violation = KeyUtils.validateStrictKeyFilePermissions(file);
+ assertNotNull("Unexpected success for permission=" + p + " of file " + file + " permissions=" + perms, violation);
+ break;
+ }
+ }
+
+ if (violation == null) { // we expect a failure since the parent does not have the necessary permissions
+ assertNotNull("Unexpected UNIX success for file " + file + " permissions=" + perms, KeyUtils.validateStrictKeyFilePermissions(file));
+ }
+ } else {
+ assertNull("Unexpected Windows violation for file " + file + " permissions=" + perms, KeyUtils.validateStrictKeyFilePermissions(file));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/PublicKeyEntryTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/PublicKeyEntryTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/PublicKeyEntryTest.java
new file mode 100644
index 0000000..1fd372f
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/PublicKeyEntryTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.config.keys;
+
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class PublicKeyEntryTest extends JUnitTestSupport {
+ public PublicKeyEntryTest() {
+ super();
+ }
+
+ @Test
+ public void testFallbackResolver() throws Exception {
+ PublicKeyEntry entry = // TODO use some
+ PublicKeyEntry.parsePublicKeyEntry(
+ GenericUtils.join(
+ Arrays.asList(getCurrentTestName(), "AAAA", getClass().getSimpleName()), ' '));
+ for (PublicKeyEntryResolver resolver : new PublicKeyEntryResolver[]{
+ null, PublicKeyEntryResolver.FAILING, PublicKeyEntryResolver.IGNORING}) {
+ try {
+ PublicKey key = entry.resolvePublicKey(resolver);
+ assertSame("Mismatched successful resolver", PublicKeyEntryResolver.IGNORING, resolver);
+ assertNull("Unexpected success for resolver=" + resolver + ": " + KeyUtils.getFingerPrint(key), key);
+ } catch (GeneralSecurityException e) {
+ assertObjectInstanceOf("Mismatched thrown exception for resolver=" + resolver, InvalidKeySpecException.class, e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscatorTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscatorTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscatorTest.java
new file mode 100644
index 0000000..48797b8
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/AESPrivateKeyObfuscatorTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.config.keys.loader;
+
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.util.List;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class AESPrivateKeyObfuscatorTest extends JUnitTestSupport {
+ private static final Random RANDOMIZER = new Random(System.currentTimeMillis());
+
+ private final int keyLength;
+
+ public AESPrivateKeyObfuscatorTest(int keyLength) {
+ this.keyLength = keyLength;
+ }
+
+ @Parameters(name = "keyLength={0}")
+ public static List<Object[]> parameters() {
+ List<Integer> lengths = AESPrivateKeyObfuscator.getAvailableKeyLengths();
+ assertFalse("No lengths available", GenericUtils.isEmpty(lengths));
+ return parameterize(lengths);
+ }
+
+ @Test
+ public void testAvailableKeyLengthExists() throws GeneralSecurityException {
+ assertEquals("Not a BYTE size multiple", 0, keyLength % Byte.SIZE);
+
+ byte[] iv = new byte[keyLength / Byte.SIZE];
+ synchronized (RANDOMIZER) {
+ RANDOMIZER.nextBytes(iv);
+ }
+
+ Key key = new SecretKeySpec(iv, AESPrivateKeyObfuscator.CIPHER_NAME);
+ Cipher c = SecurityUtils.getCipher(AESPrivateKeyObfuscator.CIPHER_NAME);
+ c.init(Cipher.DECRYPT_MODE, key);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
new file mode 100644
index 0000000..d5c6aba
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/openssh/OpenSSHKeyPairResourceParserTest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.config.keys.loader.openssh;
+
+import java.net.URL;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
+import org.apache.sshd.common.config.keys.BuiltinIdentities;
+import org.apache.sshd.common.config.keys.FilePasswordProvider;
+import org.apache.sshd.common.config.keys.PrivateKeyEntryDecoder;
+import org.apache.sshd.common.config.keys.PublicKeyEntryResolver;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.Assume;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class OpenSSHKeyPairResourceParserTest extends JUnitTestSupport {
+ private static final OpenSSHKeyPairResourceParser PARSER = OpenSSHKeyPairResourceParser.INSTANCE;
+ private final BuiltinIdentities identity;
+
+ public OpenSSHKeyPairResourceParserTest(BuiltinIdentities identity) {
+ this.identity = identity;
+ }
+
+ @Parameters(name = "type={0}")
+ public static List<Object[]> parameters() {
+ return parameterize(BuiltinIdentities.VALUES);
+ }
+
+ @Test
+ public void testLoadKeyPairs() throws Exception {
+ Assume.assumeTrue(identity + " not supported", identity.isSupported());
+
+ String resourceKey = getClass().getSimpleName() + "-" + identity.getName().toUpperCase() + "-" + KeyPair.class.getSimpleName();
+ URL urlKeyPair = getClass().getResource(resourceKey);
+ assertNotNull("Missing key-pair resource: " + resourceKey, urlKeyPair);
+
+ Collection<KeyPair> pairs = PARSER.loadKeyPairs(urlKeyPair, FilePasswordProvider.EMPTY);
+ assertEquals("Mismatched pairs count", 1, GenericUtils.size(pairs));
+
+ URL urlPubKey = getClass().getResource(resourceKey + ".pub");
+ assertNotNull("Missing public key resource: " + resourceKey, urlPubKey);
+
+ List<AuthorizedKeyEntry> entries = AuthorizedKeyEntry.readAuthorizedKeys(urlPubKey);
+ assertEquals("Mismatched public keys count", 1, GenericUtils.size(entries));
+
+ AuthorizedKeyEntry entry = entries.get(0);
+ PublicKey pubEntry = entry.resolvePublicKey(PublicKeyEntryResolver.FAILING);
+ assertNotNull("Cannot retrieve public key", pubEntry);
+
+ Class<? extends PublicKey> pubType = identity.getPublicKeyType();
+ Class<? extends PrivateKey> prvType = identity.getPrivateKeyType();
+ for (KeyPair kp : pairs) {
+ PublicKey pubKey = ValidateUtils.checkInstanceOf(kp.getPublic(), pubType, "Mismatched public key type");
+ assertKeyEquals("Mismatched identity public key", pubEntry, pubKey);
+
+ PrivateKey prvKey = ValidateUtils.checkInstanceOf(kp.getPrivate(), prvType, "Mismatched private key type");
+ @SuppressWarnings("rawtypes")
+ PrivateKeyEntryDecoder decoder =
+ OpenSSHKeyPairResourceParser.getPrivateKeyEntryDecoder(prvKey);
+ assertNotNull("No private key decoder", decoder);
+
+ if (decoder.isPublicKeyRecoverySupported()) {
+ @SuppressWarnings("unchecked")
+ PublicKey recKey = decoder.recoverPublicKey(prvKey);
+ assertKeyEquals("Mismatched recovered public key", pubKey, recKey);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
new file mode 100644
index 0000000..406a273
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/loader/pem/PKCS8PEMResourceKeyPairParserTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.config.keys.loader.pem;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.ssl.PEMItem;
+import org.apache.commons.ssl.PEMUtil;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class PKCS8PEMResourceKeyPairParserTest extends JUnitTestSupport {
+ private final String algorithm;
+ private final int keySize;
+
+ public PKCS8PEMResourceKeyPairParserTest(String algorithm, int keySize) {
+ this.algorithm = algorithm;
+ this.keySize = keySize;
+ }
+
+ @Parameters(name = "{0} / {1}")
+ public static List<Object[]> parameters() {
+ List<Object[]> params = new ArrayList<>();
+ for (Integer ks : RSA_SIZES) {
+ params.add(new Object[]{KeyUtils.RSA_ALGORITHM, ks});
+ }
+ for (Integer ks : DSS_SIZES) {
+ params.add(new Object[]{KeyUtils.DSS_ALGORITHM, ks});
+ }
+ return params;
+ }
+
+ @Test // see SSHD-760
+ public void testPkcs8() throws IOException, GeneralSecurityException {
+ KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator(algorithm);
+ if (keySize > 0) {
+ generator.initialize(keySize);
+ }
+ KeyPair kp = generator.generateKeyPair();
+
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ Collection<Object> items = new ArrayList<>();
+ PrivateKey prv1 = kp.getPrivate();
+ items.add(new PEMItem(prv1.getEncoded(), "PRIVATE KEY"));
+ byte[] bytes = PEMUtil.encode(items);
+ os.write(bytes);
+ os.close();
+
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray())) {
+ KeyPair kp2 = SecurityUtils.loadKeyPairIdentity(getCurrentTestName(), bais, null);
+
+ assertEquals("Mismatched public key", kp.getPublic(), kp2.getPublic());
+ assertEquals("Mismatched private key", prv1, kp2.getPrivate());
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[" + algorithm + "/" + keySize + "]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/digest/BuiltinDigestsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/digest/BuiltinDigestsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/digest/BuiltinDigestsTest.java
new file mode 100644
index 0000000..9ec928b
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/digest/BuiltinDigestsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.digest;
+
+import java.lang.reflect.Field;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class BuiltinDigestsTest extends JUnitTestSupport {
+ public BuiltinDigestsTest() {
+ super();
+ }
+
+ @Test
+ public void testFromName() {
+ for (BuiltinDigests expected : BuiltinDigests.VALUES) {
+ String name = expected.getName();
+ BuiltinDigests actual = BuiltinDigests.fromFactoryName(name);
+ assertSame(name, expected, actual);
+ }
+ }
+
+ @Test
+ public void testAllConstantsCovered() throws Exception {
+ Set<BuiltinDigests> avail = EnumSet.noneOf(BuiltinDigests.class);
+ Field[] fields = BuiltinDigests.Constants.class.getFields();
+ for (Field f : fields) {
+ String name = (String) f.get(null);
+ BuiltinDigests value = BuiltinDigests.fromFactoryName(name);
+ assertNotNull("No match found for " + name, value);
+ assertTrue(name + " re-specified", avail.add(value));
+ }
+
+ assertEquals("Incomplete coverage", BuiltinDigests.VALUES, avail);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/future/DefaultSshFutureTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/future/DefaultSshFutureTest.java b/sshd-common/src/test/java/org/apache/sshd/common/future/DefaultSshFutureTest.java
new file mode 100644
index 0000000..05e3df2
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/future/DefaultSshFutureTest.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.future;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+import org.mockito.Mockito;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class DefaultSshFutureTest extends JUnitTestSupport {
+ public DefaultSshFutureTest() {
+ super();
+ }
+
+ @Test
+ @SuppressWarnings("rawtypes")
+ public void testAwaitUninterrupted() {
+ DefaultSshFuture future = new DefaultSshFuture(getCurrentTestName(), null);
+ Object expected = new Object();
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(TimeUnit.SECONDS.toMillis(2L));
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ future.setValue(expected);
+ }
+ }.start();
+
+ future.awaitUninterruptibly();
+ assertSame("Mismatched signalled value", expected, future.getValue());
+ }
+
+ @Test
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void testNotifyMultipleListeners() {
+ DefaultSshFuture future = new DefaultSshFuture(getCurrentTestName(), null);
+ AtomicInteger listenerCount = new AtomicInteger(0);
+ Object expected = new Object();
+ SshFutureListener listener = f -> {
+ assertSame("Mismatched future instance", future, f);
+ assertSame("Mismatched value object", expected, future.getValue());
+ listenerCount.incrementAndGet();
+ };
+
+ int numListeners = Byte.SIZE;
+ for (int index = 0; index < numListeners; index++) {
+ future.addListener(listener);
+ }
+
+ future.setValue(expected);
+ assertEquals("Mismatched listeners invocation count", numListeners, listenerCount.get());
+ }
+
+ @Test
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void testListenerInvokedDirectlyAfterResultSet() {
+ DefaultSshFuture future = new DefaultSshFuture(getCurrentTestName(), null);
+ AtomicInteger listenerCount = new AtomicInteger(0);
+ Object expected = new Object();
+ SshFutureListener listener = f -> {
+ assertSame("Mismatched future instance", future, f);
+ assertSame("Mismatched value object", expected, future.getValue());
+ listenerCount.incrementAndGet();
+ };
+ future.setValue(expected);
+
+ future.addListener(listener);
+ assertEquals("Mismatched number of registered listeners", 0, future.getNumRegisteredListeners());
+ assertEquals("Listener not invoked", 1, listenerCount.get());
+ }
+
+ @Test
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void testAddAndRemoveRegisteredListenersBeforeResultSet() {
+ DefaultSshFuture future = new DefaultSshFuture(getCurrentTestName(), null);
+ SshFutureListener listener = Mockito.mock(SshFutureListener.class);
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ future.addListener(listener);
+ assertEquals("Mismatched number of added listeners", index, future.getNumRegisteredListeners());
+ }
+
+ for (int index = future.getNumRegisteredListeners() - 1; index >= 0; index--) {
+ future.removeListener(listener);
+ assertEquals("Mismatched number of remaining listeners", index, future.getNumRegisteredListeners());
+ }
+ }
+
+ @Test
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void testListenerNotRemovedIfResultSet() {
+ DefaultSshFuture future = new DefaultSshFuture(getCurrentTestName(), null);
+ AtomicInteger listenerCount = new AtomicInteger(0);
+ Object expected = new Object();
+ SshFutureListener listener = f -> {
+ assertSame("Mismatched future instance", future, f);
+ assertSame("Mismatched value object", expected, future.getValue());
+ listenerCount.incrementAndGet();
+ };
+ future.addListener(listener);
+ future.setValue(expected);
+ assertEquals("Mismatched number of registered listeners", 1, future.getNumRegisteredListeners());
+ assertEquals("Listener not invoked", 1, listenerCount.get());
+
+ future.removeListener(listener);
+ assertEquals("Mismatched number of remaining listeners", 1, future.getNumRegisteredListeners());
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
new file mode 100644
index 0000000..021796b
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.keyprovider;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+import org.mockito.Mockito;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class KeyPairProviderTest extends JUnitTestSupport {
+ public KeyPairProviderTest() {
+ super();
+ }
+
+ @Test
+ public void testEmptyKeyProvider() {
+ KeyPairProvider provider = KeyPairProvider.EMPTY_KEYPAIR_PROVIDER;
+ assertTrue("Non empty loaded keys", GenericUtils.isEmpty(provider.loadKeys()));
+ assertTrue("Non empty key type", GenericUtils.isEmpty(provider.getKeyTypes()));
+
+ for (String keyType : new String[]{null, "", getCurrentTestName()}) {
+ assertNull("Unexpected key-pair loaded for type='" + keyType + "'", provider.loadKey(keyType));
+ }
+ }
+
+ @Test
+ public void testMapToKeyPairProvider() {
+ PublicKey pubKey = Mockito.mock(PublicKey.class);
+ PrivateKey prvKey = Mockito.mock(PrivateKey.class);
+ String[] testKeys = {getCurrentTestName(), getClass().getSimpleName()};
+ Map<String, KeyPair> pairsMap = GenericUtils.toSortedMap(
+ Arrays.asList(testKeys),
+ Function.identity(),
+ k -> new KeyPair(pubKey, prvKey),
+ String.CASE_INSENSITIVE_ORDER);
+
+ KeyPairProvider provider = MappedKeyPairProvider.MAP_TO_KEY_PAIR_PROVIDER.apply(pairsMap);
+ assertEquals("Key types", pairsMap.keySet(), provider.getKeyTypes());
+ assertEquals("Key pairs", pairsMap.values(), provider.loadKeys());
+
+ pairsMap.forEach((keyType, expected) -> {
+ KeyPair actual = provider.loadKey(keyType);
+ assertSame(keyType, expected, actual);
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
new file mode 100644
index 0000000..0d50c41
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/mac/BuiltinMacsTest.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.mac;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.mac.BuiltinMacs.ParseResult;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+import org.mockito.Mockito;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class BuiltinMacsTest extends JUnitTestSupport {
+ public BuiltinMacsTest() {
+ super();
+ }
+
+ @Test
+ public void testFromName() {
+ for (BuiltinMacs expected : BuiltinMacs.VALUES) {
+ String name = expected.getName();
+ BuiltinMacs actual = BuiltinMacs.fromFactoryName(name);
+ assertSame(name, expected, actual);
+ }
+ }
+
+ @Test
+ public void testAllConstantsCovered() throws Exception {
+ Set<BuiltinMacs> avail = EnumSet.noneOf(BuiltinMacs.class);
+ Field[] fields = BuiltinMacs.Constants.class.getFields();
+ for (Field f : fields) {
+ String name = (String) f.get(null);
+ BuiltinMacs value = BuiltinMacs.fromFactoryName(name);
+ assertNotNull("No match found for " + name, value);
+ assertTrue(name + " re-specified", avail.add(value));
+ }
+
+ assertEquals("Incomplete coverage", BuiltinMacs.VALUES, avail);
+ }
+
+ @Test
+ public void testParseMacsList() {
+ List<String> builtin = NamedResource.getNameList(BuiltinMacs.VALUES);
+ List<String> unknown = Arrays.asList(getClass().getPackage().getName(), getClass().getSimpleName(), getCurrentTestName());
+ Random rnd = new Random();
+ for (int index = 0; index < (builtin.size() + unknown.size()); index++) {
+ Collections.shuffle(builtin, rnd);
+ Collections.shuffle(unknown, rnd);
+
+ List<String> weavedList = new ArrayList<>(builtin.size() + unknown.size());
+ for (int bIndex = 0, uIndex = 0; (bIndex < builtin.size()) || (uIndex < unknown.size());) {
+ boolean useBuiltin = false;
+ if (bIndex < builtin.size()) {
+ useBuiltin = uIndex >= unknown.size() || rnd.nextBoolean();
+ }
+
+ if (useBuiltin) {
+ weavedList.add(builtin.get(bIndex));
+ bIndex++;
+ } else if (uIndex < unknown.size()) {
+ weavedList.add(unknown.get(uIndex));
+ uIndex++;
+ }
+ }
+
+ String fullList = GenericUtils.join(weavedList, ',');
+ ParseResult result = BuiltinMacs.parseMacsList(fullList);
+ List<String> parsed = NamedResource.getNameList(result.getParsedFactories());
+ List<String> missing = result.getUnsupportedFactories();
+
+ // makes sure not only that the contents are the same but also the order
+ assertListEquals(fullList + "[parsed]", builtin, parsed);
+ assertListEquals(fullList + "[unsupported]", unknown, missing);
+ }
+ }
+
+ @Test
+ public void testResolveFactoryOnBuiltinValues() {
+ for (MacFactory expected : BuiltinMacs.VALUES) {
+ String name = expected.getName();
+ MacFactory actual = BuiltinMacs.resolveFactory(name);
+ assertSame(name, expected, actual);
+ }
+ }
+
+ @Test
+ public void testNotAllowedToRegisterBuiltinFactories() {
+ for (MacFactory expected : BuiltinMacs.VALUES) {
+ try {
+ BuiltinMacs.registerExtension(expected);
+ fail("Unexpected success for " + expected.getName());
+ } catch (IllegalArgumentException e) {
+ // expected - ignored
+ }
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNotAllowedToOverrideRegisteredFactories() {
+ MacFactory expected = Mockito.mock(MacFactory.class);
+ Mockito.when(expected.getName()).thenReturn(getCurrentTestName());
+
+ String name = expected.getName();
+ try {
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ BuiltinMacs.registerExtension(expected);
+ assertEquals("Unexpected success at attempt #" + index, 1, index);
+ }
+ } finally {
+ BuiltinMacs.unregisterExtension(name);
+ }
+ }
+
+ @Test
+ public void testResolveFactoryOnRegisteredExtension() {
+ MacFactory expected = Mockito.mock(MacFactory.class);
+ Mockito.when(expected.getName()).thenReturn(getCurrentTestName());
+
+ String name = expected.getName();
+ try {
+ assertNull("Extension already registered", BuiltinMacs.resolveFactory(name));
+ BuiltinMacs.registerExtension(expected);
+
+ MacFactory actual = BuiltinMacs.resolveFactory(name);
+ assertSame("Mismatched resolved instance", expected, actual);
+ } finally {
+ MacFactory actual = BuiltinMacs.unregisterExtension(name);
+ assertSame("Mismatched unregistered instance", expected, actual);
+ assertNull("Extension not un-registered", BuiltinMacs.resolveFactory(name));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/mac/MacVectorsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/mac/MacVectorsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/mac/MacVectorsTest.java
new file mode 100644
index 0000000..f330d22
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/mac/MacVectorsTest.java
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.mac;
+
+import java.nio.charset.StandardCharsets;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @see <A HREF="https://tools.ietf.org/html/rfc4231">RFC 4321</A>
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class MacVectorsTest extends JUnitTestSupport {
+ private final VectorSeed seed;
+ private final Factory<? extends Mac> macFactory;
+ private final byte[] expected;
+
+ public MacVectorsTest(VectorSeed seed, String factoryName, String expected) {
+ this.seed = Objects.requireNonNull(seed, "No seed");
+ this.macFactory = ValidateUtils.checkNotNull(BuiltinMacs.fromFactoryName(factoryName), "Unknown MAC: %s", factoryName);
+ this.expected = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, expected);
+ }
+
+ @Parameters(name = "factory={1}, expected={2}, seed={0}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> ret = new ArrayList<>();
+ for (VectorTestData vector : Collections.unmodifiableList(
+ Arrays.asList(
+ ///////////////// Test Cases for HMAC-MD5 ///////////////////////
+ // see https://tools.ietf.org/html/rfc2202
+ new VectorTestData("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", false, "Hi There",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 1
+ "9294727a3638bb1c13f48ef8158bfc9d"))),
+ new VectorTestData("Jefe", "what do ya want for nothing?",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 2
+ "750c783e6ab0b503eaa86e310a5db738"))),
+ new VectorTestData("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", false, repeat("dd", 50), false,
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 3
+ "56be34521d144c88dbb8c733f0e8b3f6"))),
+ /* TODO see why it fails
+ new VectorTestData("0102030405060708090a0b0c0d0e0f10111213141516171819", false, repeat("cd", 50), false,
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 4
+ "697eaf0aca3a3aea3a75164746ffaa79"))),
+ */
+ new VectorTestData("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", false, "Test With Truncation",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 5
+ "56461ef2342edc00f9bab995690efd4c"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5_96,
+ "56461ef2342edc00f9bab995"))),
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 80), false, "Test Using Larger Than Block-Size Key - Hash Key First",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 6
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"))),
+ */
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 80), false, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_MD5, // test case 7
+ "6f630fad67cda0ee1fb1f562db3aa53e"))),
+ */
+ ///////////////// Test Cases for HMAC-SHA-1 ///////////////////////
+ // see https://tools.ietf.org/html/rfc2202
+ new VectorTestData("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", false, "Hi There",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 1
+ "b617318655057264e28bc0b6fb378c8ef146be00"))),
+ new VectorTestData("Jefe", "what do ya want for nothing?",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 2
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"))),
+ new VectorTestData("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", false, repeat("dd", 50), false,
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 3
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3"))),
+ /* TODO see why it fails
+ new VectorTestData("0102030405060708090a0b0c0d0e0f10111213141516171819", false, repeat("cd", 50), false,
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 4
+ "4c9007f4026250c6bc8414f9bf50c86c2d7235da"))),
+ */
+ new VectorTestData("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", false, "Test With Truncation",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 5
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1_96,
+ "4c1a03424b55e07fe7f27be1"))),
+ /* TODO see why this fails
+ new VectorTestData(repeat("aa", 80), false, "Test Using Larger Than Block-Size Key - Hash Key First",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 6
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112"))),
+ */
+
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 80), false, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 7
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1_96,
+ "4c1a03424b55e07fe7f27be1"))),
+ */
+
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 80), false, "Test Using Larger Than Block-Size Key - Hash Key First",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 8
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112"))),
+ */
+
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 80), false, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+ Arrays.asList(new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA1, // test case 9
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"))),
+ */
+
+ ///////////////// Test Cases for HMAC-SHA-2 ///////////////////////
+ // see https://tools.ietf.org/html/rfc4231
+ new VectorTestData(repeat("0b", 20), false, "Hi There",
+ // test case 1
+ Arrays.asList(
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"))),
+ new VectorTestData("Jefe", "what do ya want for nothing?",
+ // test case 2
+ Arrays.asList(
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"))),
+ new VectorTestData(repeat("aa", 20), false, repeat("dd", 50), false,
+ // test case 3
+ Arrays.asList(
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"))),
+ new VectorTestData("0102030405060708090a0b0c0d0e0f10111213141516171819", false, repeat("cd", 50), false,
+ // test case 4
+ Arrays.asList(
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"))),
+
+ /* TODO see why it fails
+ new VectorTestData(repeat("0c", 20), false, "Test With Truncation",
+ Arrays.asList( // test case 5
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "a3b6167473100ee06e0c796c2955552b"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "415fad6271580a531d4179bc891d87a6"))),
+ */
+
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 131), false, "Test Using Larger Than Block-Size Key - Hash Key First",
+ Arrays.asList( // test case 6
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"))),
+ */
+
+ /* TODO see why it fails
+ new VectorTestData(repeat("aa", 131), false, "This is a test using a larger than block-size"
+ + " key and a larger than block-size data."
+ + " The key needs to be hashed before being used"
+ + " by the HMAC algorithm",
+ Arrays.asList( // test case 7
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_256,
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"),
+ new SimpleImmutableEntry<>(BuiltinMacs.Constants.HMAC_SHA2_512,
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58")))
+ */
+
+ // mark end
+ new VectorTestData("", false, "", false, Collections.emptyList())))) {
+ for (Map.Entry<String, String> tc : vector.getResults()) {
+ ret.add(new Object[]{vector, tc.getKey(), tc.getValue()});
+ }
+ }
+
+ return ret;
+ }
+
+ @Test
+ public void testStandardVectorMac() throws Exception {
+ Mac mac = macFactory.create();
+ mac.init(seed.getKey());
+ mac.update(seed.getData());
+
+ byte[] actual = new byte[mac.getBlockSize()];
+ mac.doFinal(actual);
+ assertArrayEquals("Mismatched results for actual=" + BufferUtils.toHex(BufferUtils.EMPTY_HEX_SEPARATOR, actual), expected, actual);
+ }
+
+ private static class VectorSeed {
+ private final byte[] key;
+ private final String keyString;
+ private final byte[] data;
+ private final String dataString;
+
+ VectorSeed(String key, String data) {
+ this.key = key.getBytes(StandardCharsets.UTF_8);
+ this.keyString = key;
+ this.data = data.getBytes(StandardCharsets.UTF_8);
+ this.dataString = data;
+ }
+
+ VectorSeed(String key, boolean useKeyString, String data) {
+ this.key = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, key);
+ this.keyString = useKeyString ? new String(this.key, StandardCharsets.UTF_8) : key;
+ this.data = data.getBytes(StandardCharsets.UTF_8);
+ this.dataString = data;
+ }
+
+ VectorSeed(String key, boolean useKeyString, String data, boolean useDataString) {
+ this.key = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, key);
+ this.keyString = useKeyString ? new String(this.key, StandardCharsets.UTF_8) : key;
+ this.data = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, data);
+ this.dataString = useDataString ? new String(this.data, StandardCharsets.UTF_8) : data;
+ }
+
+ public byte[] getKey() {
+ return key.clone(); // clone to avoid inadvertent change
+ }
+
+ public String getKeyString() {
+ return keyString;
+ }
+
+ public byte[] getData() {
+ return data.clone(); // clone to avoid inadvertent change
+ }
+
+ public String getDataString() {
+ return dataString;
+ }
+
+ @Override
+ public String toString() {
+ return "key=" + trimToLength(getKeyString(), 32) + ", data=" + trimToLength(getDataString(), 32);
+ }
+
+ private static CharSequence trimToLength(CharSequence csq, int maxLen) {
+ if (GenericUtils.length(csq) <= maxLen) {
+ return csq;
+ }
+
+ return csq.subSequence(0, maxLen) + "...";
+ }
+ }
+
+ private static class VectorTestData extends VectorSeed {
+ private final Collection<Map.Entry<String, String>> results;
+
+ VectorTestData(String key, String data, Collection<Map.Entry<String, String>> results) {
+ super(key, data);
+ this.results = results;
+ }
+
+ VectorTestData(String key, boolean useKeyString, String data, Collection<Map.Entry<String, String>> results) {
+ super(key, useKeyString, data);
+ this.results = results;
+ }
+
+ VectorTestData(String key, boolean useKeyString, String data, boolean useDataString, Collection<Map.Entry<String, String>> results) {
+ super(key, useKeyString, data, useDataString);
+ this.results = results;
+ }
+
+ public Collection<Map.Entry<String, String>> getResults() {
+ return results;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java b/sshd-common/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java
new file mode 100644
index 0000000..08872d9
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/random/RandomFactoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.random;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.Assume;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class RandomFactoryTest extends JUnitTestSupport {
+ private final RandomFactory factory;
+
+ public RandomFactoryTest(RandomFactory factory) {
+ this.factory = factory;
+ }
+
+ @Parameters(name = "type={0}")
+ public static Collection<Object[]> parameters() {
+ Collection<RandomFactory> testCases = new LinkedList<>();
+ testCases.add(JceRandomFactory.INSTANCE);
+ if (SecurityUtils.isBouncyCastleRegistered()) {
+ testCases.add(SecurityUtils.getRandomFactory());
+ } else {
+ System.out.println("Skip BouncyCastleRandomFactory - unsupported");
+ }
+
+ return parameterize(testCases);
+ }
+
+ @Test
+ public void testRandomFactory() {
+ Assume.assumeTrue("Skip unsupported factory: " + factory.getName(), factory.isSupported());
+ long t = testRandom(factory.create());
+ System.out.println(factory.getName() + " duration: " + t + " " + TimeUnit.MICROSECONDS);
+ }
+
+ // returns duration in microseconds
+ private static long testRandom(Random random) {
+ byte[] bytes = new byte[32];
+ long l0 = System.nanoTime();
+ for (int i = 0; i < 1000; i++) {
+ random.fill(bytes, 8, 16);
+ }
+ long l1 = System.nanoTime();
+ return TimeUnit.NANOSECONDS.toMicros(l1 - l0);
+ }
+}