Skip to content

Commit 7be5a86

Browse files
committed
SSHKeysHelper: add null checks and add unit tests
1 parent aa95bc0 commit 7be5a86

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

utils/src/main/java/com/cloud/utils/ssh/SSHKeysHelper.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.StringWriter;
2424
import java.math.BigInteger;
2525
import java.nio.ByteBuffer;
26+
import java.nio.charset.StandardCharsets;
2627
import java.security.KeyPair;
2728
import java.security.MessageDigest;
2829
import java.security.NoSuchAlgorithmException;
@@ -110,6 +111,9 @@ public static String getPublicKeyFromKeyMaterial(String keyMaterial) {
110111
}
111112

112113
public String getPublicKey() {
114+
if (keyPair == null || keyPair.getPublic() == null) {
115+
return null;
116+
}
113117
try {
114118
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
115119

@@ -129,7 +133,7 @@ public String getPublicKey() {
129133
}
130134

131135
private static void writeString(ByteArrayOutputStream out, String str) throws Exception {
132-
byte[] data = str.getBytes("UTF-8");
136+
byte[] data = str.getBytes(StandardCharsets.UTF_8);
133137
out.write(ByteBuffer.allocate(4).putInt(data.length).array());
134138
out.write(data);
135139
}
@@ -141,6 +145,9 @@ private static void writeBigInt(ByteArrayOutputStream out, BigInteger value) thr
141145
}
142146

143147
public String getPrivateKey() {
148+
if (keyPair == null || keyPair.getPrivate() == null) {
149+
return null;
150+
}
144151
try {
145152
final PemObject pemObject = new PemObject("RSA PRIVATE KEY", keyPair.getPrivate().getEncoded());
146153
final StringWriter sw = new StringWriter();

utils/src/test/java/com/cloud/utils/ssh/SSHKeysHelperTest.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@
1919

2020
package com.cloud.utils.ssh;
2121

22+
import static org.junit.Assert.assertEquals;
23+
import static org.junit.Assert.assertNotNull;
24+
import static org.junit.Assert.assertNull;
2225
import static org.junit.Assert.assertTrue;
2326

27+
import java.nio.charset.StandardCharsets;
28+
import java.util.Base64;
29+
2430
import org.junit.Test;
2531

2632
public class SSHKeysHelperTest {
@@ -70,4 +76,56 @@ public void dsaKeyTest() {
7076
assertTrue("fc:6e:ef:31:93:f8:92:2b:a9:03:c7:06:90:f5:ec:bb".equals(fingerprint));
7177

7278
}
79+
80+
@Test
81+
public void getPublicKeyFromKeyMaterialShouldHandleSupportedPrefixes() {
82+
assertEquals("ecdsa-sha2-nistp256 AAAA", SSHKeysHelper.getPublicKeyFromKeyMaterial("ecdsa-sha2-nistp256 AAAA comment"));
83+
assertEquals("ecdsa-sha2-nistp384 AAAA", SSHKeysHelper.getPublicKeyFromKeyMaterial("ecdsa-sha2-nistp384 AAAA comment"));
84+
assertEquals("ecdsa-sha2-nistp521 AAAA", SSHKeysHelper.getPublicKeyFromKeyMaterial("ecdsa-sha2-nistp521 AAAA comment"));
85+
assertEquals("ssh-ed25519 AAAA", SSHKeysHelper.getPublicKeyFromKeyMaterial("ssh-ed25519 AAAA comment"));
86+
}
87+
88+
@Test
89+
public void getPublicKeyFromKeyMaterialShouldParseBase64EncodedMaterial() {
90+
String keyMaterial = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestKeyData comment";
91+
String encoded = Base64.getEncoder().encodeToString(keyMaterial.getBytes(StandardCharsets.UTF_8));
92+
93+
assertEquals("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestKeyData", SSHKeysHelper.getPublicKeyFromKeyMaterial(encoded));
94+
}
95+
96+
@Test
97+
public void getPublicKeyFromKeyMaterialShouldReturnNullForInvalidFormats() {
98+
assertNull(SSHKeysHelper.getPublicKeyFromKeyMaterial("not-a-valid-key"));
99+
assertNull(SSHKeysHelper.getPublicKeyFromKeyMaterial("ssh-unknown AAAA"));
100+
assertNull(SSHKeysHelper.getPublicKeyFromKeyMaterial("ssh-rsa"));
101+
}
102+
103+
@Test(expected = RuntimeException.class)
104+
public void getPublicKeyFingerprintShouldThrowForInvalidPublicKey() {
105+
SSHKeysHelper.getPublicKeyFingerprint("invalid-key-format");
106+
}
107+
108+
@Test
109+
public void generatedKeysShouldBeWellFormedAndFingerprintConsistent() {
110+
SSHKeysHelper helper = new SSHKeysHelper(2048);
111+
112+
String publicKey = helper.getPublicKey();
113+
String privateKey = helper.getPrivateKey();
114+
String fingerprint = helper.getPublicKeyFingerPrint();
115+
116+
assertNotNull(publicKey);
117+
assertTrue(publicKey.startsWith("ssh-rsa "));
118+
119+
String[] keyParts = publicKey.split(" ");
120+
assertEquals(2, keyParts.length);
121+
122+
assertNotNull(privateKey);
123+
assertTrue(privateKey.contains("BEGIN RSA PRIVATE KEY"));
124+
assertTrue(privateKey.contains("END RSA PRIVATE KEY"));
125+
126+
assertNotNull(fingerprint);
127+
assertEquals(SSHKeysHelper.getPublicKeyFingerprint(publicKey), fingerprint);
128+
129+
assertTrue("Legacy MD5 fingerprint should be colon-separated hex", fingerprint.matches("^([0-9a-f]{2}:){15}[0-9a-f]{2}$"));
130+
}
73131
}

0 commit comments

Comments
 (0)