PassSec API

REFERENCE DOCUMENTATION | REST API v3.2 | CYBERSECURITY PROJECT

VERSION 3.2 PUBLIC API RATE LIMITED NIST SP 800-63B
API Version
3.2  —  stable
Base URL (production)
Authentication
None  —  public API, no token required
Content-Type
application/json for all POST requests
Rate Limiting
10 req / min on /api/check
3 req / min  on /api/raport
3 req / min  on /api/bulk-check
Rate Limit Exceeded
HTTP 429 — retry after 60 seconds
Password Length Limit
1 000 chars on /api/check  ·  500 chars on /api/raport
HIBP Privacy Model
k-anonymity — only first 5 SHA-1 chars sent externally
POST /api/check 10 / min Analyze a password — full security report

Core analysis endpoint. Accepts a password string and returns a complete security evaluation: strength score, entropy, brute-force time estimate, rockyou/HIBP compromise status, per-criterion audit, improvement suggestions, and SHA-256 hash. Called on every keystroke by the web UI (debounced 500 ms).

>_ Request Body
"password": "string" // required · max 1 000 chars { "password": "Tr0ub4dor&3xZ!" }
>_ Response Fields
FieldTypeDescriptionCondition
scorintegerStrength score 0–100always
nivelstringWEAK · AVERAGE · GOOD · STRONG · FORTRESS · COMPROMISEDalways
culoarestringHex color matching nivel for UI renderingalways
criteriiobjectMap of criterion label → boolean (pass/fail)always
sugestiistring[]Human-readable improvement recommendationsalways
penalizaristring[]Applied penalties with point deductionsalways
entropie.bitifloatShannon entropy in bits — log2(alphabet^length)always
entropie.alfabetintegerEffective alphabet size used for entropy calcalways
entropie.componentestring[]Character classes detected (e.g. "26 litere mici")always
entropie.nivelstringNIST SP 800-63B entropy categoryalways
timp_spargerestringBrute-force estimate at RTX 4090 speed (164B hash/s)always
hash_sha256stringSHA-256 hex digest of the passwordalways
in_rockyoubooleanFound in rockyou.txt / internal common-password listalways
lungimeintegerPassword length in charactersalways
tipuri_caractereintegerNumber of distinct character classes used (0–4)not COMPROMISED
hibp_compromisabooleanFound in HaveIBeenPwned breach databaseHIBP hit only
hibp_aparitiiintegerNumber of times seen across HIBP breachesHIBP hit only
>_ Response Example — FORTRESS (200)
{ "scor": 88, "nivel": "FORTRESS", "culoare": "#00ff88", "criterii": { "Lungime excelentă (20+ caractere)": true, "Conține litere mari (A-Z)": true, "Conține litere mici (a-z)": true, "Conține cifre (0-9)": true, "Conține simboluri speciale (!@#$...)": true, "Diversitate maximă (toate tipurile)": true }, "sugestii": [], "penalizari": [], "entropie": { "biti": 98.6, "alfabet": 94, "componente": ["26 litere mici", "26 litere mari", "10 cifre", "32 simboluri speciale"], "nivel": "Puternică" }, "timp_spargere": "practic imposibil de spart", "hash_sha256": "a3f1b2...e9d4c7", "in_rockyou": false, "lungime": 15, "tipuri_caractere": 4 }
>_ Response Example — COMPROMISED via HIBP (200)
{ "scor": 0, "nivel": "COMPROMISED", "culoare": "#ff0040", "criterii": { "Parola apare în breach-uri reale (HIBP)": false }, "sugestii": ["Această parolă a fost găsită de 54,277 ori în breach-uri..."], "penalizari": ["Prezentă în HIBP (54,277 apariții)"], "entropie": { "biti": 52.4, "alfabet": 62, "componente": ["..."], "nivel": "Rezonabilă" }, "timp_spargere": "< 1 secundă (breach lookup)", "hash_sha256": "5e884898...d69731", "in_rockyou": false, "hibp_compromisa": true, "hibp_aparitii": 54277, "lungime": 8 }
>_ Error Codes
CodeWhenResponse body
400Missing "password" field or length > 1 000{"eroare": "..."}
429More than 10 requests per minute from same IP{"eroare": "Rate limit depasit: ..."}
500Unexpected server errorFlask default error page
POST /api/bulk-check 3 / min Analyze multiple passwords in one request

