KpqC

KpqC provides safe, synchronous Dart APIs for AIMer, HAETAE, NTRU+, and SMAUG-T.

Runtime support

  • Dart 3.13 or newer
  • Linux, macOS, or Windows
  • A supported C11 toolchain for the target platform

The package uses Dart build hooks to compile and bundle its native code. macOS on Apple silicon is currently verified locally; desktop CI is configured for Linux, macOS, and Windows. Android and iOS build targets are implemented but remain unverified. Dart Web is not supported because the implementation uses dart:ffi.

Use dart run, dart test, or dart build cli so that Dart runs the native build hooks. The legacy dart compile exe command does not bundle code assets.

Install

dart pub add kpqc

Available schemes

Algorithm Type Exports
AIMer Signature aimer128f, aimer128s, aimer192f, aimer192s, aimer256f, aimer256s
HAETAE Signature haetae2, haetae3, haetae5
NTRU+ Key encapsulation ntruplus768, ntruplus864, ntruplus1152
SMAUG‑T Key encapsulation smaugt128, smaugt192, smaugt256, timer

Importing an algorithm family keeps the entry point focused:

import 'dart:convert';
import 'dart:typed_data';

import 'package:kpqc/aimer.dart';

void main() {
  final payload = Uint8List.fromList(utf8.encode('release-manifest:v3'));
  final keys = aimer128f.generateKeyPair();
  try {
    final proof = aimer128f.sign(payload, keys.secretKey);
    if (!aimer128f.verify(payload, proof, keys.publicKey)) {
      throw StateError('Signature verification failed');
    }
  } finally {
    keys.dispose();
  }
}

Signature contexts

AIMer and HAETAE accept an optional context. A context separates signatures created for different application purposes and may contain up to 255 bytes.

import 'dart:convert';
import 'dart:typed_data';

import 'package:kpqc/haetae.dart';

void main() {
  final payload = Uint8List.fromList(utf8.encode('account=42'));
  final context = Uint8List.fromList(utf8.encode('audit-record'));
  final keys = haetae3.generateKeyPair();
  try {
    final signature = haetae3.sign(
      payload,
      keys.secretKey,
      context: context,
    );
    final valid = haetae3.verify(
      payload,
      signature,
      keys.publicKey,
      context: context,
    );
    print(valid); // true
  } finally {
    keys.dispose();
  }
}

Verification fails when the supplied context does not match the one used for signing.

Key encapsulation

A KEM creates a shared secret for a sender and a recipient. The public key may be distributed; the secret key and resulting shared secret must remain private.

import 'dart:typed_data';

import 'package:kpqc/smaugt.dart';

void main() {
  final recipient = smaugt192.generateKeyPair();
  try {
    final outbound = smaugt192.encapsulate(recipient.publicKey);
    try {
      // Send outbound.ciphertext to the recipient.
      final inboundSecret = smaugt192.decapsulate(
        outbound.ciphertext,
        recipient.secretKey,
      );
      try {
        print(_sameBytes(inboundSecret, outbound.sharedSecret)); // true
      } finally {
        inboundSecret.fillRange(0, inboundSecret.length, 0);
      }
    } finally {
      outbound.dispose();
    }
  } finally {
    recipient.dispose();
  }
}

bool _sameBytes(Uint8List left, Uint8List right) {
  if (left.length != right.length) return false;
  var difference = 0;
  for (var index = 0; index < left.length; index++) {
    difference |= left[index] ^ right[index];
  }
  return difference == 0;
}

Imports

Each family has a dedicated library:

import 'package:kpqc/aimer.dart';
import 'package:kpqc/haetae.dart';
import 'package:kpqc/ntruplus.dart';
import 'package:kpqc/smaugt.dart';

All named algorithms are also exported from the package root:

import 'package:kpqc/kpqc.dart';

final SignatureAlgorithm signer = aimer192f;
final KeyEncapsulationAlgorithm keyExchange = ntruplus864;

Data and failures

Inputs and outputs use Uint8List. Each algorithm exposes an id and a sizes value. Incorrect key or ciphertext lengths throw ArgumentError; native failures throw KpqCException. Signature verification returns false for an invalid signature.

Parameter sizes

All sizes are in bytes.

Signatures

Algorithm Public key Secret key Signature
aimer128f 32 48 5,888
aimer128s 32 48 4,160
aimer192f 48 72 13,056
aimer192s 48 72 9,120
aimer256f 64 96 25,120
aimer256s 64 96 17,056
haetae2 992 1,408 1,474
haetae3 1,472 2,112 2,349
haetae5 2,080 2,752 2,948

Key encapsulation

Algorithm Public key Secret key Ciphertext Shared secret
ntruplus768 1,152 2,336 1,152 32
ntruplus864 1,296 2,624 1,296 32
ntruplus1152 1,728 3,488 1,728 32
smaugt128 672 832 672 32
smaugt192 1,088 1,312 992 32
smaugt256 1,440 1,728 1,376 32
timer 672 832 608 32

Methods reject values of the wrong size. Signature verification returns false for an invalid signature. NTRU+ rejects an invalid ciphertext. SMAUG-T performs implicit rejection and returns a replacement secret instead; that value will not equal the sender's shared secret.

Distribution

The published package includes Dart libraries and the bundled native sources. Build hooks compile each parameter set with its upstream configuration macros, isolate its C symbols, and use Dart 3.13 link-time usage recording to bundle only the native assets used by the application.

KeyPair.dispose() and EncapsulatedSecret.dispose() overwrite their secret byte lists on a best-effort basis. The caller is responsible for clearing the list returned directly by decapsulate.

Building from source

A C11 compiler and the Dart SDK are required for normal development:

dart pub get
dart analyze
dart test

Security

The native cores are compiled from the upstream algorithm implementations. This package has not received an independent security audit and does not provide a constant-time execution guarantee. Assess those constraints before using it with sensitive production keys.

Third-party licenses and attributions are listed in THIRD_PARTY_NOTICES.md.

Libraries

aimer
AIMer signature parameter sets.
haetae
HAETAE signature parameter sets.
kpqc
Safe, synchronous Dart APIs for KpqC post-quantum cryptography.
ntruplus
NTRU+ key-encapsulation parameter sets.
smaugt
SMAUG-T key-encapsulation parameter sets.