Skip to content

Commit

Permalink
review, added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
profhenry committed Dec 30, 2023
1 parent 1a1e47f commit 611275f
Show file tree
Hide file tree
Showing 19 changed files with 538 additions and 94 deletions.
24 changes: 24 additions & 0 deletions sshsig-bcprov/SshPublicKeyEncoderTest (bcprov)(JDK17).launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/sshsig-bcprov/src/test/java/de/profhenry/sshsig/bcprov/SshPublicKeyEncoderTest.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.core.SOURCE_PATH_COMPUTER_ID" value="de.gebit.maven.osgi.launcher.plugin.sourcelookup.patchedJavaSourcePathComputer"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit5"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_SHOW_CODEDETAILS_IN_EXCEPTION_MESSAGES" value="true"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="de.profhenry.sshsig.bcprov.SshPublicKeyEncoderTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="sshsig-bcprov"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
</launchConfiguration>
20 changes: 20 additions & 0 deletions sshsig-bcprov/SshPublicKeyEncoderTest (bcprov)(JDK8).launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/sshsig-bcprov/src/test/java/de/profhenry/sshsig/bcprov/SshPublicKeyEncoderTest.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.core.SOURCE_PATH_COMPUTER_ID" value="de.gebit.maven.osgi.launcher.plugin.sourcelookup.patchedJavaSourcePathComputer"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit5"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="de.profhenry.sshsig.bcprov.SshPublicKeyEncoderTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="sshsig-bcprov"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
</launchConfiguration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2023 Jan Henrik Wiesner
*
* 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 de.profhenry.sshsig.bcprov;

import static org.assertj.core.api.Assertions.assertThat;

import java.security.PublicKey;
import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import de.profhenry.sshsig.core.SshPublicKeyEncoder;

/**
* Unit tests for {@link SshPublicKeyEncoder}.
* <p>
*
* @author profhenry
*/
public class SshPublicKeyEncoderTest {

@BeforeAll
static void setup() {
Security.addProvider(new BouncyCastleProvider());
}

@Test
@Disabled
void testEncodeDsaPublicKey() throws Exception {
PublicKey tPublicKey = SshKeyUtil.readDsaKeyPair().getPublic();

SshPublicKeyEncoder tPublicKeyEncoder = new SshPublicKeyEncoder();
byte[] tSshEncodedPublicKey = tPublicKeyEncoder.encodePublicKey(tPublicKey);

assertThat(tSshEncodedPublicKey).asBase64Encoded()
.isEqualTo(
"AAAAB3NzaC1kc3MAAACBAP8BC5pi3uxvOtlb1ikWNeLUubiaT0l7aMOhAbOFmtivswcg0r+rZiX/UOjhxCATRiaTXV42byLnf0cKzQrZ5QEnm8uTf1aK0gdT/bdQaZwWmkMB2LdHQ4xEt3slsDLYoXwwzV+stpRcFQ1VyUlJQV754HqHZT8RbkUBJHIsIqslAAAAFQCKvLgJmuxvJy6DvdRB5Fm/VZR5PwAAAIEA1y5UQItEth5WSS6166Aujc+7x9jgaztoC4Uo0iskMM5D0oVrJSyVwCAOcNPEeya4zNnJgkD16Wco3XOryBcgjWScEoTgict2J8rnaUWDkyOMptfbiF+oU39INh3m+2tvIfsgX81bAQJD0STYiF9J3G/PQYjvRIxhybtHJHGcuaUAAACBANTDVZW7LC9PbzQ1e2SxMOznf76/WV8RfwfKALh0DpJvyaEuOQkgwO/AzSNoN1mJgkn7mjXKgsJLYB/49d1arv8n/nG+7oLGdKYlKlXOkJ2bW+yxnFwLvBTBniCbdyylPP1iNbw2SArns44xxBszjTedAZcpJQiv+ThZI3Bzg5dM");
}

@Test
void testEncodeRsaPublicKey() throws Exception {
PublicKey tPublicKey = SshKeyUtil.readRsaKeyPair().getPublic();

SshPublicKeyEncoder tPublicKeyEncoder = new SshPublicKeyEncoder();
byte[] tSshEncodedPublicKey = tPublicKeyEncoder.encodePublicKey(tPublicKey);

assertThat(tSshEncodedPublicKey).asBase64Encoded()
.isEqualTo(
"AAAAB3NzaC1yc2EAAAADAQABAAABgQDg9Lf347GyGfq+SZjWnLEFY61tz3czkkpeU71piNtCD9M18vsonIKmLRwUC4dKBE+UJQf7F79Mx/Z6XqgNCTP9tAVj1YMKtIIXbl6F4hkMWZr1XTjq78jCk3yWx7BA9CYaTxK185l3WbcZovrx9iTrVafi6+cXhxAC4HYHQYjB/1YubPhWIJ4mtqo7e22xP84Kdr/aYmSJbx0vaUjRJQaFJkYVi2Sb8GYAagd5YQ5aODU6CuY/ycp18UMQ56G/uSR19O+OGXrHbF2GEZTko6ESOAbu7EjquU1fOL3xeh/3GYNtYjeztQFCXGz2iXrKNk+wMjHGvrg8w11NdgpT983UMwA8bV8kctz4qaH/89HhR49pkLSxOc9AMzjSL8N4bueId598KnfutEzT0N+Ghwsi+1fDrohCTRx2x+PyLYe5syehjn/IxhnQlKEvtRitjUqCn32mAufx2BbCl8rykPTUxBE/QAUYPlA/Surv8j9yE8tEpDIdEBc78kpwBxH60p8=");
}

@Test
void testEncodeEd25519PublicKey() throws Exception {
PublicKey tPublicKey = SshKeyUtil.readEd25519KeyPair().getPublic();

SshPublicKeyEncoder tPublicKeyEncoder = new SshPublicKeyEncoder();
byte[] tSshEncodedPublicKey = tPublicKeyEncoder.encodePublicKey(tPublicKey);

assertThat(tSshEncodedPublicKey).asBase64Encoded()
.isEqualTo("AAAAC3NzaC1lZDI1NTE5AAAAIDuDUZReuNqkLI5pqXRzx6+LtMtLMji2HPoDccHOE4XF");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void testVerifyWithSshKeyGen() throws SshSignatureException, IOException, Interr
+ "."
+ sshSignatureGenerator.getHashAlgorithm()
+ ".sig";
tSignature.write(Paths.get(tSignatureFileName));
tSignature.writeAsPem(Paths.get(tSignatureFileName));

verifyUsingSshKeygen(MESSAGE, NAMESPACE, tSignatureFileName);
}
Expand Down Expand Up @@ -179,7 +179,7 @@ void testVerifyWithSshKeyGen() throws SshSignatureException, IOException, Interr
+ "."
+ sshSignatureGenerator.getHashAlgorithm()
+ ".sig";
tSignature.write(Paths.get(tSignatureFileName));
tSignature.writeAsPem(Paths.get(tSignatureFileName));

verifyUsingSshKeygen(MESSAGE, NAMESPACE, tSignatureFileName);
}
Expand Down Expand Up @@ -259,7 +259,7 @@ void testVerifyWithSshKeyGen() throws SshSignatureException, IOException, Interr
+ "."
+ sshSignatureGenerator.getHashAlgorithm()
+ ".sig";
tSignature.write(Paths.get(tSignatureFileName));
tSignature.writeAsPem(Paths.get(tSignatureFileName));

