PQCrypto.Lai
0.1.0
dotnet add package PQCrypto.Lai --version 0.1.0
NuGet\Install-Package PQCrypto.Lai -Version 0.1.0
<PackageReference Include="PQCrypto.Lai" Version="0.1.0" />
<PackageVersion Include="PQCrypto.Lai" Version="0.1.0" />
<PackageReference Include="PQCrypto.Lai" />
paket add PQCrypto.Lai --version 0.1.0
#r "nuget: PQCrypto.Lai, 0.1.0"
#addin nuget:?package=PQCrypto.Lai&version=0.1.0
#tool nuget:?package=PQCrypto.Lai&version=0.1.0
<p align="center"> <img src="https://raw.githubusercontent.com/4211421036/pqcrypto/main/logo.png" alt="PQCrypto Logo" width="200" /> </p>
PQCrypto.Lai
Post-Quantum Lemniscate-AGM Isogeny (LAI) Encryption Library for .NET
A .NET(Standard) library implementing the mathematical primitives and high-level API of the Lemniscate-AGM Isogeny (LAI) encryption scheme. The LAI scheme is a promising post-quantum cryptosystem built on isogenies of elliptic curves over lemniscate lattices. It offers conjectured resistance against quantum-capable adversaries, making it a strong candidate for post-quantum encryption in academic research, prototyping, and security-critical .NET applications.
Table of Contents
Overview
Lemniscate-AGM Isogeny (LAI) is an isogeny-based public-key scheme defined over a prime field $\mathbb{F}_p$. Compared to conventional elliptic‐curve cryptography, LAI leverages isogenies of elliptic curves defined over lemniscate lattices. Its security relies on the hardness of computing iterated isogeny walks when a quantum adversary is present.
This library provides:
- A pure-.NET implementation of all low-level primitives: SHA-256 seed hashing, Tonelli–Shanks modular square root, and the LAI transformation $T$.
- A high-level API (
KeyGen
,Encrypt
,Decrypt
) for message confidentiality. - A byte-to-integer block encoder/decoder to enable arbitrary text or binary payload encryption.
- Comprehensive documentation with direct correspondence to mathematical formulas and pseudocode.
It is designed for researchers, educators, and developers who wish to experiment with or integrate a reference LAI implementation into .NET projects.
Mathematical Background
Below is a concise summary of the key mathematical components. For full details, see the corresponding scientific papers on LAI.
1. Hash-Based Seed Function
Define $H(x, y, s)$ over $\mathbb{F}_p$ as:
$$ H(x,,y,,s) ;=; \bigl(\mathrm{SHA256}\bigl(\text{bytes}(x),|,\text{bytes}(y),|,\text{bytes}(s)\bigr)\bigr)\bmod p, $$
where $| $ denotes byte-concatenation and $\text{bytes}(\cdot)$ is the big-endian representation of each integer.
2. Modular Square Root (Tonelli–Shanks)
To solve $z^2 \equiv a ;(\bmod,p)$ for prime $p$:
If $p \equiv 3 \pmod{4}$, then
$$ z ;=; a^{\frac{p+1}{4}}\bmod p. $$
Else, employ the general Tonelli–Shanks algorithm to find $z$ such that $z^2 \equiv a\pmod{p}$, or determine that no square root exists (when $a$ is not a quadratic residue).
3. LAI Transformation $T$
Given:
- a point $(x,,y)\in \mathbb{F}_p^2$,
- a constant parameter $a \in \mathbb{F}_p$,
- an iteration index $s \in \mathbb{Z}$, the LAI step $T((x,y),,s)$ is defined as:
$$
\begin{aligned}
h ; &=, H\bigl(x,,y,,s\bigr)\pmod p,\
x' ; &=, \frac{x + a + h}{2}\pmod p,\
y' ; &=, \sqrt{x,y + h}\pmod p\quad (\text{Tonelli–Shanks}).
\end{aligned}
$$
Hence
$$ T\bigl((x,y),,s; a,p\bigr) ;=;\bigl(x',,y'\bigr). $$
4. Binary Exponentiation of $T$
To efficiently compute $\displaystyle T^k(P_0)$ (iterating $T$ exactly $k$ times, with increasing seed index at each step), use exponentiation by squaring:
function PowT(P, k):
result ← P
base ← P
s ← 1
while k > 0:
if (k mod 2 == 1):
result = T(result, s)
base = T(base, s)
k = k >> 1
s = s + 1
return result
Features
- .NET Standard 2.0-compatible: Library can be consumed by .NET Framework, .NET Core, .NET 5/6/7+, Xamarin, Unity, etc.
- Pure-C# Implementation: Relies only on
System.Numerics.BigInteger
,System.Security.Cryptography
, and built-in cryptographic primitives. - Dynamic JSON Decryption: The
DecryptAll(dynamic laiData)
method can parse and decrypt a JSON payload conforming to the LAI-ciphertext format. - Comprehensive Documentation: All methods carry XML documentation comments linking directly to the mathematical definitions.
- Automated CI/CD: Ready to be extended or forked—includes GitHub Actions workflows for building, packing, and publishing to GitHub Packages and NuGet.org.
Installation
Via NuGet.org
dotnet add package PQCrypto.Lai --version 0.1.0
Or in your .csproj
:
<PackageReference Include="PQCrypto.Lai" Version="0.1.0" />
Once installed, simply add:
using PQCrypto;
From Source
If you prefer to build locally:
git clone https://github.com/4211421036/pqcrypto.git
cd pqcrypto/laicrypto
dotnet restore
dotnet build --configuration Release
dotnet pack --configuration Release -o nupkg
# You can then push the .nupkg or reference the DLL directly in your project.
Usage
The following examples assume you have installed the PQCrypto.Lai
NuGet package into a .NET project.
Key Generation, Encryption & Decryption (C#)
using System;
using System.Numerics;
using PQCrypto;
class Program
{
static void Main()
{
// 1. Define parameters:
// p = a large prime (must satisfy p ≡ 3 (mod 4) or general Tonelli–Shanks),
// a = curve parameter (any integer < p),
// P0 = initial point (x0, y0) ∈ F_p × F_p. For example:
BigInteger p = 10007;
BigInteger a = 5;
(BigInteger X, BigInteger Y) P0 = (1, 0);
// 2. Key Generation:
// Produces a random private scalar 'k' and public point 'Q = T^k(P0)'.
var (k, Q) = LaiCrypto.KeyGen(p, a, P0);
Console.WriteLine($"Private key: {k}");
Console.WriteLine($"Public key: ({Q.X}, {Q.Y})");
// 3. Plaintext message (integer < p):
BigInteger message = 2024;
Console.WriteLine($"Plaintext message: {message}");
// 4. Encryption:
// Returns (C1, C2, r), where C1 = T^r(P0) and C2 = M + T^r(Q).
var (C1, C2, r) = LaiCrypto.Encrypt(message, Q, p, a, P0);
Console.WriteLine($"C1: ({C1.X}, {C1.Y})");
Console.WriteLine($"C2: ({C2.X}, {C2.Y})");
Console.WriteLine($"Random r: {r}");
// 5. Decryption:
// Recovers M = C2 - T^k(C1) (take x-coordinate).
BigInteger recovered = LaiCrypto.Decrypt(C1, C2, k, r, a, p);
Console.WriteLine($"Recovered message: {recovered}");
if (recovered != message)
throw new Exception("Decryption failed: mismatch!");
Console.WriteLine("Round-trip successful. Message matches.");
}
}
Decrypting an External JSON Payload
If you receive a JSON ciphertext from another source (e.g., Python, Node.js, or a web service), you can parse and decrypt it directly:
using System;
using System.IO;
using System.Text.Json;
using System.Numerics;
using PQCrypto;
class JsonDecryptExample
{
static void Main()
{
// 1. Load a JSON file that contains the LAI ciphertext representation:
// {
// "p": 10007,
// "a": 5,
// "P0": [1, 0],
// "k": 1234,
// "Q": [Xq, Yq],
// "blocks": [
// { "C1": [x1, y1], "C2": [x2, y2], "r": r1 },
// { "C1": [x3, y3], "C2": [x4, y4], "r": r2 },
// ...
// ]
// }
string json = File.ReadAllText("ciphertext.json");
// 2. Deserialize into a dynamic object (System.Text.Json):
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
dynamic laiData = JsonSerializer.Deserialize<dynamic>(json, options);
// 3. Call DecryptAll(...) to obtain the raw plaintext bytes:
byte[] plaintextBytes = LaiCrypto.DecryptAll(laiData);
// 4. Convert bytes to UTF-8 string (or any other encoding as needed):
string recoveredText = System.Text.Encoding.UTF8.GetString(plaintextBytes);
Console.WriteLine("Decrypted text:");
Console.WriteLine(recoveredText);
}
}
API Reference
Below is a summary of the public API methods exposed by the PQCrypto.Lai
namespace. Each method includes a brief description and required parameters.
Method Signature | Description |
---|---|
static (BigInteger k, (BigInteger X, BigInteger Y) Q) KeyGen( \) |
Generate a random private key k and compute public point Q = T^k(P0) . |
(BigInteger p, BigInteger a, (BigInteger X, BigInteger Y) P0) |
Parameters: p = prime modulus <br> a = transform parameter <br> P0 = base point $(x_0,y_0)$. |
static ( (BigInteger X, BigInteger Y) C1, (BigInteger X, BigInteger Y) C2, BigInteger r ) Encrypt( \) |
Encrypt a single integer message m < p . <br> Returns ciphertext pair (C1,C2) and random nonce r . |
( BigInteger m, (BigInteger X, BigInteger Y) Q, BigInteger p, BigInteger a, (BigInteger X, BigInteger Y) P0 ) |
Parameters: m = integer message <br> Q = public point <br> p = prime <br> a = transform parameter <br> P0 = base point |
static BigInteger Decrypt( \) |
Decrypt a single ciphertext (C1,C2,r) to recover original integer m . |
( (BigInteger X, BigInteger Y) C1, (BigInteger X, BigInteger Y) C2, BigInteger k, BigInteger r, BigInteger a, BigInteger p ) |
Parameters: C1 = first cipher point <br> C2 = second cipher point <br> k = private key <br> r = nonce used at encryption <br> a , p |
static byte[] DecryptAll( \) |
Decrypt all blocks in a JSON-like dynamic object and return the concatenated plaintext bytes. |
(dynamic laiData) |
Parameter: laiData = dynamic object containing p, a, P0, k, Q, blocks[] (where each block has C1[], C2[], r ). |
static BigInteger H( \) |
Compute the SHA-256–based seed: H(x, y, s) mod p . |
(BigInteger x, BigInteger y, BigInteger s, BigInteger p) |
Parameters: points x,y and iteration index s , prime modulus p . |
static BigInteger? SqrtMod( \) |
Compute a modular square root of a modulo prime p , using Tonelli–Shanks or shortcut p ≡ 3 (mod 4) . Returns null if no solution exists. |
(BigInteger a, BigInteger p) |
Parameters: a = residue, p = prime modulus. |
static (BigInteger X, BigInteger Y) T( \) |
Perform one LAI transform step on a point (x,y) using seed index s . |
((BigInteger X, BigInteger Y) point, BigInteger s, BigInteger a, BigInteger p) |
Parameters: point = $(x,y)$, s = seed index, a = transform parameter, p = prime. |
static (BigInteger X, BigInteger Y) PowT( \) |
Repeatedly apply T exactly exp times starting from seed startS . |
((BigInteger X, BigInteger Y) P, BigInteger startS, int exp, BigInteger a, BigInteger p) |
Parameters: P = initial point, startS = first seed index, exp = number of iterations, a , p |
Testing
This library includes a suite of unit tests that verify correctness of:
- Key generation → Public point consistency
- Encryption/Decryption → Round-trip accuracy over random messages
- Tonelli–Shanks → Validation on both $p \equiv 3\pmod{4}$ and general primes
- Dynamic JSON decryption → Interoperability with payloads produced by Python or Node.js reference implementations
To run tests locally:
cd laicrypto
dotnet test --configuration Release
Contributing
Contributions are welcome! Please follow these steps:
Fork the repository and create a new feature branch:
git checkout -b feature/YourNewFeature
Implement your changes in C# under
laicrypto/
.Add corresponding unit tests under
laicrypto.Tests/
.Run tests locally to ensure everything passes:
cd laicrypto dotnet test
Submit a Pull Request with a clear description of your changes and any relevant benchmarks.
Please adhere to these guidelines:
- Follow .NET code style: use
camelCase
for method parameters,PascalCase
for public methods, etc. - Include XML documentation comments for all public types and methods.
- Write or update unit tests to cover new functionality or edge cases.
- Keep external dependencies to a minimum—prefer built-in .NET libraries.
License
This project is licensed under the MIT License. See LICENSE for full details.
For more information or to report issues, please visit the GitHub repository.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.CSharp (>= 4.7.0)
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 |
---|---|---|
0.1.0 | 208 | 6/2/2025 |