وَقفٌ تقنيّ، صدقةً جاريةً عن أرواح شهداء سوريا.
A technical waqf — a perpetual open-source endowment, given as an ongoing charity for the souls of the martyrs of Syria.
إلى أرواح شهداء سوريا. / To the souls of the martyrs of Syria. See
DEDICATION.md.
Reverse SMS verification for regions where outbound OTP delivery is unreliable. Instead of sending an OTP to the user, the user sends a short verification message from their phone to a local receiver number — domestic SMS works even when international inbound routes are blocked.
In regions where international outbound SMS routes are unreliable (Syria and similar networks), traditional OTP-by-SMS is broken. SYROTP flips the direction:
- Your app calls
POST /v1/verificationswith a phone number. - The server returns a unique code and a local receiver MSISDN.
- The user sends
VERIFY <code>to the receiver from their own phone. - A receiver gateway (Android app or USB GSM modem) forwards the inbound SMS to the server.
- The server verifies the sender matches the asked-for phone, and
the verification turns
verified.
Because the user's carrier delivers the SMS domestically — which works even when international inbound is blocked — the protocol is robust where outbound OTP is not.
| Path | Description |
|---|---|
apps/server |
Core verification server (Node + Postgres + Redis). |
apps/android-gateway |
Android app that captures inbound SMS and forwards it. |
apps/gsm-gateway |
Python USB GSM modem alternative for Linux. |
apps/web-demo |
Vanilla-JS verification demo. |
packages/sdk-js |
TypeScript/JavaScript client SDK. |
packages/sdk-python |
Python client SDK. |
packages/sdk-php |
PHP client SDK + Laravel package. |
packages/sdk-swift |
Swift client SDK. |
packages/sdk-kotlin |
Kotlin client SDK. |
packages/cli |
Operator CLI for bootstrap, smoke, and loadtest. |
packages/react |
React UI components for the verification flow. |
packages/web-component |
Vanilla web-component (framework-agnostic). |
packages/flutter |
Flutter widget package. |
packages/android-ui |
Android-native UI components (Compose). |
packages/swift-ui |
SwiftUI components for iOS. |
docs |
Operator + integration documentation. |
openapi.yaml |
OpenAPI 3.1 contract for the server. |
docs/ar/integration-guide.md |
دليل التكامل العربي الشامل — Arabic-language full integration guide for Arab developers (Fusha). |
pnpm install
cp .env.example .env
# Generate fresh secrets:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Paste the output into MASTER_ENCRYPTION_KEY and COOKIE_SECRET in .env
docker compose up -d postgres redis
docker compose --profile migrate run --rm migrate
docker compose up -d server
pnpm syrotp doctor
pnpm syrotp bootstrap \
--app-name "My App" \
--msisdn +963991234567 \
--simulate-heartbeat
pnpm syrotp smoke # end-to-end verification dry run
⚠️ Secrets shown once. Bootstrap prints the publishable key (pk_live_*), the secret API key (sk_live_*), and the gateway signing key exactly once. Save them in your secret manager before you run anything else — they are never displayed again.
import { SyrotpClient } from "@syrotp/sdk";
const syrotp = new SyrotpClient({
baseUrl: "https://otp.example.com",
apiKey: process.env.SYROTP_SECRET_KEY!,
});
const v = await syrotp.startVerification({
phone: "0991234567",
purpose: "login",
});
console.log(`Send "${v.message}" to ${v.send_to}`);
const result = await syrotp.waitForVerification(v.id);
if (result.status === "verified") {
// phone owned by sender
}The web demo at apps/web-demo/index.html
is a complete vanilla-JS UI you can open in a browser.
The Android app captures incoming SMS on a phone you own (a dedicated receiver phone with a local SIM, e.g. Syriatel or MTN), and forwards them HMAC-signed to your SYROTP server.
- A spare Android device (Android 7.0 / API 24+).
- A SIM card on the operator you want to receive on.
- Android Studio Hedgehog or newer.
- The Receiver ID and Signing key printed by the bootstrap step.
cd apps/android-gateway
./gradlew :app:assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk- Open SYROTP Gateway on the phone.
- Enter:
- Server URL —
https://otp.example.com(no trailing slash) - Receiver ID —
rcv_... - Signing key — the long hex value (paste once; it's stored encrypted via Android Keystore and never shown again).
- Server URL —
- Tap Save & pair. Grant SMS permissions when prompted.
- The status should switch to Paired and the queue depth should be
0.
From another device, send VERIFY ABCDEF to the gateway's SIM number.
The queue depth briefly ticks up, then returns to 0 as the gateway
uploads the SMS. The server marks any matching verification as
verified.
- Battery optimization — disable battery optimization for the gateway app (Settings → Apps → SYROTP Gateway → Battery → Unrestricted).
- Multi-SIM — the manifest declares support; the SIM slot is reported per inbound when available.
- Cleartext — the network security config blocks plaintext HTTP.
For local development against
http://10.0.2.2:3000(emulator), editnetwork_security_config.xml.
iOS does not allow programmatic SMS reading. iOS apps can be SYROTP clients via the SDK; they cannot be receivers. Use Android or a USB GSM modem instead.
If you'd rather use a Linux box + USB GSM modem (SIM800/SIM900,
Quectel/Huawei sticks) than a phone, use the Python gateway in
apps/gsm-gateway/. Same wire protocol as the
Android gateway, same HMAC scheme, runs as a systemd service.
sudo useradd --system --home /opt/syrotp-gateway --shell /usr/sbin/nologin syrotp-gateway
sudo usermod -a -G dialout syrotp-gateway
sudo python3 -m venv /opt/syrotp-gateway/venv
sudo /opt/syrotp-gateway/venv/bin/pip install ./apps/gsm-gateway
sudo install -d -m 750 -o syrotp-gateway -g syrotp-gateway /etc/syrotp-gateway
sudo install -m 600 -o syrotp-gateway -g syrotp-gateway \
apps/gsm-gateway/config.example.toml /etc/syrotp-gateway/config.toml
sudoedit /etc/syrotp-gateway/config.toml
sudo install -m 644 apps/gsm-gateway/systemd/syrotp-gateway.service \
/etc/systemd/system/syrotp-gateway.service
sudo systemctl daemon-reload
sudo systemctl enable --now syrotp-gateway
journalctl -u syrotp-gateway -fFull operator guide: docs/gsm-gateway.md.
Before pointing real users at your SYROTP instance:
-
MASTER_ENCRYPTION_KEYandCOOKIE_SECRETare unique 64-hex values, not the.env.exampleplaceholders. - Bootstrap-issued API keys (
pk_live_*,sk_live_*) and gateway signing keys are stored in a real secret manager. - Postgres + Redis are behind a private network — not exposed.
- TLS termination is configured (Nginx, Caddy, or cloud LB).
- Postgres backups configured and tested.
- Rate limiting (Cloudflare or in-app) is active.
- Server logs go to a centralized store, not just the local disk.
- Android gateway phone is plugged in (not just on battery).
- Battery optimization disabled for the gateway app.
- SIM card has enough balance for inbound SMS reception.
- Heartbeat is live (
pnpm syrotp receiver listshows green).
| Component | Status |
|---|---|
| Protocol v1.0 | Frozen |
| Server | Production-ready |
| JS SDK | Stable |
| Python SDK | Stable |
| PHP SDK + Laravel | Stable |
| Swift SDK | Beta |
| Kotlin SDK | Beta |
| Android UI | Beta |
| Flutter | Beta |
| SwiftUI | Alpha |
| Android gateway | Stable |
| GSM gateway | Stable |
See ROADMAP.md for v1.1+ work.
MIT — see LICENSE.
SYROTP is released openly for anyone, anywhere, for any purpose, without
restriction. We only ask that you use it for good. See DEDICATION.md
for the spirit behind this release.
For security disclosures, see SECURITY.md. Report
vulnerabilities via a private security advisory on GitHub
or by email to info@mhd-shekho.com — do not file public issues for security matters.
Muhammed Shekho — SYR-ROOT
Website: https://mhd-shekho.com