website

Abhrankan Chakrabarti

API contracts: lab-api and crypto-lab

This document describes the current production-facing contracts for lab-api and crypto-lab as deployed today.

The service is intentionally small and intentionally narrow:

Service architecture

Internet
   ↓
HTTPS
   ↓
Nginx
  ├── /api/* and /school/* → 127.0.0.1:8088 → lab-api → systemd
  └── /crypto-api/*        → 127.0.0.1:8089 → crypto-lab → systemd

Public URL vs local backend URL

Public URL

https://abhrankan.duckdns.org/api/health
https://abhrankan.duckdns.org/api/v1/info
https://abhrankan.duckdns.org/api/v1/math/catalan/10
https://abhrankan.duckdns.org/api/v1/math/fibonacci/10
https://abhrankan.duckdns.org/api/v1/math/gcd/84/30
https://abhrankan.duckdns.org/api/v1/math/is-prime/97
https://abhrankan.duckdns.org/api/v1/math/next-prime/100
https://abhrankan.duckdns.org/api/v1/math/previous-prime/100
https://abhrankan.duckdns.org/api/v1/math/prime-gap/1000
https://abhrankan.duckdns.org/api/v1/math/prime-pi/1000
https://abhrankan.duckdns.org/api/v1/math/pi/1000
https://abhrankan.duckdns.org/api/v1/math/factor/360
https://abhrankan.duckdns.org/api/v1/math/totient/36
https://abhrankan.duckdns.org/api/v1/math/mobius/30
https://abhrankan.duckdns.org/api/v1/math/divisor-count/360
https://abhrankan.duckdns.org/api/v1/math/divisor-sum/360
https://abhrankan.duckdns.org/api/v1/math/divisors/360
https://abhrankan.duckdns.org/api/v1/snapshot
https://abhrankan.duckdns.org/school/
https://abhrankan.duckdns.org/school/api/health
https://abhrankan.duckdns.org/school/api/tables
https://abhrankan.duckdns.org/school/api/tables/II_A/students/1001
https://abhrankan.duckdns.org/school/api/admin/tables/II_A/students/1001
https://abhrankan.duckdns.org/school/api/admin/audit

These are consumed through Nginx, which terminates TLS and forwards traffic to the backend.

Local backend URL

http://127.0.0.1:8088/health
http://127.0.0.1:8088/v1/info
http://127.0.0.1:8088/v1/math/catalan/10
http://127.0.0.1:8088/v1/math/fibonacci/10
http://127.0.0.1:8088/v1/math/gcd/84/30
http://127.0.0.1:8088/v1/math/is-prime/97
http://127.0.0.1:8088/v1/math/next-prime/100
http://127.0.0.1:8088/v1/math/previous-prime/100
http://127.0.0.1:8088/v1/math/prime-gap/1000
http://127.0.0.1:8088/v1/math/prime-pi/1000
http://127.0.0.1:8088/v1/math/pi/1000
http://127.0.0.1:8088/v1/math/factor/360
http://127.0.0.1:8088/v1/math/totient/36
http://127.0.0.1:8088/v1/math/mobius/30
http://127.0.0.1:8088/v1/math/divisor-count/360
http://127.0.0.1:8088/v1/math/divisor-sum/360
http://127.0.0.1:8088/v1/math/divisors/360
http://127.0.0.1:8088/v1/snapshot
http://127.0.0.1:8088/school/
http://127.0.0.1:8088/school/api/health
http://127.0.0.1:8088/school/api/tables
http://127.0.0.1:8088/school/api/tables/II_A/students/1001
http://127.0.0.1:8088/school/api/admin/tables/II_A/students/1001
http://127.0.0.1:8088/school/api/admin/audit

The backend itself is only accessible from the local machine. It should not be exposed directly on a public interface or a public port.

Endpoint summary

The routes in this table are backend paths. Public clients prefix core routes with /api. School routes already include their /school prefix.

Method Endpoint Auth (public edge) Purpose
GET /health None Service health
GET /v1/info None Non-sensitive application metadata and endpoint discovery
GET /v1/math/catalan/:n None Catalan number, 0 ≤ n ≤ 34
GET /v1/math/fibonacci/:n None Fibonacci number, 0 ≤ n ≤ 186
GET /v1/math/gcd/:a/:b None Greatest common divisor of two u64 values
GET /v1/math/is-prime/:n None Primality test, 0 ≤ n ≤ 1,000,000
GET /v1/math/next-prime/:n None Next prime greater than n, 0 ≤ n ≤ 1,000,000
GET /v1/math/previous-prime/:n None Previous prime less than n, 2 < n ≤ 1,000,000
GET /v1/math/prime-gap/:n None Surrounding prime gap, 2 < n ≤ 1,000,000
GET /v1/math/prime-pi/:n None Prime-counting function π(n), 0 ≤ n ≤ 1,000,000
GET /v1/math/pi/:n None Prime-counting function π(n), compatibility alias
GET /v1/math/factor/:n None Prime factorisation, 0 ≤ n ≤ 1,000,000
GET /v1/math/totient/:n None Euler’s totient φ(n), 0 ≤ n ≤ 1,000,000
GET /v1/math/mobius/:n None Möbius function μ(n), 0 ≤ n ≤ 1,000,000
GET /v1/math/divisor-count/:n None Divisor-count function τ(n), 0 ≤ n ≤ 1,000,000
GET /v1/math/divisor-sum/:n None Divisor-sum function σ(n), 0 ≤ n ≤ 1,000,000
GET /v1/math/divisors/:n None Sorted positive divisors of n, 0 ≤ n ≤ 1,000,000
GET /v1/catalan/:n None Deprecated Catalan compatibility alias; use /v1/math/catalan/:n, 0 ≤ n ≤ 34
GET /v1/snapshot Nginx Basic Auth Host/system snapshot
GET /school/ None Public School portal UI and static assets
GET /school/api/health None School API health
GET /school/api/tables Nginx Basic Auth Available School tables
GET /school/api/tables/{table} Nginx Basic Auth Paginated, searchable safe student rows
GET /school/api/tables/{table}/schema Nginx Basic Auth Discovered table schema
GET /school/api/tables/{table}/students/{student_id} Nginx Basic Auth Privacy-filtered student detail
GET /school/api/admin/tables/{table}/students/{student_id} Nginx Basic Auth + admin allowlist Full student detail and audit event
GET /school/api/admin/audit Nginx Basic Auth + admin allowlist Paginated admin student-detail audit events

{table} is a discovered class table name (for example II_A, LPP). {student_id} is the table’s primary-key value (for example Student Code or Roll No), not a nested path segment named students.

School API

The core /api/* service does not use a database. The separate School API under /school/ reads SQLite from SCHOOL_DB_PATH and is read-only during normal runtime. The /school/ UI is served from the backend’s static/school directory.

In production, the public /school/ location serves the UI and static assets without authentication. The exact /school/api/health location is also public for health checks. Nginx Basic Authentication applies to /school/api/ for table, schema, student, admin, and audit requests. The Rust process itself does not enforce Basic Authentication; it assumes that Nginx provides this edge protection. Admin detail and audit add an application allowlist on top of that.

The Nginx exact health location takes precedence over the broader protected /school/api/ prefix:

location = /school/api/health {
    proxy_pass http://127.0.0.1:8088;
}

location /school/api/ {
    auth_basic "School Database";
    auth_basic_user_file /etc/nginx/school.htpasswd;
    proxy_pass http://127.0.0.1:8088;
    proxy_set_header X-Authenticated-User $remote_user;
}

location /school/ {
    proxy_pass http://127.0.0.1:8088;
}

The /school/api/ proxy preserves the /school/api/... path when forwarding to Axum. The /school/ location is for the portal UI and static assets, not for bypassing API authorization.

Table listing and schema

GET /school/api/tables
GET /school/api/tables/{table}?limit=25&offset=0&search=Abhrankan
GET /school/api/tables/{table}/schema

All three routes require Nginx Basic Authentication. The table route returns safe/display columns only and supports optional limit, offset, and search query parameters. The default page size is 25 and the backend caps page sizes at 100. Schema discovery returns the table’s columns and primary-key metadata.

Safe student detail

GET /school/api/tables/{table}/students/{student_id}

Example:

GET /school/api/tables/II_A/students/1001

This endpoint excludes explicitly sensitive contact, financial, and identity fields.

Admin full student detail

GET /school/api/admin/tables/{table}/students/{student_id}

Example:

GET /school/api/admin/tables/II_A/students/1001

The admin endpoint returns every column discovered from the selected table schema. It requires both:

  1. Nginx Basic Authentication for the protected /school/api/ location.
  2. The authenticated username in the backend X-Authenticated-User header and in LAB_API_ADMIN_USERS.

Configure the backend with a comma-separated allowlist, for example:

LAB_API_ADMIN_USERS=abhrankan,teacher1,principal

Missing authentication at Nginx yields 401 Unauthorized.
Authenticated but non-admin (or missing X-Authenticated-User) yields 403 Forbidden:

{
  "error": "admin access required"
}

The backend listens only on 127.0.0.1:8088, so the authenticated identity header is intended to be supplied by the local Nginx reverse proxy rather than by an Internet client. Nginx should set it inside the authenticated /school/api/ location:

location /school/api/ {
    auth_basic "School Database";
    auth_basic_user_file /etc/nginx/school.htpasswd;

    proxy_pass http://127.0.0.1:8088;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Authenticated-User $remote_user;
}

Do not expose the backend directly on a public interface. The public health route does not provide table or student data.

Admin audit

GET /school/api/admin/audit?limit=50&offset=0

This route requires both School API Basic Authentication and an authenticated username listed in LAB_API_ADMIN_USERS. It returns recent admin student-detail access events. limit defaults to 50 and is capped at 100; offset defaults to 0. Admin student-detail responses are returned only after the corresponding audit event is recorded.

HTTP status codes

Status Meaning
200 OK Successful request
400 Bad Request Invalid mathematical input, including values above the documented prime limits
401 Unauthorized Missing or invalid HTTP Basic credentials at Nginx for protected School/API routes or the snapshot
403 Forbidden Authenticated School user is not on the admin allowlist (admin detail only)
404 Not Found Route not defined, or unknown table/student
500 Internal Server Error Unexpected backend failure

The most important contract checks are:

Math endpoints

The math endpoints are public, read-only GET routes. They use u128 arithmetic where applicable and return numeric values as strings to preserve the exact result in JSON clients.

Catalan

GET /v1/math/catalan/:n

Supports 0 ≤ n ≤ 34. The existing GET /v1/catalan/:n route is retained as a deprecated compatibility alias with the same response and limit.

Fibonacci

GET /v1/math/fibonacci/:n

Supports 0 ≤ n ≤ 186. F(186) is the largest Fibonacci value representable by the implementation’s u128 boundary; n = 187 returns 400 Bad Request.

Example response:

{
  "n": 10,
  "value": "55"
}

Greatest common divisor

GET /v1/math/gcd/:a/:b

Computes the GCD of two u64 path values using the Euclidean algorithm. Zero is valid, including gcd(0, 0) = 0.

curl -sS 'https://abhrankan.duckdns.org/api/v1/math/gcd/84/30'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/fibonacci/10'
{
  "a": 84,
  "b": 30,
  "gcd": 6
}

Prime-number endpoints

GET /v1/math/is-prime/:n
GET /v1/math/next-prime/:n
GET /v1/math/previous-prime/:n
GET /v1/math/prime-gap/:n
GET /v1/math/prime-pi/:n
GET /v1/math/pi/:n

These public, read-only endpoints support values up to 1,000,000. The /v1/math/pi/:n route is a compatibility alias for /v1/math/prime-pi/:n. Prime-counting uses a bounded sieve so requests above the limit return 400 Bad Request rather than allocating unbounded memory. Prime searches and prime gaps use the same upper bound.

Examples:

curl -sS 'https://abhrankan.duckdns.org/api/v1/math/is-prime/97'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/next-prime/100'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/previous-prime/100'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/prime-gap/1000'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/prime-pi/1000'
{
  "n": 97,
  "prime": true
}

next-prime and prime-counting return { "n": ..., "value": "..." }. previous-prime returns the greatest prime strictly less than n using the same response shape. It returns 400 Bad Request for n ≤ 2. prime-gap returns the previous prime, next prime, and gap:

{
  "n": 1000,
  "previous_prime": 997,
  "next_prime": 1009,
  "gap": 12
}

Factorisation and multiplicative functions

GET /v1/math/factor/:n
GET /v1/math/totient/:n
GET /v1/math/mobius/:n
GET /v1/math/divisor-count/:n
GET /v1/math/divisor-sum/:n
GET /v1/math/divisors/:n

These public, read-only endpoints support values from 0 through 1,000,000. They use bounded trial division and are intended for demonstrations, not as a general-purpose factoring service. Values above the limit return 400 Bad Request.

Prime factors are returned in ascending order. The value 1 has no prime factors, so factorisation returns an empty list for n = 1.

Factorisation example:

curl -sS 'https://abhrankan.duckdns.org/api/v1/math/factor/360'
{
  "n": 360,
  "factors": [
    { "prime": 2, "power": 3 },
    { "prime": 3, "power": 2 },
    { "prime": 5, "power": 1 }
  ]
}

Totient and Möbius examples:

curl -sS 'https://abhrankan.duckdns.org/api/v1/math/totient/36'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/mobius/30'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/divisor-count/360'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/divisor-sum/360'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/divisors/12'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/mobius/36'
{ "n": 36, "value": "12" }
{ "n": 30, "value": -1 }
{ "n": 36, "value": 0 }

The endpoint semantics are:

The divisor functions use the same factorisation:

GET /v1/math/divisor-count/:n
GET /v1/math/divisor-sum/:n

Both routes support 0 ≤ n ≤ 1,000,000 and return the standard string-valued mathematical response. For n = 0, both return 0; for n = 360, they return 24 and 1170, respectively.

The divisors route returns all positive divisors in ascending order:

GET /v1/math/divisors/:n

For n = 12:

{
  "n": 12,
  "divisors": [1, 2, 3, 4, 6, 12]
}

For n = 0, divisors is an empty array. The list verifies τ(n) = divisors.length and σ(n) = sum(divisors).

Application information endpoint

Route

GET /v1/info

This public endpoint describes the running application and its public route surface. It does not require authentication and must not expose hostnames, filesystem paths, credentials, secret environment variables, or system snapshot data. The environment field is only a non-secret deployment label.

Request examples

curl -sS 'https://abhrankan.duckdns.org/api/v1/info'
curl -sS 'http://127.0.0.1:8088/v1/info'

Response

{
  "service": "lab-api",
  "api_version": "v1",
  "app_version": "0.9.2",
  "endpoints": [
    "GET /health",
    "GET /v1/info",
    "GET /v1/math/catalan/:n",
    "GET /v1/math/fibonacci/:n",
    "GET /v1/math/gcd/:a/:b",
    "GET /v1/math/is-prime/:n",
    "GET /v1/math/next-prime/:n",
    "GET /v1/math/previous-prime/:n",
    "GET /v1/math/prime-pi/:n",
    "GET /v1/math/pi/:n",
    "GET /v1/math/prime-gap/:n",
    "GET /v1/math/factor/:n",
    "GET /v1/math/totient/:n",
    "GET /v1/math/mobius/:n",
    "GET /v1/math/divisor-count/:n",
    "GET /v1/math/divisor-sum/:n",
    "GET /v1/math/divisors/:n",
    "GET /v1/catalan/:n",
    "GET /v1/snapshot",
    "GET /school/",
    "GET /school/api/health",
    "GET /school/api/tables",
    "GET /school/api/tables/:table",
    "GET /school/api/tables/:table/schema",
    "GET /school/api/tables/:table/students/:student_code",
    "GET /school/api/admin/tables/:table/students/:student_code",
    "GET /school/api/admin/audit"
  ],
  "build_profile": "release",
  "environment": "production"
}

Status

app_version is taken from the package version at build time. build_profile identifies whether the binary was compiled with debug assertions. environment is an optional LAB_API_ENV deployment label, defaults to unknown, and must remain free of secrets.

Health endpoint

Request

curl -sS https://abhrankan.duckdns.org/api/health

Response

{
  "ok": true,
  "service": "lab-api"
}

Local backend example

curl -sS http://127.0.0.1:8088/health

Status

This endpoint is intended to remain publicly readable for simple service checks and monitoring.

Catalan number endpoint

Route

GET /v1/math/catalan/:n

Request examples

curl -sS 'https://abhrankan.duckdns.org/api/v1/math/catalan/0'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/catalan/10'
curl -sS 'https://abhrankan.duckdns.org/api/v1/math/catalan/34'

Success response

{
  "n": 10,
  "value": "16796"
}

Maximum supported value

The implementation computes Catalan numbers in u128 and therefore intentionally limits input to:

0 ≤ n ≤ 34

This is a deliberate product choice, not a general-purpose arbitrary-precision implementation.

The calculation uses the standard recurrence:

C(0) = 1
C(n) = C(n-1) * 2 * (2n - 1) / (n + 1)

Out-of-range error

curl -sS -i 'https://abhrankan.duckdns.org/api/v1/math/catalan/35'
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "n must be <= 34 for this demo (u128 limit)"
}

Status

Snapshot endpoint

Route

GET /v1/snapshot

This endpoint provides a minimal system summary from the host running lab-api.

Example response

{
  "hostname": "ip-172-31-77-184.ec2.internal",
  "uptime": "up 2 days, 2 hours, 52 minutes",
  "loadavg": "0.13 0.15 0.13",
  "mem_available_kb": 580200
}

Data collected

Request example

curl -sS -u 'username:password' https://abhrankan.duckdns.org/api/v1/snapshot

Local backend example

curl -sS -u 'username:password' http://127.0.0.1:8088/v1/snapshot

Authentication behavior

The snapshot endpoint is protected by Nginx HTTP Basic Authentication.

The Rust application itself does not enforce credentials for this route. Authentication is enforced at the public entry point before traffic reaches the backend.

If the client omits credentials or provides invalid credentials, the response is:

HTTP/1.1 401 Unauthorized

This is intentional. The endpoint exposes host-level information and is therefore treated as sensitive.

Authentication model

Core /api/* (public edge)

School /school/* (public edge)

Auth implementation

For /v1/snapshot, Nginx enforces HTTP Basic Authentication before proxying; the core Rust handler does not validate those credentials.

For School, Nginx authenticates only the protected /school/api/ API location and forwards $remote_user as X-Authenticated-User. The admin detail and audit handlers additionally check that value against LAB_API_ADMIN_USERS. The public UI and health route do not receive this authentication gate.

Do not expose port 8088 publicly: without Nginx, School routes would not have the edge Basic Auth gate.

Example Nginx blocks

# Public core API (no auth)
location /api/ {
    proxy_pass http://127.0.0.1:8088/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# Snapshot only
location = /api/v1/snapshot {
    auth_basic "Private API";
    auth_basic_user_file /etc/nginx/status.htpasswd;
    proxy_pass http://127.0.0.1:8088/v1/snapshot;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# Public School health
location = /school/api/health {
    proxy_pass http://127.0.0.1:8088;
}

# Protected School API
location /school/api/ {
    auth_basic "School Database";
    auth_basic_user_file /etc/nginx/school.htpasswd;
    proxy_pass http://127.0.0.1:8088;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Authenticated-User $remote_user;
}

# Public School UI and static assets
location /school/ {
    proxy_pass http://127.0.0.1:8088;
}

Exact matches for /api/v1/snapshot take precedence over the /api/ prefix. Health, info, math, and the Catalan alias remain public.

Nginx routing

https://abhrankan.duckdns.org/api/...     →  http://127.0.0.1:8088/...
https://abhrankan.duckdns.org/school/...  →  http://127.0.0.1:8088/school/...

Examples:

https://abhrankan.duckdns.org/api/health
  → http://127.0.0.1:8088/health

https://abhrankan.duckdns.org/api/v1/math/catalan/10
  → http://127.0.0.1:8088/v1/math/catalan/10

https://abhrankan.duckdns.org/api/v1/info
  → http://127.0.0.1:8088/v1/info

https://abhrankan.duckdns.org/school/api/tables/II_A/students/1001
  → http://127.0.0.1:8088/school/api/tables/II_A/students/1001

Security model

crypto-lab API

crypto-lab is a separate Rust/Axum service on 127.0.0.1:8089. Nginx publishes it under /crypto-api/, leaves health, info, and math exploration public, and protects hash/HMAC operations with HTTP Basic Authentication.

Repository: foxhackerzdevs/crypto-lab

Purpose and non-goals

Purpose: small, self-hosted service for SHA-2 hashing, HMAC generate/verify, and number-theoretic / elliptic curve cryptography exploration (FoxMath algorithms) for learning and lab experiments.

Non-goals (intentionally unsupported):

Warning: do not submit production private keys, passwords, API tokens, or other long-lived secrets. Examples use throwaway strings only.

Public and local URLs

https://abhrankan.duckdns.org/crypto-api/health
https://abhrankan.duckdns.org/crypto-api/v1/info
https://abhrankan.duckdns.org/crypto-api/v1/math/legendre
https://abhrankan.duckdns.org/crypto-api/v1/math/sqrtmod
https://abhrankan.duckdns.org/crypto-api/v1/math/factor
https://abhrankan.duckdns.org/crypto-api/v1/math/totient
https://abhrankan.duckdns.org/crypto-api/v1/math/order
https://abhrankan.duckdns.org/crypto-api/v1/math/dlog
https://abhrankan.duckdns.org/crypto-api/v1/math/mobius
https://abhrankan.duckdns.org/crypto-api/v1/math/sigma
https://abhrankan.duckdns.org/crypto-api/v1/math/tau
https://abhrankan.duckdns.org/crypto-api/v1/math/crt
https://abhrankan.duckdns.org/crypto-api/v1/math/cf
https://abhrankan.duckdns.org/crypto-api/v1/math/ecadd
https://abhrankan.duckdns.org/crypto-api/v1/math/ecmul
https://abhrankan.duckdns.org/crypto-api/v1/math/challenge
https://abhrankan.duckdns.org/crypto-api/v1/hash
https://abhrankan.duckdns.org/crypto-api/v1/hmac
https://abhrankan.duckdns.org/crypto-api/v1/hmac/verify

http://127.0.0.1:8089/health
http://127.0.0.1:8089/v1/info
http://127.0.0.1:8089/v1/math/legendre
http://127.0.0.1:8089/v1/math/sqrtmod
http://127.0.0.1:8089/v1/math/factor
http://127.0.0.1:8089/v1/math/totient
http://127.0.0.1:8089/v1/math/order
http://127.0.0.1:8089/v1/math/dlog
http://127.0.0.1:8089/v1/math/mobius
http://127.0.0.1:8089/v1/math/sigma
http://127.0.0.1:8089/v1/math/tau
http://127.0.0.1:8089/v1/math/crt
http://127.0.0.1:8089/v1/math/cf
http://127.0.0.1:8089/v1/math/ecadd
http://127.0.0.1:8089/v1/math/ecmul
http://127.0.0.1:8089/v1/math/challenge
http://127.0.0.1:8089/v1/hash
http://127.0.0.1:8089/v1/hmac
http://127.0.0.1:8089/v1/hmac/verify

Authentication and routing

Route Auth
GET /crypto-api/health None
GET /crypto-api/v1/info None
GET, POST /crypto-api/v1/math/legendre None
GET, POST /crypto-api/v1/math/sqrtmod None
GET, POST /crypto-api/v1/math/factor None
GET, POST /crypto-api/v1/math/totient None
GET, POST /crypto-api/v1/math/order None
GET, POST /crypto-api/v1/math/dlog None
GET, POST /crypto-api/v1/math/mobius None
GET, POST /crypto-api/v1/math/sigma None
GET, POST /crypto-api/v1/math/tau None
GET, POST /crypto-api/v1/math/crt None
GET, POST /crypto-api/v1/math/cf None
GET, POST /crypto-api/v1/math/ecadd None
GET, POST /crypto-api/v1/math/ecmul None
GET, POST /crypto-api/v1/math/challenge None
POST /crypto-api/v1/hash Nginx Basic Auth
POST /crypto-api/v1/hmac Nginx Basic Auth
POST /crypto-api/v1/hmac/verify Nginx Basic Auth

Example Nginx (htpasswd path is site-specific):

location = /crypto-api/health {
    proxy_pass http://127.0.0.1:8089/health;
}

location = /crypto-api/v1/info {
    proxy_pass http://127.0.0.1:8089/v1/info;
}

# Public math & number theory endpoints (FoxMath)
location /crypto-api/v1/math/ {
    proxy_pass http://127.0.0.1:8089/v1/math/;
}

location /crypto-api/ {
    auth_basic "crypto-lab";
    auth_basic_user_file /etc/nginx/status.htpasswd;
    proxy_pass http://127.0.0.1:8089/;
}

Exact health/info and math prefix matches keep those exploration endpoints public. Trailing slash on /crypto-api/ maps /crypto-api/v1/hash → /v1/hash on the backend.

Concepts (contract-level)

Operation Role
Hash Digest of data only. Does not prove who sent the data.
HMAC Tag over data under a shared key. Verifier needs the same key.
Verify Recomputes the tag and compares in constant time. Wrong but well-formed MAC → 200 + "valid": false. Malformed hex → 400.
Legendre Euler’s criterion $(a/p)$ over odd prime $p$. Returns $1$, $-1$, or $0$.
Jacobi Evaluates the Jacobi symbol $(a/n)$ for odd positive $n$ via quadratic reciprocity in $O(\log n)$ without factoring.
Solovay–Strassen Probabilistic primality test verifying Euler's criterion $a^{(n-1)/2} \equiv (a/n) \pmod n$ with error bound $\le 2^{-\text{rounds}}$.
SqrtMod Tonelli-Shanks modular square roots modulo odd prime $p$. Returns positive roots.
CRT Extended Euclidean GCD solver for simultaneous modular congruences.
CF Continued fraction expansions and rational convergents for $num/den$.
EC Add / Mul Weierstrass curve group addition and scalar multiplication ($k \cdot P$) over finite field $\mathbb{F}_p$. Built-in presets: toy97 and toy193.
Dlog Discrete logarithm ($g^x \equiv h \pmod p$) via Baby-step Giant-step.
Arithmetic Foundational multiplicative functions: Möbius $\mu(n)$, divisor sum $\sigma_k(n)$, divisor count $\tau(n)$ via individual routes or unified suite (/arith).
Challenge Deterministic seeded problem generator for practice and self-study.

Application information

curl -sS https://abhrankan.duckdns.org/crypto-api/v1/info
{
  "service": "crypto-lab",
  "api": "v1",
  "version": "0.6.0",
  "endpoints": [
    "GET /health",
    "GET /v1/info",
    "POST /v1/hash",
    "POST /v1/hmac",
    "POST /v1/hmac/verify",
    "GET /v1/math/legendre",
    "POST /v1/math/legendre",
    "GET /v1/math/jacobi",
    "POST /v1/math/jacobi",
    "GET /v1/math/solovay",
    "POST /v1/math/solovay",
    "GET /v1/math/sqrtmod",
    "POST /v1/math/sqrtmod",
    "GET /v1/math/factor",
    "POST /v1/math/factor",
    "GET /v1/math/totient",
    "POST /v1/math/totient",
    "GET /v1/math/order",
    "POST /v1/math/order",
    "GET /v1/math/dlog",
    "POST /v1/math/dlog",
    "GET /v1/math/mobius",
    "POST /v1/math/mobius",
    "GET /v1/math/sigma",
    "POST /v1/math/sigma",
    "GET /v1/math/tau",
    "POST /v1/math/tau",
    "GET /v1/math/arith",
    "POST /v1/math/arith",
    "GET /v1/math/crt",
    "POST /v1/math/crt",
    "GET /v1/math/cf",
    "POST /v1/math/cf",
    "GET /v1/math/ecadd",
    "POST /v1/math/ecadd",
    "GET /v1/math/ecmul",
    "POST /v1/math/ecmul",
    "GET /v1/math/challenge",
    "POST /v1/math/challenge"
  ],
  "build_profile": "release",
  "environment": "production"
}

environment is an optional non-secret deployment label (e.g. LAB_API_ENV); default unknown.

Hash

curl -sS -u 'username:password' \
  -H 'Content-Type: application/json' \
  -d '{"algorithm":"sha256","data":"hello"}' \
  https://abhrankan.duckdns.org/crypto-api/v1/hash
{
  "algorithm": "sha256",
  "digest": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}

HMAC generation

curl -sS -u 'username:password' \
  -H 'Content-Type: application/json' \
  -d '{"algorithm":"sha256","key":"secret","data":"message"}' \
  https://abhrankan.duckdns.org/crypto-api/v1/hmac
{
  "algorithm": "sha256",
  "mac": "8b5f48702995c1598c573db1e21866a9b825d4a794d169d7060a03605796360b"
}

HMAC verification

curl -sS -u 'username:password' \
  -H 'Content-Type: application/json' \
  -d '{"algorithm":"sha256","key":"secret","data":"message","mac":"8b5f48702995c1598c573db1e21866a9b825d4a794d169d7060a03605796360b"}' \
  https://abhrankan.duckdns.org/crypto-api/v1/hmac/verify
{
  "algorithm": "sha256",
  "valid": true
}

Number theory and elliptic curves (FoxMath Core)

All math endpoints accept either query parameters (GET) or a JSON payload (POST). No authentication is required for /crypto-api/v1/math/*.

Legendre symbol

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/legendre?a=10&p=13"
{"a": 10, "p": 13, "value": 1}

Jacobi symbol

Evaluates the Jacobi symbol $(a/n)$ for odd positive integer $n$ via quadratic reciprocity without factoring:

# GET via query parameters
curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/jacobi?a=10&n=21"
{"a": 10, "n": 21, "value": -1}
# POST via JSON payload
curl -sS -H "Content-Type: application/json" \
  -d '{"a": 2, "n": 15}' \
  https://abhrankan.duckdns.org/crypto-api/v1/math/jacobi
{"a": 2, "n": 15, "value": 1}

Solovay–Strassen primality test

Probabilistic primality test verifying Euler's criterion $a^{(n-1)/2} \equiv (a/n) \pmod n$ for $k$ random bases $a$:

# GET via query parameters (probable prime)
curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/solovay?n=104729&rounds=20"
{"n": 104729, "rounds": 20, "is_prime": true, "method": "solovay_strassen"}
# POST via JSON payload (detects Carmichael composite)
curl -sS -H "Content-Type: application/json" \
  -d '{"n": 561, "rounds": 20, "seed": 42}' \
  https://abhrankan.duckdns.org/crypto-api/v1/math/solovay
{"n": 561, "rounds": 20, "is_prime": false, "method": "solovay_strassen"}

Modular square root (Tonelli-Shanks)

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/sqrtmod?a=10&p=13"
{"a": 10, "p": 13, "roots": [6, 7]}

Prime factorization (Pollard's $\rho$)

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/factor?n=360"
{"n": 360, "factors": [{"prime": 2, "power": 3}, {"prime": 3, "power": 2}, {"prime": 5, "power": 1}], "prime_factors": [2, 3, 5], "expression": "2^3 * 3^2 * 5", "is_prime": false}

Euler's totient & Carmichael function

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/totient?n=360"
{"n": 360, "phi": 96, "lambda": 12, "is_cyclic": false}

Multiplicative order & primitive roots

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/order?a=3&m=7"
{"a": 3, "m": 7, "order": 6, "is_primitive_root": true}

Discrete logarithm (BSGS)

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/dlog?g=3&h=6&p=7"
{"g": 3, "h": 6, "p": 7, "x": 3, "order": 6}

Classical arithmetic functions

Unified arithmetic suite (evaluates $\mu(n)$, $\sigma_k(n)$, and $\tau(n)$ in one request via a single factorization):

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/arith?n=12&k=1"
{"n": 12, "k": 1, "mobius": 0, "sigma": 28, "tau": 6}

Individual endpoints:

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/mobius?n=30"
{"n": 30, "value": -1}
curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/sigma?n=12&k=1"
{"n": 12, "k": 1, "value": 28}
curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/tau?n=12"
{"n": 12, "value": 6}

Chinese Remainder Theorem

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/crt?r=2,3,2&m=3,5,7"
{"remainders": [2, 3, 2], "moduli": [3, 5, 7], "x": 23, "modulus": 105}

Continued fractions

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/cf?num=355&den=113"
{"num": 355, "den": 113, "cf": [3, 7, 16], "convergents": [[3, 1], [22, 7], [355, 113]]}

Elliptic curve scalar multiplication ($k \cdot P$)

curl -sS -H "Content-Type: application/json" \
  -d '{"curve":"toy193","k":7}' \
  https://abhrankan.duckdns.org/crypto-api/v1/math/ecmul
{"curve": "toy193", "k": 7, "point": [1, 59], "result": [66, 24], "result_on_curve": true}

Seeded challenge generator

curl -sS "https://abhrankan.duckdns.org/crypto-api/v1/math/challenge?topic=mixed&seed=42"
{"topic": "mixed", "seed": 42, "count": 1, "problems": [{"topic": "sqrtmod", "question": "Smaller positive root of x² ≡ 12 (mod 13)", "answer": 5}]}

Input contract and status codes

Security boundary

This service is a lab, not a secrets backend.