mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-15 17:02:06 +01:00
More cleanup and better error reporting
This commit is contained in:
parent
5f0c56f5b3
commit
a85d72f635
5 changed files with 48 additions and 15 deletions
|
@ -6,6 +6,9 @@ package org.pgpainless.decryption_verification.syntax_check;
|
||||||
|
|
||||||
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class describes the syntax for OpenPGP messages as specified by rfc4880.
|
* This class describes the syntax for OpenPGP messages as specified by rfc4880.
|
||||||
*
|
*
|
||||||
|
@ -19,7 +22,7 @@ import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
||||||
public class OpenPgpMessageSyntax implements Syntax {
|
public class OpenPgpMessageSyntax implements Syntax {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transition transition(State from, InputSymbol input, StackSymbol stackItem)
|
public @Nonnull Transition transition(@Nonnull State from, @Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException {
|
throws MalformedOpenPgpMessageException {
|
||||||
switch (from) {
|
switch (from) {
|
||||||
case OpenPgpMessage:
|
case OpenPgpMessage:
|
||||||
|
@ -37,7 +40,7 @@ public class OpenPgpMessageSyntax implements Syntax {
|
||||||
throw new MalformedOpenPgpMessageException(from, input, stackItem);
|
throw new MalformedOpenPgpMessageException(from, input, stackItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition fromOpenPgpMessage(InputSymbol input, StackSymbol stackItem)
|
Transition fromOpenPgpMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException {
|
throws MalformedOpenPgpMessageException {
|
||||||
if (stackItem != StackSymbol.msg) {
|
if (stackItem != StackSymbol.msg) {
|
||||||
throw new MalformedOpenPgpMessageException(State.OpenPgpMessage, input, stackItem);
|
throw new MalformedOpenPgpMessageException(State.OpenPgpMessage, input, stackItem);
|
||||||
|
@ -65,7 +68,7 @@ public class OpenPgpMessageSyntax implements Syntax {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition fromLiteralMessage(InputSymbol input, StackSymbol stackItem)
|
Transition fromLiteralMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException {
|
throws MalformedOpenPgpMessageException {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case Signature:
|
case Signature:
|
||||||
|
@ -84,7 +87,7 @@ public class OpenPgpMessageSyntax implements Syntax {
|
||||||
throw new MalformedOpenPgpMessageException(State.LiteralMessage, input, stackItem);
|
throw new MalformedOpenPgpMessageException(State.LiteralMessage, input, stackItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition fromCompressedMessage(InputSymbol input, StackSymbol stackItem)
|
Transition fromCompressedMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException {
|
throws MalformedOpenPgpMessageException {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case Signature:
|
case Signature:
|
||||||
|
@ -103,7 +106,7 @@ public class OpenPgpMessageSyntax implements Syntax {
|
||||||
throw new MalformedOpenPgpMessageException(State.CompressedMessage, input, stackItem);
|
throw new MalformedOpenPgpMessageException(State.CompressedMessage, input, stackItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition fromEncryptedMessage(InputSymbol input, StackSymbol stackItem)
|
Transition fromEncryptedMessage(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException {
|
throws MalformedOpenPgpMessageException {
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case Signature:
|
case Signature:
|
||||||
|
@ -122,7 +125,7 @@ public class OpenPgpMessageSyntax implements Syntax {
|
||||||
throw new MalformedOpenPgpMessageException(State.EncryptedMessage, input, stackItem);
|
throw new MalformedOpenPgpMessageException(State.EncryptedMessage, input, stackItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transition fromValid(InputSymbol input, StackSymbol stackItem)
|
Transition fromValid(@Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException {
|
throws MalformedOpenPgpMessageException {
|
||||||
// There is no applicable transition rule out of Valid
|
// There is no applicable transition rule out of Valid
|
||||||
throw new MalformedOpenPgpMessageException(State.Valid, input, stackItem);
|
throw new MalformedOpenPgpMessageException(State.Valid, input, stackItem);
|
||||||
|
|
|
@ -20,10 +20,13 @@ public class PDA {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(PDA.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(PDA.class);
|
||||||
|
|
||||||
|
// right now we implement what rfc4880 specifies.
|
||||||
|
// TODO: Consider implementing what we proposed here:
|
||||||
|
// https://mailarchive.ietf.org/arch/msg/openpgp/uepOF6XpSegMO4c59tt9e5H1i4g/
|
||||||
|
private final Syntax syntax = new OpenPgpMessageSyntax();
|
||||||
private final Stack<StackSymbol> stack = new Stack<>();
|
private final Stack<StackSymbol> stack = new Stack<>();
|
||||||
private final List<InputSymbol> inputs = new ArrayList<>(); // keep track of inputs for debugging / error reporting
|
private final List<InputSymbol> inputs = new ArrayList<>(); // Track inputs for debugging / error reporting
|
||||||
private State state;
|
private State state;
|
||||||
private Syntax syntax = new OpenPgpMessageSyntax();
|
|
||||||
|
|
||||||
public PDA() {
|
public PDA() {
|
||||||
state = State.OpenPgpMessage;
|
state = State.OpenPgpMessage;
|
||||||
|
@ -32,16 +35,20 @@ public class PDA {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void next(InputSymbol input) throws MalformedOpenPgpMessageException {
|
public void next(InputSymbol input) throws MalformedOpenPgpMessageException {
|
||||||
|
StackSymbol stackSymbol = popStack();
|
||||||
try {
|
try {
|
||||||
Transition transition = syntax.transition(state, input, popStack());
|
Transition transition = syntax.transition(state, input, stackSymbol);
|
||||||
inputs.add(input);
|
|
||||||
state = transition.getNewState();
|
state = transition.getNewState();
|
||||||
for (StackSymbol item : transition.getPushedItems()) {
|
for (StackSymbol item : transition.getPushedItems()) {
|
||||||
pushStack(item);
|
pushStack(item);
|
||||||
}
|
}
|
||||||
|
inputs.add(input);
|
||||||
} catch (MalformedOpenPgpMessageException e) {
|
} catch (MalformedOpenPgpMessageException e) {
|
||||||
MalformedOpenPgpMessageException wrapped = new MalformedOpenPgpMessageException("Malformed message: After reading stream " + Arrays.toString(inputs.toArray()) +
|
MalformedOpenPgpMessageException wrapped = new MalformedOpenPgpMessageException(
|
||||||
", token '" + input + "' is unexpected and illegal.", e);
|
"Malformed message: After reading stream " + Arrays.toString(inputs.toArray()) +
|
||||||
|
", token '" + input + "' is not allowed." +
|
||||||
|
"\nNo transition from state '" + state + "' with stack " + Arrays.toString(stack.toArray()) +
|
||||||
|
(stackSymbol != null ? "||'" + stackSymbol + "'." : "."), e);
|
||||||
LOGGER.debug("Invalid input '" + input + "'", wrapped);
|
LOGGER.debug("Invalid input '" + input + "'", wrapped);
|
||||||
throw wrapped;
|
throw wrapped;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ package org.pgpainless.decryption_verification.syntax_check;
|
||||||
|
|
||||||
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
import org.pgpainless.exception.MalformedOpenPgpMessageException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface can be used to define a custom syntax for the {@link PDA}.
|
* This interface can be used to define a custom syntax for the {@link PDA}.
|
||||||
*/
|
*/
|
||||||
|
@ -25,6 +28,6 @@ public interface Syntax {
|
||||||
* @return applicable transition rule containing the new state and pushed stack symbols
|
* @return applicable transition rule containing the new state and pushed stack symbols
|
||||||
* @throws MalformedOpenPgpMessageException if there is no applicable transition rule (the input symbol is illegal)
|
* @throws MalformedOpenPgpMessageException if there is no applicable transition rule (the input symbol is illegal)
|
||||||
*/
|
*/
|
||||||
Transition transition(State from, InputSymbol input, StackSymbol stackItem)
|
@Nonnull Transition transition(@Nonnull State from, @Nonnull InputSymbol input, @Nullable StackSymbol stackItem)
|
||||||
throws MalformedOpenPgpMessageException;
|
throws MalformedOpenPgpMessageException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,44 @@
|
||||||
|
|
||||||
package org.pgpainless.decryption_verification.syntax_check;
|
package org.pgpainless.decryption_verification.syntax_check;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result of applying a transition rule.
|
||||||
|
* Transition rules can be described by implementing the {@link Syntax} interface.
|
||||||
|
*/
|
||||||
public class Transition {
|
public class Transition {
|
||||||
|
|
||||||
private final List<StackSymbol> pushedItems = new ArrayList<>();
|
private final List<StackSymbol> pushedItems = new ArrayList<>();
|
||||||
private final State newState;
|
private final State newState;
|
||||||
|
|
||||||
public Transition(State newState, StackSymbol... pushedItems) {
|
public Transition(@Nonnull State newState, @Nonnull StackSymbol... pushedItems) {
|
||||||
this.newState = newState;
|
this.newState = newState;
|
||||||
this.pushedItems.addAll(Arrays.asList(pushedItems));
|
this.pushedItems.addAll(Arrays.asList(pushedItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the new {@link State} that is reached by applying the transition.
|
||||||
|
*
|
||||||
|
* @return new state
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
public State getNewState() {
|
public State getNewState() {
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of {@link StackSymbol StackSymbols} that are pushed onto the stack
|
||||||
|
* by applying the transition.
|
||||||
|
* The list contains items in the order in which they are pushed onto the stack.
|
||||||
|
* The list may be empty.
|
||||||
|
*
|
||||||
|
* @return list of items to be pushed onto the stack
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
public List<StackSymbol> getPushedItems() {
|
public List<StackSymbol> getPushedItems() {
|
||||||
return new ArrayList<>(pushedItems);
|
return new ArrayList<>(pushedItems);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class PDATest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncryptedMessageWithAppendedStandalongSigIsNotValid() {
|
public void testEncryptedMessageWithAppendedStandaloneSigIsNotValid() {
|
||||||
PDA check = new PDA();
|
PDA check = new PDA();
|
||||||
check.next(InputSymbol.EncryptedData);
|
check.next(InputSymbol.EncryptedData);
|
||||||
assertThrows(MalformedOpenPgpMessageException.class,
|
assertThrows(MalformedOpenPgpMessageException.class,
|
||||||
|
|
Loading…
Reference in a new issue