Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time claims #50

Merged
merged 2 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@

import com.nimbusds.jose.util.Base64URL;

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
*/
Expand Down Expand Up @@ -47,8 +52,19 @@ public Base64URL getEncodedHeader(){
}

/**
* Serialize the JWT/JWE to a string in compact serializiation form
* Serialize the JWT/JWE to a string in compact serialization form
* @return the compact serialized JWE/JWS
*/
public abstract String serialize();

public abstract List<TimeClaim> timeClaims();

public String getWarnings() {
String warnings = timeClaims().stream()
.map(TimeClaim::warning)
.filter(not(String::isEmpty))
.collect(joining(", "));

return warnings.isEmpty() ? "" : warnings + ".";
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/blackberry/jwteditor/model/jose/JWE.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
import java.security.Provider;
import java.security.Security;
import java.text.ParseException;
import java.util.List;

import static java.util.Collections.emptyList;

/**
* Class representing a JWE
Expand Down Expand Up @@ -64,6 +67,11 @@ public String serialize() {
return"%s.%s.%s.%s.%s".formatted(header.toString(), encryptedKey.toString(), iv.toString(), ciphertext.toString(), tag.toString());
}

@Override
public List<TimeClaim> timeClaims() {
return emptyList();
}

/**
* Get the encrypted key component as bytes
*
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/blackberry/jwteditor/model/jose/JWS.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
import java.nio.charset.StandardCharsets;
import java.security.Provider;
import java.security.Security;
import java.util.List;

/**
* Class representing a JWS
*/
public class JWS extends JOSEObject {
private final Base64URL payload;
private final Base64URL signature;
private final List<TimeClaim> timeClaims;

/**
* Construct a JWS from encoded components
Expand All @@ -46,6 +48,7 @@ public class JWS extends JOSEObject {
super(header);
this.payload = payload;
this.signature = signature;
this.timeClaims = TimeClaim.from(payload.decodeToString());
}

/**
Expand Down Expand Up @@ -80,6 +83,11 @@ public String serialize() {
return "%s.%s.%s".formatted(header.toString(), payload.toString(), signature.toString());
}

@Override
public List<TimeClaim> timeClaims() {
return timeClaims;
}

/**
* Verify JWS with a JWK and an algorithm
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,8 @@ public JOSEObject getModified() {
public String getOriginal() {
return original;
}

public String getWarnings() {
return modified.getWarnings();
}
}
84 changes: 84 additions & 0 deletions src/main/java/com/blackberry/jwteditor/model/jose/TimeClaim.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
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.model.jose;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.List;
import java.util.Optional;

import static java.util.Arrays.stream;
import static java.util.Collections.emptyList;

public record TimeClaim(TimeClaimType type, String data, Long value) {

public boolean isValid() {
return type.isValid(value);
}

public String warning() {
if (isValid()) {
return "";
}

if (value == null || value < 0) {
return "'%s' value is invalid".formatted(type.name);
}

String futurePast = type.dateInThePastRequired() ? "future" : "past";

return "'%s' date is in the %s".formatted(type.name, futurePast);
}

static List<TimeClaim> from(String payloadJson) {
Optional<JSONObject> optional = parsePayload(payloadJson);

if (optional.isEmpty()) {
return emptyList();
}

JSONObject jsonObject = optional.get();

return stream(TimeClaimType.values())
.filter(type -> jsonObject.has(type.name))
.map(type -> new TimeClaim(
type,
jsonObject.get(type.name).toString(),
numberValue(jsonObject, type.name))
)
.toList();
}

private static Optional<JSONObject> parsePayload(String payloadJson) {
try {
return Optional.of(new JSONObject(payloadJson));
} catch (JSONException e) {
return Optional.empty();
}
}

private static Long numberValue(JSONObject jsonObject, String name) {
try {
return jsonObject.getLong(name);
} catch (JSONException e) {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
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.model.jose;

import java.time.Instant;

import static java.time.Instant.now;

public enum TimeClaimType {
EXPIRATION_TIME("exp"),
NOT_BEFORE_TIME("nbf"),
ISSUED_AT_TIME("iat");

final String name;

TimeClaimType(String name) {
this.name = name;
}

public boolean isValid(Long value) {
if (value == null || value < 0) {
return false;
}

Instant valueTime = Instant.ofEpochSecond(value);

return dateInThePastRequired() ? valueTime.isBefore(now()) : valueTime.isAfter(now());
}

public boolean dateInThePastRequired() {
return switch (this) {
case EXPIRATION_TIME -> false;
case NOT_BEFORE_TIME, ISSUED_AT_TIME -> true;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ public void componentChanged() {
mutableJoseObject.setModified(joseObject);
//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());
}

/**
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/com/blackberry/jwteditor/view/editor/EditorView.form
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,15 @@
</tabbedpane>
</children>
</splitpane>
<grid id="b3ff" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="b3ff" layout-manager="GridLayoutManager" row-count="1" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<border type="empty">
<size top="0" left="0" bottom="0" right="5"/>
</border>
<children>
<hspacer id="15da0">
<constraints>
Expand Down Expand Up @@ -464,6 +466,14 @@
<text resource-bundle="strings" key="attack"/>
</properties>
</component>
<component id="9b06b" class="javax.swing.JLabel" binding="labelWarnings">
<constraints>
<grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value=""/>
</properties>
</component>
</children>
</grid>
</children>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

import static java.awt.Color.RED;
import static java.awt.EventQueue.invokeLater;
import static java.awt.Font.BOLD;
import static java.awt.event.HierarchyEvent.SHOWING_CHANGED;
import static org.exbin.deltahex.EditationAllowed.ALLOWED;
import static org.exbin.deltahex.EditationAllowed.READ_ONLY;
Expand Down Expand Up @@ -92,6 +93,7 @@ public abstract class EditorView implements ExtensionProvidedEditor {
private JCheckBox checkBoxJWSPayloadCompactJSON;
private JSplitPane upperSplitPane;
private JSplitPane lowerSplitPane;
private JLabel labelWarnings;

private CodeArea codeAreaSignature;
private CodeArea codeAreaEncryptedKey;
Expand Down Expand Up @@ -546,6 +548,13 @@ private void createUIComponents() {
textAreaPayload = rstaFactory.buildDefaultTextArea();
}

public void setWarnings(String text) {
invokeLater(() -> {
labelWarnings.setFont(labelWarnings.getFont().deriveFont(BOLD));
labelWarnings.setText(text);
});
}

private class ResizeSplitPanesOnFirstRenderHierarchyListener implements HierarchyListener {
@Override
public void hierarchyChanged(HierarchyEvent e) {
Expand Down
Loading
Loading