aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/androidTest
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2014-10-01 23:04:51 +0100
committerKenny Root <kenny@the-b.org>2014-10-01 12:48:19 +0100
commit49b779dcaf03e3598d2709b321e20ea029b25163 (patch)
tree05af547b1f1433d7dd6f7373d0b25a455e053a03 /app/src/androidTest
parentd64786d9197090c74072b648e487e3d34817bb57 (diff)
downloadconnectbot-49b779dcaf03e3598d2709b321e20ea029b25163.tar.gz
connectbot-49b779dcaf03e3598d2709b321e20ea029b25163.tar.bz2
connectbot-49b779dcaf03e3598d2709b321e20ea029b25163.zip
Convert to gradle build system
Diffstat (limited to 'app/src/androidTest')
-rw-r--r--app/src/androidTest/java/org/connectbot/HostBeanTest.java96
-rw-r--r--app/src/androidTest/java/org/connectbot/HostListActivityTest.java47
-rw-r--r--app/src/androidTest/java/org/connectbot/SelectionAreaTest.java141
-rw-r--r--app/src/androidTest/java/org/connectbot/SettingsActivityTest.java47
-rw-r--r--app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java105
-rw-r--r--app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java229
-rw-r--r--app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java33
-rw-r--r--app/src/androidTest/java/org/connectbot/mock/NullTransport.java138
-rw-r--r--app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java345
9 files changed, 1181 insertions, 0 deletions
diff --git a/app/src/androidTest/java/org/connectbot/HostBeanTest.java b/app/src/androidTest/java/org/connectbot/HostBeanTest.java
new file mode 100644
index 0000000..a252aca
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/HostBeanTest.java
@@ -0,0 +1,96 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot;
+
+import org.connectbot.bean.HostBean;
+import org.connectbot.mock.BeanTestCase;
+
+import android.test.AndroidTestCase;
+
+/**
+ * @author Kenny Root
+ *
+ */
+public class HostBeanTest extends AndroidTestCase {
+ private static final String[] FIELDS = { "nickname", "username",
+ "hostname", "port" };
+
+ HostBean host1;
+ HostBean host2;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ host1 = new HostBean();
+ host1.setNickname("Home");
+ host1.setUsername("bob");
+ host1.setHostname("server.example.com");
+ host1.setPort(22);
+
+ host2 = new HostBean();
+ host2.setNickname("Home");
+ host2.setUsername("bob");
+ host2.setHostname("server.example.com");
+ host2.setPort(22);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIdEquality() {
+ host1.setId(1);
+ host2.setId(1);
+ assertTrue(host1.equals(host2));
+ assertTrue(host1.hashCode() == host2.hashCode());
+ }
+
+ public void testIdInequality() {
+ host1.setId(1);
+ host2.setId(2);
+ // HostBeans shouldn't be equal when their IDs are not the same
+ assertFalse("HostBeans are equal when their ID is different", host1
+ .equals(host2));
+ assertFalse("HostBean hash codes are equal when their ID is different",
+ host1.hashCode() == host2.hashCode());
+ }
+
+ public void testIdEquality2() {
+ host1.setId(1);
+ host2.setId(1);
+ host2.setNickname("Work");
+ host2.setUsername("alice");
+ host2.setHostname("client.example.com");
+ assertTrue(
+ "HostBeans are not equal when their ID is the same but other fields are different!",
+ host1.equals(host2));
+ assertTrue(
+ "HostBeans hashCodes are not equal when their ID is the same but other fields are different!",
+ host1.hashCode() == host2.hashCode());
+ }
+
+ public void testBeanMeetsEqualsContract() {
+ BeanTestCase.assertMeetsEqualsContract(HostBean.class, FIELDS);
+ }
+
+ public void testBeanMeetsHashCodeContract() {
+ BeanTestCase.assertMeetsHashCodeContract(HostBean.class, FIELDS);
+ }
+}
diff --git a/app/src/androidTest/java/org/connectbot/HostListActivityTest.java b/app/src/androidTest/java/org/connectbot/HostListActivityTest.java
new file mode 100644
index 0000000..3962c9a
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/HostListActivityTest.java
@@ -0,0 +1,47 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * This is a simple framework for a test of an Application. See
+ * {@link android.test.ApplicationTestCase ApplicationTestCase} for more
+ * information on how to write and extend Application tests.
+ * <p/>
+ * To run this test, you can type: adb shell am instrument -w \ -e class
+ * org.connectbot.HostListActivityTest \
+ * org.connectbot.tests/android.test.InstrumentationTestRunner
+ */
+public class HostListActivityTest extends ActivityInstrumentationTestCase2<HostListActivity> {
+ private Activity mActivity;
+
+ public HostListActivityTest() {
+ super("org.connectbot", HostListActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ setActivityInitialTouchMode(false);
+
+ mActivity = getActivity();
+ }
+}
diff --git a/app/src/androidTest/java/org/connectbot/SelectionAreaTest.java b/app/src/androidTest/java/org/connectbot/SelectionAreaTest.java
new file mode 100644
index 0000000..93e0293
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/SelectionAreaTest.java
@@ -0,0 +1,141 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot;
+
+import org.connectbot.bean.SelectionArea;
+
+import android.test.AndroidTestCase;
+
+/**
+ * @author Kenny Root
+ *
+ */
+public class SelectionAreaTest extends AndroidTestCase {
+ private static final int WIDTH = 80;
+ private static final int HEIGHT = 24;
+
+ public void testCreate() {
+ SelectionArea sa = new SelectionArea();
+
+ assertTrue(sa.getLeft() == 0);
+ assertTrue(sa.getRight() == 0);
+ assertTrue(sa.getTop() == 0);
+ assertTrue(sa.getBottom() == 0);
+ assertTrue(sa.isSelectingOrigin());
+ }
+
+ public void testCheckMovement() {
+ SelectionArea sa = new SelectionArea();
+
+ sa.setBounds(WIDTH, HEIGHT);
+
+ sa.incrementColumn();
+
+ // Should be (1,0) to (1,0)
+ assertTrue(sa.getLeft() == 1);
+ assertTrue(sa.getTop() == 0);
+ assertTrue(sa.getRight() == 1);
+ assertTrue(sa.getBottom() == 0);
+
+ sa.finishSelectingOrigin();
+ assertFalse(sa.isSelectingOrigin());
+
+ sa.incrementColumn();
+ sa.incrementColumn();
+
+ // Should be (1,0) to (3,0)
+ assertTrue(sa.getLeft() == 1);
+ assertTrue(sa.getTop() == 0);
+ assertTrue(sa.getRight() == 3);
+ assertTrue(sa.getBottom() == 0);
+ }
+
+ public void testBounds() {
+ SelectionArea sa = new SelectionArea();
+
+ sa.setBounds(WIDTH, HEIGHT);
+
+ for (int i = 0; i <= WIDTH; i++)
+ sa.decrementColumn();
+ assertTrue("Left bound should be 0, but instead is " + sa.getLeft(),
+ sa.getLeft() == 0);
+
+ for (int i = 0; i <= HEIGHT; i++)
+ sa.decrementRow();
+ assertTrue("Top bound should be 0, but instead is " + sa.getLeft(),
+ sa.getTop() == 0);
+
+ sa.finishSelectingOrigin();
+
+ for (int i = 0; i <= WIDTH * 2; i++)
+ sa.incrementColumn();
+
+ assertTrue("Left bound should be 0, but instead is " + sa.getLeft(),
+ sa.getLeft() == 0);
+ assertTrue("Right bound should be " + (WIDTH - 1) + ", but instead is " + sa.getRight(),
+ sa.getRight() == (WIDTH - 1));
+
+ for (int i = 0; i <= HEIGHT * 2; i++)
+ sa.incrementRow();
+
+ assertTrue("Bottom bound should be " + (HEIGHT - 1) + ", but instead is " + sa.getBottom(),
+ sa.getBottom() == (HEIGHT - 1));
+ assertTrue("Top bound should be 0, but instead is " + sa.getTop(),
+ sa.getTop() == 0);
+ }
+
+ public void testSetThenMove() {
+ SelectionArea sa = new SelectionArea();
+
+ sa.setBounds(WIDTH, HEIGHT);
+
+ int targetColumn = WIDTH / 2;
+ int targetRow = HEIGHT / 2;
+
+ sa.setColumn(targetColumn);
+ sa.setRow(targetRow);
+
+ sa.incrementRow();
+ assertTrue("Row should be " + (targetRow + 1) + ", but instead is " + sa.getTop(),
+ sa.getTop() == (targetRow + 1));
+
+ sa.decrementColumn();
+ assertTrue("Column shold be " + (targetColumn - 1) + ", but instead is " + sa.getLeft(),
+ sa.getLeft() == (targetColumn - 1));
+
+ sa.finishSelectingOrigin();
+
+ sa.setRow(0);
+ sa.setColumn(0);
+
+ sa.incrementRow();
+ sa.decrementColumn();
+
+ assertTrue("Top row should be 1, but instead is " + sa.getTop(),
+ sa.getTop() == 1);
+
+ assertTrue("Left column shold be 0, but instead is " + sa.getLeft(),
+ sa.getLeft() == 0);
+
+ assertTrue("Bottom row should be " + (targetRow + 1) + ", but instead is " + sa.getBottom(),
+ sa.getBottom() == (targetRow + 1));
+
+ assertTrue("Right column shold be " + (targetColumn - 1) + ", but instead is " + sa.getRight(),
+ sa.getRight() == (targetColumn - 1));
+ }
+}
diff --git a/app/src/androidTest/java/org/connectbot/SettingsActivityTest.java b/app/src/androidTest/java/org/connectbot/SettingsActivityTest.java
new file mode 100644
index 0000000..6b79136
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/SettingsActivityTest.java
@@ -0,0 +1,47 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * This is a simple framework for a test of an Application. See
+ * {@link android.test.ApplicationTestCase ApplicationTestCase} for more
+ * information on how to write and extend Application tests.
+ * <p/>
+ * To run this test, you can type:
+ * adb shell am instrument -w \
+ * -e class org.connectbot.HostListActivityTest \
+ * org.connectbot.tests/android.test.InstrumentationTestRunner
+ */
+public class SettingsActivityTest extends
+ ActivityInstrumentationTestCase2<SettingsActivity> {
+
+ public SettingsActivityTest() {
+ super("org.connectbot", SettingsActivity.class);
+ }
+
+ public void testOpenMenu() {
+ SettingsActivity a = getActivity();
+
+ a.openOptionsMenu();
+
+ a.closeOptionsMenu();
+ }
+
+}
diff --git a/app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java b/app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java
new file mode 100644
index 0000000..bfa5e23
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/TerminalBridgeTest.java
@@ -0,0 +1,105 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot;
+
+import android.test.AndroidTestCase;
+
+/**
+ * @author Kenny Root
+ *
+ */
+public class TerminalBridgeTest extends AndroidTestCase {
+ public void testShiftLock() throws SecurityException, NoSuchFieldException,
+ IllegalArgumentException, IllegalAccessException {
+// TerminalBridge bridge = new TerminalBridge();
+// AbsTransport nullTransport = new NullTransport();
+//
+// // Make sure onKey will work when we call it
+// Field disconnected = TerminalBridge.class
+// .getDeclaredField("disconnected");
+// Field keymode = TerminalBridge.class.getDeclaredField("keymode");
+// Field transport = TerminalBridge.class.getDeclaredField("transport");
+//
+// disconnected.setAccessible(true);
+// keymode.setAccessible(true);
+// transport.setAccessible(true);
+//
+// disconnected.setBoolean(bridge, false);
+// keymode.set(bridge, PreferenceConstants.KEYMODE_RIGHT);
+// transport.set(bridge, nullTransport);
+//
+// // Begin tests
+// assertTrue("Meta state is " + bridge.getMetaState()
+// + " when it should be 0", bridge.getMetaState() == 0);
+//
+// KeyEvent shiftDown = new KeyEvent(KeyEvent.ACTION_DOWN,
+// KeyEvent.KEYCODE_SHIFT_LEFT);
+// bridge.onKey(null, shiftDown.getKeyCode(), shiftDown);
+//
+// assertTrue("Shift test: after shift press, meta state is "
+// + bridge.getMetaState() + " when it should be "
+// + TerminalBridge.META_SHIFT_ON,
+// bridge.getMetaState() == TerminalBridge.META_SHIFT_ON);
+//
+// KeyEvent shiftUp = KeyEvent.changeAction(shiftDown, KeyEvent.ACTION_UP);
+// bridge.onKey(null, shiftUp.getKeyCode(), shiftUp);
+//
+// assertTrue("Shift test: after shift release, meta state is "
+// + bridge.getMetaState() + " when it should be "
+// + TerminalBridge.META_SHIFT_ON,
+// bridge.getMetaState() == TerminalBridge.META_SHIFT_ON);
+//
+// KeyEvent letterAdown = new KeyEvent(KeyEvent.ACTION_DOWN,
+// KeyEvent.KEYCODE_A);
+// KeyEvent letterAup = KeyEvent.changeAction(letterAdown,
+// KeyEvent.ACTION_UP);
+//
+// bridge.onKey(null, letterAdown.getKeyCode(), letterAdown);
+// bridge.onKey(null, letterAup.getKeyCode(), letterAup);
+//
+// assertTrue("Shift test: after letter press and release, meta state is "
+// + bridge.getMetaState() + " when it should be 0", bridge
+// .getMetaState() == 0);
+//
+// bridge.onKey(null, shiftDown.getKeyCode(), shiftDown);
+// bridge.onKey(null, shiftUp.getKeyCode(), shiftUp);
+// bridge.onKey(null, shiftDown.getKeyCode(), shiftDown);
+// bridge.onKey(null, shiftUp.getKeyCode(), shiftUp);
+//
+// assertTrue("Shift lock test: after two shift presses, meta state is "
+// + bridge.getMetaState() + " when it should be "
+// + TerminalBridge.META_SHIFT_LOCK,
+// bridge.getMetaState() == TerminalBridge.META_SHIFT_LOCK);
+//
+// bridge.onKey(null, letterAdown.getKeyCode(), letterAdown);
+//
+// assertTrue(
+// "Shift lock test: after letter press, meta state is "
+// + bridge.getMetaState() + " when it should be "
+// + TerminalBridge.META_SHIFT_LOCK,
+// bridge.getMetaState() == TerminalBridge.META_SHIFT_LOCK);
+//
+// bridge.onKey(null, letterAup.getKeyCode(), letterAup);
+//
+// assertTrue(
+// "Shift lock test: after letter press and release, meta state is "
+// + bridge.getMetaState() + " when it should be "
+// + TerminalBridge.META_SHIFT_LOCK,
+// bridge.getMetaState() == TerminalBridge.META_SHIFT_LOCK);
+ }
+}
diff --git a/app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java b/app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java
new file mode 100644
index 0000000..5d13d9f
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/mock/BeanTestCase.java
@@ -0,0 +1,229 @@
+/**
+ * Originally from http://www.cornetdesign.com/files/BeanTestCase.java.txt
+ */
+package org.connectbot.mock;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Field;
+
+public class BeanTestCase extends TestCase {
+
+ private static final String TEST_STRING_VAL1 = "Some Value";
+ private static final String TEST_STRING_VAL2 = "Some Other Value";
+
+ public static void assertMeetsEqualsContract(Class<?> classUnderTest,
+ String[] fieldNames) {
+ Object o1;
+ Object o2;
+ try {
+ // Get Instances
+ o1 = classUnderTest.newInstance();
+ o2 = classUnderTest.newInstance();
+
+ assertTrue(
+ "Instances with default constructor not equal (o1.equals(o2))",
+ o1.equals(o2));
+ assertTrue(
+ "Instances with default constructor not equal (o2.equals(o1))",
+ o2.equals(o1));
+
+ Field[] fields = getFieldsByNameOrAll(classUnderTest, fieldNames);
+
+ for (int i = 0; i < fields.length; i++) {
+
+ // Reset the instances
+ o1 = classUnderTest.newInstance();
+ o2 = classUnderTest.newInstance();
+
+ Field field = fields[i];
+ field.setAccessible(true);
+ if (field.getType() == String.class) {
+ field.set(o1, TEST_STRING_VAL1);
+ } else if (field.getType() == boolean.class) {
+ field.setBoolean(o1, true);
+ } else if (field.getType() == short.class) {
+ field.setShort(o1, (short) 1);
+ } else if (field.getType() == long.class) {
+ field.setLong(o1, (long) 1);
+ } else if (field.getType() == float.class) {
+ field.setFloat(o1, (float) 1);
+ } else if (field.getType() == int.class) {
+ field.setInt(o1, 1);
+ } else if (field.getType() == byte.class) {
+ field.setByte(o1, (byte) 1);
+ } else if (field.getType() == char.class) {
+ field.setChar(o1, (char) 1);
+ } else if (field.getType() == double.class) {
+ field.setDouble(o1, (double) 1);
+ } else if (field.getType().isEnum()) {
+ field.set(o1, field.getType().getEnumConstants()[0]);
+ } else if (Object.class.isAssignableFrom(field.getType())) {
+ field.set(o1, field.getType().newInstance());
+ } else {
+ fail("Don't know how to set a " + field.getType().getName());
+ }
+
+ assertFalse("Instances with o1 having " + field.getName()
+ + " set and o2 having it not set are equal", o1
+ .equals(o2));
+
+ field.set(o2, field.get(o1));
+
+ assertTrue(
+ "After setting o2 with the value of the object in o1, the two objects in the field are not equal",
+ field.get(o1).equals(field.get(o2)));
+
+ assertTrue(
+ "Instances with o1 having "
+ + field.getName()
+ + " set and o2 having it set to the same object of type "
+ + field.get(o2).getClass().getName()
+ + " are not equal", o1.equals(o2));
+
+ if (field.getType() == String.class) {
+ field.set(o2, TEST_STRING_VAL2);
+ } else if (field.getType() == boolean.class) {
+ field.setBoolean(o2, false);
+ } else if (field.getType() == short.class) {
+ field.setShort(o2, (short) 0);
+ } else if (field.getType() == long.class) {
+ field.setLong(o2, (long) 0);
+ } else if (field.getType() == float.class) {
+ field.setFloat(o2, (float) 0);
+ } else if (field.getType() == int.class) {
+ field.setInt(o2, 0);
+ } else if (field.getType() == byte.class) {
+ field.setByte(o2, (byte) 0);
+ } else if (field.getType() == char.class) {
+ field.setChar(o2, (char) 0);
+ } else if (field.getType() == double.class) {
+ field.setDouble(o2, (double) 1);
+ } else if (field.getType().isEnum()) {
+ field.set(o2, field.getType().getEnumConstants()[1]);
+ } else if (Object.class.isAssignableFrom(field.getType())) {
+ field.set(o2, field.getType().newInstance());
+ } else {
+ fail("Don't know how to set a " + field.getType().getName());
+ }
+ if (field.get(o1).equals(field.get(o2))) {
+ // Even though we have different instances, they are equal.
+ // Let's walk one of them
+ // to see if we can find a field to set
+ Field[] paramFields = field.get(o1).getClass()
+ .getDeclaredFields();
+ for (int j = 0; j < paramFields.length; j++) {
+ paramFields[j].setAccessible(true);
+ if (paramFields[j].getType() == String.class) {
+ paramFields[j].set(field.get(o1), TEST_STRING_VAL1);
+ }
+ }
+ }
+
+ assertFalse(
+ "After setting o2 with a different object than what is in o1, the two objects in the field are equal. "
+ + "This is after an attempt to walk the fields to make them different",
+ field.get(o1).equals(field.get(o2)));
+ assertFalse(
+ "Instances with o1 having "
+ + field.getName()
+ + " set and o2 having it set to a different object are equal",
+ o1.equals(o2));
+ }
+
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to construct an instance of the class under test");
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to construct an instance of the class under test");
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to read the field from the class under test");
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to find field in the class under test");
+ }
+ }
+
+ /**
+ * @param classUnderTest
+ * @param fieldNames
+ * @return
+ * @throws NoSuchFieldException
+ */
+ private static Field[] getFieldsByNameOrAll(Class<?> classUnderTest,
+ String[] fieldNames) throws NoSuchFieldException {
+ Field fields[];
+ if (fieldNames == null) {
+ fields = classUnderTest.getDeclaredFields();
+ } else {
+ fields = new Field[fieldNames.length];
+ for (int i = 0; i < fieldNames.length; i++)
+ fields[i] = classUnderTest.getDeclaredField(fieldNames[i]);
+ }
+ return fields;
+ }
+
+ public static void assertMeetsHashCodeContract(Class<?> classUnderTest,
+ String[] fieldNames) {
+ try {
+ Field[] fields = getFieldsByNameOrAll(classUnderTest, fieldNames);
+
+ for (int i = 0; i < fields.length; i++) {
+ Object o1 = classUnderTest.newInstance();
+ int initialHashCode = o1.hashCode();
+
+ Field field = fields[i];
+ field.setAccessible(true);
+ if (field.getType() == String.class) {
+ field.set(o1, TEST_STRING_VAL1);
+ } else if (field.getType() == boolean.class) {
+ field.setBoolean(o1, true);
+ } else if (field.getType() == short.class) {
+ field.setShort(o1, (short) 1);
+ } else if (field.getType() == long.class) {
+ field.setLong(o1, (long) 1);
+ } else if (field.getType() == float.class) {
+ field.setFloat(o1, (float) 1);
+ } else if (field.getType() == int.class) {
+ field.setInt(o1, 1);
+ } else if (field.getType() == byte.class) {
+ field.setByte(o1, (byte) 1);
+ } else if (field.getType() == char.class) {
+ field.setChar(o1, (char) 1);
+ } else if (field.getType() == double.class) {
+ field.setDouble(o1, (double) 1);
+ } else if (field.getType().isEnum()) {
+ field.set(o1, field.getType().getEnumConstants()[0]);
+ } else if (Object.class.isAssignableFrom(field.getType())) {
+ field.set(o1, field.getType().newInstance());
+ } else {
+ fail("Don't know how to set a " + field.getType().getName());
+ }
+ int updatedHashCode = o1.hashCode();
+ assertFalse(
+ "The field "
+ + field.getName()
+ + " was not taken into account for the hashCode contract ",
+ initialHashCode == updatedHashCode);
+ }
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to construct an instance of the class under test");
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to construct an instance of the class under test");
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ throw new AssertionError(
+ "Unable to find field in the class under test");
+ }
+ }
+}
diff --git a/app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java b/app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java
new file mode 100644
index 0000000..79b8e72
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/mock/NullOutputStream.java
@@ -0,0 +1,33 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot.mock;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author Kenny Root
+ *
+ */
+public class NullOutputStream extends OutputStream {
+ @Override
+ public void write(int arg0) throws IOException {
+ // do nothing
+ }
+
+}
diff --git a/app/src/androidTest/java/org/connectbot/mock/NullTransport.java b/app/src/androidTest/java/org/connectbot/mock/NullTransport.java
new file mode 100644
index 0000000..d841e6a
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/mock/NullTransport.java
@@ -0,0 +1,138 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot.mock;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.connectbot.bean.HostBean;
+import org.connectbot.service.TerminalBridge;
+import org.connectbot.service.TerminalManager;
+import org.connectbot.transport.AbsTransport;
+
+import android.net.Uri;
+
+/**
+ * @author kenny
+ *
+ */
+public class NullTransport extends AbsTransport {
+
+ /**
+ *
+ */
+ public NullTransport() {
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * @param host
+ * @param bridge
+ * @param manager
+ */
+ public NullTransport(HostBean host, TerminalBridge bridge,
+ TerminalManager manager) {
+ super(host, bridge, manager);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public void close() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void connect() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public HostBean createHost(Uri uri) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void flush() throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getDefaultNickname(String username, String hostname, int port) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getDefaultPort() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void getSelectionArgs(Uri uri, Map<String, String> selection) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isConnected() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isSessionOpen() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int read(byte[] buffer, int offset, int length) throws IOException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void setDimensions(int columns, int rows, int width, int height) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void write(byte[] buffer) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void write(int c) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean usesNetwork() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java b/app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java
new file mode 100644
index 0000000..1eb1ee6
--- /dev/null
+++ b/app/src/androidTest/java/org/connectbot/util/PubkeyUtilsTest.java
@@ -0,0 +1,345 @@
+/*
+ * ConnectBot: simple, powerful, open-source SSH client for Android
+ * Copyright 2007 Kenny Root, Jeffrey Sharkey
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.connectbot.util;
+
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+
+import android.test.AndroidTestCase;
+
+/**
+ * @author Kenny Root
+ *
+ */
+public class PubkeyUtilsTest extends AndroidTestCase {
+ public void testEncodeHex_Null_Failure() throws Exception {
+ try {
+ PubkeyUtils.encodeHex(null);
+ fail("Should throw null pointer exception when argument is null");
+ } catch (NullPointerException e) {
+ // success
+ }
+ }
+ public void testEncodeHex_Success() throws Exception {
+ byte[] input = {(byte) 0xFF, 0x00, (byte) 0xA5, 0x5A, 0x12, 0x23};
+ String expected = "ff00a55a1223";
+
+ assertEquals("Encoded hex should match expected",
+ PubkeyUtils.encodeHex(input), expected);
+ }
+
+ public void testSha256_Empty_Success() throws Exception {
+ byte[] empty_hashed = new byte[] {
+ (byte) 0xe3, (byte) 0xb0, (byte) 0xc4, (byte) 0x42,
+ (byte) 0x98, (byte) 0xfc, (byte) 0x1c, (byte) 0x14,
+ (byte) 0x9a, (byte) 0xfb, (byte) 0xf4, (byte) 0xc8,
+ (byte) 0x99, (byte) 0x6f, (byte) 0xb9, (byte) 0x24,
+ (byte) 0x27, (byte) 0xae, (byte) 0x41, (byte) 0xe4,
+ (byte) 0x64, (byte) 0x9b, (byte) 0x93, (byte) 0x4c,
+ (byte) 0xa4, (byte) 0x95, (byte) 0x99, (byte) 0x1b,
+ (byte) 0x78, (byte) 0x52, (byte) 0xb8, (byte) 0x55,
+ };
+
+ final byte[] empty = new byte[] {};
+
+ assertTrue("Empty string should be equal to known test vector",
+ Arrays.equals(empty_hashed, PubkeyUtils.sha256(empty)));
+ }
+
+ /* openssl ecparam -genkey -name prime256v1 -noout | openssl pkcs8 -topk8 -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' */
+ private static final byte[] EC_KEY_PKCS8 = new byte[] { (byte) 0x30, (byte) 0x81, (byte) 0x87,
+ (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x13, (byte) 0x06,
+ (byte) 0x07, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xCE, (byte) 0x3D,
+ (byte) 0x02, (byte) 0x01, (byte) 0x06, (byte) 0x08, (byte) 0x2A, (byte) 0x86,
+ (byte) 0x48, (byte) 0xCE, (byte) 0x3D, (byte) 0x03, (byte) 0x01, (byte) 0x07,
+ (byte) 0x04, (byte) 0x6D, (byte) 0x30, (byte) 0x6B, (byte) 0x02, (byte) 0x01,
+ (byte) 0x01, (byte) 0x04, (byte) 0x20, (byte) 0xC7, (byte) 0x6B, (byte) 0xA5,
+ (byte) 0xB6, (byte) 0xB7, (byte) 0x4E, (byte) 0x0B, (byte) 0x70, (byte) 0x2E,
+ (byte) 0xA0, (byte) 0x5D, (byte) 0x8D, (byte) 0x0A, (byte) 0xF5, (byte) 0x43,
+ (byte) 0xEF, (byte) 0x54, (byte) 0x2F, (byte) 0x05, (byte) 0x5B, (byte) 0x66,
+ (byte) 0x50, (byte) 0xC5, (byte) 0xB4, (byte) 0xA8, (byte) 0x60, (byte) 0x16,
+ (byte) 0x8E, (byte) 0x8D, (byte) 0xCD, (byte) 0x11, (byte) 0xFA, (byte) 0xA1,
+ (byte) 0x44, (byte) 0x03, (byte) 0x42, (byte) 0x00, (byte) 0x04, (byte) 0x12,
+ (byte) 0xE2, (byte) 0x70, (byte) 0x30, (byte) 0x87, (byte) 0x2F, (byte) 0xDE,
+ (byte) 0x10, (byte) 0xD9, (byte) 0xC9, (byte) 0x83, (byte) 0xC7, (byte) 0x8D,
+ (byte) 0xC9, (byte) 0x9B, (byte) 0x94, (byte) 0x24, (byte) 0x50, (byte) 0x5D,
+ (byte) 0xEC, (byte) 0xF1, (byte) 0x4F, (byte) 0x52, (byte) 0xC6, (byte) 0xE7,
+ (byte) 0xA3, (byte) 0xD7, (byte) 0xF4, (byte) 0x7C, (byte) 0x09, (byte) 0xA1,
+ (byte) 0x10, (byte) 0x11, (byte) 0xE4, (byte) 0x9E, (byte) 0x90, (byte) 0xAF,
+ (byte) 0xF9, (byte) 0x4A, (byte) 0x74, (byte) 0x09, (byte) 0x93, (byte) 0xC7,
+ (byte) 0x9A, (byte) 0xB3, (byte) 0xE2, (byte) 0xD8, (byte) 0x61, (byte) 0x5F,
+ (byte) 0x86, (byte) 0x14, (byte) 0x91, (byte) 0x7A, (byte) 0x23, (byte) 0x81,
+ (byte) 0x42, (byte) 0xA9, (byte) 0x02, (byte) 0x1D, (byte) 0x33, (byte) 0x19,
+ (byte) 0xC0, (byte) 0x4B, (byte) 0xCE
+ };
+
+ private static final BigInteger EC_KEY_priv = new BigInteger("c76ba5b6b74e0b702ea05d8d0af543ef542f055b6650c5b4a860168e8dcd11fa", 16);
+ private static final BigInteger EC_KEY_pub_x = new BigInteger("12e27030872fde10d9c983c78dc99b9424505decf14f52c6e7a3d7f47c09a110", 16);
+ private static final BigInteger EC_KEY_pub_y = new BigInteger("11e49e90aff94a740993c79ab3e2d8615f8614917a238142a9021d3319c04bce", 16);
+
+ /* openssl genrsa 512 | openssl pkcs8 -topk8 -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g' */
+ private static final byte[] RSA_KEY_PKCS8 = new byte[] { (byte) 0x30, (byte) 0x82, (byte) 0x01,
+ (byte) 0x55, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, (byte) 0x0D,
+ (byte) 0x06, (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+ (byte) 0xF7, (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+ (byte) 0x00, (byte) 0x04, (byte) 0x82, (byte) 0x01, (byte) 0x3F, (byte) 0x30,
+ (byte) 0x82, (byte) 0x01, (byte) 0x3B, (byte) 0x02, (byte) 0x01, (byte) 0x00,
+ (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xC6, (byte) 0x00, (byte) 0x79,
+ (byte) 0x0C, (byte) 0x46, (byte) 0xF9, (byte) 0x03, (byte) 0x15, (byte) 0xBA,
+ (byte) 0x35, (byte) 0x63, (byte) 0x6C, (byte) 0x97, (byte) 0x3A, (byte) 0x6C,
+ (byte) 0xC8, (byte) 0x15, (byte) 0x32, (byte) 0x2A, (byte) 0x62, (byte) 0x72,
+ (byte) 0xBD, (byte) 0x05, (byte) 0x01, (byte) 0xCF, (byte) 0xE6, (byte) 0x49,
+ (byte) 0xEC, (byte) 0xC9, (byte) 0x8A, (byte) 0x3A, (byte) 0x4E, (byte) 0xB1,
+ (byte) 0xF2, (byte) 0x3E, (byte) 0x86, (byte) 0x3C, (byte) 0x64, (byte) 0x4A,
+ (byte) 0x0A, (byte) 0x29, (byte) 0xD6, (byte) 0xFA, (byte) 0xF9, (byte) 0xAC,
+ (byte) 0xD8, (byte) 0x7B, (byte) 0x9F, (byte) 0x2A, (byte) 0x6B, (byte) 0x13,
+ (byte) 0x06, (byte) 0x06, (byte) 0xEB, (byte) 0x83, (byte) 0x1B, (byte) 0xB8,
+ (byte) 0x97, (byte) 0xA3, (byte) 0x91, (byte) 0x95, (byte) 0x60, (byte) 0x15,
+ (byte) 0xE5, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01,
+ (byte) 0x02, (byte) 0x40, (byte) 0x0F, (byte) 0xDA, (byte) 0x33, (byte) 0xD6,
+ (byte) 0xCE, (byte) 0xCB, (byte) 0xDA, (byte) 0xFA, (byte) 0x5F, (byte) 0x59,
+ (byte) 0x2C, (byte) 0xE7, (byte) 0xA1, (byte) 0xC7, (byte) 0xF4, (byte) 0xB3,
+ (byte) 0xA4, (byte) 0x36, (byte) 0xCA, (byte) 0xFB, (byte) 0xEC, (byte) 0xD1,
+ (byte) 0xC3, (byte) 0x57, (byte) 0xDC, (byte) 0xCC, (byte) 0x44, (byte) 0x38,
+ (byte) 0xE7, (byte) 0xFD, (byte) 0xE0, (byte) 0x23, (byte) 0x0E, (byte) 0x97,
+ (byte) 0x87, (byte) 0x55, (byte) 0x80, (byte) 0x2B, (byte) 0xF2, (byte) 0xF4,
+ (byte) 0x1C, (byte) 0x03, (byte) 0xD2, (byte) 0x3E, (byte) 0x09, (byte) 0x72,
+ (byte) 0x49, (byte) 0xD8, (byte) 0x9C, (byte) 0xAC, (byte) 0xDA, (byte) 0x65,
+ (byte) 0x68, (byte) 0x4D, (byte) 0x38, (byte) 0x19, (byte) 0xD8, (byte) 0xB1,
+ (byte) 0x5B, (byte) 0xB7, (byte) 0x38, (byte) 0xC8, (byte) 0x94, (byte) 0xB5,
+ (byte) 0x02, (byte) 0x21, (byte) 0x00, (byte) 0xF7, (byte) 0x8E, (byte) 0x20,
+ (byte) 0xDC, (byte) 0x26, (byte) 0x12, (byte) 0x3A, (byte) 0x85, (byte) 0x91,
+ (byte) 0x5F, (byte) 0x45, (byte) 0xA6, (byte) 0x95, (byte) 0xE5, (byte) 0x22,
+ (byte) 0xD0, (byte) 0xC4, (byte) 0xD7, (byte) 0x6A, (byte) 0xF1, (byte) 0x43,
+ (byte) 0x38, (byte) 0x88, (byte) 0x20, (byte) 0x7D, (byte) 0x80, (byte) 0x73,
+ (byte) 0x7B, (byte) 0xDC, (byte) 0x73, (byte) 0x51, (byte) 0x3B, (byte) 0x02,
+ (byte) 0x21, (byte) 0x00, (byte) 0xCC, (byte) 0xC1, (byte) 0x99, (byte) 0xC8,
+ (byte) 0xC0, (byte) 0x54, (byte) 0xBC, (byte) 0xE9, (byte) 0xFB, (byte) 0x77,
+ (byte) 0x28, (byte) 0xB8, (byte) 0x26, (byte) 0x02, (byte) 0xC0, (byte) 0x0C,
+ (byte) 0xDE, (byte) 0xFD, (byte) 0xEA, (byte) 0xD0, (byte) 0x15, (byte) 0x4B,
+ (byte) 0x3B, (byte) 0xD1, (byte) 0xDD, (byte) 0xFD, (byte) 0x5B, (byte) 0xAC,
+ (byte) 0xB3, (byte) 0xCF, (byte) 0xC3, (byte) 0x5F, (byte) 0x02, (byte) 0x21,
+ (byte) 0x00, (byte) 0xCD, (byte) 0x8C, (byte) 0x25, (byte) 0x9C, (byte) 0xA5,
+ (byte) 0xBF, (byte) 0xDC, (byte) 0xF7, (byte) 0xAA, (byte) 0x8D, (byte) 0x00,
+ (byte) 0xB8, (byte) 0x21, (byte) 0x1D, (byte) 0xF0, (byte) 0x9A, (byte) 0x87,
+ (byte) 0xD6, (byte) 0x95, (byte) 0xE5, (byte) 0x5D, (byte) 0x7B, (byte) 0x43,
+ (byte) 0x0C, (byte) 0x37, (byte) 0x28, (byte) 0xC0, (byte) 0xBA, (byte) 0xC7,
+ (byte) 0x80, (byte) 0xB8, (byte) 0xA1, (byte) 0x02, (byte) 0x21, (byte) 0x00,
+ (byte) 0xCC, (byte) 0x26, (byte) 0x6F, (byte) 0xAD, (byte) 0x60, (byte) 0x4E,
+ (byte) 0x5C, (byte) 0xB9, (byte) 0x32, (byte) 0x57, (byte) 0x61, (byte) 0x8B,
+ (byte) 0x11, (byte) 0xA3, (byte) 0x06, (byte) 0x57, (byte) 0x0E, (byte) 0xF2,
+ (byte) 0xBE, (byte) 0x6F, (byte) 0x4F, (byte) 0xFB, (byte) 0xDE, (byte) 0x1D,
+ (byte) 0xE6, (byte) 0xA7, (byte) 0x19, (byte) 0x03, (byte) 0x7D, (byte) 0x98,
+ (byte) 0xB6, (byte) 0x23, (byte) 0x02, (byte) 0x20, (byte) 0x24, (byte) 0x80,
+ (byte) 0x94, (byte) 0xFF, (byte) 0xDD, (byte) 0x7A, (byte) 0x22, (byte) 0x7D,
+ (byte) 0xC4, (byte) 0x5A, (byte) 0xFD, (byte) 0x84, (byte) 0xC1, (byte) 0xAD,
+ (byte) 0x8A, (byte) 0x13, (byte) 0x2A, (byte) 0xF9, (byte) 0x5D, (byte) 0xFF,
+ (byte) 0x0B, (byte) 0x2E, (byte) 0x0F, (byte) 0x61, (byte) 0x42, (byte) 0x88,
+ (byte) 0x57, (byte) 0xCF, (byte) 0xC1, (byte) 0x71, (byte) 0xC9, (byte) 0xB9
+ };
+
+ private static final BigInteger RSA_KEY_N = new BigInteger("C600790C46F90315BA35636C973A6CC815322A6272BD0501CFE649ECC98A3A4EB1F23E863C644A0A29D6FAF9ACD87B9F2A6B130606EB831BB897A391956015E5", 16);
+ private static final BigInteger RSA_KEY_E = new BigInteger("010001", 16);
+
+ /*
+ openssl dsaparam -genkey -text -out dsakey.pem 1024
+ openssl dsa -in dsakey.pem -text -noout
+ openssl pkcs8 -topk8 -in dsakey.pem -outform d -nocrypt | recode ../x1 | sed 's/0x/(byte) 0x/g'
+ */
+ private static final byte[] DSA_KEY_PKCS8 = new byte[] {
+ (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x4A, (byte) 0x02, (byte) 0x01,
+ (byte) 0x00, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x2B, (byte) 0x06,
+ (byte) 0x07, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0xCE, (byte) 0x38,
+ (byte) 0x04, (byte) 0x01, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x1E,
+ (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xD2, (byte) 0x18,
+ (byte) 0xDB, (byte) 0x94, (byte) 0x7C, (byte) 0xD6, (byte) 0x2E, (byte) 0xE2,
+ (byte) 0x07, (byte) 0x38, (byte) 0x42, (byte) 0xC4, (byte) 0x16, (byte) 0x24,
+ (byte) 0x94, (byte) 0x2F, (byte) 0xC1, (byte) 0x0F, (byte) 0x92, (byte) 0x0A,
+ (byte) 0x44, (byte) 0x44, (byte) 0x99, (byte) 0xFC, (byte) 0x01, (byte) 0x1B,
+ (byte) 0xF8, (byte) 0xF3, (byte) 0x82, (byte) 0x57, (byte) 0x01, (byte) 0x8D,
+ (byte) 0xE6, (byte) 0x22, (byte) 0x70, (byte) 0xA0, (byte) 0xD6, (byte) 0x05,
+ (byte) 0x0F, (byte) 0xF1, (byte) 0xD0, (byte) 0xF4, (byte) 0x0B, (byte) 0xA2,
+ (byte) 0xE4, (byte) 0x1E, (byte) 0xD3, (byte) 0x44, (byte) 0x79, (byte) 0x74,
+ (byte) 0x4C, (byte) 0xC1, (byte) 0xA7, (byte) 0xA5, (byte) 0x84, (byte) 0xD8,
+ (byte) 0xB9, (byte) 0xDF, (byte) 0xA3, (byte) 0x85, (byte) 0xFA, (byte) 0xF2,
+ (byte) 0xFD, (byte) 0x44, (byte) 0x0B, (byte) 0xB1, (byte) 0xA5, (byte) 0x82,
+ (byte) 0x8D, (byte) 0x06, (byte) 0x92, (byte) 0xCA, (byte) 0xB4, (byte) 0xFB,
+ (byte) 0xDF, (byte) 0xC2, (byte) 0xFD, (byte) 0xA7, (byte) 0xCB, (byte) 0x6F,
+ (byte) 0x03, (byte) 0xB9, (byte) 0xEF, (byte) 0xFD, (byte) 0x7F, (byte) 0xBC,
+ (byte) 0xB3, (byte) 0x1D, (byte) 0xA4, (byte) 0xE8, (byte) 0x7D, (byte) 0xA2,
+ (byte) 0xCF, (byte) 0x62, (byte) 0x35, (byte) 0x06, (byte) 0xC8, (byte) 0xFE,
+ (byte) 0xE6, (byte) 0xE7, (byte) 0x6E, (byte) 0xAE, (byte) 0x22, (byte) 0xE7,
+ (byte) 0x82, (byte) 0x38, (byte) 0x54, (byte) 0x82, (byte) 0xCD, (byte) 0xEA,
+ (byte) 0xD8, (byte) 0x69, (byte) 0xBB, (byte) 0x1C, (byte) 0xD3, (byte) 0x70,
+ (byte) 0x32, (byte) 0xB1, (byte) 0xFB, (byte) 0x07, (byte) 0x01, (byte) 0x66,
+ (byte) 0xCC, (byte) 0x24, (byte) 0xD6, (byte) 0x50, (byte) 0x46, (byte) 0x9B,
+ (byte) 0x02, (byte) 0x15, (byte) 0x00, (byte) 0xD6, (byte) 0xE6, (byte) 0x7E,
+ (byte) 0x1A, (byte) 0xE5, (byte) 0xCA, (byte) 0x1D, (byte) 0xB6, (byte) 0xAF,
+ (byte) 0x4E, (byte) 0xD9, (byte) 0x18, (byte) 0xE8, (byte) 0x87, (byte) 0xB1,
+ (byte) 0xBC, (byte) 0x93, (byte) 0xE1, (byte) 0x80, (byte) 0xF5, (byte) 0x02,
+ (byte) 0x81, (byte) 0x80, (byte) 0x19, (byte) 0x20, (byte) 0xCC, (byte) 0x18,
+ (byte) 0xF6, (byte) 0x8F, (byte) 0x73, (byte) 0xFA, (byte) 0x9F, (byte) 0x50,
+ (byte) 0xC8, (byte) 0x92, (byte) 0xBE, (byte) 0x07, (byte) 0x7C, (byte) 0x34,
+ (byte) 0xD8, (byte) 0x6F, (byte) 0x63, (byte) 0xC9, (byte) 0x35, (byte) 0x48,
+ (byte) 0x79, (byte) 0x79, (byte) 0x26, (byte) 0xEF, (byte) 0x1E, (byte) 0x99,
+ (byte) 0x54, (byte) 0xD7, (byte) 0x30, (byte) 0x2C, (byte) 0x68, (byte) 0xBC,
+ (byte) 0xFF, (byte) 0xF2, (byte) 0x4C, (byte) 0x6A, (byte) 0xD3, (byte) 0x2D,
+ (byte) 0x1C, (byte) 0x7A, (byte) 0x06, (byte) 0x11, (byte) 0x72, (byte) 0x92,
+ (byte) 0x9C, (byte) 0xAA, (byte) 0x95, (byte) 0x0E, (byte) 0x44, (byte) 0x2C,
+ (byte) 0x5F, (byte) 0x19, (byte) 0x25, (byte) 0xB4, (byte) 0xBF, (byte) 0x21,
+ (byte) 0x8F, (byte) 0xB7, (byte) 0x7E, (byte) 0x4B, (byte) 0x64, (byte) 0x83,
+ (byte) 0x59, (byte) 0x20, (byte) 0x20, (byte) 0x36, (byte) 0x84, (byte) 0xA4,
+ (byte) 0x1D, (byte) 0xB5, (byte) 0xCA, (byte) 0x7F, (byte) 0x10, (byte) 0x4E,
+ (byte) 0x27, (byte) 0x21, (byte) 0x8E, (byte) 0x2C, (byte) 0xA5, (byte) 0xF8,
+ (byte) 0xAC, (byte) 0xBD, (byte) 0xF5, (byte) 0xB5, (byte) 0xBA, (byte) 0xEB,
+ (byte) 0x86, (byte) 0x6F, (byte) 0x7F, (byte) 0xB1, (byte) 0xE0, (byte) 0x90,
+ (byte) 0x35, (byte) 0xCA, (byte) 0xA8, (byte) 0x64, (byte) 0x6E, (byte) 0x06,
+ (byte) 0x3D, (byte) 0x02, (byte) 0x3D, (byte) 0x95, (byte) 0x57, (byte) 0xB3,
+ (byte) 0x8A, (byte) 0xE2, (byte) 0x0B, (byte) 0xD3, (byte) 0x9E, (byte) 0x1C,
+ (byte) 0x13, (byte) 0xDE, (byte) 0x48, (byte) 0xA3, (byte) 0xC2, (byte) 0x11,
+ (byte) 0xDA, (byte) 0x75, (byte) 0x09, (byte) 0xF6, (byte) 0x92, (byte) 0x0F,
+ (byte) 0x0F, (byte) 0xA6, (byte) 0xF3, (byte) 0x3E, (byte) 0x04, (byte) 0x16,
+ (byte) 0x02, (byte) 0x14, (byte) 0x29, (byte) 0x50, (byte) 0xE4, (byte) 0x77,
+ (byte) 0x4F, (byte) 0xB2, (byte) 0xFF, (byte) 0xFB, (byte) 0x5D, (byte) 0x33,
+ (byte) 0xC9, (byte) 0x37, (byte) 0xF0, (byte) 0xB5, (byte) 0x8F, (byte) 0xFB,
+ (byte) 0x0D, (byte) 0x45, (byte) 0xC2, (byte) 0x00
+ };
+
+ private static final BigInteger DSA_KEY_P = new BigInteger("00d218db947cd62ee2073842c41624942fc10f920a444499fc011bf8f38257018de62270a0d6050ff1d0f40ba2e41ed34479744cc1a7a584d8b9dfa385faf2fd440bb1a5828d0692cab4fbdfc2fda7cb6f03b9effd7fbcb31da4e87da2cf623506c8fee6e76eae22e782385482cdead869bb1cd37032b1fb070166cc24d650469b", 16);
+ private static final BigInteger DSA_KEY_Q = new BigInteger("00d6e67e1ae5ca1db6af4ed918e887b1bc93e180f5", 16);
+ private static final BigInteger DSA_KEY_G = new BigInteger("1920cc18f68f73fa9f50c892be077c34d86f63c93548797926ef1e9954d7302c68bcfff24c6ad32d1c7a061172929caa950e442c5f1925b4bf218fb77e4b64835920203684a41db5ca7f104e27218e2ca5f8acbdf5b5baeb866f7fb1e09035caa8646e063d023d9557b38ae20bd39e1c13de48a3c211da7509f6920f0fa6f33e", 16);
+
+ private static final BigInteger DSA_KEY_priv = new BigInteger("2950e4774fb2fffb5d33c937f0b58ffb0d45c200", 16);
+ private static final BigInteger DSA_KEY_pub = new BigInteger("0087b82cdf3232db3bec0d00e96c8393bc7f5629551ea1a00888961cf56e80a36f2a7b316bc10b1d367a5ea374235c9361a472a9176f6cf61f708b86a52b4fae814abd1f1bdd16eea94aea9281851032b1bad7567624c615d6899ca1c94ad614f14e767e49d2ba5223cd113a0d02b66183653cd346ae76d85843afe66520904274", 16);
+
+ public void testGetOidFromPkcs8Encoded_Ec_NistP256() throws Exception {
+ assertEquals("1.2.840.10045.2.1", PubkeyUtils.getOidFromPkcs8Encoded(EC_KEY_PKCS8));
+ }
+
+ public void testGetOidFromPkcs8Encoded_Rsa() throws Exception {
+ assertEquals("1.2.840.113549.1.1.1", PubkeyUtils.getOidFromPkcs8Encoded(RSA_KEY_PKCS8));
+ }
+
+ public void testGetOidFromPkcs8Encoded_Dsa() throws Exception {
+ assertEquals("1.2.840.10040.4.1", PubkeyUtils.getOidFromPkcs8Encoded(DSA_KEY_PKCS8));
+ }
+
+ public void testGetOidFromPkcs8Encoded_Null_Failure() throws Exception {
+ try {
+ PubkeyUtils.getOidFromPkcs8Encoded(null);
+ fail("Should throw NoSuchAlgorithmException");
+ } catch (NoSuchAlgorithmException expected) {
+ }
+ }
+
+ public void testGetOidFromPkcs8Encoded_NotCorrectDer_Failure() throws Exception {
+ try {
+ PubkeyUtils.getOidFromPkcs8Encoded(new byte[] { 0x30, 0x01, 0x00 });
+ fail("Should throw NoSuchAlgorithmException");
+ } catch (NoSuchAlgorithmException expected) {
+ }
+ }
+
+ public void testGetAlgorithmForOid_Ecdsa() throws Exception {
+ assertEquals("EC", PubkeyUtils.getAlgorithmForOid("1.2.840.10045.2.1"));
+ }
+
+ public void testGetAlgorithmForOid_Rsa() throws Exception {
+ assertEquals("RSA", PubkeyUtils.getAlgorithmForOid("1.2.840.113549.1.1.1"));
+ }
+
+ public void testGetAlgorithmForOid_Dsa() throws Exception {
+ assertEquals("DSA", PubkeyUtils.getAlgorithmForOid("1.2.840.10040.4.1"));
+ }
+
+ public void testGetAlgorithmForOid_NullInput_Failure() throws Exception {
+ try {
+ PubkeyUtils.getAlgorithmForOid(null);
+ fail("Should throw NoSuchAlgorithmException");
+ } catch (NoSuchAlgorithmException expected) {
+ }
+ }
+
+ public void testGetAlgorithmForOid_UnknownOid_Failure() throws Exception {
+ try {
+ PubkeyUtils.getAlgorithmForOid("1.3.66666.2000.4000.1");
+ fail("Should throw NoSuchAlgorithmException");
+ } catch (NoSuchAlgorithmException expected) {
+ }
+ }
+
+ public void testRecoverKeyPair_Dsa() throws Exception {
+ KeyPair kp = PubkeyUtils.recoverKeyPair(DSA_KEY_PKCS8);
+
+ DSAPublicKey pubKey = (DSAPublicKey) kp.getPublic();
+
+ assertEquals(DSA_KEY_pub, pubKey.getY());
+
+ DSAParams params = pubKey.getParams();
+ assertEquals(params.getG(), DSA_KEY_G);
+ assertEquals(params.getP(), DSA_KEY_P);
+ assertEquals(params.getQ(), DSA_KEY_Q);
+ }
+
+ public void testRecoverKeyPair_Rsa() throws Exception {
+ KeyPair kp = PubkeyUtils.recoverKeyPair(RSA_KEY_PKCS8);
+
+ RSAPublicKey pubKey = (RSAPublicKey) kp.getPublic();
+
+ assertEquals(RSA_KEY_N, pubKey.getModulus());
+ assertEquals(RSA_KEY_E, pubKey.getPublicExponent());
+ }
+
+ public void testRecoverKeyPair_Ec() throws Exception {
+ KeyPair kp = PubkeyUtils.recoverKeyPair(EC_KEY_PKCS8);
+
+ ECPublicKey pubKey = (ECPublicKey) kp.getPublic();
+
+ assertEquals(EC_KEY_pub_x, pubKey.getW().getAffineX());
+ assertEquals(EC_KEY_pub_y, pubKey.getW().getAffineY());
+ }
+
+ private static class MyPrivateKey implements PrivateKey {
+ public String getAlgorithm() {
+ throw new UnsupportedOperationException();
+ }
+
+ public byte[] getEncoded() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getFormat() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void testRecoverPublicKey_FakeKey_Failure() throws Exception {
+ try {
+ PubkeyUtils.recoverPublicKey(null, new MyPrivateKey());
+ fail("Should not accept unknown key types");
+ } catch (NoSuchAlgorithmException expected) {
+ }
+ }
+}