Merge Fix Flaky Crypto Tests
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'security-nullability'
|
id 'security-nullability'
|
||||||
|
id 'java-test-fixtures'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'io.spring.convention.spring-module'
|
apply plugin: 'io.spring.convention.spring-module'
|
||||||
@@ -10,6 +11,8 @@ dependencies {
|
|||||||
optional 'org.bouncycastle:bcpkix-jdk18on'
|
optional 'org.bouncycastle:bcpkix-jdk18on'
|
||||||
optional libs.com.password4j.password4j
|
optional libs.com.password4j.password4j
|
||||||
|
|
||||||
|
testFixturesImplementation "org.assertj:assertj-core"
|
||||||
|
|
||||||
testImplementation "org.assertj:assertj-core"
|
testImplementation "org.assertj:assertj-core"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-present the original author or authors.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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 org.springframework.security.crypto.assertions;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link CryptoAssertions} and {@link CryptoStringAssert}.
|
||||||
|
*/
|
||||||
|
class CryptoAssertionsTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void doesNotDecryptToPassesWhenSupplierThrows() {
|
||||||
|
CryptoAssertions.assertThat((() -> {
|
||||||
|
throw new RuntimeException("decrypt failed");
|
||||||
|
})).doesNotDecryptTo("any");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void doesNotDecryptToPassesWhenResultDiffersFromExpected() {
|
||||||
|
CryptoAssertions.assertThat(() -> "other").doesNotDecryptTo("plaintext");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void doesNotDecryptToFailsWhenResultEqualsExpected() {
|
||||||
|
assertThatExceptionOfType(AssertionError.class)
|
||||||
|
.isThrownBy(() -> CryptoAssertions.assertThat(() -> "plaintext").doesNotDecryptTo("plaintext"))
|
||||||
|
.withMessageContaining("Expected supplier not to return <plaintext> but it did");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+8
-4
@@ -22,8 +22,9 @@ import java.security.interfaces.RSAPublicKey;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.security.crypto.assertions.CryptoAssertions;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
@@ -86,13 +87,15 @@ public class RsaSecretEncryptorTests {
|
|||||||
@Test
|
@Test
|
||||||
public void roundTripWithMixedAlgorithm() {
|
public void roundTripWithMixedAlgorithm() {
|
||||||
RsaSecretEncryptor oaep = new RsaSecretEncryptor(RsaAlgorithm.OAEP);
|
RsaSecretEncryptor oaep = new RsaSecretEncryptor(RsaAlgorithm.OAEP);
|
||||||
assertThatIllegalStateException().isThrownBy(() -> oaep.decrypt(this.encryptor.encrypt("encryptor")));
|
CryptoAssertions.assertThat(() -> oaep.decrypt(this.encryptor.encrypt("encryptor")))
|
||||||
|
.doesNotDecryptTo("encryptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void roundTripWithMixedSalt() {
|
public void roundTripWithMixedSalt() {
|
||||||
RsaSecretEncryptor other = new RsaSecretEncryptor(this.encryptor.getPublicKey(), RsaAlgorithm.DEFAULT, "salt");
|
RsaSecretEncryptor other = new RsaSecretEncryptor(this.encryptor.getPublicKey(), RsaAlgorithm.DEFAULT, "salt");
|
||||||
assertThatIllegalStateException().isThrownBy(() -> this.encryptor.decrypt(other.encrypt("encryptor")));
|
CryptoAssertions.assertThat(() -> this.encryptor.decrypt(other.encrypt("encryptor")))
|
||||||
|
.doesNotDecryptTo("encryptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -106,7 +109,8 @@ public class RsaSecretEncryptorTests {
|
|||||||
public void publicKeyCannotDecrypt() {
|
public void publicKeyCannotDecrypt() {
|
||||||
RsaSecretEncryptor encryptor = new RsaSecretEncryptor(this.encryptor.getPublicKey());
|
RsaSecretEncryptor encryptor = new RsaSecretEncryptor(this.encryptor.getPublicKey());
|
||||||
assertThat(encryptor.canDecrypt()).as("Encryptor schould not be able to decrypt").isFalse();
|
assertThat(encryptor.canDecrypt()).as("Encryptor schould not be able to decrypt").isFalse();
|
||||||
assertThatIllegalStateException().isThrownBy(() -> encryptor.decrypt(encryptor.encrypt("encryptor")));
|
CryptoAssertions.assertThat(() -> encryptor.decrypt(encryptor.encrypt("encryptor")))
|
||||||
|
.doesNotDecryptTo("encryptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-present the original author or authors.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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 org.springframework.security.crypto.assertions;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AssertJ entry point for crypto-related assertions. Use {@link #assertThat(Supplier)} to
|
||||||
|
* assert on a {@link Supplier}<{@link String}> (e.g. a decryption lambda).
|
||||||
|
* <p>
|
||||||
|
* Example: <pre>
|
||||||
|
* assertThat(() -> encryptor.decrypt(ciphertext)).doesNotDecryptTo("plaintext");
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class CryptoAssertions {
|
||||||
|
|
||||||
|
private CryptoAssertions() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create assertions for the given supplier (e.g. a decryption expression).
|
||||||
|
* @param actual the supplier to assert on
|
||||||
|
* @return assertion object with methods like
|
||||||
|
* {@link CryptoStringAssert#doesNotDecryptTo(String)}
|
||||||
|
*/
|
||||||
|
public static CryptoStringAssert assertThat(Supplier<String> actual) {
|
||||||
|
return new CryptoStringAssert(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-present the original author or authors.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* https://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 org.springframework.security.crypto.assertions;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.assertj.core.api.AbstractObjectAssert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AssertJ assertion for {@link Supplier}<{@link String}>, supporting
|
||||||
|
* decryption-related checks such as {@link #doesNotDecryptTo(String)}.
|
||||||
|
*/
|
||||||
|
public final class CryptoStringAssert extends AbstractObjectAssert<CryptoStringAssert, Supplier<String>> {
|
||||||
|
|
||||||
|
CryptoStringAssert(Supplier<String> actual) {
|
||||||
|
super(actual, CryptoStringAssert.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that either the supplier throws an exception when invoked, or the value it
|
||||||
|
* returns is not equal to the given string. Use this to assert that a decryption
|
||||||
|
* attempt does not yield a specific plaintext (e.g. wrong key or tampered
|
||||||
|
* ciphertext).
|
||||||
|
* @param expected the value that the supplier must not return
|
||||||
|
* @return this assertion for chaining
|
||||||
|
*/
|
||||||
|
public CryptoStringAssert doesNotDecryptTo(String expected) {
|
||||||
|
isNotNull();
|
||||||
|
try {
|
||||||
|
String result = this.actual.get();
|
||||||
|
if (Objects.equals(result, expected)) {
|
||||||
|
failWithMessage("Expected supplier not to return <%s> but it did", expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
// Exception thrown: supplier does not "decrypt to" the expected value
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user