diff --git a/whois-nrtm4-client/pom.xml b/whois-nrtm4-client/pom.xml
index 81c43d28b2..a30f61ca84 100644
--- a/whois-nrtm4-client/pom.xml
+++ b/whois-nrtm4-client/pom.xml
@@ -50,6 +50,16 @@
+
+
+ com.nimbusds
+ nimbus-jose-jwt
+
+
+ com.google.crypto.tink
+ tink
+
+
net.ripe.db
diff --git a/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/client/NrtmRestClient.java b/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/client/NrtmRestClient.java
index e08b8e76c6..1178427bf1 100644
--- a/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/client/NrtmRestClient.java
+++ b/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/client/NrtmRestClient.java
@@ -79,17 +79,17 @@ public List getNrtmAvailableSources(){
}
}
- public UpdateNotificationFileResponse getNotificationFile(final String source){
+ public String getNotificationFileSignature(final String source){
return client.target(String.format("%s/%s", baseUrl, source))
- .path("update-notification-file.json")
- .request(MediaType.APPLICATION_JSON_TYPE)
- .get(UpdateNotificationFileResponse.class);
+ .path("update-notification-file.jose")
+ .request("application/jose+json")
+ .get(String.class);
}
@Nullable
public byte[] getSnapshotFile(final String url){
try {
- final Response response = client.target(url)
+ final Response response = client.target(String.format("%s/%s", baseUrl, url))
.request(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeader.X_FORWARDED_PROTO.asString(), HttpScheme.HTTPS.asString())
.get(Response.class);
diff --git a/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessor.java b/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessor.java
index ef0796eeb1..a7eb6a41ce 100644
--- a/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessor.java
+++ b/whois-nrtm4-client/src/main/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessor.java
@@ -1,5 +1,12 @@
package net.ripe.db.nrtm4.client.processor;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSObject;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.Ed25519Verifier;
+import com.nimbusds.jose.jwk.OctetKeyPair;
import net.ripe.db.nrtm4.client.client.NrtmRestClient;
import net.ripe.db.nrtm4.client.client.UpdateNotificationFileResponse;
import net.ripe.db.nrtm4.client.condition.Nrtm4ClientCondition;
@@ -12,6 +19,11 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import javax.annotation.Nullable;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -28,6 +40,8 @@ public class UpdateNotificationFileProcessor {
private final SnapshotImporter snapshotImporter;
+ private final static String PUBLIC_KEY_PATH = "public.key";
+
public UpdateNotificationFileProcessor(final NrtmRestClient nrtmRestClient,
final Nrtm4ClientMirrorRepository nrtm4ClientMirrorDao,
final SnapshotImporter snapshotImporter) {
@@ -38,25 +52,41 @@ public UpdateNotificationFileProcessor(final NrtmRestClient nrtmRestClient,
@Transactional(rollbackFor = Exception.class)
public void processFile(){
- final Map notificationFilePerSource =
+ final Map notificationFilePerSource =
nrtmRestClient.getNrtmAvailableSources()
.stream()
.collect(Collectors.toMap(
string -> string,
- nrtmRestClient::getNotificationFile
+ nrtmRestClient::getNotificationFileSignature
));
LOGGER.info("Succeeded to read notification files from {}", notificationFilePerSource.keySet());
final List nrtmLastVersionInfoPerSource = nrtm4ClientMirrorDao.getNrtmLastVersionInfoForUpdateNotificationFile();
- //TODO: [MH] Review integrity of the data checking the signature using the public key
-
- notificationFilePerSource.forEach((source, updateNotificationFile) -> {
+ notificationFilePerSource.forEach((source, updateNotificationSignature) -> {
final NrtmClientVersionInfo nrtmClientLastVersionInfo = nrtmLastVersionInfoPerSource
.stream()
.filter(nrtmVersionInfo -> nrtmVersionInfo.source() != null && nrtmVersionInfo.source().equals(source))
.findFirst()
.orElse(null);
+ final JWSObject jwsObjectParsed;
+ try {
+ jwsObjectParsed = JWSObject.parse(updateNotificationSignature);
+ } catch (ParseException e) {
+ return;
+ }
+
+ if (!isCorrectSignature(jwsObjectParsed)){
+ LOGGER.error("Update Notification File not corrected signed for {} source", source);
+ return;
+ }
+
+ final UpdateNotificationFileResponse updateNotificationFile = getUpdateNotificationFileResponse(jwsObjectParsed);
+
+ if (updateNotificationFile == null){
+ return;
+ }
+
if (nrtmClientLastVersionInfo != null && !nrtmClientLastVersionInfo.sessionID().equals(updateNotificationFile.getSessionID())){
LOGGER.info("Different session");
snapshotImporter.initializeNRTMClientForSource(source, updateNotificationFile);
@@ -83,4 +113,42 @@ public void processFile(){
});
}
+
+ @Nullable
+ private UpdateNotificationFileResponse getUpdateNotificationFileResponse(final JWSObject jwsObjectParsed) {
+ try {
+ String payloadJson = jwsObjectParsed.getPayload().toString();
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.readValue(payloadJson, UpdateNotificationFileResponse.class);
+ } catch (JsonProcessingException ex){
+ LOGGER.error("Unable to get the update notification file from the signature");
+ return null;
+ }
+ }
+
+ private boolean isCorrectSignature(final JWSObject jwsObjectParsed) {
+ try {
+ final OctetKeyPair parsedPublicKey = OctetKeyPair.parse(readPublicKey());
+
+ final JWSVerifier verifier = new Ed25519Verifier(parsedPublicKey);
+ return jwsObjectParsed.verify(verifier);
+ } catch (JOSEException | ParseException ex) {
+ LOGGER.error("failed to verify signature {}", ex.getMessage());
+ return false;
+ }
+ }
+
+ private static String readPublicKey() {
+ try {
+ try (InputStream inputStream = UpdateNotificationFileProcessor.class.getClassLoader().getResourceAsStream(PUBLIC_KEY_PATH)) {
+ if (inputStream == null) {
+ throw new FileNotFoundException("Public key file not found in resources: " + PUBLIC_KEY_PATH);
+ }
+ return new String(inputStream.readAllBytes());
+ }
+ } catch (IOException ex){
+ throw new IllegalStateException("Public key file not found in resources: " + PUBLIC_KEY_PATH);
+ }
+ }
+
}
diff --git a/whois-nrtm4-client/src/main/resources/public.key b/whois-nrtm4-client/src/main/resources/public.key
new file mode 100644
index 0000000000..6cea2917ad
--- /dev/null
+++ b/whois-nrtm4-client/src/main/resources/public.key
@@ -0,0 +1 @@
+{"kty":"OKP","crv":"Ed25519","kid":"a9ddf4a5-0ca0-47b1-a80d-3c63fd5c19c5","x":"ry9yLgcy1eUNX1lDs852mmUXRoy4qZW1HSOu54qBCHI"}
\ No newline at end of file
diff --git a/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/AbstractNrtmClientIntegrationTest.java b/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/AbstractNrtmClientIntegrationTest.java
index 9d64f27d12..cac266a927 100644
--- a/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/AbstractNrtmClientIntegrationTest.java
+++ b/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/AbstractNrtmClientIntegrationTest.java
@@ -48,6 +48,7 @@ public void reset(){
@BeforeAll
public static void setUp(){
System.setProperty("nrtm4.client.enabled", "true");
+
}
@AfterAll
diff --git a/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/NrtmServerDummy.java b/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/NrtmServerDummy.java
index c5d965ba43..f33b6390f6 100644
--- a/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/NrtmServerDummy.java
+++ b/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/NrtmServerDummy.java
@@ -1,6 +1,14 @@
package net.ripe.db.nrtm4.client;
import com.google.common.io.Resources;
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSObject;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.Payload;
+import com.nimbusds.jose.crypto.Ed25519Signer;
+import com.nimbusds.jose.jwk.OctetKeyPair;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.servlet.http.HttpServletRequest;
@@ -28,6 +36,7 @@
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
@@ -57,13 +66,13 @@ public class NrtmServerDummy implements Stub {
"version": 1,
"snapshot": {
"version": 1,
- "url": "http://localhost:%s/nrtmv4/RIPE/nrtm-snapshot.4.RIPE.4521174b-548f-4e51-98fc-dfd720011a0c.82542bd048e111fe57db404d08b6433e.json.gz",
+ "url": "RIPE/nrtm-snapshot.4.RIPE.4521174b-548f-4e51-98fc-dfd720011a0c.82542bd048e111fe57db404d08b6433e.json.gz",
"hash": "%s"
},
"deltas": [
{
"version": 1,
- "url": "http://localhost:%s/nrtmv4/RIPE/nrtm-delta.4.RIPE.4521174b-548f-4e51-98fc-dfd720011a0c.e3be41ff312010046b67d099faa58f44.json",
+ "url": "RIPE/nrtm-delta.4.RIPE.4521174b-548f-4e51-98fc-dfd720011a0c.e3be41ff312010046b67d099faa58f44.json",
"hash": "c50dd7554cb35ef5f2f45d7bfa09fc51033cbe1152d29b36cb1178319e22be3e"
}
]
@@ -80,7 +89,7 @@ public class NrtmServerDummy implements Stub {
"version": 1,
"snapshot": {
"version": 1,
- "url": "http://localhost:%s/nrtmv4/RIPE-NONAUTH/nrtm-snapshot.1.RIPE-NONAUTH.6328095e-7d46-415b-9333-8f2ae274b7c8.f1195bb8a666fe7b97fa74009a70cefa.json.gz",
+ "url": "RIPE-NONAUTH/nrtm-snapshot.1.RIPE-NONAUTH.6328095e-7d46-415b-9333-8f2ae274b7c8.f1195bb8a666fe7b97fa74009a70cefa.json.gz",
"hash": "%s"
},
"deltas": []
@@ -155,21 +164,29 @@ public void resetDefaultMocks(){
public void setFakeHashMocks(){
mocks.clear();
mocks.add(new NrtmResponseMock("/nrtmv4", "nrtm-sources.html", "application/html"));
- mocks.add(new NrtmResponseMock("/nrtmv4/RIPE-NONAUTH/update-notification-file.json", getFakeUpdateNotificationNonAuthResponse(), "application/json"));
- mocks.add(new NrtmResponseMock("/nrtmv4/RIPE/update-notification-file.json", getFakeUpdateNotificationRipeResponse(), "application/json"));
+ mocks.add(new NrtmResponseMock("/nrtmv4/RIPE/update-notification-file.jose", "fake-nrtm-RIPE-signature.jose", "application/jose+json"));
+ mocks.add(new NrtmResponseMock("/nrtmv4/RIPE-NONAUTH/update-notification-file.jose", "fake-nrtm-RIPE-NONAUTH-signature.jose", "application/jose+json"));
mocks.add(new NrtmCompressedResponseMock("/nrtmv4/RIPE-NONAUTH/nrtm-snapshot.1.RIPE-NONAUTH.6328095e-7d46-415b-9333-8f2ae274b7c8.f1195bb8a666fe7b97fa74009a70cefa.json.gz", "nrtm-snapshot.1.RIPE-NONAUTH.json"));
mocks.add(new NrtmCompressedResponseMock("/nrtmv4/RIPE/nrtm-snapshot.4.RIPE.4521174b-548f-4e51-98fc-dfd720011a0c.82542bd048e111fe57db404d08b6433e.json.gz", "nrtm-snapshot.1.RIPE.json"));
}
+ public void setWrongSignedUNF(){
+ mocks.clear();
+ mocks.add(new NrtmResponseMock("/nrtmv4", "nrtm-sources.html", "application/html"));
+ mocks.add(new NrtmResponseMock("/nrtmv4/RIPE/update-notification-file.jose", "nrtm-RIPE-wrong-signature.jose", "application/jose+json"));
+ mocks.add(new NrtmResponseMock("/nrtmv4/RIPE-NONAUTH/update-notification-file.jose", "nrtm-RIPE-NONAUTH-wrong-signature.jose", "application/jose+json"));
+ }
+
private void initialiseMocks() {
mocks.add(new NrtmResponseMock("/nrtmv4", "nrtm-sources.html", "application/html"));
- mocks.add(new NrtmResponseMock("/nrtmv4/RIPE-NONAUTH/update-notification-file.json", getUpdateNotificationFileNonAuthResponse(), "application/json"));
- mocks.add(new NrtmResponseMock("/nrtmv4/RIPE/update-notification-file.json", getUpdateNotificationFileRipeResponse(), "application/json"));
+ mocks.add(new NrtmResponseMock("/nrtmv4/RIPE/update-notification-file.jose", "nrtm-RIPE-signature.jose", "application/jose+json"));
+ mocks.add(new NrtmResponseMock("/nrtmv4/RIPE-NONAUTH/update-notification-file.jose", "nrtm-RIPE-NONAUTH-signature.jose", "application/jose+json"));
mocks.add(new NrtmCompressedResponseMock("/nrtmv4/RIPE-NONAUTH/nrtm-snapshot.1.RIPE-NONAUTH.6328095e-7d46-415b-9333-8f2ae274b7c8.f1195bb8a666fe7b97fa74009a70cefa.json.gz", "nrtm-snapshot.1.RIPE-NONAUTH.json"));
mocks.add(new NrtmCompressedResponseMock("/nrtmv4/RIPE/nrtm-snapshot.4.RIPE.4521174b-548f-4e51-98fc-dfd720011a0c.82542bd048e111fe57db404d08b6433e.json.gz", "nrtm-snapshot.1.RIPE.json"));
}
+
private interface Mock {
String PATH = "mock/";
@@ -261,20 +278,4 @@ public Object response() {
return response;
}
}
-
- private String getFakeUpdateNotificationRipeResponse(){
- return String.format(unfRipeTemplate, port, "fake_hash", port);
- }
-
- private String getFakeUpdateNotificationNonAuthResponse(){
- return String.format(unfRipeNonAuthTemplate, port, "fake_hash");
- }
-
- private String getUpdateNotificationFileRipeResponse(){
- return String.format(unfRipeTemplate, port, "b293e92997d3be7a5156fdca832af378c3989b2cefa9e3e37caaeeba0ca971e9", port);
- }
-
- private String getUpdateNotificationFileNonAuthResponse(){
- return String.format(unfRipeNonAuthTemplate, port, "148c3c411b8f044f5fc0ab201f6dd03e80c862e27ad1a63488aee337dc7eb4a2");
- }
}
diff --git a/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessorTestIntegration.java b/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessorTestIntegration.java
index a51d30dc13..a8fb367ea6 100644
--- a/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessorTestIntegration.java
+++ b/whois-nrtm4-client/src/test/java/net/ripe/db/nrtm4/client/processor/UpdateNotificationFileProcessorTestIntegration.java
@@ -72,6 +72,15 @@ public void UNF_with_different_hash_then_no_snapshot(){
assertThat(snapshotVersionPerSource, is(empty()));
}
+ @Test
+ public void wrongly_signed_UNF_then_no_UNF_added(){
+ nrtmServerDummy.setWrongSignedUNF();
+ updateNotificationFileProcessor.processFile();
+
+ final List versionInfosPerSource = nrtm4ClientMirrorRepository.getNrtmLastVersionInfoForUpdateNotificationFile();
+ assertThat(versionInfosPerSource, is(empty()));
+ }
+
@Test
public void process_UNF_but_DB_Ahead_Then_ReInitialize(){
// TODO: [MH] Re-initialize
diff --git a/whois-nrtm4-client/src/test/resources/mock/fake-nrtm-RIPE-NONAUTH-signature.jose b/whois-nrtm4-client/src/test/resources/mock/fake-nrtm-RIPE-NONAUTH-signature.jose
new file mode 100644
index 0000000000..38c331c7d2
--- /dev/null
+++ b/whois-nrtm4-client/src/test/resources/mock/fake-nrtm-RIPE-NONAUTH-signature.jose
@@ -0,0 +1 @@
+eyJraWQiOiJhOWRkZjRhNS0wY2EwLTQ3YjEtYTgwZC0zYzYzZmQ1YzE5YzUiLCJhbGciOiJFZDI1NTE5In0.ewogICJucnRtX3ZlcnNpb24iOiAxLAogICJ0aW1lc3RhbXAiOiAiMjAyNC0xMC0yNFQxMzoyMDowMFoiLAogICJ0eXBlIjogIm5vdGlmaWNhdGlvbiIsCiAgInNvdXJjZSI6ICJSSVBFLU5PTkFVVEgiLAogICJzZXNzaW9uX2lkIjogIjYzMjgwOTVlLTdkNDYtNDE1Yi05MzMzLThmMmFlMjc0YjdjOCIsCiAgInZlcnNpb24iOiAxLAogICJzbmFwc2hvdCI6IHsKICAgICJ2ZXJzaW9uIjogMSwKICAgICJ1cmwiOiAiUklQRS1OT05BVVRIL25ydG0tc25hcHNob3QuMS5SSVBFLU5PTkFVVEguNjMyODA5NWUtN2Q0Ni00MTViLTkzMzMtOGYyYWUyNzRiN2M4LmYxMTk1YmI4YTY2NmZlN2I5N2ZhNzQwMDlhNzBjZWZhLmpzb24uZ3oiLAogICAgImhhc2giOiAiZmFrZV9oYXNoIgogIH0sCiAgImRlbHRhcyI6IFtdCn0K.ByryeIsmJSVpuHg0nGnn06VsufJ60wdO5UHHiWjm_FzAThtAICZ8uiUkeiNDmrp0fpRWapH5CeTlxhdCfMqwDg
\ No newline at end of file
diff --git a/whois-nrtm4-client/src/test/resources/mock/fake-nrtm-RIPE-signature.jose b/whois-nrtm4-client/src/test/resources/mock/fake-nrtm-RIPE-signature.jose
new file mode 100644
index 0000000000..83b3084c5a
--- /dev/null
+++ b/whois-nrtm4-client/src/test/resources/mock/fake-nrtm-RIPE-signature.jose
@@ -0,0 +1 @@
+eyJraWQiOiJhOWRkZjRhNS0wY2EwLTQ3YjEtYTgwZC0zYzYzZmQ1YzE5YzUiLCJhbGciOiJFZDI1NTE5In0.ewogICJucnRtX3ZlcnNpb24iOiA0LAogICJ0aW1lc3RhbXAiOiAiMjAyNC0xMC0yNVQwMDowNzowMFoiLAogICJ0eXBlIjogIm5vdGlmaWNhdGlvbiIsCiAgInNvdXJjZSI6ICJSSVBFIiwKICAic2Vzc2lvbl9pZCI6ICI0NTIxMTc0Yi01NDhmLTRlNTEtOThmYy1kZmQ3MjAwMTFhMGMiLAogICJ2ZXJzaW9uIjogMSwKICAic25hcHNob3QiOiB7CiAgICAidmVyc2lvbiI6IDEsCiAgICAidXJsIjogIlJJUEUvbnJ0bS1zbmFwc2hvdC40LlJJUEUuNDUyMTE3NGItNTQ4Zi00ZTUxLTk4ZmMtZGZkNzIwMDExYTBjLjgyNTQyYmQwNDhlMTExZmU1N2RiNDA0ZDA4YjY0MzNlLmpzb24uZ3oiLAogICAgImhhc2giOiAiZmFrZV9oYXNoIgogIH0sCiAgImRlbHRhcyI6IFsKICAgIHsKICAgICAgInZlcnNpb24iOiAxLAogICAgICAidXJsIjogIlJJUEUvbnJ0bS1kZWx0YS40LlJJUEUuNDUyMTE3NGItNTQ4Zi00ZTUxLTk4ZmMtZGZkNzIwMDExYTBjLmUzYmU0MWZmMzEyMDEwMDQ2YjY3ZDA5OWZhYTU4ZjQ0Lmpzb24iLAogICAgICAiaGFzaCI6ICJjNTBkZDc1NTRjYjM1ZWY1ZjJmNDVkN2JmYTA5ZmM1MTAzM2NiZTExNTJkMjliMzZjYjExNzgzMTllMjJiZTNlIgogICAgfQogIF0KfQo.FleGXqvep1AmVmnn3Hk9oU0eGNEOtE8vEY19tKVdpJMSHAijOtzWcyasVI1vHA3vGxj7jaxqm-l3LnG6ZoyDAw
\ No newline at end of file
diff --git a/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-NONAUTH-signature.jose b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-NONAUTH-signature.jose
new file mode 100644
index 0000000000..f47af5594e
--- /dev/null
+++ b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-NONAUTH-signature.jose
@@ -0,0 +1 @@
+eyJraWQiOiJhOWRkZjRhNS0wY2EwLTQ3YjEtYTgwZC0zYzYzZmQ1YzE5YzUiLCJhbGciOiJFZDI1NTE5In0.ewogICJucnRtX3ZlcnNpb24iOiAxLAogICJ0aW1lc3RhbXAiOiAiMjAyNC0xMC0yNFQxMzoyMDowMFoiLAogICJ0eXBlIjogIm5vdGlmaWNhdGlvbiIsCiAgInNvdXJjZSI6ICJSSVBFLU5PTkFVVEgiLAogICJzZXNzaW9uX2lkIjogIjYzMjgwOTVlLTdkNDYtNDE1Yi05MzMzLThmMmFlMjc0YjdjOCIsCiAgInZlcnNpb24iOiAxLAogICJzbmFwc2hvdCI6IHsKICAgICJ2ZXJzaW9uIjogMSwKICAgICJ1cmwiOiAiUklQRS1OT05BVVRIL25ydG0tc25hcHNob3QuMS5SSVBFLU5PTkFVVEguNjMyODA5NWUtN2Q0Ni00MTViLTkzMzMtOGYyYWUyNzRiN2M4LmYxMTk1YmI4YTY2NmZlN2I5N2ZhNzQwMDlhNzBjZWZhLmpzb24uZ3oiLAogICAgImhhc2giOiAiMTQ4YzNjNDExYjhmMDQ0ZjVmYzBhYjIwMWY2ZGQwM2U4MGM4NjJlMjdhZDFhNjM0ODhhZWUzMzdkYzdlYjRhMiIKICB9LAogICJkZWx0YXMiOiBbXQp9Cg.AGsn3z7Yd_-unMprcjUMB5nBkqdPrQuiC2C494Joz7CoGxfJEc9zWsVQ28nlK3GJVwMtSBCWP8msPEV_lX_lCg
\ No newline at end of file
diff --git a/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-NONAUTH-wrong-signature.jose b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-NONAUTH-wrong-signature.jose
new file mode 100644
index 0000000000..363e644a9b
--- /dev/null
+++ b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-NONAUTH-wrong-signature.jose
@@ -0,0 +1 @@
+eyJraWQiOiJhOWRkZjRhNS0wY2EwLTQ3YjEtYTgwZC0zYzYzZmQ1YzE5YzUiLCJhbGciOiJFZDI1NTE5In0.ewogICJucnRtX3ZlcnNpb24iOiAxLAogICJ0aW1lc3RhbXAiOiAiMjAyNC0xMC0yNFQxMzoyMDowMFoiLAogICJ0eXBlIjogIm5vdGlmaWNhdGlvbiIsCiAgInNvdXJjZSI6ICJSSVBFLU5PTkFVVEgiLAogICJzZXNzaW9uX2lkIjogIjYzMjgwOTVlLTdkNDYtNDE1Yi05MzMzLThmMmFlMjc0YjdjOCIsCiAgInZlcnNpb24iOiAxLAogICJzbmFwc2hvdCI6IHsKICAgICJ2ZXJzaW9uIjogMSwKICAgICJ1cmwiOiAiUklQRS1OT05BVVRIL25ydG0tc25hcHNob3QuMS5SSVBFLU5PTkFVVEguNjMyODA5NWUtN2Q0Ni00MTViLTkzMzMtOGYyYWUyNzRiN2M4LmYxMTk1YmI4YTY2NmZlN2I5N2ZhNzQwMDlhNzBjZWZhLmpzb24uZ3oiLAogICAgImhhc2giOiAiMTQ4YzNjNDExYjhmMDQ0ZjVmYzBhYjIwMWY2ZGQwM2U4MGM4NjJlMjdhZDFhNjM0ODhhZWUzMzdkYzdlYjRhMiIKICB9LAogICJkZWx0YXMiOiBbXQp9Cg.AGsn3z7Yd_-unMprcjUMB5nBkqdPrQuiC2C494Joz7CoGxfJEc9zWsVQ28nlK3GJVwMtSBCWP8msPEV_lX_lCF
\ No newline at end of file
diff --git a/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-signature.jose b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-signature.jose
new file mode 100644
index 0000000000..58083acc84
--- /dev/null
+++ b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-signature.jose
@@ -0,0 +1 @@
+eyJraWQiOiJhOWRkZjRhNS0wY2EwLTQ3YjEtYTgwZC0zYzYzZmQ1YzE5YzUiLCJhbGciOiJFZDI1NTE5In0.ewogICJucnRtX3ZlcnNpb24iOiA0LAogICJ0aW1lc3RhbXAiOiAiMjAyNC0xMC0yNVQwMDowNzowMFoiLAogICJ0eXBlIjogIm5vdGlmaWNhdGlvbiIsCiAgInNvdXJjZSI6ICJSSVBFIiwKICAic2Vzc2lvbl9pZCI6ICI0NTIxMTc0Yi01NDhmLTRlNTEtOThmYy1kZmQ3MjAwMTFhMGMiLAogICJ2ZXJzaW9uIjogMSwKICAic25hcHNob3QiOiB7CiAgICAidmVyc2lvbiI6IDEsCiAgICAidXJsIjogIlJJUEUvbnJ0bS1zbmFwc2hvdC40LlJJUEUuNDUyMTE3NGItNTQ4Zi00ZTUxLTk4ZmMtZGZkNzIwMDExYTBjLjgyNTQyYmQwNDhlMTExZmU1N2RiNDA0ZDA4YjY0MzNlLmpzb24uZ3oiLAogICAgImhhc2giOiAiYjI5M2U5Mjk5N2QzYmU3YTUxNTZmZGNhODMyYWYzNzhjMzk4OWIyY2VmYTllM2UzN2NhYWVlYmEwY2E5NzFlOSIKICB9LAogICJkZWx0YXMiOiBbCiAgICB7CiAgICAgICJ2ZXJzaW9uIjogMSwKICAgICAgInVybCI6ICJSSVBFL25ydG0tZGVsdGEuNC5SSVBFLjQ1MjExNzRiLTU0OGYtNGU1MS05OGZjLWRmZDcyMDAxMWEwYy5lM2JlNDFmZjMxMjAxMDA0NmI2N2QwOTlmYWE1OGY0NC5qc29uIiwKICAgICAgImhhc2giOiAiYzUwZGQ3NTU0Y2IzNWVmNWYyZjQ1ZDdiZmEwOWZjNTEwMzNjYmUxMTUyZDI5YjM2Y2IxMTc4MzE5ZTIyYmUzZSIKICAgIH0KICBdCn0K.PPu7vdJJW-8h1GsLlXKhGCmzkUt_cTQVpC9WLvhSFlfbM78kJYLFO_9YgaA-0oRaBfSmprCBUA3PZoP6UK3mAg
\ No newline at end of file
diff --git a/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-wrong-signature.jose b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-wrong-signature.jose
new file mode 100644
index 0000000000..f3628874f7
--- /dev/null
+++ b/whois-nrtm4-client/src/test/resources/mock/nrtm-RIPE-wrong-signature.jose
@@ -0,0 +1 @@
+eyJraWQiOiJhOWRkZjRhNS0wY2EwLTQ3YjEtYTgwZC0zYzYzZmQ1YzE5YzUiLCJhbGciOiJFZDI1NTE5In0.ewogICJucnRtX3ZlcnNpb24iOiA0LAogICJ0aW1lc3RhbXAiOiAiMjAyNC0xMC0yNVQwMDowNzowMFoiLAogICJ0eXBlIjogIm5vdGlmaWNhdGlvbiIsCiAgInNvdXJjZSI6ICJSSVBFIiwKICAic2Vzc2lvbl9pZCI6ICI0NTIxMTc0Yi01NDhmLTRlNTEtOThmYy1kZmQ3MjAwMTFhMGMiLAogICJ2ZXJzaW9uIjogMSwKICAic25hcHNob3QiOiB7CiAgICAidmVyc2lvbiI6IDEsCiAgICAidXJsIjogIlJJUEUvbnJ0bS1zbmFwc2hvdC40LlJJUEUuNDUyMTE3NGItNTQ4Zi00ZTUxLTk4ZmMtZGZkNzIwMDExYTBjLjgyNTQyYmQwNDhlMTExZmU1N2RiNDA0ZDA4YjY0MzNlLmpzb24uZ3oiLAogICAgImhhc2giOiAiYjI5M2U5Mjk5N2QzYmU3YTUxNTZmZGNhODMyYWYzNzhjMzk4OWIyY2VmYTllM2UzN2NhYWVlYmEwY2E5NzFlOSIKICB9LAogICJkZWx0YXMiOiBbCiAgICB7CiAgICAgICJ2ZXJzaW9uIjogMSwKICAgICAgInVybCI6ICJSSVBFL25ydG0tZGVsdGEuNC5SSVBFLjQ1MjExNzRiLTU0OGYtNGU1MS05OGZjLWRmZDcyMDAxMWEwYy5lM2JlNDFmZjMxMjAxMDA0NmI2N2QwOTlmYWE1OGY0NC5qc29uIiwKICAgICAgImhhc2giOiAiYzUwZGQ3NTU0Y2IzNWVmNWYyZjQ1ZDdiZmEwOWZjNTEwMzNjYmUxMTUyZDI5YjM2Y2IxMTc4MzE5ZTIyYmUzZSIKICAgIH0KICBdCn0K.PPu7vdJJW-8h1GsLlXKhGCmzkUt_cTQVpC9WLvhSFlfbM78kJYLFO_9YgaA-0oRaBfSmprCBUA3PZoP6UK3mAF
\ No newline at end of file