Skip to content

Commit bc6e44a

Browse files
authored
Fixes #41 by removing javax.xml.bind.DatatypeConverter usage (#42)
* Fixes #41 by removing javax.xml.bind.DatatypeConverter usage * Suppressed deprecation warning * Enabled all warnings when compiling.
1 parent a849fff commit bc6e44a

File tree

6 files changed

+66
-28
lines changed

6 files changed

+66
-28
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## [4.0.5] - ?
6+
7+
### Fixed
8+
- [Removed use of javax.xml.bind.DatatypeConverter](https://github.com/joyent/java-http-signature/issues/41)
9+
510
## [4.0.4] - 2017-10-06
611

712
### Changed

common/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<!-- Dependency versions -->
2323
<dependency.bouncycastle.version>1.58</dependency.bouncycastle.version>
2424
<dependency.jnagmp.version>2.0.0</dependency.jnagmp.version>
25+
<dependency.commons-codec.version>1.10</dependency.commons-codec.version>
2526
</properties>
2627

2728
<dependencies>
@@ -46,6 +47,13 @@
4647
</exclusion>
4748
</exclusions>
4849
</dependency>
50+
<dependency>
51+
<groupId>commons-codec</groupId>
52+
<artifactId>commons-codec</artifactId>
53+
<version>${dependency.commons-codec.version}</version>
54+
<scope>test</scope>
55+
</dependency>
56+
4957
</dependencies>
5058

5159
<build>

common/src/main/java/com/joyent/http/signature/KeyFingerprinter.java

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@
1919
import java.security.interfaces.RSAPublicKey;
2020
import java.util.Base64;
2121
import java.util.Objects;
22-
import javax.xml.bind.DatatypeConverter;
2322

2423
/**
2524
* Utiility class for calculating and verifying SSH key fingerprints as defined by OpenSSH.
2625
*/
2726
public final class KeyFingerprinter {
2827

29-
/** OpenSSH does not pad.
28+
/**
29+
* OpenSSH does not pad.
3030
*/
3131
private static Base64.Encoder b64Encoder = Base64.getEncoder().withoutPadding();
3232

33+
/**
34+
* Hexadecimal characters to translate to when converting from a byte[]
35+
* array to a hex string.
36+
*/
37+
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
38+
3339
@SuppressWarnings("checkstyle:javadocmethod")
3440
private KeyFingerprinter() {
3541
}
@@ -56,7 +62,7 @@ public static String md5Fingerprint(final KeyPair keyPair) {
5662
byte[] encoded = SshEncoder.encode(keyPair.getPublic());
5763
md.update(encoded);
5864
byte[] digest = md.digest();
59-
return colonify(DatatypeConverter.printHexBinary(digest));
65+
return colonify(digest);
6066
}
6167

6268
/**
@@ -115,23 +121,36 @@ public static boolean verifyFingerprint(final KeyPair keyPair, final String fing
115121
}
116122

117123
/**
118-
* Given a hex encoded string, space it out with colons and
119-
* lowercase each character to match the OpenSSH format. For
120-
* example {@code 9F0B50AEE3DAF6EBB5719A69EE799EC2} becomes {@code
124+
* Given a byte array, space it out with colons and
125+
* lowercase each character to match the OpenSSH format.
126+
* Example output would be {@code
121127
* 9f:0b:50:ae:e3:da:f6:eb:b5:71:9a:69:ee:79:9e:c2}
122128
*
123-
* @param str The hex encoded string
124-
* @return str with colons
129+
* @param bytes byte array to convert to hex string
130+
* @return hex string with colons
125131
*/
126-
private static String colonify(final String str) {
127-
StringBuilder sb = new StringBuilder();
128-
for (int i = 0; i < str.length(); i++) {
129-
sb.append(Character.toLowerCase(str.charAt(i)));
130-
if (i % 2 == 1 && i != str.length() - 1) {
131-
sb.append(":");
132+
@SuppressWarnings("MagicNumber")
133+
static String colonify(final byte[] bytes) {
134+
Objects.requireNonNull(bytes, "byte array is null");
135+
136+
if (bytes.length == 0) {
137+
return "";
138+
}
139+
140+
final char[] chars = new char[bytes.length * 3 - 1];
141+
142+
int charPos = 0;
143+
for (int i = 0; i < bytes.length; i++) {
144+
final int val = bytes[i] & 0xFF;
145+
chars[charPos++] = HEX_CHARS[val >>> 4];
146+
chars[charPos++] = HEX_CHARS[val & 0x0F];
147+
148+
if (charPos + 1 < chars.length) {
149+
chars[charPos++] = ':';
132150
}
133151
}
134-
return sb.toString();
152+
153+
return new String(chars);
135154
}
136155

137156
/*

common/src/test/java/com/joyent/http/signature/KeyFingerprinterTest.java

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@
77
*/
88
package com.joyent.http.signature;
99

10+
import org.bouncycastle.util.encoders.Hex;
1011
import org.testng.Assert;
11-
import org.testng.annotations.BeforeClass;
12-
import org.testng.annotations.Optional;
13-
import org.testng.annotations.Parameters;
1412
import org.testng.annotations.Test;
1513

1614

15+
@Test
1716
public class KeyFingerprinterTest {
1817

19-
@Test
2018
public void rsaMd5() throws Exception {
2119
Assert.assertEquals(KeyFingerprinter.md5Fingerprint(SignerTestUtil.testKeyPair("rsa_1024")),
2220
SignerTestUtil.testKeyMd5Fingerprint("rsa_1024"));
@@ -28,7 +26,6 @@ public void rsaMd5() throws Exception {
2826
SignerTestUtil.testKeyMd5Fingerprint("rsa_4096"));
2927
}
3028

31-
@Test
3229
public void rsaSha256() throws Exception {
3330
Assert.assertEquals(KeyFingerprinter.sha256Fingerprint(SignerTestUtil.testKeyPair("rsa_1024")),
3431
SignerTestUtil.testKeySha256Fingerprint("rsa_1024"));
@@ -40,19 +37,16 @@ public void rsaSha256() throws Exception {
4037
SignerTestUtil.testKeySha256Fingerprint("rsa_4096"));
4138
}
4239

43-
@Test
4440
public void dsaMd5() throws Exception {
4541
Assert.assertEquals(KeyFingerprinter.md5Fingerprint(SignerTestUtil.testKeyPair("dsa_1024")),
4642
SignerTestUtil.testKeyMd5Fingerprint("dsa_1024"));
4743
}
4844

49-
@Test
5045
public void dsaSha256() throws Exception {
5146
Assert.assertEquals(KeyFingerprinter.sha256Fingerprint(SignerTestUtil.testKeyPair("dsa_1024")),
5247
SignerTestUtil.testKeySha256Fingerprint("dsa_1024"));
5348
}
5449

55-
@Test
5650
public void ecdsaMd5() throws Exception {
5751
Assert.assertEquals(KeyFingerprinter.md5Fingerprint(SignerTestUtil.testKeyPair("ecdsa_256")),
5852
SignerTestUtil.testKeyMd5Fingerprint("ecdsa_256"));
@@ -62,7 +56,6 @@ public void ecdsaMd5() throws Exception {
6256
SignerTestUtil.testKeyMd5Fingerprint("ecdsa_521"));
6357
}
6458

65-
@Test
6659
public void ecdsaSha256() throws Exception {
6760
Assert.assertEquals(KeyFingerprinter.sha256Fingerprint(SignerTestUtil.testKeyPair("ecdsa_256")),
6861
SignerTestUtil.testKeySha256Fingerprint("ecdsa_256"));
@@ -72,27 +65,38 @@ public void ecdsaSha256() throws Exception {
7265
SignerTestUtil.testKeySha256Fingerprint("ecdsa_521"));
7366
}
7467

75-
@Test
7668
public void testVerifyDefault() throws Exception {
7769
Assert.assertTrue(KeyFingerprinter.verifyFingerprint(SignerTestUtil.testKeyPair("rsa_2048"),
7870
SignerTestUtil.testKeyMd5Fingerprint("rsa_2048")));
7971
Assert.assertFalse(KeyFingerprinter.verifyFingerprint(SignerTestUtil.testKeyPair("rsa_2048"),
8072
"1" + SignerTestUtil.testKeyMd5Fingerprint("rsa_2048")));
8173
}
8274

83-
@Test
8475
public void testVerifyMd5() throws Exception {
8576
Assert.assertTrue(KeyFingerprinter.verifyFingerprint(SignerTestUtil.testKeyPair("rsa_2048"),
8677
"MD5:" + SignerTestUtil.testKeyMd5Fingerprint("rsa_2048")));
8778
Assert.assertFalse(KeyFingerprinter.verifyFingerprint(SignerTestUtil.testKeyPair("rsa_2048"),
8879
"MD5:foo"));
8980
}
9081

91-
@Test
9282
public void testVerifySha256() throws Exception {
9383
Assert.assertTrue(KeyFingerprinter.verifyFingerprint(SignerTestUtil.testKeyPair("rsa_2048"),
9484
"SHA256:" + SignerTestUtil.testKeySha256Fingerprint("rsa_2048")));
9585
Assert.assertFalse(KeyFingerprinter.verifyFingerprint(SignerTestUtil.testKeyPair("rsa_2048"),
9686
"SHA256:LP3pWCEhg6rdmE05GhUKbZ7uOZqsJd0sK0AR3sVoMq4"));
9787
}
88+
89+
public void canColonifyByteArray() {
90+
final String expected = "9f:0b:50:ae:e3:da:f6:eb:b5:71:9a:69:ee:79:9e:c2";
91+
final byte[] bytes = Hex.decode(expected.replaceAll(":", ""));
92+
final String actual = KeyFingerprinter.colonify(bytes);
93+
94+
Assert.assertEquals(actual, expected);
95+
}
96+
97+
public void canColonifyEmptyByteArray() {
98+
final String actual = KeyFingerprinter.colonify(new byte[0]);
99+
100+
Assert.assertEquals(actual, "");
101+
}
98102
}

jaxrs-client/src/test/java/com/joyent/http/signature/jaxrs/client/SignedRequestClientRequestFilterIT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public static WebArchive createDeployment() {
9999
* @throws IOException if unable to read test key
100100
*/
101101
@Test
102+
@SuppressWarnings("deprecation")
102103
public void testSignedRequestWithFilter() throws URISyntaxException, IOException {
103104
Assert.assertNotNull(endpointBaseUrl);
104105

pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@
175175
<forceJavacCompilerUse>true</forceJavacCompilerUse>
176176
<source>${java.min.version}</source>
177177
<target>${java.min.version}</target>
178+
<showWarnings>true</showWarnings>
178179
<compilerArgs>
179-
<arg>-Xlint:deprecation</arg>
180+
<arg>-Xlint:all</arg>
180181
</compilerArgs>
181182
</configuration>
182183
<dependencies>

0 commit comments

Comments
 (0)