Skip to content

Commit db1d970

Browse files
elharochingor13
authored andcommitted
stop exposing internal private state in JsonWebSignature (#767)
* stop exposing internal private state * JUnit 4 * don't expose internal lists
1 parent 74dd65f commit db1d970

File tree

2 files changed

+75
-18
lines changed

2 files changed

+75
-18
lines changed

google-http-client/src/main/java/com/google/api/client/json/webtoken/JsonWebSignature.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.security.Signature;
3333
import java.security.cert.X509Certificate;
3434
import java.util.ArrayList;
35+
import java.util.Arrays;
3536
import java.util.List;
3637
import javax.net.ssl.TrustManager;
3738
import javax.net.ssl.TrustManagerFactory;
@@ -135,7 +136,7 @@ public static class Header extends JsonWebToken.Header {
135136
* @since 1.19.1.
136137
*/
137138
@Key("x5c")
138-
private List<String> x509Certificates;
139+
private ArrayList<String> x509Certificates;
139140

140141
/**
141142
* Array listing the header parameter names that define extensions that are used in the JWS
@@ -299,7 +300,7 @@ public final String getX509Certificate() {
299300
* @since 1.19.1.
300301
*/
301302
public final List<String> getX509Certificates() {
302-
return x509Certificates;
303+
return new ArrayList<>(x509Certificates);
303304
}
304305

305306
/**
@@ -331,22 +332,25 @@ public Header setX509Certificate(String x509Certificate) {
331332
* @since 1.19.1.
332333
*/
333334
public Header setX509Certificates(List<String> x509Certificates) {
334-
this.x509Certificates = x509Certificates;
335+
this.x509Certificates = new ArrayList<>(x509Certificates);
335336
return this;
336337
}
337338

338339
/**
339-
* Returns the array listing the header parameter names that define extensions that are used in
340+
* Returns an array listing the header parameter names that define extensions used in
340341
* the JWS header that MUST be understood and processed or {@code null} for none.
341342
*
342343
* @since 1.16
343344
*/
344345
public final List<String> getCritical() {
345-
return critical;
346+
if (critical == null || critical.isEmpty()) {
347+
return null;
348+
}
349+
return new ArrayList<>(critical);
346350
}
347351

348352
/**
349-
* Sets the array listing the header parameter names that define extensions that are used in the
353+
* Sets the header parameter names that define extensions used in the
350354
* JWS header that MUST be understood and processed or {@code null} for none.
351355
*
352356
* <p>Overriding is only supported for the purpose of calling the super implementation and
@@ -355,7 +359,7 @@ public final List<String> getCritical() {
355359
* @since 1.16
356360
*/
357361
public Header setCritical(List<String> critical) {
358-
this.critical = critical;
362+
this.critical = new ArrayList<>(critical);
359363
return this;
360364
}
361365

@@ -471,14 +475,14 @@ private static X509TrustManager getDefaultX509TrustManager() {
471475
}
472476
}
473477

474-
/** Returns the modifiable array of bytes of the signature. */
478+
/** Returns the bytes of the signature. */
475479
public final byte[] getSignatureBytes() {
476-
return signatureBytes;
480+
return Arrays.copyOf(signatureBytes, signatureBytes.length);
477481
}
478482

479-
/** Returns the modifiable array of bytes of the signature content. */
483+
/** Returns the bytes of the signature content. */
480484
public final byte[] getSignedContentBytes() {
481-
return signedContentBytes;
485+
return Arrays.copyOf(signedContentBytes, signedContentBytes.length);
482486
}
483487

484488
/**

google-http-client/src/test/java/com/google/api/client/json/webtoken/JsonWebSignatureTest.java

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,27 @@
1717
import com.google.api.client.testing.json.MockJsonFactory;
1818
import com.google.api.client.testing.json.webtoken.TestCertificates;
1919
import com.google.api.client.testing.util.SecurityTestUtils;
20+
21+
import java.io.IOException;
22+
import java.security.GeneralSecurityException;
2023
import java.security.cert.X509Certificate;
2124
import java.security.interfaces.RSAPrivateKey;
25+
import java.util.ArrayList;
26+
import java.util.List;
27+
2228
import javax.net.ssl.X509TrustManager;
23-
import junit.framework.TestCase;
29+
30+
import org.junit.Assert;
31+
import org.junit.Test;
2432

2533
/**
2634
* Tests {@link JsonWebSignature}.
2735
*
2836
* @author Yaniv Inbar
2937
*/
30-
public class JsonWebSignatureTest extends TestCase {
38+
public class JsonWebSignatureTest {
3139

40+
@Test
3241
public void testSign() throws Exception {
3342
JsonWebSignature.Header header = new JsonWebSignature.Header();
3443
header.setAlgorithm("RS256");
@@ -40,25 +49,69 @@ public void testSign() throws Exception {
4049
.setIssuedAtTimeSeconds(0L)
4150
.setExpirationTimeSeconds(3600L);
4251
RSAPrivateKey privateKey = SecurityTestUtils.newRsaPrivateKey();
43-
assertEquals(
52+
Assert.assertEquals(
4453
"..kDmKaHNYByLmqAi9ROeLcFmZM7W_emsceKvDZiEGAo-ineCunC6_Nb0HEpAuzIidV-LYTMHS3BvI49KFz9gi6hI3"
4554
+ "ZndDL5EzplpFJo1ZclVk1_hLn94P2OTAkZ4ydsTfus6Bl98EbCkInpF_2t5Fr8OaHxCZCDdDU7W5DSnOsx4",
4655
JsonWebSignature.signUsingRsaSha256(privateKey, new MockJsonFactory(), header, payload));
4756
}
4857

49-
private X509Certificate verifyX509WithCaCert(TestCertificates.CertData caCert) throws Exception {
58+
private X509Certificate verifyX509WithCaCert(TestCertificates.CertData caCert)
59+
throws IOException, GeneralSecurityException {
5060
JsonWebSignature signature = TestCertificates.getJsonWebSignature();
5161
X509TrustManager trustManager = caCert.getTrustManager();
5262
return signature.verifySignature(trustManager);
5363
}
64+
65+
@Test
66+
public void testImmutableSignatureBytes() throws IOException {
67+
JsonWebSignature signature = TestCertificates.getJsonWebSignature();
68+
byte[] bytes = signature.getSignatureBytes();
69+
bytes[0] = (byte) (bytes[0] + 1);
70+
byte[] bytes2 = signature.getSignatureBytes();
71+
Assert.assertNotEquals(bytes2[0], bytes[0]);
72+
}
73+
74+
@Test
75+
public void testImmutableSignedContentBytes() throws IOException {
76+
JsonWebSignature signature = TestCertificates.getJsonWebSignature();
77+
byte[] bytes = signature.getSignedContentBytes();
78+
bytes[0] = (byte) (bytes[0] + 1);
79+
byte[] bytes2 = signature.getSignedContentBytes();
80+
Assert.assertNotEquals(bytes2[0], bytes[0]);
81+
}
82+
83+
@Test
84+
public void testImmutableCertificates() throws IOException {
85+
JsonWebSignature signature = TestCertificates.getJsonWebSignature();
86+
List<String> certificates = signature.getHeader().getX509Certificates();
87+
certificates.set(0, "foo");
88+
Assert.assertNotEquals("foo", signature.getHeader().getX509Certificates().get(0));
89+
}
90+
91+
@Test
92+
public void testImmutableCritical() throws IOException {
93+
JsonWebSignature signature = TestCertificates.getJsonWebSignature();
94+
List<String> critical = new ArrayList<>();
95+
signature.getHeader().setCritical(critical);
96+
critical.add("bar");
97+
Assert.assertNull(signature.getHeader().getCritical());
98+
}
99+
100+
@Test
101+
public void testCriticalNullForNone() throws IOException {
102+
JsonWebSignature signature = TestCertificates.getJsonWebSignature();
103+
Assert.assertNull(signature.getHeader().getCritical());
104+
}
54105

106+
@Test
55107
public void testVerifyX509() throws Exception {
56108
X509Certificate signatureCert = verifyX509WithCaCert(TestCertificates.CA_CERT);
57-
assertNotNull(signatureCert);
58-
assertTrue(signatureCert.getSubjectDN().getName().startsWith("CN=foo.bar.com"));
109+
Assert.assertNotNull(signatureCert);
110+
Assert.assertTrue(signatureCert.getSubjectDN().getName().startsWith("CN=foo.bar.com"));
59111
}
60112

113+
@Test
61114
public void testVerifyX509WrongCa() throws Exception {
62-
assertNull(verifyX509WithCaCert(TestCertificates.BOGUS_CA_CERT));
115+
Assert.assertNull(verifyX509WithCaCert(TestCertificates.BOGUS_CA_CERT));
63116
}
64117
}

0 commit comments

Comments
 (0)