verifyUsingSshKeygen(MESSAGE, NAMESPACE, tSignatureFileName);
}
Expand Down Expand Up @@ -327,7 +327,7 @@ void testVerifyWithSshKeyGen() throws SshSignatureException, IOException, Interr
+ "."
+ sshSignatureGenerator.getHashAlgorithm()
+ ".sig";
tSignature.write(Paths.get(tSignatureFileName));
tSignature.writeAsPem(Paths.get(tSignatureFileName));

verifyUsingSshKeygen(MESSAGE, NAMESPACE, tSignatureFileName);
}
Expand Down Expand Up @@ -394,7 +394,7 @@ void testVerifyWithSshKeyGen() throws SshSignatureException, IOException, Interr
+ "."
+ sshSignatureGenerator.getHashAlgorithm()
+ ".sig";
tSignature.write(Paths.get(tSignatureFileName));
tSignature.writeAsPem(Paths.get(tSignatureFileName));

verifyUsingSshKeygen(MESSAGE, NAMESPACE, tSignatureFileName);
}
Expand Down Expand Up @@ -449,7 +449,7 @@ void testVerifyWithSshKeyGen() throws SshSignatureException, IOException, Interr
+ "."
+ sshSignatureGenerator.getHashAlgorithm()
+ ".sig";
tSignature.write(Paths.get(tSignatureFileName));
tSignature.writeAsPem(Paths.get(tSignatureFileName));

