From 1b561090cdf5870bfb7d4a67f35c632de2251aa5 Mon Sep 17 00:00:00 2001 From: Dolph Flynn <96876199+DolphFlynn@users.noreply.github.com> Date: Sun, 4 Aug 2024 13:52:55 +0100 Subject: [PATCH 1/4] Remove warnings label. --- .../jwteditor/presenter/EditorPresenter.java | 2 +- .../blackberry/jwteditor/view/editor/EditorView.form | 10 +--------- .../blackberry/jwteditor/view/editor/EditorView.java | 9 +-------- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java b/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java index 26c72e5..9e5cc9b 100644 --- a/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java +++ b/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java @@ -449,7 +449,7 @@ public void componentChanged() { //Highlight the serialized text as changed if it differs from the original, and the change wasn't triggered by onSelectionChanging view.setSerialized(joseObject.serialize(), mutableJoseObject.changed() && !selectionChanging); - view.setWarnings(mutableJoseObject.getWarnings()); + view.setInformation(mutableJoseObject.getWarnings()); } /** diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form index 8b93403..958ca6b 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form +++ b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form @@ -427,7 +427,7 @@ - + @@ -466,14 +466,6 @@ - - - - - - - - diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java index 87049a0..3125e5a 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java @@ -42,8 +42,6 @@ import java.util.List; import static java.awt.Color.RED; -import static java.awt.EventQueue.invokeLater; -import static java.awt.Font.BOLD; import static org.exbin.deltahex.EditationAllowed.ALLOWED; import static org.exbin.deltahex.EditationAllowed.READ_ONLY; @@ -89,7 +87,6 @@ public abstract class EditorView { private JCheckBox checkBoxJWSPayloadCompactJSON; private JSplitPane upperSplitPane; private JSplitPane lowerSplitPane; - private JLabel labelWarnings; private CodeArea codeAreaSignature; private CodeArea codeAreaEncryptedKey; @@ -549,10 +546,6 @@ private void createUIComponents() { textAreaPayload = rstaFactory.buildDefaultTextArea(); } - public void setWarnings(String text) { - invokeLater(() -> { - labelWarnings.setFont(labelWarnings.getFont().deriveFont(BOLD)); - labelWarnings.setText(text); - }); + public void setInformation(String text) { } } From 32ed1f85d87bb36fbdfb6106f75cbd0a42242872 Mon Sep 17 00:00:00 2001 From: Dolph Flynn <96876199+DolphFlynn@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:02:56 +0100 Subject: [PATCH 2/4] Remove warnings from JOSEObject. --- .../jwteditor/model/jose/JOSEObject.java | 12 --- .../model/jose/MutableJOSEObject.java | 6 +- .../jwteditor/presenter/EditorPresenter.java | 8 +- .../jwteditor/model/jose/TimeClaimTest.java | 95 ------------------- 4 files changed, 7 insertions(+), 114 deletions(-) diff --git a/src/main/java/com/blackberry/jwteditor/model/jose/JOSEObject.java b/src/main/java/com/blackberry/jwteditor/model/jose/JOSEObject.java index 67e7cd2..f2bcc68 100644 --- a/src/main/java/com/blackberry/jwteditor/model/jose/JOSEObject.java +++ b/src/main/java/com/blackberry/jwteditor/model/jose/JOSEObject.java @@ -22,9 +22,6 @@ import java.util.List; -import static java.util.function.Predicate.not; -import static java.util.stream.Collectors.joining; - /** * Abstract class representing common elements of JWE/JWT */ @@ -58,13 +55,4 @@ public Base64URL getEncodedHeader(){ public abstract String serialize(); public abstract List timeClaims(); - - public String getWarnings() { - String warnings = timeClaims().stream() - .map(TimeClaim::warning) - .filter(not(String::isEmpty)) - .collect(joining(", ")); - - return warnings.isEmpty() ? "" : warnings + "."; - } } diff --git a/src/main/java/com/blackberry/jwteditor/model/jose/MutableJOSEObject.java b/src/main/java/com/blackberry/jwteditor/model/jose/MutableJOSEObject.java index 114849d..a9235e6 100644 --- a/src/main/java/com/blackberry/jwteditor/model/jose/MutableJOSEObject.java +++ b/src/main/java/com/blackberry/jwteditor/model/jose/MutableJOSEObject.java @@ -18,6 +18,8 @@ package com.blackberry.jwteditor.model.jose; +import java.util.List; + /** * Class for a JOSE object change set */ @@ -72,7 +74,7 @@ public String getOriginal() { return original; } - public String getWarnings() { - return modified.getWarnings(); + public List timeClaims() { + return modified.timeClaims(); } } diff --git a/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java b/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java index 9e5cc9b..23aaa69 100644 --- a/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java +++ b/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java @@ -19,10 +19,7 @@ package com.blackberry.jwteditor.presenter; import burp.api.montoya.collaborator.CollaboratorPayloadGenerator; -import com.blackberry.jwteditor.model.jose.JOSEObject; -import com.blackberry.jwteditor.model.jose.JWE; -import com.blackberry.jwteditor.model.jose.JWS; -import com.blackberry.jwteditor.model.jose.MutableJOSEObject; +import com.blackberry.jwteditor.model.jose.*; import com.blackberry.jwteditor.model.keys.Key; import com.blackberry.jwteditor.model.keys.KeyRing; import com.blackberry.jwteditor.utils.Utils; @@ -449,7 +446,8 @@ public void componentChanged() { //Highlight the serialized text as changed if it differs from the original, and the change wasn't triggered by onSelectionChanging view.setSerialized(joseObject.serialize(), mutableJoseObject.changed() && !selectionChanging); - view.setInformation(mutableJoseObject.getWarnings()); + List timeClaims = mutableJoseObject.timeClaims(); + view.setInformation(""); // TODO } /** diff --git a/src/test/java/com/blackberry/jwteditor/model/jose/TimeClaimTest.java b/src/test/java/com/blackberry/jwteditor/model/jose/TimeClaimTest.java index 020b036..bbea770 100644 --- a/src/test/java/com/blackberry/jwteditor/model/jose/TimeClaimTest.java +++ b/src/test/java/com/blackberry/jwteditor/model/jose/TimeClaimTest.java @@ -38,13 +38,6 @@ void givenJWSWithNoTimeClaims_thenTimeClaimsIsEmpty() throws ParseException { assertThat(jws.timeClaims()).isEmpty(); } - @Test - void givenJWSWithNoTimeClaims_thenWarningsAreEmpty() throws ParseException { - JWS jws = JWSFactory.parse("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJUZXN0In0.WVLalefVZ5Rj991Cjgh0qBjKSIQaqC_CgN3b-30GKpQ"); - - assertThat(jws.getWarnings()).isEmpty(); - } - @ParameterizedTest @ValueSource(strings = { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjoxNzE2MjM5MDIyfQ.FuJB22Dq3zXcFXtIAc59tWnmbbFC6jRXzb_2ejbhhoQ", @@ -74,14 +67,6 @@ void givenJWSWithExpTimeClaims_whenExpiryDateInTheFuture_thenTimeClaimValid(Stri assertThat(timeClaim.isValid()).isTrue(); } - @ParameterizedTest - @MethodSource("jwsWithValidExpValues") - void givenJWSWithExpTimeClaims_whenExpiryDateInTheFuture_thenWarningsEmpty(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEmpty(); - } - private static Stream jwsWithInvalidExpValues() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjoiemVvbGl0ZSJ9.Vsy0uiJVpA17ys9DRFWldEcgiut_N5QhvHCRRcp8Xow", @@ -101,14 +86,6 @@ void givenJWSWithExpTimeClaims_whenExpiryDateInvalid_thenTimeClaimNotValid(Strin assertThat(timeClaim.isValid()).isFalse(); } - @ParameterizedTest - @MethodSource("jwsWithInvalidExpValues") - void givenJWSWithExpTimeClaims_whenExpiryDateInvalid_thenWarningsAreCorrect(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEqualTo("'exp' value is invalid."); - } - private static Stream jwsWithExpValuesInThePast() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJleHAiOjE1MTYyMzkwMjJ9.mVGXFv3OuwtuZPsdaf_oGUYm2uOH-T-JRTDQE1c10q0", @@ -127,14 +104,6 @@ void givenJWSWithExpTimeClaims_whenExpiryDateIsInThePast_thenTimeClaimNotValid(S assertThat(timeClaim.isValid()).isFalse(); } - @ParameterizedTest - @MethodSource("jwsWithExpValuesInThePast") - void givenJWSWithExpTimeClaims_whenExpiryDateIsInThePast_thenWarningsCorrect(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEqualTo("'exp' date is in the past."); - } - @ParameterizedTest @ValueSource(strings = { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwibmJmIjoxNzE2MjM5MDIyfQ.mZ_wGwRA0BBp_m6LJOPOBfwMosKrhTf9DbnKZYTzBzg", @@ -167,14 +136,6 @@ void givenJWSWithNbfTimeClaims_whenNotBeforeDateInThePast_thenTimeClaimValid(Str assertThat(timeClaim.isValid()).isTrue(); } - @ParameterizedTest - @MethodSource("jwsWithValidNbfValues") - void givenJWSWithNbfTimeClaims_whenNotBeforeDateInThePast_thenWarningsEmpty(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEmpty(); - } - private static Stream jwsWithInvalidNbfValues() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwibmJmIjoiemVvbGl0ZSJ9.kmx4FteQrcATfc2Zx47WypsqrIC-e1IM4opeLJxLyrI", @@ -193,15 +154,6 @@ void givenJWSWithNbfTimeClaims_whenNotBeforeDateInvalid_thenTimeClaimNotValid(St assertThat(timeClaim.type()).isEqualTo(NOT_BEFORE_TIME); assertThat(timeClaim.isValid()).isFalse(); } - - @ParameterizedTest - @MethodSource("jwsWithInvalidNbfValues") - void givenJWSWithNbfTimeClaims_whenNotBeforeDateInvalid_thenWarningsCorrect(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEqualTo("'nbf' value is invalid."); - } - private static Stream jwsWithFutureNbfValues() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJuYmYiOjIzMjIxNjc0Nzd9.cMocfo6ghvuYBqDwZ9GBdfbCnMLsUcZe2GZRuaah0-c", @@ -220,14 +172,6 @@ void givenJWSWithNbfTimeClaims_whenNotBeforeDateIsInTheFuture_thenTimeClaimNotVa assertThat(timeClaim.isValid()).isFalse(); } - @ParameterizedTest - @MethodSource("jwsWithFutureNbfValues") - void givenJWSWithNbfTimeClaims_whenNotBeforeDateIsInTheFuture_thenWarningsCorrect(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEqualTo("'nbf' date is in the future."); - } - private static Stream jwsWithValidIatValues() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3MTYyMzkwMjJ9.y06rqsXv0DMutukwDaUJU0Sf-Ye3qrDkyFpOaj1J08A", @@ -243,14 +187,6 @@ void givenJWSWithNIatTimeClaims_thenTimeClaimsCorrect(String data) throws ParseE assertThat(jws.timeClaims()).containsExactly(new TimeClaim(ISSUED_AT_TIME, "1716239022", 1716239022L)); } - @ParameterizedTest - @MethodSource("jwsWithValidIatValues") - void givenJWSWithNIatTimeClaims_thenWarningsEmpty(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEmpty(); - } - private static Stream jwsWithValidIatDatesInThePast() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE3MTYyMzkwMjJ9.y06rqsXv0DMutukwDaUJU0Sf-Ye3qrDkyFpOaj1J08A", @@ -272,14 +208,6 @@ void givenJWSWithIatTimeClaims_whenIssuedAtDateInThePast_thenTimeClaimValid(Stri assertThat(timeClaim.isValid()).isTrue(); } - @ParameterizedTest - @MethodSource("jwsWithValidIatDatesInThePast") - void givenJWSWithIatTimeClaims_whenIssuedAtDateInThePast_thenWarningsEmpty(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEmpty(); - } - private static Stream jwsWithInvalidIatValues() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOiJ6ZW9saXRlIn0.-IpgDK_M_jQJQ6FDa-wd25xGFJ2bHNthdYn1JlQNxjg", @@ -298,14 +226,6 @@ void givenJWSWithIatTimeClaims_whenIssuedAtDateInvalid_thenTimeClaimNotValid(Str assertThat(timeClaim.isValid()).isFalse(); } - @ParameterizedTest - @MethodSource("jwsWithInvalidIatValues") - void givenJWSWithIatTimeClaims_whenIssuedAtDateInvalid_thenWarningsCorrect(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEqualTo("'iat' value is invalid."); - } - private static Stream jwsWithFutureIatDates() { return Stream.of( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjIzMjIxNjc0Nzd9.3UYGoLpdXRhnlai81VFV_iWmW90xnCimcYverY1-Zk4", @@ -323,25 +243,10 @@ void givenJWSWithIatTimeClaims_whenIssuedAtDateIsInTheFuture_thenTimeClaimNotVal assertThat(timeClaim.isValid()).isFalse(); } - @ParameterizedTest - @MethodSource("jwsWithFutureIatDates") - void givenJWSWithIatTimeClaims_whenIssuedAtDateIsInTheFuture_thenWarningsCorrect(String data) throws ParseException { - JWS jws = JWSFactory.parse(data); - - assertThat(jws.getWarnings()).isEqualTo("'iat' date is in the future."); - } - @Test void givenJWE_thenTimeClaimsIsEmpty() throws ParseException { JWE jwe = JWEFactory.parse("eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtXIn0.H3X6mT5HLgcFfzLoe4ku6Knhh9Ofv1eL.qF5-N_7K8VQ4yMSz.WXUNY6eg5fR4tc8Hqf5XDRM9ALGwcQyYG4IYwwg8Ctkx1UuxoV7t6UnemjzCj2sOYUqi3KYpDzrKVJpzokz0vcIem4lFe5N_ds8FAMpW0GSF9ePA8qvV99WaP0N2ECVPmgihvL6qwNhdptlLKtxcOpE41U5LnU22voPK55VF4_1j0WmTgWgZ7DwLDysp6EIDjrrt-DY.febBmP71KADmKRVfeSnv_g"); assertThat(jwe.timeClaims()).isEmpty(); } - - @Test - void givenJWE_thenWarningsAreEmpty() throws ParseException { - JWE jwe = JWEFactory.parse("eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtXIn0.H3X6mT5HLgcFfzLoe4ku6Knhh9Ofv1eL.qF5-N_7K8VQ4yMSz.WXUNY6eg5fR4tc8Hqf5XDRM9ALGwcQyYG4IYwwg8Ctkx1UuxoV7t6UnemjzCj2sOYUqi3KYpDzrKVJpzokz0vcIem4lFe5N_ds8FAMpW0GSF9ePA8qvV99WaP0N2ECVPmgihvL6qwNhdptlLKtxcOpE41U5LnU22voPK55VF4_1j0WmTgWgZ7DwLDysp6EIDjrrt-DY.febBmP71KADmKRVfeSnv_g"); - - assertThat(jwe.getWarnings()).isEmpty(); - } } \ No newline at end of file From 4e26afff95f674ccb67cbd76ccbf2eafaa7d4807 Mon Sep 17 00:00:00 2001 From: Dolph Flynn <96876199+DolphFlynn@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:41:00 +0100 Subject: [PATCH 3/4] Add Information panel. --- .../jwteditor/view/editor/EditorView.form | 49 +++++++++++++++---- .../jwteditor/view/editor/EditorView.java | 6 ++- src/main/resources/strings.properties | 1 + 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form index 958ca6b..d40e4aa 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form +++ b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form @@ -136,7 +136,7 @@ - + @@ -275,17 +275,48 @@ - - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java index 3125e5a..c814661 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java @@ -42,6 +42,7 @@ import java.util.List; import static java.awt.Color.RED; +import static java.awt.EventQueue.invokeLater; import static org.exbin.deltahex.EditationAllowed.ALLOWED; import static org.exbin.deltahex.EditationAllowed.READ_ONLY; @@ -86,7 +87,9 @@ public abstract class EditorView { private JButton buttonJWSPayloadFormatJSON; private JCheckBox checkBoxJWSPayloadCompactJSON; private JSplitPane upperSplitPane; + private JSplitPane midSplitPane; private JSplitPane lowerSplitPane; + private JTextPane informationTextPane; private CodeArea codeAreaSignature; private CodeArea codeAreaEncryptedKey; @@ -112,7 +115,8 @@ public abstract class EditorView { panel, () -> { upperSplitPane.setDividerLocation(0.25); - lowerSplitPane.setDividerLocation(0.75); + lowerSplitPane.setDividerLocation(0.5); + invokeLater(() -> midSplitPane.setDividerLocation(0.693)); } )); diff --git a/src/main/resources/strings.properties b/src/main/resources/strings.properties index 7ac3f4d..632480c 100644 --- a/src/main/resources/strings.properties +++ b/src/main/resources/strings.properties @@ -6,6 +6,7 @@ burp_proxy_comment = %d JWTs, %d JWEs header = Header payload = Payload signature = Signature +information = Information encrypted_key = Encrypted Key ciphertext = Ciphertext initialization_vector = Initialization Vector From d90114a62da90fba7d1896b100342bc1b8e11c18 Mon Sep 17 00:00:00 2001 From: Dolph Flynn <96876199+DolphFlynn@users.noreply.github.com> Date: Sun, 4 Aug 2024 18:36:37 +0100 Subject: [PATCH 4/4] Show time claim information within Information panel. --- .../jwteditor/model/jose/TimeClaim.java | 31 +++-- .../jwteditor/model/jose/TimeClaimType.java | 17 ++- .../jwteditor/presenter/EditorPresenter.java | 12 +- .../jwteditor/presenter/Information.java | 36 ++++++ .../jwteditor/view/editor/EditorView.form | 10 +- .../jwteditor/view/editor/EditorView.java | 11 +- .../jwteditor/view/editor/HttpEditorView.java | 2 + .../view/editor/HttpRequestEditorView.java | 1 + .../view/editor/HttpResponseEditorView.java | 1 + .../view/editor/InformationPanel.java | 111 ++++++++++++++++++ .../view/editor/InformationPanelFactory.java | 36 ++++++ .../view/editor/WebSocketEditorView.java | 1 + .../jwteditor/presenter/InformationTest.java | 58 +++++++++ 13 files changed, 300 insertions(+), 27 deletions(-) create mode 100644 src/main/java/com/blackberry/jwteditor/presenter/Information.java create mode 100644 src/main/java/com/blackberry/jwteditor/view/editor/InformationPanel.java create mode 100644 src/main/java/com/blackberry/jwteditor/view/editor/InformationPanelFactory.java create mode 100644 src/test/java/com/blackberry/jwteditor/presenter/InformationTest.java diff --git a/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaim.java b/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaim.java index 751f15e..8dc53f3 100644 --- a/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaim.java +++ b/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaim.java @@ -21,30 +21,37 @@ import org.json.JSONException; import org.json.JSONObject; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; import java.util.Optional; +import static java.time.ZoneOffset.UTC; import static java.util.Arrays.stream; import static java.util.Collections.emptyList; public record TimeClaim(TimeClaimType type, String data, Long value) { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss").withZone(ZoneId.from(UTC)); - public boolean isValid() { - return type.isValid(value); - } - - public String warning() { - if (isValid()) { - return ""; + public String date() { + if (value == null) { + return null; } - if (value == null || value < 0) { - return "'%s' value is invalid".formatted(type.name); - } + Instant instant = Instant.ofEpochSecond(value); + ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, UTC); - String futurePast = type.dateInThePastRequired() ? "future" : "past"; + return FORMATTER.format(zonedDateTime); + } + + public boolean hasDate() { + return value != null; + } - return "'%s' date is in the %s".formatted(type.name, futurePast); + public boolean isValid() { + return type.isValid(value); } static List from(String payloadJson) { diff --git a/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaimType.java b/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaimType.java index a012996..3fa36db 100644 --- a/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaimType.java +++ b/src/main/java/com/blackberry/jwteditor/model/jose/TimeClaimType.java @@ -23,14 +23,16 @@ import static java.time.Instant.now; public enum TimeClaimType { - EXPIRATION_TIME("exp"), - NOT_BEFORE_TIME("nbf"), - ISSUED_AT_TIME("iat"); + EXPIRATION_TIME("exp", "Expiration Time"), + NOT_BEFORE_TIME("nbf", "Not Before"), + ISSUED_AT_TIME("iat", "Issued At"); final String name; + private final String displayName; - TimeClaimType(String name) { + TimeClaimType(String name, String displayName) { this.name = name; + this.displayName = displayName; } public boolean isValid(Long value) { @@ -43,10 +45,15 @@ public boolean isValid(Long value) { return dateInThePastRequired() ? valueTime.isBefore(now()) : valueTime.isAfter(now()); } - public boolean dateInThePastRequired() { + private boolean dateInThePastRequired() { return switch (this) { case EXPIRATION_TIME -> false; case NOT_BEFORE_TIME, ISSUED_AT_TIME -> true; }; } + + @Override + public String toString() { + return displayName; + } } diff --git a/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java b/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java index 23aaa69..e979c73 100644 --- a/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java +++ b/src/main/java/com/blackberry/jwteditor/presenter/EditorPresenter.java @@ -19,7 +19,10 @@ package com.blackberry.jwteditor.presenter; import burp.api.montoya.collaborator.CollaboratorPayloadGenerator; -import com.blackberry.jwteditor.model.jose.*; +import com.blackberry.jwteditor.model.jose.JOSEObject; +import com.blackberry.jwteditor.model.jose.JWE; +import com.blackberry.jwteditor.model.jose.JWS; +import com.blackberry.jwteditor.model.jose.MutableJOSEObject; import com.blackberry.jwteditor.model.keys.Key; import com.blackberry.jwteditor.model.keys.KeyRing; import com.blackberry.jwteditor.utils.Utils; @@ -446,8 +449,11 @@ public void componentChanged() { //Highlight the serialized text as changed if it differs from the original, and the change wasn't triggered by onSelectionChanging view.setSerialized(joseObject.serialize(), mutableJoseObject.changed() && !selectionChanging); - List timeClaims = mutableJoseObject.timeClaims(); - view.setInformation(""); // TODO + List information = mutableJoseObject.timeClaims().stream() + .map(Information::from) + .toList(); + + view.setInformation(information); } /** diff --git a/src/main/java/com/blackberry/jwteditor/presenter/Information.java b/src/main/java/com/blackberry/jwteditor/presenter/Information.java new file mode 100644 index 0000000..68de9e1 --- /dev/null +++ b/src/main/java/com/blackberry/jwteditor/presenter/Information.java @@ -0,0 +1,36 @@ +/* +Author : Dolph Flynn + +Copyright 2024 Dolph Flynn + +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 com.blackberry.jwteditor.presenter; + +import com.blackberry.jwteditor.model.jose.TimeClaim; + +public record Information(String text, boolean isWarning) { + + static Information from(TimeClaim timeClaim) { + StringBuilder sb = new StringBuilder(timeClaim.type().toString()).append(" - "); + + if (timeClaim.hasDate()) { + sb.append(timeClaim.date()); + } else { + sb.append("invalid value: ").append(timeClaim.data()); + } + + return new Information(sb.toString(), !timeClaim.isValid()); + } +} diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form index d40e4aa..c2cd3b3 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form +++ b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form @@ -305,14 +305,14 @@ - + - - - + - + + + diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java index c814661..1405646 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/EditorView.java @@ -21,6 +21,7 @@ import burp.api.montoya.collaborator.CollaboratorPayloadGenerator; import burp.api.montoya.ui.Selection; import com.blackberry.jwteditor.presenter.EditorPresenter; +import com.blackberry.jwteditor.presenter.Information; import com.blackberry.jwteditor.presenter.PresenterStore; import com.blackberry.jwteditor.utils.Utils; import com.blackberry.jwteditor.view.hexcodearea.HexCodeAreaFactory; @@ -59,6 +60,7 @@ public abstract class EditorView { private final RstaFactory rstaFactory; private final boolean editable; private final HexCodeAreaFactory hexCodeAreaFactory; + private final InformationPanel informationPanel; private final boolean isProVersion; private EditorMode mode; @@ -89,7 +91,7 @@ public abstract class EditorView { private JSplitPane upperSplitPane; private JSplitPane midSplitPane; private JSplitPane lowerSplitPane; - private JTextPane informationTextPane; + private JScrollPane informationScrollPane; private CodeArea codeAreaSignature; private CodeArea codeAreaEncryptedKey; @@ -103,6 +105,7 @@ public abstract class EditorView { HexCodeAreaFactory hexAreaCodeFactory, CollaboratorPayloadGenerator collaboratorPayloadGenerator, ErrorLoggingActionListenerFactory actionListenerFactory, + InformationPanelFactory informationPanelFactory, boolean editable, boolean isProVersion) { this.rstaFactory = rstaFactory; @@ -110,6 +113,9 @@ public abstract class EditorView { this.hexCodeAreaFactory = hexAreaCodeFactory; this.isProVersion = isProVersion; this.presenter = new EditorPresenter(this, collaboratorPayloadGenerator, actionListenerFactory, presenters); + this.informationPanel = informationPanelFactory.build(); + + informationScrollPane.setViewportView(informationPanel); panel.addHierarchyListener(new RunEDTActionOnFirstRenderHierarchyListener( panel, @@ -550,6 +556,7 @@ private void createUIComponents() { textAreaPayload = rstaFactory.buildDefaultTextArea(); } - public void setInformation(String text) { + public void setInformation(List information) { + informationPanel.updateInformation(information); } } diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/HttpEditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/HttpEditorView.java index 954bd9f..48bb13a 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/HttpEditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/HttpEditorView.java @@ -33,6 +33,7 @@ abstract class HttpEditorView extends EditorView implements ExtensionProvidedEdi HexCodeAreaFactory hexAreaCodeFactory, CollaboratorPayloadGenerator collaboratorPayloadGenerator, ErrorLoggingActionListenerFactory actionListenerFactory, + InformationPanelFactory informationPanelFactory, boolean editable, boolean isProVersion) { super( @@ -41,6 +42,7 @@ abstract class HttpEditorView extends EditorView implements ExtensionProvidedEdi hexAreaCodeFactory, collaboratorPayloadGenerator, actionListenerFactory, + informationPanelFactory, editable, isProVersion ); diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/HttpRequestEditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/HttpRequestEditorView.java index f1a22be..1baae3a 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/HttpRequestEditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/HttpRequestEditorView.java @@ -49,6 +49,7 @@ public HttpRequestEditorView( new HexCodeAreaFactory(logging, userInterface), collaboratorPayloadGenerator, new ErrorLoggingActionListenerFactory(logging), + new InformationPanelFactory(userInterface, logging), editable, isProVersion ); diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/HttpResponseEditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/HttpResponseEditorView.java index 0676623..069d167 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/HttpResponseEditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/HttpResponseEditorView.java @@ -47,6 +47,7 @@ public HttpResponseEditorView( new HexCodeAreaFactory(logging, userInterface), collaboratorPayloadGenerator, new ErrorLoggingActionListenerFactory(logging), + new InformationPanelFactory(userInterface, logging), editable, isProVersion ); diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/InformationPanel.java b/src/main/java/com/blackberry/jwteditor/view/editor/InformationPanel.java new file mode 100644 index 0000000..e80f6bc --- /dev/null +++ b/src/main/java/com/blackberry/jwteditor/view/editor/InformationPanel.java @@ -0,0 +1,111 @@ +/* +Author : Dolph Flynn + +Copyright 2024 Dolph Flynn + +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 com.blackberry.jwteditor.view.editor; + +import burp.api.montoya.logging.Logging; +import com.blackberry.jwteditor.presenter.Information; + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static java.awt.EventQueue.invokeLater; + +class InformationPanel extends JTextPane { + private final Supplier fontSupplier; + private final Logging logging; + private final List informationList; + private final Style informationStyle; + private final Style warningStyle; + private final Style lineSpacingStyle; + + InformationPanel(Supplier fontSupplier, Logging logging) { + this.fontSupplier = fontSupplier; + this.logging = logging; + this.informationList = new ArrayList<>(); + this.informationStyle = addStyle("informationStyleName", null); + this.warningStyle = addStyle("warningStyleName", null); + this.lineSpacingStyle = addStyle("lineSpacingStyleName", null); + + setBorder(BorderFactory.createEmptyBorder(10, 10, 5, 5)); + + configureStyles(); + } + + void updateInformation(List infoList) { + invokeLater(() -> { + informationList.clear(); + informationList.addAll(infoList); + updateDocument(); + }); + } + + private void configureStyles() { + Font font = fontSupplier.get(); + + StyleConstants.setFontFamily(informationStyle, font.getFamily()); + StyleConstants.setFontSize(informationStyle, font.getSize()); + + StyleConstants.setFontFamily(warningStyle, font.getFamily()); + StyleConstants.setFontSize(warningStyle, font.getSize()); + StyleConstants.setForeground(warningStyle, Color.RED); + + StyleConstants.setFontFamily(lineSpacingStyle, font.getFamily()); + StyleConstants.setFontSize(lineSpacingStyle, Math.round(font.getSize() * 0.3F)); + } + + private void updateDocument() { + setText(""); + + try { + for (Information information : informationList) { + addInformation(information); + } + } catch (BadLocationException e) { + logging.logToError(e); + } + } + + private void addInformation(Information information) throws BadLocationException { + StyledDocument document = getStyledDocument(); + + document.insertString(document.getLength(), "• ", informationStyle); + + Style style = information.isWarning() ? warningStyle : informationStyle; + document.insertString(document.getLength(), information.text() + "\n", style); + + document.insertString(document.getLength(), "\n", lineSpacingStyle); + } + + @Override + public void updateUI() { + super.updateUI(); + + if (fontSupplier != null) { + configureStyles(); + updateDocument(); + } + } +} diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/InformationPanelFactory.java b/src/main/java/com/blackberry/jwteditor/view/editor/InformationPanelFactory.java new file mode 100644 index 0000000..5a90c47 --- /dev/null +++ b/src/main/java/com/blackberry/jwteditor/view/editor/InformationPanelFactory.java @@ -0,0 +1,36 @@ +/* +Author : Dolph Flynn + +Copyright 2024 Dolph Flynn + +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 com.blackberry.jwteditor.view.editor; + +import burp.api.montoya.logging.Logging; +import burp.api.montoya.ui.UserInterface; + +public class InformationPanelFactory { + private final UserInterface userInterface; + private final Logging logging; + + public InformationPanelFactory(UserInterface userInterface, Logging logging) { + this.userInterface = userInterface; + this.logging = logging; + } + + InformationPanel build() { + return new InformationPanel(userInterface::currentDisplayFont, logging); + } +} diff --git a/src/main/java/com/blackberry/jwteditor/view/editor/WebSocketEditorView.java b/src/main/java/com/blackberry/jwteditor/view/editor/WebSocketEditorView.java index 850773b..c697f26 100644 --- a/src/main/java/com/blackberry/jwteditor/view/editor/WebSocketEditorView.java +++ b/src/main/java/com/blackberry/jwteditor/view/editor/WebSocketEditorView.java @@ -44,6 +44,7 @@ public WebSocketEditorView(PresenterStore presenters, new HexCodeAreaFactory(logging, userInterface), collaboratorPayloadGenerator, new ErrorLoggingActionListenerFactory(logging), + new InformationPanelFactory(userInterface, logging), editable, isProVersion ); diff --git a/src/test/java/com/blackberry/jwteditor/presenter/InformationTest.java b/src/test/java/com/blackberry/jwteditor/presenter/InformationTest.java new file mode 100644 index 0000000..11404d9 --- /dev/null +++ b/src/test/java/com/blackberry/jwteditor/presenter/InformationTest.java @@ -0,0 +1,58 @@ +/* +Author : Dolph Flynn + +Copyright 2024 Dolph Flynn + +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 com.blackberry.jwteditor.presenter; + +import com.blackberry.jwteditor.model.jose.TimeClaim; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static com.blackberry.jwteditor.model.jose.TimeClaimType.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +class InformationTest { + + static Stream data() { + return Stream.of( + arguments(new TimeClaim(ISSUED_AT_TIME, "isogeny", null), "Issued At - invalid value: isogeny", true), + arguments(new TimeClaim(ISSUED_AT_TIME, "1516239022", 1516239022L), "Issued At - Thu Jan 18 2018 01:30:22", false), + arguments(new TimeClaim(ISSUED_AT_TIME, "1516239022", 2516239022L), "Issued At - Sun Sept 26 2049 03:17:02", true), + arguments(new TimeClaim(NOT_BEFORE_TIME, "isogeny", null), "Not Before - invalid value: isogeny", true), + arguments(new TimeClaim(NOT_BEFORE_TIME, "1516239022", 1516239022L), "Not Before - Thu Jan 18 2018 01:30:22", false), + arguments(new TimeClaim(NOT_BEFORE_TIME, "1516239022", 2516239022L), "Not Before - Sun Sept 26 2049 03:17:02", true), + arguments(new TimeClaim(EXPIRATION_TIME, "isogeny", null), "Expiration Time - invalid value: isogeny", true), + arguments(new TimeClaim(EXPIRATION_TIME, "1516239022", 1516239022L), "Expiration Time - Thu Jan 18 2018 01:30:22", true), + arguments(new TimeClaim(EXPIRATION_TIME, "1516239022", 2516239022L), "Expiration Time - Sun Sept 26 2049 03:17:02", false) + ); + } + + @Disabled + @MethodSource("data") + @ParameterizedTest + void testInformationFromTimeClaims(TimeClaim timeClaim, String expectedText, boolean expectedIsWarning) { + Information information = Information.from(timeClaim); + + assertThat(information.text()).isEqualTo(expectedText); + assertThat(information.isWarning()).isEqualTo(expectedIsWarning); + } +} \ No newline at end of file