liboqs 2.1.0
liboqs: ^2.1.0 copied to clipboard
Dart FFI bindings for liboqs — high-performance post-quantum cryptography (PQC) with ML-KEM, ML-DSA, Falcon, SLH-DSA for key encapsulation and signatures.
2.1.0 - 2026-08-01 #
For Users #
✨ Highlights
- Third-party notices now ship with the package —
THIRD_PARTY_NOTICES.txtcarries the attribution for the third-party code compiled into the native library, both at the package root and inside every native release archive. Redistributors of an app embedding this package need it; see Third-party notices in the README for how to surface it in-app. - Consuming projects build faster — the Build Hook stopped re-running on every single build and now reuses its cached result.
- Dart API unchanged — nothing to migrate.
KEM,SignatureandOQSRandomare exactly as in 2.0.0, and the bundled liboqs is still 0.16.0.
Added
-
THIRD_PARTY_NOTICES.txt— attribution for the code inside the native library. liboqs is MIT "in general", and its ownLICENSE.txtsays the rest out loud: "liboqs includes some third party libraries or modules that are licensed differently; the corresponding subfolder contains the license that applies in that case." This package was shipping a compiled binary containing that code while carrying only the top-level MIT — so the notices Apache-2.0, BSD-3-Clause and the various public-domain dedications require were not travelling with it. Flutter'sLicenseRegistrydoes not close this: it collects LICENSE files of pub packages, not of C code compiled into a native library. The file now ships at the root of the package and inside every native release archive, and the README explains how to surface it in an app.Two findings from building it are worth stating, because they are what the inventory is actually for.
src/common/common.cisApache-2.0 AND MIT— a conjunction, not a choice — and it is linked into all eleven artifacts, so Apache-2.0's terms bind every binary this package ships. And one file in the Keccak tree,KeccakP-1600-AVX2.S, is under the CRYPTOGAMS licence rather than the CC0 waiver the directory around it carries; it has no SPDX identifier and no licence file, so nothing short of reading the header would have found it.
Fixed
- The Build Hook no longer re-runs on every build.
hook/build.dartdeclared the.skip_liboqs_hookmarker as a build dependency unconditionally, andhooks_runnerreports a declared file that does not exist as modified during the build — so every build in a consuming project re-ran the hook instead of reusing its cached result. The marker is now declared only while it exists, which is the only direction that needs invalidation: whenmake buildremoves it, the skipped result is dropped. A marker created after a full run leaves that run cached, and downloading nothing is exactly what the marker asks for.
For Contributors #
Added
-
make third-party-notices/make verify-third-party-noticesgenerate and check the notice inventory. The generator resolves each liboqs source through its own SPDX tag, then the nearest licence file, thendocs/algorithms/<class>/<family>.yml, then an explicit override — and fails on a source matched by none of them, so a liboqs release that vendors an unfamiliar licence stops for a person instead of being filed under MIT. A single walk up to the nearest LICENSE, which is the obvious implementation, would have been wrong about 43% of the sources: 2532 of the 5957 files undersrc/have no licence file anywhere between them and the repository root. Verification is byte-exact and runs in the test workflow, before the native build, and in both release preflights;.gitattributesmarks the file-textso a clean checkout materialises the same bytes the generator wrote.The inventory covers the whole liboqs tree minus
src/sig_stfl/, which is not a shortcut: the union of the real link lines across all eleven shipped artifacts implicates 151 of the tree's 153 licence files, and the two it omits are exactly the stateful-signature ones. Deriving it from the sources rather than from a configured build is what lets the check be byte-exact at all — an inventory built from CMake would depend on whether the host had Xcode and an NDK. -
make lint-workflowsandmake check-action-pinsrun in CI as one fast job, covering the two workflows nothing else touches before a release. actionlint reads the workflows statically — expressions,needs/stepsreferences, runner labels, the reusable-workflow contract, and shellcheck over everyrun:block — and is pinned by version and SHA256, because release assets are mutable.check-action-pinsresolves every third-partyuses:against the GitHub API, which actionlint cannot do: it is entirely offline, and on an action ref its bundled snapshot does not recognise it silently switches its checks off rather than reporting one, so a fabricated@v999or a made-up 40-character SHA passes it without a word. Adopting actionlint also required suppressing two of its findings in.github/actionlint.yaml— its snapshot predatescreate-github-app-token'sclient-id, so it is wrong about the very change made above.
Changed
- Quoted every
>> "$GITHUB_OUTPUT"-style redirect across the workflows and thesetup-fvmcomposite action, and grouped the three step-summary blocks into a single redirect. All 25 were shellcheckSC2086findings surfaced by the new lint job. None could actually misbehave — GitHub sets those paths to space-free values — but they are fixed rather than suppressed, so the rule stays live to catch a word-splitting bug that would matter. - GitHub Actions moved to their current majors —
actions/checkoutv4→v7,actions/upload-artifactv4→v7,actions/download-artifactv4→v8,actions/cachev4→v6,actions/create-github-app-tokenv2→v3,android-actions/setup-androidv3.2.2→v4.0.1 andschneegans/dynamic-badges-actionv1.7.0→v1.9.0. Mostly the Node 20→24 runtime migration, which needs no change on GitHub-hosted runners. Two are worth knowing about:download-artifactv8 now fails a run on an artifact digest mismatch instead of logging a warning, which is a welcome hardening of thecreate-releasejob that packages the native archives consumers download; andcheckoutv7 refuses to check out a fork PR underpull_request_target/workflow_run, which does not affect this repo —pull_request_targetis never used, and the oneworkflow_runtrigger (test.yml, afterbuild-liboqs.yml) fires off a tag push or a dispatch, so the guard short- circuits before it can apply. Artifact layout is unchanged: v5's breaking path fix only covers single downloads byartifact-ids, whilecreate-releasedownloads every artifact by name intoartifacts/<name>/. create-github-app-tokenis called withclient-id— the v2→v3 bump above made every run that mints an App token annotateInput 'app-id' has been deprecated with message: Use 'client-id' instead.The rename is the entire change: the action collapsesclient-id || app-idinto a single value and passes it as the JWTissclaim, and GitHub has accepted either the numeric App ID or theIv23…client ID there since May 2024 — sovars.APP_IDkeeps both its name and its value, and no repository variable had to be created.app-idis deprecated by annotation only, with no removal scheduled, so this is cosmetic; it is worth doing because the warning was otherwise printed bycheck-liboqs-updates.ymlon every daily run and bybuild-liboqs.ymlon every native release.- Dependabot branches are exempt from the branch rulesets —
Signing commitappliesnon_fast_forwardto~ALLbranches with no bypass actors, so Dependabot, which refreshes an open PR by force-pushing a rewritten commit, could never rebase one onto a movedmain; its first scheduled run gave up with "because the branch … is protected it was unable to do so", leaving the PR frozen at the day it was opened.refs/heads/dependabot/**/*is now excluded from that ruleset and fromDelete branches(which blocked@dependabot recreateand branch cleanup for the same reason). Nothing is weakened: Dependabot signs its commits regardless of the rule, andmainkeeps both its pull-request gate andrequired_signatures. The trailing/*is load-bearing — these arefnmatchpatterns in pathname mode, so a bare**stops at the first/and would miss the multi-segment names Dependabot actually generates.
Fixed
make releasefailed its own validation step, so no release could be cut. It bumpedpubspec.yamland finalized the CHANGELOG, then ranmake publish-dry-runon that bumped-but-uncommitted tree — and pub answers a modified tracked file with "checked-in files are modified in git", which is a warning, anddart pub publish --dry-runexits 65 on any warning at all. The step's own comment asserted the opposite ("pub exits 0 on warnings"), so the release aborted and reverted every time, on a state it had created itself. The dry-run now runs before the bump, on the clean tree, which is where the sibling template has had it since it introduced the two-stage flow. Catching power is unchanged: the dry-run validates package structure — files present, archive size, pubspec validity — and neither a version bump nor a CHANGELOG edit can affect that. Nothing is modified at that point either, so the revert path it needed is gone with it.insertChangelogEntrymatched the target subsection withline.startsWith('#### Changed'), which also matches#### Changed (Breaking). Because the branch fires once per matching heading, an[Unreleased]section carrying both subsections — the shape this CHANGELOG's 2.0.0 section already has — got the routine dependency bump announced as a breaking change and repeated under the real#### Changed. When only the breaking variant was present,#### Changedwas never created at all. The heading is now matched exactly, and a#### Changedthat has to be created is anchored just before the first subsection that follows it in the documented order (#### Security,#### Fixed, …) instead of being appended below them. Missing#### ✨ Highlightslikewise moves to the top of the### For Usersblock rather than wherever the scan happened to be. Backported from the copier template, whose generated projects share this script; the two failure shapes are now covered intest/scripts/release_test.dart, which had no case with a breaking subsection present.- The FVM cache in CI never saved anything.
setup-fvmcached~/.fvm, but.fvmis FVM's project-local directory name — installed SDKs live in$HOME/fvm/versions(fvmDir = cachePath ?? $HOME/fvmin FVM 4.x). That path never existed, soactions/cacheended every job withPath Validation Error: … hence no cache is being savedin a green post-step, the repository held no cache entries at all, and each job on all four platforms reinstalled Flutter from scratch (~80 s apiece). The action now caches~/fvm/versionsand makes that location a contract rather than a guess:FVM_CACHE_PATHis set explicitly, and FVM itself is pinned to 4.1.2 (exposed as the action'sfvm-versioninput, since Dependabot cannot see adart pub global activateline) so no unannounced major can relocate the SDKs. A step afterfvm installthen fails the job if they land anywhere else — annotate-and-continue is precisely the mode that hid this bug for months, so it is not the safe option but the broken one with a louder log line, and nothing irreversible sits behind the check: setup-fvm runs before the release archives, the tag and the pub.dev publish, so a release is re-run rather than broken. Two latent problems came out with it: the key gainedrunner.arch, becauseubuntu-latestandubuntu-24.04-armboth reportrunner.os == 'Linux'and shared one key — the first working save would have handed an x86-64 SDK to the ARM64 runner — andrestore-keysis gone, since a partial hit restores the previous SDK,fvm installadds the new one beside it, and the cache would grow by ~2.5 GB with every Flutter bump. Verified onmain: four entries saved, one per (OS, arch), 700–710 MiB each (1.2–1.3 GB unpacked), and no morePath Validation Error. - Pull requests that only touch CI ran no checks at all.
test.ymlfiltered onlib/**,test/**andpubspec.yaml(plus its own two workflow files on push), so a Dependabot action bump could merge unverified — #5 had to be validated by hand withworkflow_dispatchon the PR branch — and even a matching path would then have been skipped byuser.type != 'Bot', a guard meant only for the liboqs update PRs..github/**is now covered on bothpull_requestandpush, and update PRs are matched by branch name (update-liboqs-*, created bycheck-liboqs-updates.yml) instead of author type, so Dependabot PRs run the full matrix whilenative_versionbumps keep skipping until their native libraries exist. Apull_requestrun resolvestest-reusable.ymland.github/actions/*from the PR's merge ref, so a bumped action really does execute; thepushfilter earns its place too, because PR runs may read the base branch's cache scope but never the reverse — without a run onmainafter each CI change, every PR's first run would start from a cold FVM cache.hook/**,scripts/**andMakefilejoined the same filters for the same reason one level down:test/hook/build_hook_test.dartandtest/scripts/release_test.dartcover exactly those, so a change to the Build Hook or to the release scripts was the one commit its own tests never ran on. - A broken liboqs update checker looked exactly like "up to date". The
scheduled check ran
make check … || true, which it has to: the checker exits 1 to signal "update available", and GNU make collapses any non-zero recipe status into its own exit 2, so the exit code cannot tell that apart from a crash (rate limit, API change, network) — an available update and a rejected--versionargument both come back asmakeexit 2. The step now gates on the artefact instead — the checker writesneeds_update=toGITHUB_OUTPUTbefore signalling, and not at all when it throws — and fails the run when that line is missing rather than reporting the current version as the latest forever. Both paths were exercised locally through the real target. The manually dispatchedtarget_versionis shape-checked in the workflow as well, before it is interpolated intomake check ARGS=…where a;would reach the recipe shell. - A release could be aborted by an unrelated diverged tag.
make releaseandmake release-nativefetchedorigin --tags, so a single diverged tag anywhere in the namespace failed the fetch and stopped the release. Both now fetchorigin main --no-tags: the behind/ahead check needs onlyorigin/main, and the "tag already on origin?" check asksgit ls-remotedirectly. - Upstream version tags are validated on every path, not just the API
response.
validateUpstreamTag(exported and covered bytest/scripts/check_updates_test.dart) now also guards the--versionargument passed by hand and the version recorded inpubspec.yaml— both reachGITHUB_OUTPUT, a branch name and amakerecipe. Its pattern additionally rejects non-canonical segments such as0.016.0, which the previous\d+groups accepted. - Releasing no longer leaves an empty
## [Unreleased]behind.finalizeChangelogrenames the heading in place, so an empty section stops shipping to pub.dev with every release; the scripts that record unreleased changes create the section when it is absent, and the footer[Unreleased]:compare link — load-bearing, it carries the repo URL and the previous version — is deliberately kept. Relatedly, when## [Unreleased]exists without a### For Userssubsection,insertChangelogEntrynow creates one at the top of the section instead of appending it below### For Contributors, and no longer duplicates the### For Usersheading when the section ends with one.
2.0.0 - 2026-07-20 #
For Users #
✨ Highlights
- Bundled liboqs upgraded 0.15.0 → 0.16.0 (breaking) — includes upstream security fixes (see Security) plus the algorithm removals and renames below.
- Dart API unchanged —
KEM,Signature, andOQSRandomare source-compatible; every breaking change is in algorithm availability or the bundled native library, not the class API. - SPHINCS+ removed (breaking) —
Signature.create('SPHINCS+-…')now throwsLibOQSException; migrate to SLH-DSA (FIPS 205) or ML-DSA (FIPS 204). - HQC renamed and enabled by default (breaking) —
HQC-128/HQC-192/HQC-256→HQC-1/HQC-3/HQC-5, updated to the 2025-08-22 spec. - FrodoKEM is now the salted variant (silent breaking) — keys/ciphertexts are
not interoperable with 0.15.0; the old ephemeral behavior moved to the new
eFrodoKEM-*identifiers. - Now usable from standalone Dart — the package dropped its Flutter SDK
constraint (pure
dart:ffi), so it works outside Flutter and shows both the Dart and Flutter badges on pub.dev.
Changed (Breaking)
- Upgraded bundled liboqs native library from 0.15.0 to 0.16.0.
FrodoKEM-640-AES,FrodoKEM-640-SHAKE,FrodoKEM-976-AES,FrodoKEM-976-SHAKE,FrodoKEM-1344-AES, andFrodoKEM-1344-SHAKEnow select the salted FrodoKEM variant instead of the ephemeral variant used in 0.15.0. The identifiers are unchanged but keys and ciphertexts are not interoperable with 0.15.0. The previous ephemeral behavior is now available under the neweFrodoKEM-*identifiers (see Added). PrefereFrodoKEM-*when each keypair encapsulates only a few shared secrets, andFrodoKEM-*(salted) for high-volume encapsulation.- HQC identifiers were renamed
HQC-128/HQC-192/HQC-256→HQC-1/HQC-3/HQC-5. HQC is now enabled by default and updated to the 2025-08-22 specification.KEM.create('HQC-128')now throwsLibOQSException.
Changed
ML-DSA-44/ML-DSA-65/ML-DSA-87are now backed by the portablemldsa-nativeimplementation (with x86_64/aarch64 optimizations); identifiers and behavior are unchanged.sntrup761(NTRU Prime) now uses the public-domain OpenSSH implementation.- Dropped the
flutter: ">=3.38.0"SDK constraint. The package contains no Flutter imports (puredart:ffi), so it is now usable from standalone Dart as well as Flutter, and pub.dev reports both the Dart and Flutter SDK badges (previously Flutter only). Verified withpana. SECURITY.mdsubstantially expanded: secret lifetime and memory model (what the native/Dart layers guarantee and what garbage-collected memory cannot), timing-attack prevention, key-material handling, randomness, supply-chain integrity of the prebuilt native libraries (including the honest limits of same-release SHA256 verification), and a contributor security checklist.
Added
- Ephemeral FrodoKEM identifiers:
eFrodoKEM-640-AES,eFrodoKEM-640-SHAKE,eFrodoKEM-976-AES,eFrodoKEM-976-SHAKE,eFrodoKEM-1344-AES, andeFrodoKEM-1344-SHAKE. - HQC (
HQC-1,HQC-3,HQC-5) is now enabled by default. - MQOM signature scheme family (12
mqom2_cat{1,3,5}_gf16_{fast,short}_r{3,5}parameter sets) — a candidate in NIST's Additional Digital Signatures process, new upstream in liboqs 0.16.0 and enabled by default. - Upstream runtime-detection API for stateful signature support (
OQS_SIG_STFL_*).
Removed (Breaking)
- SPHINCS+ signature algorithms — all 12
*-simplevariants of both theSPHINCS+-SHA2-*andSPHINCS+-SHAKE-*families — were removed upstream in liboqs 0.16.0.Signature.create('SPHINCS+-…')now throwsLibOQSException. Migrate to SLH-DSA (FIPS 205,SLH_DSA_PURE_*) or ML-DSA (FIPS 204). - Legacy HQC identifiers
HQC-128/HQC-192/HQC-256(renamed; see Changed (Breaking)).
Fixed
- Build hook: the download cache key now includes the full version
(
native_version+native_build) and the full platform variant. Previously it keyed only onos-arch, which (1) let iOS device and simulator builds shareios-arm64on Apple-silicon hosts and poison each other's cache (dyld "incompatible platform" at runtime), and (2) omitted the version, so after a version bump a stale binary from the previous release could be reused instead of downloading the new one. - Build hook: download/cache resilience against partial and transient failures.
A cache entry is now reused only after a
.download-completemarker proves the extraction finished, so an interruptedtarno longer leaves a truncated library that is registered and reused forever; and both the checksums fetch and the binary download now retry on transient HTTP 5xx/429 instead of failing the build on a single network blip.
Security
- Build hook: SHA256 verification of downloaded native libraries is now
fail-closed. Previously a missing or unreachable checksums file (e.g. a
MITM blocking the checksums URL) was downgraded to a warning and the
unverified binary was installed anyway. The build now aborts unless the new
LIBOQS_ALLOW_UNVERIFIED_DOWNLOAD=1escape hatch is explicitly set.
Includes the following upstream liboqs 0.16.0 security fixes:
- Fixed uninitialized
encaps_derandpointer dereference (open-quantum-safe/liboqs#2460). - Fixed out-of-bounds read in XMSS/XMSS^MT signature verification (open-quantum-safe/liboqs#2384).
- Fixed integer underflow in CROSS
crypto_sign_open(). - Fixed incorrect array size when calling
secure_clean. - Added the
OQS_MEM_BLACK_BOXoptimization barrier hardening FrodoKEMct_selectconstant-time protection (open-quantum-safe/liboqs#2431).
See the full liboqs 0.16.0 release notes.
For Contributors #
Added
make check-targets— guard that keeps the iOS/macOS deployment targets in the native build scripts internally consistent (scripts/check_deployment_targets.dart); now also enforced in CI (see Changed).make release— one-command scripted release (scripts/release.dart): checks you are on a clean, up-to-datemain, verifies the nativeliboqs-<fullVersion>GitHub Release exists (fail-closed — the published build hook downloads it), bumpspubspec.yaml, finalizes the CHANGELOG[Unreleased]section including the bottom compare links, validates with a publish dry-run, then creates a signed commit + signedvX.Y.Ztag and pushes to trigger the pub.dev publish. Comes with arelease-packageskill guide and unit tests for the CHANGELOG finalization.make update-changelog— AI-drafted CHANGELOG entry for liboqs version bumps (scripts/update_changelog.dart, GitHub Models): classifies upstream changes by user visibility (algorithm additions/removals/renames and wire-format changes are breaking and user-visible; CI/docs/build-system churn is not). The liboqs update checker now includes such a draft[Unreleased]entry in its automated PRs (requires theAI_MODELS_TOKENrepository secret; non-fatal when absent).make release-native— deliberate, scripted release of the native libraries (scripts/release_native.dart): verifies a cleanmainexactly in sync withorigin/mainand thatliboqs-<fullVersion>(tag and release) doesn't exist yet, then creates a signedliboqs-<fullVersion>tag and pushes it, which triggers the native build.make setup-repo-protections— applies the committed repository rulesets (.github/rulesets/*.json: protected release tags, protectedmain, signed commits, no branch deletion) and configures thenative-buildenvironment with a required reviewer viagh(scripts/setup_repo_protections.dart; runbook in.github/rulesets/README.md).- Build provenance attestation for the native release archives:
build-liboqs.ymlattests every archive with GitHub Artifact Attestations (Sigstore, SLSA Build L2) and attaches the Sigstore bundle (liboqs-<fullVersion>.sigstore.jsonl) to the release, so any downloaded binary can be verified — online or fully offline — withgh attestation verify(see SECURITY.md → Authenticity). This breaks the self-trust of the same-release SHA256 checksums file. - Dependabot for GitHub Actions (
.github/dependabot.yml): weekly grouped update PRs (Monday 06:00 UTC,chore(deps)prefix) bump the pinned actions — commit SHA and its version comment — across the workflows and the composite actions, so the SHA pins from the supply-chain audit don't go stale.
Changed
- Regenerated FFI bindings for liboqs 0.16.0.
- CI hardening & reliability (Phase 4). Workflows now run with a
least-privilege
GITHUB_TOKEN(workflow-levelcontents: read; only the release-publishing jobs opt up to the specific writes they need). The native-library build workflow serializes concurrent runs for the same ref via aconcurrencygroup. Windows runners install GNU Make from a pinned GitHub release (with retry + size check) via asetup-makecomposite action instead of Chocolatey. The deployment-target guard (make check-targets) runs in the CI quality checks alongsideanalyze/format-check. The publish workflow gained a dedicated package-validation (publish-dry-run) job that gates publishing. The liboqs update checker skips when an open update PR for the same version already exists, so scheduled runs no longer force-push over manual commits on that PR. - CI supply-chain hardening (pre-release audit). The upstream version tag
from the liboqs update check is format-validated before it reaches
GITHUB_OUTPUT, and workflowrun:blocks read it (and the other step outputs) viaenv:instead of inline${{ }}interpolation — closing a shell-injection path from upstream release names. Third-party GitHub Actions are pinned to commit SHAs, and the Windows GNU Make helper binary is verified against a hardcoded SHA256 before use. - Tag-triggered native builds.
build-liboqs.ymlnow triggers on aliboqs-<fullVersion>tag push (created bymake release-native) instead of everypubspec.yamlpush tomain: merging a version bump no longer builds or publishes anything by itself, the tag is validated againstpubspec.yamlat the tagged commit, the GitHub Release is created on that same tag (the delete-then-recreate step is gone), and the release-publishing job is gated by thenative-buildenvironment (mirrors the pub.dev publish gate; inert until reviewers are configured). - Release notes hardened against changelog injection.
publish.ymlnow passes the version and changelog throughenv:and writes the release notes withprintfto a--notes-file, so a literalEOFline in the changelog can no longer terminate the inline heredoc early and execute the remaining text as shell under thecontents: writetoken. - Release-exists CI probe fails closed.
check_release.dartnow distinguishes exists / missing / inconclusive and aborts (exit 1) on an API error or network failure instead of reporting the release as absent and letting a build proceed on a wrong assumption. - Release-script robustness.
runInheritfails loud on any non-zero exit (previously swallowed when no failure message was passed),finalizeChangelogvalidates the--date(YYYY-MM-DD) before stamping the immutable released heading, and the commit-failure message now states the version bump is left staged and how to recover.
Removed
- All platform-plugin scaffolding: the
ios/macos/liboqs.podspecfiles, theios/Classes/LiboqsPlugin.swiftstub, theandroid/Gradle project (build.gradle,settings.gradle,AndroidManifest.xml), and thelinux//windows/CMakeLists.txt(plus stale generated app registrants). This is a plain Dart FFI package, not a Flutter plugin, so none of these files were ever consumed — a consuming app'spod installinstalls onlyFlutter/FlutterMacOS, and platform support is declared purely via the top-levelplatforms:key. Verified withpana(all five platform badges unchanged) and by rebuilding/running the iOS and macOS example. Native libraries continue to ship via Build Hooks.
1.2.1 - 2026-05-14 #
Fixed #
- Android: native libraries are now built with LOAD segments aligned to 16 KB, so they load correctly on Android 15+ devices that use 16 KB memory pages (#1). The Android build script now passes
-Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384to the linker and verifies alignment on the 64-bit ABIs viallvm-readelf/readelfafter the build.
1.2.0 - 2026-02-07 #
Changed #
- Raised minimum iOS deployment target from 12.0 to 13.0 (matches Flutter 3.38.x minimum)
- Raised minimum macOS deployment target from 10.14 to 10.15 (matches Flutter 3.32+ minimum)
1.1.3 - 2026-02-07 #
Fixed #
- macOS x86_64 build deployment target lowered from 10.15 to 10.14 (matches podspec minimum)
1.1.2 - 2026-01-10 #
Added #
- Pre-commit git hook for format check and static analysis (configured via
make setup) - Multi-platform testing workflow (
test-reusable.yml): Linux x86_64, Linux ARM64, macOS ARM64, Windows x86_64 - GitHub App token support for signed commits in CI workflows
- Skip tests for automated bot PRs (native libraries not yet built)
.claude/skills/folder now included in repository and published package
Changed #
Signature.sign()andSignature.verify()now allow empty messages (valid per FIPS 204 and liboqs)- Simplified
check-liboqs-updates.ymlworkflow: removed AI analysis, now only updatesnative_versionin pubspec.yaml - Removed
--ai,--no-ai,--bump,--no-changelogflags fromcheck_updates.dart(script now focuses on version checking only) - Replaced
softprops/action-gh-releasewith officialghCLI for release creation (build-liboqs.yml, publish.yml) - Updated GitHub Actions:
peter-evans/create-pull-requestv8,actions/create-github-app-tokenv2,ilammy/msvc-dev-cmdv1.13.0 - Improved Windows FVM setup with PUB_CACHE detection and shell wrapper for Git Bash compatibility
- Native library release description simplified: removed "Usage" section, renamed "Archive Format" to "Platforms"
Fixed #
- Fixed version parsing in
build-liboqs.ymlworkflow (use Dart script instead of grep for reliable parsing) - Added checkout step to create-release job (required for gh CLI)
- FVM config changes are now discarded after setup to prevent unwanted modifications
Removed #
scripts/src/ai_analysis.dart- AI-powered changelog generation removed.github/prompts/ai-analysis-prompt.md- AI prompt template removed
1.1.1 - 2026-01-02 #
Added #
analysis_options.yamlwith recommended lints and exclusions for auto-generated bindingsmake doccommand for local API documentation generation
Fixed #
.pubignorenow includesCONTRIBUTING.mdin published package (needed for pub.dev links).pubignorenow excludes generateddoc/directory
Changed #
- Refactored CI update workflow: moved AI analysis from bash to Dart script
- Simplified
check-liboqs-updates.ymlworkflow (~540 → ~190 lines) - Added
--ai,--no-ai,--ciflags tocheck_updates.dartscript - Script now writes directly to
GITHUB_OUTPUTin CI mode (no jq parsing needed) make checkandmake combinenow create.skip_liboqs_hookto prevent build hooks during executionmake coveragenow uses--check-ignoreflag (respectscoverage:ignoreannotations)- CI test workflow now uses
make coverageinstead of direct commands - Removed
print()calls from tests (follow Dart best practices) build-liboqs.ymlworkflow now skips build if release already exists (prevents unnecessary rebuilds when only package version changes)
1.1.0 - 2025-12-28 #
Added #
LibOQSUtils.constantTimeEquals()for timing-safe byte array comparison (prevents timing attacks)LibOQSUtils.zeroMemory()for secure memory zeroing using nativeOQS_MEM_cleanse(compiler-optimization resistant)clearSecrets()method toKEMKeyPair,KEMEncapsulationResult, andSignatureKeyPairfor explicit secret zeroing- Safe getters:
publicKeyBase64,publicKeyHex,ciphertextBase64,ciphertextHex(don't expose secrets) - Export
LibOQSUtilsfrom main library entry point - Security documentation in SECURITY.md, README.md, and CLAUDE.md
- Finalizers for automatic secret zeroing on garbage collection (
KEMKeyPair,KEMEncapsulationResult,SignatureKeyPair) - SHA256 checksum verification for native library downloads in build hooks (supply chain security)
- Comprehensive test coverage (100%):
exception_test.dart,utils_test.dart, extended KEM/Signature/Random tests - Test coverage reporting with GitHub Gist badge
make coveragecommand for local coverage testing- Centralized
get_version.dartscript for version parsing runDart/runDartOrFailhelpers incommon.dartfor consistent FVM usagecryptopackage dependency for SHA256 checksum verification
Changed #
LibOQSUtils.secureFreePointer()now uses nativeOQS_MEM_secure_freeinstead of manual zeroingLibOQSUtils.constantTimeEquals()now performs constant-time length comparison (prevents length oracle attacks)LibOQSUtils.constantTimeEquals()now usessecureFreePointer()for temporary buffersclearSecrets()and Finalizers now useOQS_MEM_cleansevia centralizedzeroMemory()function- Added documentation explaining silent failure behavior in
secureFreePointer()(by design for cryptographic libraries) - Native library version moved from
LIBOQS_VERSION/NATIVE_BUILDfiles topubspec.yaml(centralized version management) - All scripts now read version from
pubspec.yamlviaget_version.dart make regennow creates.skip_liboqs_hookmarker file to prevent Build Hooks during regenerationregenerate_bindings.dartnow uses FVM Dart when available
Fixed #
dispose()operation order in KEM and Signature classes (free → detach → flag) to prevent memory leaks on exceptions- Null pointer checks for native function pointers before calling
asFunction() OQSRandom.generateBytes()now usessecureFreePointerfor sensitive data- Added explicit
nullptrcheck inKEM.generateKeyPairDerand()forkeypair_derandfunction pointer - Added signature length validation in
Signature.verify()(empty check and max length check) OQSRandom.generateInt()now has retry limit to prevent potential infinite loops in rejection sampling- CI workflow now uses
--check-ignoreflag for coverage reporting (respectscoverage:ignoreannotations) - Regex replacement bug in
check_updates.dart(replaceFirst→replaceFirstMapped)
Security #
- Added security warnings to
toStrings()andtoHexStrings()methods that expose secret keys - Examples updated to use
constantTimeEquals()instead of loop-based comparison - Defense-in-depth: Finalizers automatically zero secrets if user forgets to call
clearSecrets() - Build hooks now verify SHA256 checksums of downloaded native libraries (prevents supply chain attacks)
Removed #
LIBOQS_VERSIONfile (version now inpubspec.yaml)NATIVE_BUILDfile (build number now inpubspec.yaml)
1.0.3 - 2025-12-18 #
Added #
- Add support "@Native" annotation instead use library loader class
- Add "NATIVE_BUILD" file to manage build number of native library
- Add settings for code formatter
1.0.2 - 2025-12-14 #
Added #
- Linux ARM64 (aarch64) platform support for native libraries
- Updated README platform support table with architecture details
Fixed #
- Library loading on Linux and Windows Flutter desktop apps (paths relative to executable)
- Library loading for CLI applications in both JIT (
dart run) and AOT (dart build cli) modes - AOT detection logic no longer incorrectly triggers on project paths containing "dart" substring
1.0.1 - 2025-12-14 #
1.0.0 - 2025-12-13 #
Added #
- Pre-built native libraries for all platforms (iOS, Android, macOS, Linux, Windows)
- Key Encapsulation Mechanisms (KEM): ML-KEM, Kyber, Classic McEliece, FrodoKEM, HQC, NTRU
- Digital Signatures: ML-DSA, SLH-DSA, Falcon, SPHINCS+, MAYO, CROSS
- Cryptographically secure random number generation (
OQSRandom) - Automatic native library bundling via FFI plugin configuration
LibOQS.init()for optional library pre-initializationLibOQS.getSupportedKEMAlgorithms()andLibOQS.getSupportedSignatureAlgorithms()for runtime algorithm discoveryLibOQS.isKEMSupported()andLibOQS.isSignatureSupported()for algorithm availability checks- Algorithm name validation in
KEM.create()andSignature.create() LibOQSUtils.secureFreePointer()for secure memory clearing (zeros memory before freeing)- Comprehensive test suite (44 tests)
- GitHub Actions CI/CD pipeline for automated testing and publishing
- Automated liboqs version tracking via
LIBOQS_VERSIONfile - Cross-platform build scripts for native library compilation
- Example Flutter application demonstrating all features
Security #
- Secret keys are automatically zeroed before memory is freed
- Based on liboqs 0.15.0 with NIST-standardized algorithms (FIPS 203, 204, 205)