From 7e2c89b1b36d79694a74cdbc7a413694eb7a9843 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 20 May 2021 12:40:12 +0200 Subject: [PATCH] Trim passphrases --- .../java/org/pgpainless/util/Passphrase.java | 43 ++++++++++++++++++- .../key/protection/PassphraseTest.java | 31 +++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/util/Passphrase.java b/pgpainless-core/src/main/java/org/pgpainless/util/Passphrase.java index 6aa89e91..31bb867e 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/util/Passphrase.java +++ b/pgpainless-core/src/main/java/org/pgpainless/util/Passphrase.java @@ -32,7 +32,48 @@ public class Passphrase { * @param chars may be null for empty passwords. */ public Passphrase(@Nullable char[] chars) { - this.chars = chars; + if (chars == null) { + this.chars = null; + } else { + char[] trimmed = removeTrailingAndLeadingWhitespace(chars); + if (trimmed.length == 0) { + this.chars = null; + } else { + this.chars = trimmed; + } + } + } + + /** + * Return a copy of the passed in char array, with leading and trailing whitespace characters removed. + * + * @param chars char array + * @return copy of char array with leading and trailing whitespace characters removed + */ + private static char[] removeTrailingAndLeadingWhitespace(char[] chars) { + int i = 0; + while (i < chars.length && isWhitespace(chars[i])) { + i++; + } + int j = chars.length - 1; + while (j >= i && isWhitespace(chars[j])) { + j--; + } + + char[] trimmed = new char[chars.length - i - (chars.length - 1 - j)]; + System.arraycopy(chars, i, trimmed, 0, trimmed.length); + + return trimmed; + } + + /** + * Return true, if the passed in char is a whitespace symbol (space, newline, tab). + * + * @param xar char + * @return true if whitespace + */ + private static boolean isWhitespace(char xar) { + return xar == ' ' || xar == '\n' || xar == '\t'; } /** diff --git a/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseTest.java b/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseTest.java index 637162c6..1aa1b80c 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/key/protection/PassphraseTest.java @@ -17,6 +17,7 @@ package org.pgpainless.key.protection; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -37,4 +38,34 @@ public class PassphraseTest { assertFalse(passphrase.isValid()); assertThrows(IllegalStateException.class, passphrase::getChars); } + + @Test + public void testTrimming() { + Passphrase leadingSpace = Passphrase.fromPassword(" space"); + assertArrayEquals("space".toCharArray(), leadingSpace.getChars()); + assertFalse(leadingSpace.isEmpty()); + + Passphrase trailingSpace = Passphrase.fromPassword("space "); + assertArrayEquals("space".toCharArray(), trailingSpace.getChars()); + assertFalse(trailingSpace.isEmpty()); + + Passphrase leadingTrailingWhitespace = new Passphrase("\t Such whitespace, much wow\n ".toCharArray()); + assertArrayEquals("Such whitespace, much wow".toCharArray(), leadingTrailingWhitespace.getChars()); + assertFalse(leadingTrailingWhitespace.isEmpty()); + + Passphrase fromEmptyChars = new Passphrase(" ".toCharArray()); + assertNull(fromEmptyChars.getChars()); + assertTrue(fromEmptyChars.isEmpty()); + } + + @Test + public void testEmptyPassphrase() { + Passphrase empty = Passphrase.emptyPassphrase(); + assertNull(empty.getChars()); + assertTrue(empty.isEmpty()); + + Passphrase trimmedEmpty = Passphrase.fromPassword(" "); + assertNull(trimmedEmpty.getChars()); + assertTrue(trimmedEmpty.isEmpty()); + } }