From b552a09eebd32dca11a65f37b8d8ec32ac62ded2 Mon Sep 17 00:00:00 2001 From: Attila Kreiner Date: Thu, 27 Jun 2024 17:30:45 +0200 Subject: [PATCH 1/5] Verify public-private tls key pair --- .../binding/tls/internal/TlsEventContext.java | 44 ++++ .../tls/internal/TlsEventFormatter.java | 11 + .../tls/internal/config/TlsBindingConfig.java | 16 +- .../internal/config/TlsKeyPairVerifier.java | 91 ++++++++ .../tls/internal/stream/TlsClientFactory.java | 2 +- .../tls/internal/stream/TlsServerFactory.java | 2 +- .../config/TlsKeyPairVerifierTest.java | 202 ++++++++++++++++++ .../src/main/resources/META-INF/zilla/tls.idl | 16 +- 8 files changed, 371 insertions(+), 13 deletions(-) create mode 100644 runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java create mode 100644 runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java index 1ed0cdb060..390f17a373 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java @@ -17,9 +17,12 @@ import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_FAILED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_HANDSHAKE_FAILED; +import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_KEY_PAIR_VERIFICATION_FAILED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_KEY_REJECTED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_PEER_NOT_VERIFIED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_PROTOCOL_REJECTED; +import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairFailureType.TLS_KEY_PAIR_INVALID; +import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairFailureType.TLS_KEY_PAIR_MISSING; import java.nio.ByteBuffer; import java.time.Clock; @@ -29,6 +32,7 @@ import io.aklivity.zilla.runtime.binding.tls.internal.types.event.EventFW; import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventExFW; +import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairFailureType; import io.aklivity.zilla.runtime.engine.EngineContext; import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; @@ -46,6 +50,7 @@ public class TlsEventContext private final int tlsKeyRejectedEventId; private final int tlsPeerNotVerifiedEventId; private final int tlsHandshakeFailedEventId; + private final int tlsKeyPairVerificationFailedEventId; private final MessageConsumer eventWriter; private final Clock clock; @@ -58,6 +63,7 @@ public TlsEventContext( this.tlsKeyRejectedEventId = context.supplyEventId("binding.tls.key.rejected"); this.tlsPeerNotVerifiedEventId = context.supplyEventId("binding.tls.peer.not.verified"); this.tlsHandshakeFailedEventId = context.supplyEventId("binding.tls.handshake.failed"); + this.tlsKeyPairVerificationFailedEventId = context.supplyEventId("binding.tls.key.pair.verification.failed"); this.eventWriter = context.supplyEventWriter(); this.clock = context.clock(); } @@ -166,4 +172,42 @@ public void tlsHandshakeFailed( .build(); eventWriter.accept(tlsTypeId, event.buffer(), event.offset(), event.limit()); } + + public void tlsKeyPairMissing( + long bindingId, + String keyName) + { + tlsKeyPairVerificationFailed(TLS_KEY_PAIR_MISSING, bindingId, keyName); + } + + public void tlsKeyPairInvalid( + long bindingId, + String keyName) + { + tlsKeyPairVerificationFailed(TLS_KEY_PAIR_INVALID, bindingId, keyName); + } + + private void tlsKeyPairVerificationFailed( + TlsKeyPairFailureType failureType, + long bindingId, + String keyName) + { + TlsEventExFW extension = tlsEventExRW + .wrap(extensionBuffer, 0, extensionBuffer.capacity()) + .tlsKeyPairVerificationFailed(e -> e + .typeId(TLS_KEY_PAIR_VERIFICATION_FAILED.value()) + .failureType(t -> t.set(failureType)) + .keyName(keyName) + ) + .build(); + EventFW event = eventRW + .wrap(eventBuffer, 0, eventBuffer.capacity()) + .id(tlsKeyPairVerificationFailedEventId) + .timestamp(clock.millis()) + .traceId(0L) + .namespacedId(bindingId) + .extension(extension.buffer(), extension.offset(), extension.limit()) + .build(); + eventWriter.accept(tlsTypeId, event.buffer(), event.offset(), event.limit()); + } } diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java index 992946d7f6..a3997b9283 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java @@ -19,6 +19,7 @@ import io.aklivity.zilla.runtime.binding.tls.internal.types.event.EventFW; import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventExFW; +import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairVerificationFailedExFW; import io.aklivity.zilla.runtime.engine.Configuration; import io.aklivity.zilla.runtime.engine.event.EventFormatterSpi; @@ -68,6 +69,16 @@ public String format( result = "The client and server could not negotiate the desired level of security."; break; } + case TLS_KEY_PAIR_VERIFICATION_FAILED: + { + TlsKeyPairVerificationFailedExFW ex = extension.tlsKeyPairVerificationFailed(); + result = switch (ex.failureType().get()) + { + case TLS_KEY_PAIR_MISSING -> String.format("Key pair (%s) is missing.", ex.keyName()); + case TLS_KEY_PAIR_INVALID -> String.format("Key pair (%s) is invalid.", ex.keyName()); + }; + break; + } } return result; } diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java index 8272116134..d5c7bc0029 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java @@ -20,7 +20,6 @@ import static io.aklivity.zilla.runtime.binding.tls.internal.types.ProxyInfoType.AUTHORITY; import static io.aklivity.zilla.runtime.binding.tls.internal.types.ProxyInfoType.SECURE; import static io.aklivity.zilla.runtime.binding.tls.internal.types.ProxySecureInfoType.NAME; -import static java.lang.System.currentTimeMillis; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; import static javax.net.ssl.StandardConstants.SNI_HOST_NAME; @@ -53,6 +52,7 @@ import io.aklivity.zilla.runtime.binding.tls.config.TlsMutualConfig; import io.aklivity.zilla.runtime.binding.tls.config.TlsOptionsConfig; import io.aklivity.zilla.runtime.binding.tls.internal.TlsConfiguration; +import io.aklivity.zilla.runtime.binding.tls.internal.TlsEventContext; import io.aklivity.zilla.runtime.binding.tls.internal.identity.TlsClientX509ExtendedKeyManager; import io.aklivity.zilla.runtime.binding.tls.internal.types.Array32FW; import io.aklivity.zilla.runtime.binding.tls.internal.types.ProxyAddressFW; @@ -76,6 +76,7 @@ public final class TlsBindingConfig public final List routes; private SSLContext context; + private TlsKeyPairVerifier verifier; public TlsBindingConfig( BindingConfig binding) @@ -91,12 +92,13 @@ public TlsBindingConfig( public void init( TlsConfiguration config, VaultHandler vault, - SecureRandom random) + SecureRandom random, + TlsEventContext event) { + this.verifier = new TlsKeyPairVerifier(event); char[] keysPass = "generated".toCharArray(); KeyStore keys = newKeys(config, vault, keysPass, options.keys, options.signers); KeyStore trust = newTrust(config, vault, options.trust, options.trustcacerts && kind == KindConfig.CLIENT); - try { KeyManager[] keyManagers = null; @@ -440,16 +442,10 @@ private KeyStore newKeys( for (String keyName : keyNames) { KeyStore.PrivateKeyEntry entry = vault.key(keyName); - if (entry == null) + if (!verifier.verify(entry, keyName, this.id)) { - if (config.verbose()) - { - System.out.printf("%d [%s] key \"%s\" not found\n", - currentTimeMillis(), this.qname, keyName); - } continue; } - KeyStore.ProtectionParameter protection = new KeyStore.PasswordProtection(password); store.setEntry(keyName, entry, protection); } diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java new file mode 100644 index 0000000000..07fb4eacfb --- /dev/null +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java @@ -0,0 +1,91 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you 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. + */ +package io.aklivity.zilla.runtime.binding.tls.internal.config; + +import static org.agrona.LangUtil.rethrowUnchecked; + +import java.security.InvalidKeyException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.util.concurrent.ThreadLocalRandom; + +import io.aklivity.zilla.runtime.binding.tls.internal.TlsEventContext; + +public class TlsKeyPairVerifier +{ + private static final String ALGORITHM = "SHA256withRSA"; + + private final TlsEventContext event; + + public TlsKeyPairVerifier( + TlsEventContext event) + { + this.event = event; + } + + public boolean verify( + KeyStore.PrivateKeyEntry entry, + String keyName, + long bindingId) + { + boolean valid = false; + if (entry == null) + { + event.tlsKeyPairMissing(bindingId, keyName); + } + else + { + try + { + PrivateKey privateKey = entry.getPrivateKey(); + PublicKey publicKey = entry.getCertificate().getPublicKey(); + + // create a challenge + byte[] challenge = new byte[10000]; + ThreadLocalRandom.current().nextBytes(challenge); + + // sign using the private key + Signature sig = Signature.getInstance(ALGORITHM); + sig.initSign(privateKey); + sig.update(challenge); + byte[] signature = sig.sign(); + + // verify signature using the public key + sig.initVerify(publicKey); + sig.update(challenge); + valid = sig.verify(signature); + + if (!valid) + { + event.tlsKeyPairInvalid(bindingId, keyName); + } + } + catch (InvalidKeyException | SignatureException ex) + { + event.tlsKeyPairInvalid(bindingId, keyName); + } + catch (NoSuchAlgorithmException ex) + { + rethrowUnchecked(ex); + } + } + return valid; + } +} diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java index 3ad8e84a0e..f9375f88fd 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java @@ -207,7 +207,7 @@ public void attach( VaultHandler vault = supplyVault.apply(tlsBinding.vaultId); - tlsBinding.init(config, vault, random); + tlsBinding.init(config, vault, random, event); bindings.put(binding.id, tlsBinding); } diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java index 91d30e9b3d..5562e4ccaa 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java @@ -223,7 +223,7 @@ public void attach( VaultHandler vault = supplyVault.apply(tlsBinding.vaultId); - tlsBinding.init(config, vault, random); + tlsBinding.init(config, vault, random, event); bindings.put(binding.id, tlsBinding); } diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java new file mode 100644 index 0000000000..cfe3d92fc0 --- /dev/null +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java @@ -0,0 +1,202 @@ +/* + * Copyright 2021-2023 Aklivity Inc. + * + * Aklivity licenses this file to you 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. + */ +package io.aklivity.zilla.runtime.binding.tls.internal.config; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; + +import java.io.ByteArrayInputStream; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; + +import org.junit.Test; + +import io.aklivity.zilla.runtime.binding.tls.internal.TlsEventContext; + +public class TlsKeyPairVerifierTest +{ + private static final String PRIVATE_KEY = """ + -----BEGIN PRIVATE KEY----- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCbKSRbWWxzdJh3 + CzJETA5kLsngah/V83bEPt0AdYpFWZs2BcgPe/ZBR1HAZlyrXn7Hmz5UTlywtmSz + NgB8QBg4VaG+OLWQIk7TrHqxVPS0CIrFoXpjtHj+u9sL5+hcYscI0D7M+05ObDUm + nFw5KFuQILme0Prwzwa1IgbQy10mpxJjZZZnkMU9hhzZn+PSce/T3PI0E+7NhhTo + TO/BV4XL+slIQB82I939HpF09VsKXdlGGI6rU8TUoK4mLtZexcknYDkAiLzOKfe9 + qkPOCJGBsdbxOixGQUDslxK86qyJsQm7Ai2kduyCQj9gfGUkPBR/fkjiUWVuheeK + GgX7hzwrAgMBAAECggEALWah+UrWxYfJ7xdrG3nnwh/AuXZEH34QdAby8uXx0i4Q + kQOrEQDUQzCjtrkdB5XsYerGl7OgQqL0H04/YRv+GknQPJFqayTmzOBMvGPgAGf5 + dy+zWMZfmyYLx9WRc6sBk04f+inUtXTLLqOVBrKM7ETvG44Jx3nEfC7bMLA47wyB + 82AFYQzxgfkHCfDgc1igc0oGXxLVH70P9Wh1NMt8I8Kc10aTwfOBAAbw1uE0UgGd + w4FH/O/50CWc7tbQYvrt6DfwZp7I5TMhg08zATHHicRZMUXpwg1qs3LLh5IU/Tx+ + s6rkTL28L87SjdRdUddY79jdduYDYOzQgklTdAN7hQKBgQDY2gM5HeuDP+DQMYid + 5IIMYIJUe7RJYWO8CyXoDJ1UfuLEHeZNdVU4prnvtVjwY56PMMRPzZ0wj8t7xbvD + ic+oScRVppRx3qXdCEzMd/QG+ok6X0sJQDkR9x7a7+Hl3I+1v5HiXeqVa2zxc63c + m3LtiVkxEusHc6p6fnDvNiEzzQKBgQC3LAfFJ2LPGsmd+EpKVqoJ/gK7qYar2yJb + m42kDdBVebmfkAQxsLDPWutfMjKEhSxz5kjD022Bo0T1jLNLux5yJlwrI3Hwi5ES + GUVuu9q2wvCjECP5ckukgt6QQ6onHeNu4S24O9x/z9HLlxOFv4fQr8gKqD7eT6bU + QdekikKn1wKBgEt2+z4qSmZ/mWX6hvejqRpTj6eE8UXELagoHQX3Nd1M1u+3FAmK + tqCjbPudmZj2ohxktTysanKW6BJnyqMO14RSP5ArC2fhOsmD9O4HJJY1JAJ7XSqX + /gRhgoxghLWwnxZ513P2iQd8vgn83tlyA3nknXR1h/Ms7nv4eqbUqJNVAoGBAIEZ + KUjNH5j0OlF6I3INbr6oJmj5bI9HXQnPsp6DlegIaMmLCUm0TIl4fReVG4HHErOF + BJfwNef+mKWvytZ/RVAStTc6Ph3ZYB+va/5FrDrPXiavQ4uWALYr/o0TA6OaLyeA + 0WZd2mTCpgylp/7GJQTyPz0zo0uwO9axqTiwsZX1AoGARNMUljaCmcYKlUMWssME + 1vomOHwDkTAjcSoG5xmA0DuxglZCcvZQGLH6Xp4y9YGKoq0jauEs/P4tZ35UDBuA + 33+gdzYD5Y1xF2HoEhJam3KglUEJEIGffRgQVcih1xVupUbp7rSliXfcSmAuDoR5 + dQh9097BZt8mQAUwEk6jURo= + -----END PRIVATE KEY----- + """; + + private static final String VALID_CERTIFICATE = """ + -----BEGIN CERTIFICATE----- + MIIDpjCCAo6gAwIBAgIIYM5edJpxrNkwDQYJKoZIhvcNAQELBQAwXjERMA8GA1UE + AxMIc2VydmVyY2ExFDASBgNVBAsTC0RldmVsb3BtZW50MREwDwYDVQQKEwhBa2xp + dml0eTETMBEGA1UECBMKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMwHhcNMjQwNjI3 + MDk1NzU4WhcNMjkwNjAxMDk1NzU4WjBeMRIwEAYDVQQDEwlsb2NhbGhvc3QxFDAS + BgNVBAsTC0RldmVsb3BtZW50MRAwDgYDVQQKEwdBa2xpdnR5MRMwEQYDVQQIEwpD + YWxpZm9ybmlhMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC + AQoCggEBAJspJFtZbHN0mHcLMkRMDmQuyeBqH9XzdsQ+3QB1ikVZmzYFyA979kFH + UcBmXKtefsebPlROXLC2ZLM2AHxAGDhVob44tZAiTtOserFU9LQIisWhemO0eP67 + 2wvn6FxixwjQPsz7Tk5sNSacXDkoW5AguZ7Q+vDPBrUiBtDLXSanEmNllmeQxT2G + HNmf49Jx79Pc8jQT7s2GFOhM78FXhcv6yUhAHzYj3f0ekXT1Wwpd2UYYjqtTxNSg + riYu1l7FySdgOQCIvM4p972qQ84IkYGx1vE6LEZBQOyXErzqrImxCbsCLaR27IJC + P2B8ZSQ8FH9+SOJRZW6F54oaBfuHPCsCAwEAAaNoMGYwHQYDVR0OBBYEFJyQnLBA + tDXF3aCPrmlzZvSaq0QqMA4GA1UdDwEB/wQEAwIFoDAUBgNVHREEDTALgglsb2Nh + bGhvc3QwHwYDVR0jBBgwFoAUXkoqFX5WS6ZHxCVDlde+sGKhgyEwDQYJKoZIhvcN + AQELBQADggEBAEx1WkZ5EEtvtd2BwOEDtyKNKoYmIBvsAWBxDRDgw9zJxK1Cgpv8 + bfIed/G+O5gwAOK/QnidNoYv5ZpE7GH+b1uQy2QhXOG0RZxJj1UVTK+X6rzKUe1d + +9kCp/EFz3bZAzoJTaGW7FQsUd8Eae+pXOEkPkgY82eHC5hZ37U4PfPYvFea+j4x + eC1VtOws/2k5pexdl8FR/eC0eQQdoI3FBARzD0rlGlvDR4raqNlrBahyrsT8PmGP + bQ+xh6fzeFggjTSrhKiKm2vm3dQKP+eKbihYsZQjlPiE6gEp/pTtV7TYVoX+s+yZ + lUdAET/1jqTLi2Gd7UuYQN+mlTSoKEpT4bk= + -----END CERTIFICATE----- + """; + + private static final String INVALID_CERTIFICATE = """ + -----BEGIN CERTIFICATE----- + MIIDpjCCAo6gAwIBAgIIJWpr8WDPucUwDQYJKoZIhvcNAQELBQAwXjERMA8GA1UE + AxMIc2VydmVyY2ExFDASBgNVBAsTC0RldmVsb3BtZW50MREwDwYDVQQKEwhBa2xp + dml0eTETMBEGA1UECBMKQ2FsaWZvcm5pYTELMAkGA1UEBhMCVVMwHhcNMjQwNjI3 + MTA1OTQ5WhcNMjkwNjAxMTA1OTQ5WjBeMRIwEAYDVQQDEwlsb2NhbGhvc3QxFDAS + BgNVBAsTC0RldmVsb3BtZW50MRAwDgYDVQQKEwdBa2xpdnR5MRMwEQYDVQQIEwpD + YWxpZm9ybmlhMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC + AQoCggEBAMPa6QJuljN9vVeBHzb2sB+YgL7pFPI9tL24jaB3mlV4PvXwQ2XoZ7Oy + gR4I23iU9CfvvhHSiI2+9nAGHZgT74GZDaIiTxZNearQ+4aGRhAAENHXRb7YD6gp + FiIjZ5SWf2+yfcTIPPi1Sp+DLp9L2FiCgCtghaDBc5xdieC24zhq3Rp56tsaQGen + sEK4qZ+9bAevD7l59FWat7Yts5p/emu3+UNAka+n2zVz+BF0uc9he4NHgHMvd0uq + GlnTKWQ3zrQ+LUD7nOOq6db2Pb2+FTg+4+0y/hdzwFkuNL9OOmWvsSOPUIJIBpyR + gwi0+I+MWODoUPYJE1yLIlGJ5t7SWDsCAwEAAaNoMGYwHQYDVR0OBBYEFD2P04GZ + l36DmMNQmz7auMC7LStQMA4GA1UdDwEB/wQEAwIFoDAUBgNVHREEDTALgglsb2Nh + bGhvc3QwHwYDVR0jBBgwFoAU4ebi5t0zi0JyZI1SdZrrG9m6CIwwDQYJKoZIhvcN + AQELBQADggEBAFr0mzsLaa64aO10HnRpU9ppFkRiFiu3peaqrSZd/1mHxacwPTEr + c4QtaNhB1sVu1zVlzKPQYJ/yRsUD+wSwURud8syEjeieIXu3mytdQMQN/7hIE3KL + PO38SUk3pN8GU7auvuysT4/xbnZ7J+55UMCKkjcVO17NwVWXT9BbIKmHScLwCuB+ + +5LG02GLU6IWzrWcCsmsjbMiT+xntAHXzJChwx5abuBpg8hHN3Yaz7/K9E1dVzop + ZhqL8TG4TlhXtUJjd8VxAroyMi0VZSVHTZoqz2Zmkw/CT30rRT7E/I1zy2ZYUYqS + kuIWfzOfqCZSmGeqzuSE996ndM+FlQ6r0Zs= + -----END CERTIFICATE----- + """; + + private static final char[] PASSWORD = "generated".toCharArray(); + + private TlsEventContext event = mock(TlsEventContext.class); + + @Test + public void shouldVerifyValid() throws Exception + { + // GIVEN + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(event); + KeyStore.PrivateKeyEntry entry = privateKeyEntry(PRIVATE_KEY, VALID_CERTIFICATE, PASSWORD); + + // WHEN + boolean valid = verifier.verify(entry, "localhost", 42L); + + // THEN + assertThat(valid, equalTo(true)); + } + + @Test + public void shouldVerifyInvalid() throws Exception + { + // GIVEN + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(event); + KeyStore.PrivateKeyEntry entry = privateKeyEntry(PRIVATE_KEY, INVALID_CERTIFICATE, PASSWORD); + + // WHEN + boolean valid = verifier.verify(entry, "localhost", 42L); + + // THEN + assertThat(valid, equalTo(false)); + } + + @Test + public void shouldVerifyMissing() throws Exception + { + // GIVEN + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(event); + KeyStore.PrivateKeyEntry entry = null; + + // WHEN + boolean valid = verifier.verify(entry, "localhost", 42L); + + // THEN + assertThat(valid, equalTo(false)); + } + + private static KeyStore.PrivateKeyEntry privateKeyEntry( + String privateKeyPem, + String certificatePem, + char[] password) throws Exception + { + PrivateKey privateKey = privateKeyFromPem(privateKeyPem); + X509Certificate certificate = certificateFromPem(certificatePem); + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + keyStore.load(null, password); + X509Certificate[] certChain = {certificate}; + keyStore.setKeyEntry("localhost", privateKey, password, certChain); + return (KeyStore.PrivateKeyEntry) keyStore.getEntry("localhost", new KeyStore.PasswordProtection(password)); + } + + private static PrivateKey privateKeyFromPem( + String pem) throws Exception + { + String privateKeyPem = pem + .replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s", ""); + byte[] decoded = Base64.getDecoder().decode(privateKeyPem); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePrivate(keySpec); + } + + private static X509Certificate certificateFromPem( + String pem) throws Exception + { + String certificatePem = pem + .replace("-----BEGIN CERTIFICATE-----", "") + .replace("-----END CERTIFICATE-----", "") + .replaceAll("\\s", ""); + byte[] decoded = Base64.getDecoder().decode(certificatePem); + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(decoded)); + } +} diff --git a/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl b/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl index baa53655f6..1094e9da32 100644 --- a/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl +++ b/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl @@ -23,7 +23,20 @@ scope tls TLS_PROTOCOL_REJECTED (2), TLS_KEY_REJECTED (3), TLS_PEER_NOT_VERIFIED (4), - TLS_HANDSHAKE_FAILED (5) + TLS_HANDSHAKE_FAILED (5), + TLS_KEY_PAIR_VERIFICATION_FAILED (6) + } + + enum TlsKeyPairFailureType (uint8) + { + TLS_KEY_PAIR_MISSING (1), + TLS_KEY_PAIR_INVALID (2) + } + + struct TlsKeyPairVerificationFailedEx extends core::stream::Extension + { + TlsKeyPairFailureType failureType; + string8 keyName; } union TlsEventEx switch (TlsEventType) @@ -33,6 +46,7 @@ scope tls case TLS_KEY_REJECTED: core::stream::Extension tlsKeyRejected; case TLS_PEER_NOT_VERIFIED: core::stream::Extension tlsPeerNotVerified; case TLS_HANDSHAKE_FAILED: core::stream::Extension tlsHandshakeFailed; + case TLS_KEY_PAIR_VERIFICATION_FAILED: TlsKeyPairVerificationFailedEx tlsKeyPairVerificationFailed; } } } From 310fa87473b7c68409da92d6de8d61ce2840e182 Mon Sep 17 00:00:00 2001 From: Attila Kreiner Date: Fri, 28 Jun 2024 10:36:10 +0200 Subject: [PATCH 2/5] fix mv keypair key --- .../binding/tls/internal/TlsEventContext.java | 18 +++++++++--------- .../tls/internal/TlsEventFormatter.java | 10 +++++----- .../src/main/resources/META-INF/zilla/tls.idl | 14 +++++++------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java index 390f17a373..385df6c450 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventContext.java @@ -17,12 +17,12 @@ import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_FAILED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_HANDSHAKE_FAILED; -import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_KEY_PAIR_VERIFICATION_FAILED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_KEY_REJECTED; +import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_KEY_VERIFICATION_FAILED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_PEER_NOT_VERIFIED; import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventType.TLS_PROTOCOL_REJECTED; -import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairFailureType.TLS_KEY_PAIR_INVALID; -import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairFailureType.TLS_KEY_PAIR_MISSING; +import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyFailureType.TLS_KEY_INVALID; +import static io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyFailureType.TLS_KEY_MISSING; import java.nio.ByteBuffer; import java.time.Clock; @@ -32,7 +32,7 @@ import io.aklivity.zilla.runtime.binding.tls.internal.types.event.EventFW; import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventExFW; -import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairFailureType; +import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyFailureType; import io.aklivity.zilla.runtime.engine.EngineContext; import io.aklivity.zilla.runtime.engine.binding.function.MessageConsumer; @@ -177,25 +177,25 @@ public void tlsKeyPairMissing( long bindingId, String keyName) { - tlsKeyPairVerificationFailed(TLS_KEY_PAIR_MISSING, bindingId, keyName); + tlsKeyPairVerificationFailed(TLS_KEY_MISSING, bindingId, keyName); } public void tlsKeyPairInvalid( long bindingId, String keyName) { - tlsKeyPairVerificationFailed(TLS_KEY_PAIR_INVALID, bindingId, keyName); + tlsKeyPairVerificationFailed(TLS_KEY_INVALID, bindingId, keyName); } private void tlsKeyPairVerificationFailed( - TlsKeyPairFailureType failureType, + TlsKeyFailureType failureType, long bindingId, String keyName) { TlsEventExFW extension = tlsEventExRW .wrap(extensionBuffer, 0, extensionBuffer.capacity()) - .tlsKeyPairVerificationFailed(e -> e - .typeId(TLS_KEY_PAIR_VERIFICATION_FAILED.value()) + .tlsKeyVerificationFailed(e -> e + .typeId(TLS_KEY_VERIFICATION_FAILED.value()) .failureType(t -> t.set(failureType)) .keyName(keyName) ) diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java index a3997b9283..026e09bbca 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/TlsEventFormatter.java @@ -19,7 +19,7 @@ import io.aklivity.zilla.runtime.binding.tls.internal.types.event.EventFW; import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsEventExFW; -import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyPairVerificationFailedExFW; +import io.aklivity.zilla.runtime.binding.tls.internal.types.event.TlsKeyVerificationFailedExFW; import io.aklivity.zilla.runtime.engine.Configuration; import io.aklivity.zilla.runtime.engine.event.EventFormatterSpi; @@ -69,13 +69,13 @@ public String format( result = "The client and server could not negotiate the desired level of security."; break; } - case TLS_KEY_PAIR_VERIFICATION_FAILED: + case TLS_KEY_VERIFICATION_FAILED: { - TlsKeyPairVerificationFailedExFW ex = extension.tlsKeyPairVerificationFailed(); + TlsKeyVerificationFailedExFW ex = extension.tlsKeyVerificationFailed(); result = switch (ex.failureType().get()) { - case TLS_KEY_PAIR_MISSING -> String.format("Key pair (%s) is missing.", ex.keyName()); - case TLS_KEY_PAIR_INVALID -> String.format("Key pair (%s) is invalid.", ex.keyName()); + case TLS_KEY_MISSING -> String.format("Key pair (%s) is missing.", ex.keyName()); + case TLS_KEY_INVALID -> String.format("Key pair (%s) is invalid.", ex.keyName()); }; break; } diff --git a/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl b/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl index 1094e9da32..0f08dac473 100644 --- a/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl +++ b/specs/binding-tls.spec/src/main/resources/META-INF/zilla/tls.idl @@ -24,18 +24,18 @@ scope tls TLS_KEY_REJECTED (3), TLS_PEER_NOT_VERIFIED (4), TLS_HANDSHAKE_FAILED (5), - TLS_KEY_PAIR_VERIFICATION_FAILED (6) + TLS_KEY_VERIFICATION_FAILED (6) } - enum TlsKeyPairFailureType (uint8) + enum TlsKeyFailureType (uint8) { - TLS_KEY_PAIR_MISSING (1), - TLS_KEY_PAIR_INVALID (2) + TLS_KEY_MISSING (1), + TLS_KEY_INVALID (2) } - struct TlsKeyPairVerificationFailedEx extends core::stream::Extension + struct TlsKeyVerificationFailedEx extends core::stream::Extension { - TlsKeyPairFailureType failureType; + TlsKeyFailureType failureType; string8 keyName; } @@ -46,7 +46,7 @@ scope tls case TLS_KEY_REJECTED: core::stream::Extension tlsKeyRejected; case TLS_PEER_NOT_VERIFIED: core::stream::Extension tlsPeerNotVerified; case TLS_HANDSHAKE_FAILED: core::stream::Extension tlsHandshakeFailed; - case TLS_KEY_PAIR_VERIFICATION_FAILED: TlsKeyPairVerificationFailedEx tlsKeyPairVerificationFailed; + case TLS_KEY_VERIFICATION_FAILED: TlsKeyVerificationFailedEx tlsKeyVerificationFailed; } } } From c2a8ed10db7126c4c0ef3e3c55ec72306c87cc76 Mon Sep 17 00:00:00 2001 From: Attila Kreiner Date: Fri, 28 Jun 2024 10:38:19 +0200 Subject: [PATCH 3/5] fix TlsBindingConfig init --- .../binding/tls/internal/config/TlsBindingConfig.java | 7 ++++--- .../binding/tls/internal/stream/TlsClientFactory.java | 2 +- .../binding/tls/internal/stream/TlsServerFactory.java | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java index d5c7bc0029..1a69ad736a 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java @@ -91,14 +91,15 @@ public TlsBindingConfig( public void init( TlsConfiguration config, + TlsEventContext events, VaultHandler vault, - SecureRandom random, - TlsEventContext event) + SecureRandom random) { - this.verifier = new TlsKeyPairVerifier(event); + this.verifier = new TlsKeyPairVerifier(events); char[] keysPass = "generated".toCharArray(); KeyStore keys = newKeys(config, vault, keysPass, options.keys, options.signers); KeyStore trust = newTrust(config, vault, options.trust, options.trustcacerts && kind == KindConfig.CLIENT); + try { KeyManager[] keyManagers = null; diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java index f9375f88fd..73aaffe818 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsClientFactory.java @@ -207,7 +207,7 @@ public void attach( VaultHandler vault = supplyVault.apply(tlsBinding.vaultId); - tlsBinding.init(config, vault, random, event); + tlsBinding.init(config, event, vault, random); bindings.put(binding.id, tlsBinding); } diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java index 5562e4ccaa..fe9280f25d 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/stream/TlsServerFactory.java @@ -223,7 +223,7 @@ public void attach( VaultHandler vault = supplyVault.apply(tlsBinding.vaultId); - tlsBinding.init(config, vault, random, event); + tlsBinding.init(config, event, vault, random); bindings.put(binding.id, tlsBinding); } From 5dba8c0bc15cc53c9f132d1418491dc93e6df4fb Mon Sep 17 00:00:00 2001 From: Attila Kreiner Date: Fri, 28 Jun 2024 10:41:28 +0200 Subject: [PATCH 4/5] fix verifier --- .../binding/tls/internal/config/TlsBindingConfig.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java index 1a69ad736a..2900d2fbdf 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java @@ -76,7 +76,6 @@ public final class TlsBindingConfig public final List routes; private SSLContext context; - private TlsKeyPairVerifier verifier; public TlsBindingConfig( BindingConfig binding) @@ -95,9 +94,9 @@ public void init( VaultHandler vault, SecureRandom random) { - this.verifier = new TlsKeyPairVerifier(events); + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(events); char[] keysPass = "generated".toCharArray(); - KeyStore keys = newKeys(config, vault, keysPass, options.keys, options.signers); + KeyStore keys = newKeys(config, vault, keysPass, verifier, options.keys, options.signers); KeyStore trust = newTrust(config, vault, options.trust, options.trustcacerts && kind == KindConfig.CLIENT); try @@ -411,6 +410,7 @@ private KeyStore newKeys( TlsConfiguration config, VaultHandler vault, char[] password, + TlsKeyPairVerifier verifier, List keyNames, List signerNames) { From 585156aa607ba7b1b913fff378f8791239520342 Mon Sep 17 00:00:00 2001 From: Attila Kreiner Date: Fri, 28 Jun 2024 10:52:30 +0200 Subject: [PATCH 5/5] fix ref TlsKeyPairVerifier verify --- .../tls/internal/config/TlsBindingConfig.java | 14 +++- .../internal/config/TlsKeyPairVerifier.java | 72 +++++++------------ .../config/TlsKeyPairVerifierTest.java | 27 ++----- 3 files changed, 39 insertions(+), 74 deletions(-) diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java index 2900d2fbdf..2fafaa55b3 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsBindingConfig.java @@ -94,9 +94,9 @@ public void init( VaultHandler vault, SecureRandom random) { - TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(events); + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(); char[] keysPass = "generated".toCharArray(); - KeyStore keys = newKeys(config, vault, keysPass, verifier, options.keys, options.signers); + KeyStore keys = newKeys(config, vault, keysPass, verifier, events, options.keys, options.signers); KeyStore trust = newTrust(config, vault, options.trust, options.trustcacerts && kind == KindConfig.CLIENT); try @@ -411,6 +411,7 @@ private KeyStore newKeys( VaultHandler vault, char[] password, TlsKeyPairVerifier verifier, + TlsEventContext events, List keyNames, List signerNames) { @@ -443,8 +444,15 @@ private KeyStore newKeys( for (String keyName : keyNames) { KeyStore.PrivateKeyEntry entry = vault.key(keyName); - if (!verifier.verify(entry, keyName, this.id)) + if (entry == null) + { + events.tlsKeyPairMissing(this.id, keyName); + continue; + } + boolean valid = verifier.verify(entry); + if (!valid) { + events.tlsKeyPairInvalid(this.id, keyName); continue; } KeyStore.ProtectionParameter protection = new KeyStore.PasswordProtection(password); diff --git a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java index 07fb4eacfb..03a800810c 100644 --- a/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java +++ b/runtime/binding-tls/src/main/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifier.java @@ -26,65 +26,41 @@ import java.security.SignatureException; import java.util.concurrent.ThreadLocalRandom; -import io.aklivity.zilla.runtime.binding.tls.internal.TlsEventContext; - public class TlsKeyPairVerifier { private static final String ALGORITHM = "SHA256withRSA"; - private final TlsEventContext event; - - public TlsKeyPairVerifier( - TlsEventContext event) - { - this.event = event; - } - public boolean verify( - KeyStore.PrivateKeyEntry entry, - String keyName, - long bindingId) + KeyStore.PrivateKeyEntry entry) { boolean valid = false; - if (entry == null) - { - event.tlsKeyPairMissing(bindingId, keyName); - } - else + try { - try - { - PrivateKey privateKey = entry.getPrivateKey(); - PublicKey publicKey = entry.getCertificate().getPublicKey(); - - // create a challenge - byte[] challenge = new byte[10000]; - ThreadLocalRandom.current().nextBytes(challenge); + PrivateKey privateKey = entry.getPrivateKey(); + PublicKey publicKey = entry.getCertificate().getPublicKey(); - // sign using the private key - Signature sig = Signature.getInstance(ALGORITHM); - sig.initSign(privateKey); - sig.update(challenge); - byte[] signature = sig.sign(); + // create a challenge + byte[] challenge = new byte[10000]; + ThreadLocalRandom.current().nextBytes(challenge); - // verify signature using the public key - sig.initVerify(publicKey); - sig.update(challenge); - valid = sig.verify(signature); + // sign using the private key + Signature sig = Signature.getInstance(ALGORITHM); + sig.initSign(privateKey); + sig.update(challenge); + byte[] signature = sig.sign(); - if (!valid) - { - event.tlsKeyPairInvalid(bindingId, keyName); - } - } - catch (InvalidKeyException | SignatureException ex) - { - event.tlsKeyPairInvalid(bindingId, keyName); - } - catch (NoSuchAlgorithmException ex) - { - rethrowUnchecked(ex); - } + // verify signature using the public key + sig.initVerify(publicKey); + sig.update(challenge); + valid = sig.verify(signature); + } + catch (InvalidKeyException | SignatureException ex) + { + // key invalid + } + catch (NoSuchAlgorithmException ex) + { + rethrowUnchecked(ex); } return valid; } diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java index cfe3d92fc0..412410a0fa 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/config/TlsKeyPairVerifierTest.java @@ -17,7 +17,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Mockito.mock; import java.io.ByteArrayInputStream; import java.security.KeyFactory; @@ -30,8 +29,6 @@ import org.junit.Test; -import io.aklivity.zilla.runtime.binding.tls.internal.TlsEventContext; - public class TlsKeyPairVerifierTest { private static final String PRIVATE_KEY = """ @@ -117,17 +114,15 @@ public class TlsKeyPairVerifierTest private static final char[] PASSWORD = "generated".toCharArray(); - private TlsEventContext event = mock(TlsEventContext.class); - @Test public void shouldVerifyValid() throws Exception { // GIVEN - TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(event); + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(); KeyStore.PrivateKeyEntry entry = privateKeyEntry(PRIVATE_KEY, VALID_CERTIFICATE, PASSWORD); // WHEN - boolean valid = verifier.verify(entry, "localhost", 42L); + boolean valid = verifier.verify(entry); // THEN assertThat(valid, equalTo(true)); @@ -137,25 +132,11 @@ public void shouldVerifyValid() throws Exception public void shouldVerifyInvalid() throws Exception { // GIVEN - TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(event); + TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(); KeyStore.PrivateKeyEntry entry = privateKeyEntry(PRIVATE_KEY, INVALID_CERTIFICATE, PASSWORD); // WHEN - boolean valid = verifier.verify(entry, "localhost", 42L); - - // THEN - assertThat(valid, equalTo(false)); - } - - @Test - public void shouldVerifyMissing() throws Exception - { - // GIVEN - TlsKeyPairVerifier verifier = new TlsKeyPairVerifier(event); - KeyStore.PrivateKeyEntry entry = null; - - // WHEN - boolean valid = verifier.verify(entry, "localhost", 42L); + boolean valid = verifier.verify(entry); // THEN assertThat(valid, equalTo(false));