Skip to content

Conformance

Conformance #15

Workflow file for this run

name: Conformance
on:
workflow_dispatch:
jobs:
python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/python
docker build -t cyphera-test-python .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-python
- uses: actions/upload-artifact@v7
with:
name: results-python
path: results/python/
node:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/node
docker build -t cyphera-test-node .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-node
- uses: actions/upload-artifact@v7
with:
name: results-node
path: results/node/
java:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/java
docker build -t cyphera-test-java .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-java
- uses: actions/upload-artifact@v7
with:
name: results-java
path: results/java/
dotnet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/dotnet
docker build -t cyphera-test-dotnet .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-dotnet
- uses: actions/upload-artifact@v7
with:
name: results-dotnet
path: results/dotnet/
rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/rust
docker build -t cyphera-test-rust .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-rust
- uses: actions/upload-artifact@v7
with:
name: results-rust
path: results/rust/
php:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/php
docker build -t cyphera-test-php .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-php
- uses: actions/upload-artifact@v7
with:
name: results-php
path: results/php/
swift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/swift
docker build -t cyphera-test-swift .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-swift
- uses: actions/upload-artifact@v7
with:
name: results-swift
path: results/swift/
ruby:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/ruby
docker build -t cyphera-test-ruby .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-ruby
- uses: actions/upload-artifact@v7
with:
name: results-ruby
path: results/ruby/
go:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Build & Run
run: |
cd runners/go
docker build -t cyphera-test-go .
docker run --rm -v ${{ github.workspace }}:/vectors cyphera-test-go
- uses: actions/upload-artifact@v7
with:
name: results-go
path: results/go/
compare:
needs: [python, node, java, dotnet, rust, php, swift, ruby, go]
if: always()
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v8
with:
path: results/
pattern: results-*
merge-multiple: false
- name: Restructure artifacts
run: |
# results/results-{runner}/{cat}/{file} → flat/{runner}/{cat}/{file}
mkdir -p flat
for d in results/results-*/; do
runner=$(basename "$d" | sed 's/results-//')
if [ -d "$d" ]; then
cp -r "$d" "flat/$runner"
fi
done
- name: Engine comparison (NIST vectors — strict)
run: |
python3 -c "
import json, os, sys
runners = ['java', 'rust', 'node', 'python', 'dotnet', 'php', 'swift', 'ruby', 'go']
total = 0; match = 0; diffs = []
files = set()
for r in runners:
d = f'flat/{r}/engine'
if os.path.isdir(d): files.update(os.listdir(d))
for f in sorted(files):
results = {}
for r in runners:
p = f'flat/{r}/engine/{f}'
if os.path.exists(p):
results[r] = json.load(open(p)).get('results', [])
if len(results) < 2: continue
base = list(results.keys())[0]
for i, case in enumerate(results[base]):
total += 1
vals = {}
for r in results:
if i < len(results[r]):
vals[r] = results[r][i].get('ciphertext')
if len(set(str(v) for v in vals.values())) == 1:
match += 1
else:
pt = case.get('plaintext', '?')[:40]
diffs.append(f'engine/{f} case {i} (pt={pt}): {vals}')
print(f'=== Engine (NIST FF1/FF3): {match}/{total} unanimous ===')
for d in diffs: print(f' {d}')
if diffs:
print(f'FAIL: {len(diffs)} engine divergences — these MUST be unanimous')
sys.exit(1)
print('All engine vectors unanimous.')
"
- name: SDK comparison (compare.py — full cross-language divergence report)
continue-on-error: true
run: python3 compare.py flat
- uses: actions/upload-artifact@v7
if: always()
with:
name: conformance-results
path: flat/