Skip to main content

How to sign messages in Java and verify in Go

In my company, we use Java and Go as our development platforms and of course, sometimes those projects have to communicate with each other. In the current blog post, I would like to introduce our solution to sign messages on the Java side and verify them in a Go service.

First, let's talk a bit about architecture. Our Java application spins up new virtual machines in the cloud, and the base image of the instance contains a small Go service. That service is the main entry point of our configuration management system, and we don't want to allow any operation from untrusted clients to modify nodes. Two-way SSL with a signature in the request sounded fair enough to trust in clients. Both components are open source, we don't have any "secret" in the binaries, so we elected RSA asymmetric key pairs to generate and verify signatures. Java has the private key and Go has the public one. Time to go deeper.

Java is an old platform (personally I have many years of experience with it), has many libraries on the topic, so I started with Go. I don't have a sixth sense, but I felt that Go should be the weakest in the list of supported protocols. The good news is, Go has a built-in crypto/rsa package, the bad news is it supports only PKCS#1. During the research, I found a 3rd party library with PKCS#8 support and we had to stop and weigh at this point of the planning:
  1. built-in well-tested library with older standards
  2. unknown package with newer standards.
PKCS#1 is not the latest version of the standard, but the 3rd party looked out too risky the other hand. We selected the first option.

Back in business, we have the library, which has only one option namely the VerifyPSS function to verify PSS (Probabilistic signature scheme) signatures.

On Java side, the client puts an extra header into the request, which contains the signature of the request's body, generated with the private key. The next step is to find the signature and call the function implemented previously.
Lastly, implement the HTTP handler and wrap it with the verifier.
I wrote a unit test to be sure the verification works as designed.
Seems we are ready with the service side of the implementation, let's write some Java code. I researched how to generate PSS signatures in Java, and I found that one of our dependencies already contains the required feature. Bouncy Castle Crypto API is a well-known library in the Java world and it was straightforward to apply it.
That's it...
ps: I don't want to bore you with how to generate key pairs in Java, you can find many options on the Internet.

Popular posts from this blog

Advanced testing of Golang applications

Golang has a nice built-in framework for testing production code and you can find many articles on how to use it. In this blog post, I don't want to talk too much about the basics , table-driven testing ,  how to generate code coverage  or detect race conditions . I would like to share my personal experiences with a real-world scenario. Go is a relatively young and modern programming language on one side, and it is an old fashion procedural language on the other. You have to keep in mind that fact when you are writing production code from the beginning, otherwise, your program should become an untestable mess so easily. In a procedural way, your program is executed line by line and functions call other functions without any control of the dependencies. Hard to unit test, because you are testing underlying functions too, which are side effects from the perspective of testing.  It looks like everything is static if you are coming from object-oriented world. There are...

Kubernetes and Calico development environment as easy as a flick

I became an active member of the Calico community so I had to build my own development environment from zero. It wasn't trivial for many reasons but mainly because I have MacOS on my machine and not all of the features of Calico are available on my main operating system. The setup also makes some sense on Linux hosts, because if the node controller runs locally it might make changes to the system, which always has some risk in the playing cards. The other big challenge was that I wanted to start any version of Kubernetes with the ability to do changes in it next to Calico. Exactly I had to prepare two tightly coupled environments. My idea was to create a virtual machine with Linux on it, configure development environments for both projects in the VM and use VSCode 's nice remote development feature for code editing. In this way projects are hosted on the target operating system, I don't risk my system, I don't have to deal with poor file system sync between host a...

Autoscaling Calico Route Reflector topology in Kubernetes

Kubernetes is a great tool to organize your workloads on a low or high scale. It has many nice features in different areas, but it is totally out-sourcing the complexity of the network. Network is one of the key layers of a success story and happily there are many available solutions on the market. Calico is one of them, and it is I think the most used network provider, including big players in public cloud space and has a great community who works day by day to make Calico better. Installing Kubernetes and Calico nowadays is easy as a flick if you are happy with the default configurations. Otherwise, life became tricky very easily, there are so many options, configurations, topologies, automation, etc. Surprise or not, networking is one of the hard parts in high scale, and requires thorough design from the beginning. By default Calico uses IPIP encapsulation and full mesh BGP to share routing information within the cluster. This means every single node in the cluster is connected w...