Skip to content

Commit

Permalink
Merge pull request #65 from DolphFlynn/presenter_store
Browse files Browse the repository at this point in the history
Presenter store
  • Loading branch information
DolphFlynn authored Oct 19, 2024
2 parents 0f114f9 + dfb16c7 commit 4ae5196
Show file tree
Hide file tree
Showing 20 changed files with 201 additions and 252 deletions.
9 changes: 3 additions & 6 deletions src/main/java/burp/JWTEditorExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import com.blackberry.jwteditor.model.keys.KeysModel;
import com.blackberry.jwteditor.model.persistence.BurpKeysModelPersistence;
import com.blackberry.jwteditor.model.persistence.KeysModelPersistence;
import com.blackberry.jwteditor.presenter.PresenterStore;
import com.blackberry.jwteditor.utils.Utils;
import com.blackberry.jwteditor.view.SuiteView;
import com.blackberry.jwteditor.view.editor.HttpRequestEditorView;
Expand Down Expand Up @@ -51,13 +50,11 @@ public void initialize(MontoyaApi api) {
Window suiteWindow = userInterface.swingUtils().suiteFrame();

RstaFactory rstaFactory = new RstaFactory(userInterface, api.logging());
PresenterStore presenters = new PresenterStore();

boolean isProVersion = api.burpSuite().version().edition() == PROFESSIONAL;

SuiteView suiteView = new SuiteView(
suiteWindow,
presenters,
keysModelPersistence,
keysModel,
rstaFactory,
Expand All @@ -70,7 +67,7 @@ public void initialize(MontoyaApi api) {

userInterface.registerHttpRequestEditorProvider(editorCreationContext ->
new HttpRequestEditorView(
presenters,
keysModel,
rstaFactory,
api.logging(),
api.userInterface(),
Expand All @@ -82,7 +79,7 @@ public void initialize(MontoyaApi api) {

userInterface.registerHttpResponseEditorProvider(editorCreationContext ->
new HttpResponseEditorView(
presenters,
keysModel,
rstaFactory,
api.logging(),
api.userInterface(),
Expand All @@ -94,7 +91,7 @@ public void initialize(MontoyaApi api) {

userInterface.registerWebSocketMessageEditorProvider(editorCreationContext ->
new WebSocketEditorView(
presenters,
keysModel,
rstaFactory,
api.logging(),
api.userInterface(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,10 @@ public Key getKey(String keyId) {
return keys.get(keyId);
}
}

public boolean keyExists(String keyId) {
synchronized (lock) {
return keys.get(keyId) != null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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.model.keys.KeysModel;
import com.blackberry.jwteditor.utils.Utils;
import com.blackberry.jwteditor.view.dialog.MessageDialogFactory;
import com.blackberry.jwteditor.view.dialog.operations.*;
Expand All @@ -49,9 +50,9 @@
/**
* Presenter class for the Editor tab
*/
public class EditorPresenter extends Presenter {
public class EditorPresenter {

private final PresenterStore presenters;
private final KeysModel keysModel;
private final EditorView view;
private final CollaboratorPayloadGenerator collaboratorPayloadGenerator;
private final ErrorLoggingActionListenerFactory actionListenerFactory;
Expand All @@ -64,15 +65,13 @@ public EditorPresenter(
EditorView view,
CollaboratorPayloadGenerator collaboratorPayloadGenerator,
ErrorLoggingActionListenerFactory actionListenerFactory,
PresenterStore presenters) {
KeysModel keysModel) {
this.view = view;
this.collaboratorPayloadGenerator = collaboratorPayloadGenerator;
this.actionListenerFactory = actionListenerFactory;
this.presenters = presenters;
this.keysModel = keysModel;
this.model = new EditorModel();
this.messageDialogFactory = new MessageDialogFactory(view.uiComponent());

presenters.register(this);
}

/**
Expand Down Expand Up @@ -187,12 +186,10 @@ public void onAttackEmbedJWKClicked() {
* Handle click events from the HMAC Key Confusion button
*/
public void onAttackKeyConfusionClicked() {
KeysPresenter keysPresenter = (KeysPresenter) presenters.get(KeysPresenter.class);

List<Key> attackKeys = new ArrayList<>();

// Get a list of verification capable public keys
List<Key> verificationKeys = keysPresenter.getVerificationKeys();
List<Key> verificationKeys = keysModel.getVerificationKeys();
for (Key signingKey : verificationKeys) {
if (signingKey.isPublic() && signingKey.hasPEM()) {
attackKeys.add(signingKey);
Expand Down Expand Up @@ -286,18 +283,16 @@ public void onSignClicked() {
* @param mode mode of the signing dialog to display
*/
private void signingDialog(SignDialog.Mode mode) {
KeysPresenter keysPresenter = (KeysPresenter) presenters.get(KeysPresenter.class);

// Check there are signing keys in the keystore
if (keysPresenter.getSigningKeys().isEmpty()) {
if (keysModel.getSigningKeys().isEmpty()) {
messageDialogFactory.showWarningDialog("error_title_no_signing_keys", "error_no_signing_keys");
return;
}

SignDialog signDialog = new SignDialog(
view.window(),
actionListenerFactory,
keysPresenter.getSigningKeys(),
keysModel.getSigningKeys(),
getJWS(),
mode
);
Expand All @@ -314,7 +309,7 @@ private void signingDialog(SignDialog.Mode mode) {
* Handle click events from the Verify button
*/
public void onVerifyClicked() {
List<Key> keys = ((KeysPresenter) presenters.get(KeysPresenter.class)).getVerificationKeys();
List<Key> keys = keysModel.getVerificationKeys();

// Check there are verification keys in the keystore
if (keys.isEmpty()) {
Expand All @@ -332,10 +327,8 @@ public void onVerifyClicked() {
}

public void onEncryptClicked() {
KeysPresenter keysPresenter = (KeysPresenter) presenters.get(KeysPresenter.class);

// Check there are encryption keys in the keystore
if (keysPresenter.getEncryptionKeys().isEmpty()) {
if (keysModel.getEncryptionKeys().isEmpty()) {
messageDialogFactory.showWarningDialog("error_title_no_encryption_keys", "error_no_encryption_keys");
return;
}
Expand All @@ -344,7 +337,7 @@ public void onEncryptClicked() {
view.window(),
actionListenerFactory,
getJWS(),
keysPresenter.getEncryptionKeys()
keysModel.getEncryptionKeys()
);
encryptDialog.display();

Expand All @@ -361,17 +354,14 @@ public void onEncryptClicked() {
* Handle click events from the Decrypt button
*/
public void onDecryptClicked() {
KeysPresenter keysPresenter = (KeysPresenter) presenters.get(KeysPresenter.class);

// Check there are decryption keys in the keystore
if (keysPresenter.getDecryptionKeys().isEmpty()) {
if (keysModel.getDecryptionKeys().isEmpty()) {
messageDialogFactory.showWarningDialog("error_title_no_decryption_keys", "error_no_decryption_keys");
return;
}

// Attempt to decrypt the contents of the editor with all available keys
try {
List<Key> keys = keysPresenter.getDecryptionKeys();
List<Key> keys = keysModel.getDecryptionKeys();
Optional<JWS> jws = new KeyRing(keys).attemptDecryption(getJWE());

// If decryption was successful, set the contents of the editor to the decrypted JWS and set the editor mode to JWS
Expand Down
115 changes: 17 additions & 98 deletions src/main/java/com/blackberry/jwteditor/presenter/KeysPresenter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@
import com.blackberry.jwteditor.model.persistence.KeysModelPersistence;
import com.blackberry.jwteditor.utils.PEMUtils;
import com.blackberry.jwteditor.utils.Utils;
import com.blackberry.jwteditor.view.dialog.keys.AsymmetricKeyDialogFactory;
import com.blackberry.jwteditor.view.dialog.keys.KeyDialog;
import com.blackberry.jwteditor.view.dialog.keys.PasswordDialog;
import com.blackberry.jwteditor.view.dialog.keys.SymmetricKeyDialog;
import com.blackberry.jwteditor.view.dialog.keys.KeysDialogFactory;
import com.blackberry.jwteditor.view.keys.KeysView;
import com.blackberry.jwteditor.view.rsta.RstaFactory;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.JWK;

import javax.swing.*;
import java.util.List;
Expand All @@ -42,33 +39,19 @@
/**
* Presenter for the Keys tab
*/
public class KeysPresenter extends Presenter {
public class KeysPresenter {

private final KeysModel model;
private final KeysView view;
private final RstaFactory rstaFactory;
private final PresenterStore presenters;
private final AsymmetricKeyDialogFactory asymmetricKeyDialogFactory;
private final KeysDialogFactory keysDialogFactory;

/**
* Create a new KeysPresenter
*
* @param view the KeysView to associate with the presenter
* @param presenters the shared list of all presenters
* @param keysModelPersistence class used to persist keys model
* @param keysModel KeysModel to use (or null to create a new one)
* @param rstaFactory Factory to create RSyntaxTextArea
*/
public KeysPresenter(KeysView view,
PresenterStore presenters,
KeysModelPersistence keysModelPersistence,
KeysModel keysModel,
RstaFactory rstaFactory) {
KeysDialogFactory keysDialogFactory) {
this.view = view;
this.rstaFactory = rstaFactory;
this.presenters = presenters;
this.model = keysModel;
this.asymmetricKeyDialogFactory = new AsymmetricKeyDialogFactory(view.getParent(), presenters, rstaFactory);
this.keysDialogFactory = keysDialogFactory;

model.addKeyModelListener(new KeysModelListener() {
@Override
Expand All @@ -91,58 +74,30 @@ public void notifyKeyDeleted(int rowIndex) {
keysModelPersistence.save(keysModel);
}
});

presenters.register(this);
}

/**
* Handler for double-click events from the keys view
*/
public void onTableKeysDoubleClick() {
Key key = model.getKey(view.getSelectedRow());
KeyDialog dialog = keysDialogFactory.dialogFor(key);

KeyDialog d;

// Get the dialog type based on the key type
if (key instanceof JWKKey) {
JWK jwk = ((JWKKey) key).getJWK();
if (jwk instanceof RSAKey rsaKey) {
d = asymmetricKeyDialogFactory.rsaKeyDialog(rsaKey);
} else if (jwk instanceof ECKey ecKey) {
d = asymmetricKeyDialogFactory.ecKeyDialog(ecKey);
} else if (jwk instanceof OctetKeyPair octetKeyPair) {
d = asymmetricKeyDialogFactory.okpDialog(octetKeyPair);
} else if (jwk instanceof OctetSequenceKey octetSequenceKey) {
d = new SymmetricKeyDialog(view.getParent(), presenters, rstaFactory, octetSequenceKey);
} else {
return;
}
} else if (key instanceof PasswordKey) {
d = new PasswordDialog(view.getParent(), presenters, (PasswordKey) key);
} else {
if (dialog == null) {
return;
}

d.display();
dialog.display();

// If dialog returned a key, replace the key in the store with the new key
Key newKey = d.getKey();
Key newKey = dialog.getKey();

if (newKey != null) {
model.deleteKey(key.getID());
model.addKey(d.getKey());
model.addKey(dialog.getKey());
}
}

/**
* Check if a key exists in the key model
*
* @param keyId id of key to check
* @return true if the key exists in the model
*/
public boolean keyExists(String keyId) {
return model.getKey(keyId) != null;
}

private void onButtonNewClicked(KeyDialog d) {
d.display();

Expand All @@ -156,35 +111,35 @@ private void onButtonNewClicked(KeyDialog d) {
* Handler for button clicks for new symmetric keys
*/
public void onButtonNewSymmetricClick() {
onButtonNewClicked(new SymmetricKeyDialog(view.getParent(), presenters, rstaFactory, null));
onButtonNewClicked(keysDialogFactory.symmetricKeyDialog());
}

/**
* Handler for button clicks for new RSA keys
*/
public void onButtonNewRSAClick() {
onButtonNewClicked(asymmetricKeyDialogFactory.rsaKeyDialog());
onButtonNewClicked(keysDialogFactory.rsaKeyDialog());
}

/**
* Handler for button clicks for new EC keys
*/
public void onButtonNewECClick() {
onButtonNewClicked(asymmetricKeyDialogFactory.ecKeyDialog());
onButtonNewClicked(keysDialogFactory.ecKeyDialog());
}

/**
* Handler for button clicks for new OKPs
*/
public void onButtonNewOKPClick() {
onButtonNewClicked(asymmetricKeyDialogFactory.okpDialog());
onButtonNewClicked(keysDialogFactory.okpDialog());
}

/**
* Handler for button clicks for new passwords
*/
public void onButtonNewPasswordClick() {
onButtonNewClicked(new PasswordDialog(view.getParent(), presenters));
onButtonNewClicked(keysDialogFactory.passwordDialog());
}

/**
Expand Down Expand Up @@ -344,40 +299,4 @@ public void onPopupJWKSet(int[] rows) {

Utils.copyToClipboard(jwkSetJson);
}

/**
* Get a list of signing keys from the model
*
* @return list of keys that can be used for signing
*/
public List<Key> getSigningKeys() {
return model.getSigningKeys();
}

/**
* Get a list of encryption keys from the model
*
* @return list of keys that can be used for encryption
*/
public List<Key> getEncryptionKeys() {
return model.getEncryptionKeys();
}

/**
* Get a list of decryption keys from the model
*
* @return list of keys that can be used for decryption
*/
public List<Key> getDecryptionKeys() {
return model.getDecryptionKeys();
}

/**
* Get a list of verification keys from the model
*
* @return list of keys that can be used for verification
*/
public List<Key> getVerificationKeys() {
return model.getVerificationKeys();
}
}
Loading

0 comments on commit 4ae5196

Please sign in to comment.