This is Part 2 of the RivloTools Licensing Series. Read part 1 here.

In the first article in this series we talked about why licensing matters for software packages and why sustainable models are important for both developers and the wider Umbraco ecosystem.

In this post we’re going to look at one of the foundations that makes modern licensing systems possible: cryptography.

That word can sound intimidating, but the core ideas are actually quite approachable. Once you understand the basics, concepts like signing licence files and verifying them securely start to make a lot more sense.

What is cryptography?

At its simplest, cryptography is the practice of protecting information using mathematical techniques. It allows data to be:

Cryptography underpins huge parts of the modern internet:

Whenever a system needs to trust that some information is genuine, cryptography is usually involved.

The basic idea behind signing

When we talk about “signing” a licence file, we’re not talking about writing a name at the bottom of a document.

Instead, we use a mathematical signature that proves the file was created by someone who possesses a specific secret key.

The idea works a little like this:

  1. A developer creates a licence file containing details like domain, expiry date, or version.
  2. The licence file is signed using a private cryptographic key.
  3. The software package includes a public key that can verify that signature.
  4. When the licence file is loaded, the software checks the signature.
  5. If the signature matches, the licence is genuine.

If anyone tries to modify the file - even changing a single character - the signature will no longer match.

That’s how we know the licence hasn’t been tampered with.

Public keys and private keys

Modern signing systems use something called asymmetric cryptography.

Instead of one secret key, there are two keys:

The private key is used to create signatures.

The public key is used to verify signatures.

The clever part is that the public key can confirm a signature without revealing the private key.

That means your software can safely verify licences without exposing the secret used to create them.

How can a public key verify something created with a private key?

At first glance, public/private key cryptography feels almost magical.

You have two keys:

And somehow the public key can confirm that a piece of data was signed with the private key - even though it can’t recreate the private key itself.

How does that work?

The key idea is that both keys are built from the same underlying mathematical relationship, but they perform opposite operations.

A simplified RSA example

Most classic digital signatures rely on something called modular arithmetic. Without getting too deep into the maths, the process works roughly like this.

First, two very large prime numbers are chosen:

p = prime number
q = prime number

These are multiplied together:

n = p × q

This number n becomes part of the public key.

Here’s the important part:

If someone only knows n, figuring out p and q again is incredibly difficult when the numbers are hundreds of digits long.

This difficulty - called the integer factorisation problem - is what makes RSA secure. No efficient method for solving this problem is known for sufficiently large numbers.

Creating the key pair

Using those prime numbers, two special numbers are generated:

They are mathematically linked so that applying the private key operation and then the public key operation returns the original value.

In a simplified sense:

(data ^ privateKey) ^ publicKey = data

In other words:

But here’s the crucial detail - knowing the public key does not reveal the private key, because doing that would require factoring the massive number n back into p and q. With modern key sizes, that’s computationally impractical.

Before we move on it's important to clarify that, while the above is conceptually correct it is vastly simplified. Cryptography purists would rightly point out that RSA signatures actually use modular exponentiation, so verification is not exactly reversing encryption in the simple sense. However, this is way beyond the scope of this article and my intellect! Thankfully modern cryptography libraries handle all of that for us.

Why the public key can be shared safely

Because the public key only performs the verification step, it can safely be distributed with your application.

It proves authenticity, but it cannot generate new valid signatures. Only the private key can do that, and that private key never leaves the system that generates licences.

Why signatures are hard to fake

At this point you might reasonably wonder: couldn’t someone guess a valid signature?

In theory, yes. In practice, it’s astronomically unlikely.

Most modern signing systems use keys that are 2048 bits or larger. That means there are roughly:

22048 possible keys

For comparison, the estimated number of atoms in the observable universe is around:

1080

A 2048-bit key represents numbers vastly larger than that.

Even if a computer could test billions, or even trillions, of possibilities per second, it would take longer than the age of the universe to try them all.

Breaking a 2048-bit key

If a machine could check 1 trillion keys per second, it would still take roughly:

1052 years

The universe is about 13.8 billion years old.

Hashing: the hidden helper

Before a signature is created, most systems run the licence file through a hash function.

A hash function converts data into a fixed-length fingerprint.

For example:

Hello world

might become something like:

64ec88ca00b268e5ba1a35678a1b5316

The important properties of cryptographic hashes are:

This means the signature actually protects the hash of the licence file, not the entire file itself.

That keeps the process efficient while still guaranteeing integrity.

One character changes everything

Changing a single character in a hashed message produces a completely different fingerprint.

Hello world

vs

Hello World

Even though the difference is tiny, the resulting hashes are entirely different.

How this fits into licence validation

Putting everything together, a typical licence verification process looks like this:

  1. The software reads the licence file
  2. A hash is calculated from the contents
  3. The signature is checked using the public key
  4. If the signature matches, the licence is authentic
  5. The application then checks domain, version, expiry, or other conditions

If any part of the file has been modified, the verification step fails.

This gives developers a strong, reliable way to ensure licences are genuine.

Why this matters for package developers

For many developers, licensing can feel like an afterthought compared to building features.

But cryptographic signing gives you something extremely valuable: trust in the validation process.

You can have confidence that:

And the good news is that modern frameworks make implementing these ideas far simpler than they used to be.


Coming next

Now that we’ve covered the basic ideas behind cryptography and digital signatures, the next step is to look at how to generate and sign licence files in .NET.

In the next article we’ll walk through a practical example showing how licence files can be generated, signed, and verified.