Cryptography.Fernet 1.1.1

dotnet add package Cryptography.Fernet --version 1.1.1                
NuGet\Install-Package Cryptography.Fernet -Version 1.1.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cryptography.Fernet" Version="1.1.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Cryptography.Fernet --version 1.1.1                
#r "nuget: Cryptography.Fernet, 1.1.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Cryptography.Fernet as a Cake Addin
#addin nuget:?package=Cryptography.Fernet&version=1.1.1

// Install Cryptography.Fernet as a Cake Tool
#tool nuget:?package=Cryptography.Fernet&version=1.1.1                

Cryptography.Fernet

A .NET implementation of the full Fernet symmetric encryption standard.

Introduction

This .NET library provides routines to create and decrypt Fernet tokens. All features of the current (and only!) 0x80 specification version are included and unit-tested.

The Fernet standard is described here.

Getting Started

Encrypting a message

The simplest method to create a Fernet token is to call Encrypt with your plaintext string. No other parameters are needed. A cryptographically-secure key will be generated for you and returned along with the new token.

(string key, string token) = Cryptography.Fernet.Encrypt("My plaintext message.");
// Now save the key for decrypting the token later on...

Note: internally, .NET's System.Security.Cryptography.RandomNumberGenerator is used to generate the key.

Decrypting a message

To retrieve the original message, you will need the token and the key used to originally encrypt it. Pass both into Decrypt to obtain the original plaintext. The key and token must be in base64url format (the values returned from Encrypt are in this format).

string originalMessage = Cryptography.Fernet.Decrypt(key, token);

If your key and/or token are not in base64url already, use the included Utility.Base64UrlEncoder to convert them (see below for more information).

Additional Features

Encryption with a Key

To encrypt a plaintext message with a pre-existing key, pass it in as the first argument:

string token = Cryptography.Fernet.Encrypt(key, plaintext);

The key must be in base64url format.

Token Lifetime

The creation time is stored within each Fernet token. You can control the lifetime of a token by passing in a TimeSpan to Decrypt's tokenLifetime parameter. For example, a value of 10 seconds means that the token will expire 10 seconds after being created. Decrypt will throw an exception if the token has expired.

Here's an example of the syntax:

// Throws an exception if it has been 20 minutes or longer since the token was created.
string originalMessage = Cryptography.Fernet.Decrypt(key, token, TimeSpan.FromMinutes(20));

Note: a limitation of the Fernet specification is that the original token creation time is stored as whole seconds. As a result of this, sub-second accuracy for token expiry is not possible.

How to Create a Token Without a Timestamp

The token's timestamp field is recorded unencrypted and may in some circumstances be seen as sensitive information. For maximum security, you may wish to skip generation of the timestamp; doing this sets the creation time to the Unix Epoch of 00:00:00 January 1st 1970.

To create a token without a timestamp, set the saveTimestamp parameter of Encrypt to false.

Timestamp Validation and Clock Drift

A token may be decrypted on a machine which didn't generate it. To account for differences in the values of internal clocks between machines, it is permitted to have tokens whose creation times appear to be in the future. However, a maximum is built in to the library, and timestamps which are skewed by more than this value are deemed invalid. An exception will be thrown if you attempt to decrypt one.

The maximum time a token timestamp can be in the future is determined by the MaxClockDrift field in Fernet.cs. To customise this, you will have to edit this value and rebuild from the source code.

Base64url Encoding

Fernet keys and tokens must be in 'base64url' format. This is identical to plain base64 but with 2 character substitutions to make the strings usable in URLs and as filenames. It is described as part of RFC 4648 here.

This project includes a Utility.Base64UrlEncoder class which can be used to convert byte arrays to and from this format.

The following example shows how to use the encoder class before calling Encrypt to generate the Fernet token.

// Create a byte array of the correct size and fill it with random bytes.
byte[] key = new byte[Cryptography.Fernet.KeySize];
System.Security.Cryptography.RandomNumberGenerator.Fill(key);
// Encode the key as a base64url string with the Utility class' Base64UrlEncoder.
string keyString = Utility.Base64UrlEncoder.Encode(key);
// Create the Fernet token.
string token = Encrypt(keyString, "My plaintext message.");

If you have no need to use a specific key, it is recommended to use the Encrypt overload detailed in the Getting Started section, which has only the plaintext parameter; this will handle creating a secure key for you.

Testing

A separate MSTest project is included as part of the source code repository. Test cases for the complete Fernet specification are covered, including all validation tests detailed in the original project's repository. Tests for the Base64UrlEncoder are also included.

To run the tests, start by cloning the repository to your machine. Then either:

  1. Open the solution in Visual Studio, build the solution, and use the Test Explorer (within the Test main menu) to run them, or;
  2. Open a command prompt, navigate to the solution folder and execute dotnet test.

Attributions

File icons created by Payungkead - Flaticon

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.1.1 16,362 9/15/2022
1.1.0 401 9/7/2022
1.0.1 413 8/29/2022
1.0.0 412 8/29/2022

Minor bugfix release to correct RELEASE.md documentation link.