verifyUsingSshKeygen(MESSAGE, NAMESPACE, tSignatureFileName);
}
Expand Down
24 changes: 24 additions & 0 deletions sshsig-core/SshPublicKeyEncoderTest (core)(JDK17).launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/sshsig-core/src/test/java/de/profhenry/sshsig/core/SshPublicKeyEncoderTest.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.core.SOURCE_PATH_COMPUTER_ID" value="de.gebit.maven.osgi.launcher.plugin.sourcelookup.patchedJavaSourcePathComputer"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit5"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_SHOW_CODEDETAILS_IN_EXCEPTION_MESSAGES" value="true"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="de.profhenry.sshsig.core.SshPublicKeyEncoderTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="sshsig-core"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
</launchConfiguration>
20 changes: 20 additions & 0 deletions sshsig-core/SshPublicKeyEncoderTest (core)(JDK8).launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/sshsig-core/src/test/java/de/profhenry/sshsig/core/SshPublicKeyEncoderTest.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.core.SOURCE_PATH_COMPUTER_ID" value="de.gebit.maven.osgi.launcher.plugin.sourcelookup.patchedJavaSourcePathComputer"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit5"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="de.profhenry.sshsig.core.SshPublicKeyEncoderTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="sshsig-core"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
</launchConfiguration>
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@
* For signing you need to specify a {@link KeyPair}, the {@link PrivateKey} is required for the actual signing process,
* the {@link PublicKey} is required because it gets embedded into the SSH signature.
* <p>
* The SSH
*
* @author profhenry
*/
public class JcaSingingBackend implements SigningBackend<KeyPair> {

/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(JcaSingingBackend.class);

@Override
Expand Down Expand Up @@ -70,14 +72,18 @@ public SigningResult signData(KeyPair aKeyPair, byte[] someDataToSign) throws Ss
if ("RSA".equals(tPrivateKey.getAlgorithm())) {
return signRsa(tPrivateKey, tPublicKey, someDataToSign);
}
if ("EdDSA".equals(tPrivateKey.getAlgorithm())) {
// used by JDK17 and net.i2p.crypto
// JDK17 uses EdDSA for Ed25519 and Ed448
// TODO i would love to prevent Ed448 but i think this is not possible when compiling againt JDK8 :-/
if ("Ed25519".equals(tPrivateKey.getAlgorithm())) {
// used by org.bouncycastle:bcprov in default configuration
return signEd25519(tPrivateKey, tPublicKey, someDataToSign);
}
if ("Ed25519".equals(tPrivateKey.getAlgorithm())) {
// used by org.bouncycastle
if ("EdDSA".equals(tPrivateKey.getAlgorithm())) {
// used by
// - JDK17
// - net.i2p.crypto:eddsa
// - org.bouncycastle:bcprov (with activated org.bouncycastle.emulate.oracle property)

// EdDSA is also used for Ed448 (at least when using JDK17)
// TODO i would love to prevent using Ed448 but i think this is not possible when compiling againt JDK8 :-/
return signEd25519(tPrivateKey, tPublicKey, someDataToSign);
}

Expand Down
69 changes: 69 additions & 0 deletions sshsig-core/src/main/java/de/profhenry/sshsig/core/PemWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2023 Jan Henrik Wiesner
*
* 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 de.profhenry.sshsig.core;

import java.io.PrintWriter;
import java.io.Writer;
import java.util.Base64;

/**
* @author profhenry
*/
public class PemWriter {

/**
* The default line length of the base 64 encoded content.
* <p>
* RFC7468 states that the base 64 content MUST wrap after 64 chars.
*/
private static final int DEFAULT_LINE_LENGTH = 64;

private final PrintWriter printWriter;

private final int lineLength;

public PemWriter(Writer aWriter, int aLineLength) {
printWriter = new PrintWriter(aWriter);
lineLength = aLineLength;
}

public PemWriter(Writer aWriter) {
this(aWriter, DEFAULT_LINE_LENGTH);
}

public void writeData(String aLabel, byte[] someBytes) {
writeHeader(aLabel);
writeData(someBytes);
writeFooter(aLabel);
printWriter.flush();
}

private void writeHeader(String aLabel) {
printWriter.println("-----BEGIN " + aLabel + "-----");
}

private void writeData(byte[] someBytes) {
String tEncoded = Base64.getEncoder().encodeToString(someBytes);

for (int i = 0; i < tEncoded.length(); i += lineLength) {
printWriter.println(tEncoded.substring(i, Math.min(tEncoded.length(), i + lineLength)));
}
}

private void writeFooter(String aLabel) {
printWriter.println("-----END " + aLabel + "-----");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void appendBigInteger(BigInteger aBigInteger) {
/**
* Appends a sequence of a string and a byte array.
* <p>
* First writes the overall bytes required by this sequence followed by the string and the byte array (eqch with
* First writes the overall bytes required by this sequence followed by the string and the byte array (each with
* their length fields as well).
* <p>
* Added bytes: 4 + 4 + number of chars + 4 + length of the byte array
Expand Down
Loading

0 comments on commit 611275f

Please sign in to comment.