import org.onap.aaf.certservice.certification.CertificationModelFactory;
import org.onap.aaf.certservice.certification.CsrModelFactory;
import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64;
-import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.DecryptionException;
import org.onap.aaf.certservice.certification.model.CertificationModel;
import org.onap.aaf.certservice.certification.model.CsrModel;
-import org.onap.aaf.certservice.certification.model.ErrorResponseModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@PathVariable String caName,
@RequestHeader("CSR") String encodedCsr,
@RequestHeader("PK") String encodedPrivateKey
- ) {
+ ) throws DecryptionException {
+
caName = caName.replaceAll("[\n|\r|\t]", "_");
LOGGER.info("Received certificate signing request for CA named: {}", caName);
+ CsrModel csrModel = csrModelFactory.createCsrModel(
+ new StringBase64(encodedCsr),
+ new StringBase64(encodedPrivateKey)
+ );
+ LOGGER.debug("Received CSR meta data: \n{}", csrModel);
+ CertificationModel certificationModel = certificationModelFactory
+ .createCertificationModel(csrModel,caName);
+ return new ResponseEntity<>(new Gson().toJson(certificationModel), HttpStatus.OK);
- try {
- CsrModel csrModel = csrModelFactory.createCsrModel(
- new StringBase64(encodedCsr),
- new StringBase64(encodedPrivateKey)
- );
- LOGGER.debug("Received CSR meta data: \n{}", csrModel);
- CertificationModel certificationModel = certificationModelFactory
- .createCertificationModel(csrModel,caName);
- return new ResponseEntity<>(
- new Gson().toJson(certificationModel),
- HttpStatus.OK);
- } catch (CsrDecryptionException e) {
- LOGGER.error("Exception occurred during decoding certificate sign request:", e);
- return getErrorResponseEntity("Wrong certificate signing request (CSR) format");
- } catch (PemDecryptionException e) {
- LOGGER.error("Exception occurred during decoding key:", e);
- return getErrorResponseEntity("Wrong key (PK) format");
- }
- }
-
- private ResponseEntity<String> getErrorResponseEntity(String errorMessage) {
- ErrorResponseModel errorResponse = new ErrorResponseModel(errorMessage);
- return new ResponseEntity<>(
- new Gson().toJson(errorResponse),
- HttpStatus.BAD_REQUEST);
}
package org.onap.aaf.certservice.certification;
-import java.io.IOException;
import java.util.Base64;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.util.io.pem.PemObject;
import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.DecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
import org.onap.aaf.certservice.certification.model.CsrModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CsrModelFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(CsrModelFactory.class);
- private final PemObjectFactory pemObjectFactory = new PemObjectFactory();
+ private final PemObjectFactory pemObjectFactory
+ = new PemObjectFactory();
+ private final PKCS10CertificationRequestFactory certificationRequestFactory
+ = new PKCS10CertificationRequestFactory();
+
public CsrModel createCsrModel(StringBase64 csr, StringBase64 privateKey)
- throws CsrDecryptionException, PemDecryptionException {
+ throws DecryptionException {
LOGGER.debug("Decoded CSR: \n{}", csr);
+ PKCS10CertificationRequest decodedCsr = decodeCsr(csr);
+ PemObject decodedPrivateKey = decodePrivateKey(privateKey);
+ return new CsrModel(decodedCsr, decodedPrivateKey);
+ }
- try {
- PemObject pemObject = pemObjectFactory.createPemObject(csr.asString());
- PKCS10CertificationRequest decodedCsr = new PKCS10CertificationRequest(
- pemObject.getContent()
- );
- PemObject decodedPrivateKey = pemObjectFactory.createPemObject(privateKey.asString());
- return new CsrModel(decodedCsr, decodedPrivateKey);
- } catch (IOException e) {
- throw new CsrDecryptionException("Incorrect CSR, decryption failed", e);
- }
+ private PemObject decodePrivateKey(StringBase64 privateKey)
+ throws KeyDecryptionException {
+ return pemObjectFactory.createPemObject(privateKey.asString()).orElseThrow(
+ () -> new KeyDecryptionException("Incorrect Key, decryption failed")
+ );
+ }
+
+ private PKCS10CertificationRequest decodeCsr(StringBase64 csr)
+ throws CsrDecryptionException {
+ return pemObjectFactory.createPemObject(csr.asString())
+ .flatMap(
+ certificationRequestFactory::createKCS10CertificationRequest
+ ).orElseThrow(
+ () -> new CsrDecryptionException("Incorrect CSR, decryption failed")
+ );
}
public static class StringBase64 {
return new String(decoder.decode(value));
}
}
+
}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification;
+
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.util.io.pem.PemObject;
+
+import java.io.IOException;
+import java.util.Optional;
+
+public class PKCS10CertificationRequestFactory {
+
+ public Optional<PKCS10CertificationRequest> createKCS10CertificationRequest(PemObject pemObject) {
+ try {
+ return Optional.of(new PKCS10CertificationRequest(pemObject.getContent()));
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ }
+}
import java.io.IOException;
import java.io.StringReader;
+import java.util.Optional;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
-
public class PemObjectFactory {
- public PemObject createPemObject(String pem) throws PemDecryptionException {
+ public Optional<PemObject> createPemObject(String pem) {
try (StringReader stringReader = new StringReader(pem);
PemReader pemReader = new PemReader(stringReader)) {
- return pemReader.readPemObject();
+ return Optional.ofNullable(pemReader.readPemObject());
} catch (IOException e) {
- throw new PemDecryptionException("Unable to create PEM", e);
+ return Optional.empty();
}
}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification.exceptions;
+
+import com.google.gson.Gson;
+import org.onap.aaf.certservice.certification.model.ErrorResponseModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+@ControllerAdvice
+public class CertificationExceptionController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CertificationExceptionController.class);
+
+ @ExceptionHandler(value = CsrDecryptionException.class)
+ public ResponseEntity<String> handle(CsrDecryptionException exception) {
+ LOGGER.error("Exception occurred during decoding certificate sign request:", exception);
+ return getErrorResponseEntity("Wrong certificate signing request (CSR) format");
+ }
+
+ @ExceptionHandler(value = KeyDecryptionException.class)
+ public ResponseEntity<String> handle(KeyDecryptionException exception) {
+ LOGGER.error("Exception occurred during decoding key:", exception);
+ return getErrorResponseEntity("Wrong key (PK) format");
+ }
+
+ private ResponseEntity<String> getErrorResponseEntity(String errorMessage) {
+ ErrorResponseModel errorResponse = new ErrorResponseModel(errorMessage);
+ return new ResponseEntity<>(
+ new Gson().toJson(errorResponse),
+ HttpStatus.BAD_REQUEST
+ );
+ }
+}
public CsrDecryptionException(String message, Throwable cause) {
super(message, cause);
}
+ public CsrDecryptionException(String message) {
+ super(message);
+ }
}
public DecryptionException(String message, Throwable cause) {
super(message, cause);
}
+ public DecryptionException(String message) {
+ super(message);
+ }
}
package org.onap.aaf.certservice.certification.exceptions;
-public class PemDecryptionException extends DecryptionException {
- public PemDecryptionException(String message, Throwable cause) {
+public class KeyDecryptionException extends DecryptionException {
+ public KeyDecryptionException(String message, Throwable cause) {
super(message, cause);
}
-
+ public KeyDecryptionException(String message) {
+ super(message);
+ }
}
import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64;
import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
import org.onap.aaf.certservice.certification.exceptions.DecryptionException;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
import org.onap.aaf.certservice.certification.model.CertificationModel;
import org.onap.aaf.certservice.certification.model.CsrModel;
import org.springframework.http.HttpStatus;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
}
@Test
- void shouldReturnBadRequestWhenCreatingCsrModelFails() throws DecryptionException {
+ void shouldThrowCsrDecryptionExceptionWhenCreatingCsrModelFails() throws DecryptionException {
// given
+ String expectedMessage = "Incorrect CSR, decryption failed";
when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class)))
- .thenThrow(new CsrDecryptionException("CSR creation fail",new IOException()));
+ .thenThrow(new CsrDecryptionException(expectedMessage,new IOException()));
// when
- ResponseEntity<String> testResponse =
- certificationService.signCertificate("TestCa", "encryptedCSR", "encryptedPK");
+ Exception exception = assertThrows(
+ CsrDecryptionException.class, () -> certificationService.
+ signCertificate("TestCa", "encryptedCSR", "encryptedPK")
+ );
- String expectedMessage = "Wrong certificate signing request (CSR) format";
+ String actualMessage = exception.getMessage();
// then
- assertEquals(HttpStatus.BAD_REQUEST, testResponse.getStatusCode());
- assertTrue(
- testResponse.toString().contains(expectedMessage)
- );
-
+ assertEquals(expectedMessage, actualMessage);
}
@Test
- void shouldReturnBadRequestWhenCreatingPemModelFails() throws DecryptionException {
+ void shouldThrowPemDecryptionExceptionWhenCreatingPemModelFails() throws DecryptionException {
// given
+ String expectedMessage = "Incorrect PEM, decryption failed";
when(csrModelFactory.createCsrModel(any(StringBase64.class), any(StringBase64.class)))
- .thenThrow(new PemDecryptionException("PEM creation fail",new IOException()));
+ .thenThrow(new KeyDecryptionException(expectedMessage,new IOException()));
// when
- ResponseEntity<String> testResponse =
- certificationService.signCertificate("TestCa", "encryptedCSR", "encryptedPK");
+ Exception exception = assertThrows(
+ KeyDecryptionException.class, () -> certificationService.
+ signCertificate("TestCa", "encryptedCSR", "encryptedPK")
+ );
- String expectedMessage = "Wrong key (PK) format";
+ String actualMessage = exception.getMessage();
// then
- assertEquals(HttpStatus.BAD_REQUEST, testResponse.getStatusCode());
- assertTrue(
- testResponse.toString().contains(expectedMessage)
- );
-
+ assertEquals(expectedMessage, actualMessage);
}
}
import org.onap.aaf.certservice.certification.CsrModelFactory.StringBase64;
import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
import org.onap.aaf.certservice.certification.exceptions.DecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
import org.onap.aaf.certservice.certification.model.CsrModel;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.onap.aaf.certservice.certification.TestData.TEST_CSR;
import static org.onap.aaf.certservice.certification.TestData.TEST_PK;
import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_CSR;
+import static org.onap.aaf.certservice.certification.TestData.TEST_WRONG_PEM;
class CsrModelFactoryTest {
);
}
-
@Test
- void shouldThrowCsrDecryptionExceptionWhenCsrAreIncorrect() {
+ void shouldThrowCsrDecryptionExceptionWhenCsrIsIncorrect() {
// given
String encoderPK = new String(Base64.encode(TEST_PK.getBytes()));
String wrongCsr = new String(Base64.encode(TEST_WRONG_CSR.getBytes()));
assertTrue(actualMessage.contains(expectedMessage));
}
+ @Test
+ void shouldThrowKeyDecryptionExceptionWhenKeyIsIncorrect() {
+ // given
+ String encoderPK = new String(Base64.encode(TEST_WRONG_PEM.getBytes()));
+ String wrongCsr = new String(Base64.encode(TEST_CSR.getBytes()));
+
+ // when
+ Exception exception = assertThrows(
+ KeyDecryptionException.class, () -> csrModelFactory
+ .createCsrModel(new StringBase64(wrongCsr), new StringBase64(encoderPK))
+ );
+
+ String expectedMessage = "Incorrect Key, decryption failed";
+ String actualMessage = exception.getMessage();
+
+ // then
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
}
import org.bouncycastle.util.io.pem.PemObject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.DecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
}
@Test
- void shouldTransformStringInToPemObjectAndBackToString() throws PemDecryptionException {
+ void shouldTransformStringInToPemObjectAndBackToString() throws DecryptionException {
// when
- PemObject pemObject = pemObjectFactory.createPemObject(TEST_PEM);
+ PemObject pemObject = pemObjectFactory.createPemObject(TEST_PEM).orElseThrow(
+ () -> new DecryptionException("Pem decryption failed")
+ );
String parsedPemObject = pemObjectToString(pemObject);
// then
@Test
void shouldThrowExceptionWhenParsingPemFailed() {
+ // given
+ String expectedMessage = "Unable to create PEM";
+
// when
Exception exception = assertThrows(
- PemDecryptionException.class, () -> pemObjectFactory.createPemObject(TEST_WRONG_PEM)
+ DecryptionException.class, () -> pemObjectFactory.createPemObject(TEST_WRONG_PEM).orElseThrow(
+ () -> new DecryptionException(expectedMessage)
+ )
);
- String expectedMessage = "Unable to create PEM";
String actualMessage = exception.getMessage();
// then
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
import java.io.IOException;
import java.io.StringWriter;
private TestUtils() {
}
- public static String pemObjectToString(PemObject pemObject) throws PemDecryptionException {
+ public static String pemObjectToString(PemObject pemObject) throws KeyDecryptionException {
try (StringWriter output = new StringWriter()) {
PemWriter pemWriter = new PemWriter(output);
pemWriter.writeObject(pemObject);
return output.getBuffer().toString();
} catch (IOException e) {
- throw new PemDecryptionException("Writing PAM Object to string failed", e);
+ throw new KeyDecryptionException("Writing PAM Object to string failed", e);
}
}
}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * PROJECT
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.aaf.certservice.certification.exception;
+
+import com.google.gson.Gson;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.aaf.certservice.certification.exceptions.CertificationExceptionController;
+import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
+import org.onap.aaf.certservice.certification.model.ErrorResponseModel;
+import org.springframework.http.ResponseEntity;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CertificationExceptionControllerTest {
+
+ private CertificationExceptionController certificationExceptionController;
+
+ @BeforeEach
+ void setUp() {
+ certificationExceptionController =
+ new CertificationExceptionController();
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenCsrDecryptionException() {
+ // given
+ String expectedMessage = "Wrong certificate signing request (CSR) format";
+ CsrDecryptionException csrDecryptionException = new CsrDecryptionException("test csr exception");
+
+ // when
+ ResponseEntity<String> responseEntity = certificationExceptionController.handle(csrDecryptionException);
+
+ ErrorResponseModel response = new Gson().fromJson(responseEntity.getBody(), ErrorResponseModel.class);
+
+ // then
+ assertEquals(expectedMessage, response.getErrorMessage());
+ }
+
+ @Test
+ void shouldReturnResponseEntityWithAppropriateErrorMessageWhenGivenKeyDecryptionException() {
+ // given
+ String expectedMessage = "Wrong key (PK) format";
+ KeyDecryptionException csrDecryptionException = new KeyDecryptionException("test pk exception");
+
+ // when
+ ResponseEntity<String> responseEntity = certificationExceptionController.handle(csrDecryptionException);
+
+ ErrorResponseModel response = new Gson().fromJson(responseEntity.getBody(), ErrorResponseModel.class);
+
+ // then
+ assertEquals(expectedMessage, response.getErrorMessage());
+ }
+
+}
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.util.io.pem.PemObject;
import org.junit.jupiter.api.Test;
+import org.onap.aaf.certservice.certification.PKCS10CertificationRequestFactory;
import org.onap.aaf.certservice.certification.PemObjectFactory;
import org.onap.aaf.certservice.certification.exceptions.CsrDecryptionException;
import org.onap.aaf.certservice.certification.exceptions.DecryptionException;
-import org.onap.aaf.certservice.certification.exceptions.PemDecryptionException;
+import org.onap.aaf.certservice.certification.exceptions.KeyDecryptionException;
import java.io.IOException;
class CsrModelTest {
-
+ private final PKCS10CertificationRequestFactory certificationRequestFactory
+ = new PKCS10CertificationRequestFactory();
+ private final PemObjectFactory pemObjectFactory
+ = new PemObjectFactory();
@Test
void shouldByConstructedAndReturnProperFields() throws DecryptionException, IOException {
// given
}
@Test
- void shouldThrowExceptionWhenKeyIsNotCorrect() throws PemDecryptionException ,IOException {
+ void shouldThrowExceptionWhenPublicKeyIsNotCorrect() throws KeyDecryptionException, IOException {
// given
PemObjectFactory pemObjectFactory = new PemObjectFactory();
PKCS10CertificationRequest testCsr = mock(PKCS10CertificationRequest.class);
.thenReturn(wrongKryInfo);
when(wrongKryInfo.getEncoded())
.thenThrow(new IOException());
- PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK);
+ PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow(
+ () -> new KeyDecryptionException("Private key decoding fail")
+ );
CsrModel csrModel = new CsrModel(testCsr, testPrivateKey);
// when
assertTrue(actualMessage.contains(expectedMessage));
}
- private CsrModel generateTestCsrModel() throws PemDecryptionException, IOException {
- PemObjectFactory pemObjectFactory = new PemObjectFactory();
- PKCS10CertificationRequest testCsr = new PKCS10CertificationRequest(
- pemObjectFactory.createPemObject(TEST_CSR).getContent()
+ private CsrModel generateTestCsrModel() throws DecryptionException {
+ PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK).orElseThrow(
+ () -> new DecryptionException("Incorrect Private Key, decryption failed")
);
- PemObject testPrivateKey = pemObjectFactory.createPemObject(TEST_PK);
+ PKCS10CertificationRequest testCsr = generateTestCertificationRequest();
return new CsrModel(testCsr, testPrivateKey);
}
- private PemObject generateTestPublicKey() throws PemDecryptionException, IOException {
- PemObjectFactory pemObjectFactory = new PemObjectFactory();
- PKCS10CertificationRequest testCsr = new PKCS10CertificationRequest(
- pemObjectFactory.createPemObject(TEST_CSR).getContent()
- );
+ private PemObject generateTestPublicKey() throws DecryptionException, IOException {
+ PKCS10CertificationRequest testCsr = generateTestCertificationRequest();
return new PemObject("PUBLIC KEY", testCsr.getSubjectPublicKeyInfo().getEncoded());
}
+
+ private PKCS10CertificationRequest generateTestCertificationRequest() throws DecryptionException {
+ return pemObjectFactory.createPemObject(TEST_CSR)
+ .flatMap(
+ certificationRequestFactory::createKCS10CertificationRequest
+ ).orElseThrow(
+ () -> new DecryptionException("Incorrect CSR, decryption failed")
+ );
+ }
+
}