Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Build Status License Coverage Lines of code Maintainability


This is a framework for building negative tests and fuzzers for TLS 1.3 implementations. The idea is to split the TLS handshake and application data exchange to simple steps which can be easily configured and re-used in various TLS clients and servers.

The framework provides a set of basic steps which can be used in a TLS connection, for example:

  • Generating a ClientHello message
  • Wrapping a handshake message into a Handshake structure
  • Wrapping a handshake message into a TLSPlaintext structure
  • Key exchange and deriving symmetric keys
  • Receiving incoming encrypted data
  • Parsing a TLSCiphertext message
  • Decrypting a TLSCiphertext message
  • and so on

These basic blocks allow to control and test each step in a TLS 1.3 connection.

The framework also provides an engine which runs specified actions. The engine allows adding checks which can be run after a connection finishes. The checks can examine the established connection, and detect potential issues.

Supported features

  • TLS 1.3 protocol defined in RFC 8446
  • Client and server modes
  • Key exchange with ECDHE mechanism and secp256r1 curve
  • Signatures with ecdsa_secp256r1_sha256
  • Both client and server authentication
  • AES-GCM cipher with 128-bit key


Here is what a simple HTTPS client looks like:

    .set("localhost", 433)









tlsbunny provides several fuzzers for TLS 1.3 structures such as TLSPlaintext, Handshake, ClientHello, Finished and so on.

On the one hand, such a fuzzer is not going to be as fast as, for example, LibFuzzer. On the other hand, the fuzzer can be easily re-used with multiple TLS implementations written in any language (not only C/C++).

Traditionally, fuzzing is used for testing applications written in C/C++ to uncover memory corruption issues which most likely may have security implications. However, fuzzing can also be also used for testing applications written in other languages even if those languages, like Java, prevent using memory directly. See for example AFL-based Java fuzzers and the Java Security Manager.

No matter which programming language is used, a good TLS implementation should properly handle incorrect data and react in an expected way, for example, by throwing a documented exception. An unexpected behavior while processing incorrect data may still have security implications. even it the TLS implementation is written in a memory-safe programming language.

Example: Fuzzing TLSv1.3 server

Let's run DeepHandshakeFuzzyClient that fuzzes a TLSv1.3 server.

First, make sure that you use Java 11+. Then, build tlsbunny:

mvn clean install -DskipTests

Next, start a target TLSv1.3 server that you'd like to fuzz. Let's assume that it runs on port 50101. It is better to run the server with AddressSanitizer and other sanitizers. They'll report memory corruptions that didn't result to a crash.

Then, prepare a config for tlsbunny:


The certs directory contains certiticates and keys for testing.

total is a number of iterations for the fuzzer.

Finally, run the fuzzer:

java -cp target/tlsbunny-1.0-SNAPSHOT-all.jar \

Watch how the server handles fuzzed TLS messages.

Similar projects

  • tlsfuzzer: SSL and TLS protocol test suite and fuzzer (python)
  • TLS-Attacker: TLS-Attacker is a Java-based framework for analyzing TLS libraries. It is developed by the Ruhr University Bochum and the Hackmanit GmbH.

Discovered bugs


Framework for creating fuzzers and negative tests for TLS 1.3 implementations





No releases published

Sponsor this project


No packages published