Batch analysis endpoint. Accepts a JSON array of up to 10 passwords and returns a full /api/check-equivalent result for each, indexed by position. Each password is XSS-sanitized (HTML-escaped) before analysis. Useful for auditing password lists without issuing multiple individual requests.

>_ Request Body
{ "passwords": [ // required · array · max 10 items "hunter2", // each item: string · max 500 chars "Tr0ub4dor&3xZ!", "correct-horse-battery" ] }
>_ Response Fields
FieldTypeDescriptionCondition
totalintegerNumber of passwords analyzedalways
resultsarrayOrdered list of analysis objects (same fields as /api/check)always
results[n].indexinteger0-based position of the password in the input arrayalways
results[n].scorintegerStrength score 0–100always
results[n].nivelstringWEAK · AVERAGE · GOOD · STRONG · FORTRESS · COMPROMISEDalways
results[n].*mixedAll other fields identical to /api/check responsealways
>_ Response Example (200)
{ "total": 3, "results": [ { "index": 0, "scor": 0, "nivel": "WEAK", "in_rockyou": true, "lungime": 7 // ... all /api/check fields }, { "index": 1, "scor": 88, "nivel": "FORTRESS", "in_rockyou": false, "lungime": 15 // ... }, { "index": 2, "scor": 62, "nivel": "GOOD", "in_rockyou": false, "lungime": 21 // ... } ] }
>_ Error Codes
CodeWhenResponse body
400Missing "passwords" field{"eroare": "Câmpul 'passwords' lipsește din request."}
400"passwords" is not an array{"eroare": "Câmpul 'passwords' trebuie să fie o listă."}
400More than 10 passwords in the array{"eroare": "Prea multe parole (N). Maxim 10 parole per request."}
400An item is not a string{"eroare": "Parola la indexul N nu este un string."}
400An item exceeds 500 characters{"eroare": "Parola la indexul N depășește 500 de caractere (max 500)."}
429More than 3 requests per minute from same IP{"eroare": "Rate limit depasit: ..."}
500Unexpected server errorFlask default error page
POST /api/raport 3 / min Generate a downloadable PDF security report

Generates a full PDF report for a given password, saves it server-side under rapoarte/, and returns a one-time download URL. The password is HTML-escaped before analysis and never stored in clear text — only the masked form and SHA-256 hash appear in the PDF.

>_ Request Body
{ "password": "Tr0ub4dor&3xZ!" // required · max 500 chars · Content-Type: application/json }
>_ Response (200)
{ "succes": true, "fisier": "passsec_report_20240915_143022_0042.pdf", "download_url": "/api/download/passsec_report_20240915_143022_0042.pdf" }
>_ Error Codes
CodeWhenResponse body
400Missing "password" field, not a string, or length > 500{"eroare": "..."}
415Content-Type is not application/json{"eroare": "Content-Type trebuie application/json."}
429More than 3 requests per minute from same IP{"eroare": "Rate limit depasit: ..."}
500PDF generation failureFlask default error page
GET /api/download/{fisier} Download a generated PDF report

Serves a previously generated PDF report as a file attachment. The filename is validated server-side against the strict pattern passsec_report_YYYYMMDD_HHMMSSnnnn.pdf — arbitrary path traversal or filenames are rejected with 400.

>_ URL Parameter
GET /api/download/passsec_report_20240915_143022_0042.pdf // Filename must match: passsec_report_YYYYMMDD_HHMMSSnnnn.pdf // Any other pattern returns 400.
>_ Response (200)
// Binary PDF stream with headers: // Content-Disposition: attachment; filename="passsec_report_*.pdf" // Content-Type: application/pdf
>_ Error Codes
CodeWhenResponse body
400Filename does not match the expected pattern{"eroare": "Nume de fișier invalid."}
404File not found on disk (expired or never generated)Flask default 404
GET /api/status Health check — server and dictionary status

Health-check endpoint. Returns server version, whether the rockyou.txt dictionary is loaded, and whether PDF report generation is available. No authentication or rate limit applied.

>_ Response (200)
{ "status": "online", "versiune": "3.2", "parole_incarcate": 500000, // entries loaded from rockyou.txt "rockyou": true, // false = only the 60-entry fallback list "pdf_reports": true // PDF generation available }
>_ Error Codes
CodeWhenResponse body
500Server error during status checkFlask default error page
GET /api/docs This documentation page

Returns this HTML documentation page. No parameters, no authentication, no rate limit. The page is self-contained and served inline by Flask.

>_ Response (200)
// Content-Type: text/html; charset=utf-8 // This page.