Derive AES Keys (Gio_CreateKeyAndIv)
HMAC-SHA512Menderivasi AES key, IV, dan CS dari clientID + timestamp. Replika tepat dari PHP
Gio_CreateKeyAndIv($clientID, $timeStamp). Digunakan pada saat registrasi perangkat baru (bukan DB lookup).Cara kerja: HMAC-SHA512(key=timestamp, msg=clientID) → 64 bytes → slice ke-HH:MM:SS untuk dapat key/iv/cs. AES Key = 32 bytes, IV = 16 bytes, CS = 8 bytes. X-CLIENT-ID di-encode otomatis menggunakan clientID + timestamp yang sama.
# CLI:
node lpd-crypto.cjs keygen "AQ3A.240912.001.01102025120205" "2026-04-20 11:44:20"
node lpd-crypto.cjs keygen "AQ3A.240912.001.01102025120205" "2026-04-20 11:44:20"
Timestamp Jakarta (WIB UTC+7)
UtilityMenghasilkan timestamp waktu Jakarta sekarang dalam dua format: YYYY-MM-DD HH:MM:SS (untuk iOS API) dan ISO8601+07:00 (untuk SNAP API).
# Format iOS (gmob_request, X-TIMESTAMP field):
2026-04-20 11:44:20
# Format SNAP (ISO8601 dengan offset):
2026-04-20T11:44:20+07:00
2026-04-20 11:44:20
# Format SNAP (ISO8601 dengan offset):
2026-04-20T11:44:20+07:00
Generate X-REFERENCE
Unique IDGenerate nomor referensi unik format SMYHHMMSSxxxxO1012YYYYMMDD. Setiap request transfer membutuhkan X-REFERENCE yang belum pernah digunakan (status 45 = duplikat).
Penting: Setiap X-REFERENCE hanya bisa digunakan SATU KALI per endpoint. Jika server mengembalikan status 45 ("No. referensi duplikat"), generate reference baru.
AES-256-CBC Encrypt (Gio_Encrypt)
AES-256-CBCEnkripsi plaintext dengan AES-256-CBC. Replika dari PHP
openssl_encrypt($plain,'AES-256-CBC',$key,OPENSSL_RAW_DATA,$iv). Gunakan key/iv dari hasil Derive AES Keys.
# CLI:
node lpd-crypto.cjs encrypt "plaintext" "<aesKey_b64>" "<aesIv_b64>"
node lpd-crypto.cjs encrypt "plaintext" "<aesKey_b64>" "<aesIv_b64>"
AES-256-CBC Decrypt (Gio_Decrypt)
AES-256-CBCDekripsi ciphertext base64 kembali ke plaintext. Replika dari PHP
openssl_decrypt(base64_decode($enc),'AES-256-CBC',$key,OPENSSL_RAW_DATA,$iv).
# CLI:
node lpd-crypto.cjs decrypt "<cipher_b64>" "<aesKey_b64>" "<aesIv_b64>"
node lpd-crypto.cjs decrypt "<cipher_b64>" "<aesKey_b64>" "<aesIv_b64>"
Decrypt Full Request Body
Batch DecryptCatatan: Body field (from_acc, to_acc, dst) hanya bisa didekripsi jika AES key/IV-nya SAMA dengan yang digunakan saat enkripsi (dari DB atau Gio_CreateKeyAndIv). Data dari curl real membutuhkan AES key dari tabel gmob_nasabah di database.
Decode X-CLIENT-ID (Gio_DecryptDID)
DIDDekode header X-CLIENT-ID menjadi
app|clientID|timestamp. Algoritma custom: ekstrak 3 segmen base64 dari posisi tersembunyi, decode, split oleh "|".
# CLI:
node lpd-crypto.cjs did "<X-CLIENT-ID>"
node lpd-crypto.cjs did "<X-CLIENT-ID>"
Encode X-CLIENT-ID (kebalikan DID)
DID EncodeBuat X-CLIENT-ID dari clientID + timestamp. Berguna untuk simulasi request dari perangkat baru.
Decode JWT (Authorization header)
JWT RS256Decode JWT Authorization header. Format custom LPD: header berisi
trans_no + alg:RS256; payload berisi trans_time. Dibuat oleh lamanuna.biz.id Get_Token.
# CLI:
node lpd-crypto.cjs jwt "<token>"
node lpd-crypto.cjs jwt "<token>"
Decode X-SIGNATURE / X-PARTNER-ID
base64 → hexDecode X-SIGNATURE atau X-PARTNER-ID dari base64 ke hex. Keduanya menggunakan formula yang sama:
base64(HMAC-SHA512(token:timestamp, aes_cs)).
# CLI:
node lpd-crypto.cjs sig "<base64_signature>"
node lpd-crypto.cjs sig "<base64_signature>"
Generate X-SIGNATURE & X-PARTNER-ID
HMAC-SHA512Generate X-SIGNATURE dan X-PARTNER-ID. Formula:
base64(HMAC-SHA512(token + ":" + timestamp, aes_cs)). Keduanya menghasilkan nilai yang SAMA jika menggunakan aes_cs yang sama.
# Formula:
base64( HMAC-SHA512( token + ":" + timestamp, aes_cs ) )
base64( HMAC-SHA512( token + ":" + timestamp, aes_cs ) )
iOS Token Signature (iosTokenCtrl)
RSA-SHA256Generate X-SIGNATURE untuk endpoint
POST /api/smart/access/token. Formula: RSA-SHA256(SHA256("Seminyak|" + timestamp)) menggunakan private_key_lpd.pem.
# Formula PHP (iosTokenCtrl.php):
$clientStamp = hash("sha256", "Seminyak|" . $timeStamp);
openssl_sign($clientStamp, $sig, $privateKey);
base64_encode($sig);
$clientStamp = hash("sha256", "Seminyak|" . $timeStamp);
openssl_sign($clientStamp, $sig, $privateKey);
base64_encode($sig);
SNAP Token Signature (BPD)
RSA-SHA256Generate X-SIGNATURE untuk endpoint
POST /api/v1.0/access-token/b2b. Formula: RSA-SHA256(clientKey + "|" + timestamp) menggunakan private_bpd_003.pem.
# Formula SNAP BPD:
message = clientKey + "|" + timestamp
RSA-SHA256(message, private_bpd_003.pem)
base64_encode(signature)
message = clientKey + "|" + timestamp
RSA-SHA256(message, private_bpd_003.pem)
base64_encode(signature)
Hash Code Transfer
SHA-256Formula Check/Inquiry:
SHA256("%"+fromAcc+"#"+amount+"@"+dateTime+"^"+refNo+"*"+destBank+"~"+destAcc+"|"+BPD_HASHCODE+"%")Formula Posting:
SHA256("@"+fromAcc+"|"+amount+"~"+dateTime+"*"+refNo+"^"+destBank+"#"+destAcc+"("+destName+")"+BPD_HASHCODE+"@")Formula LPD Internal:
SHA256("{"+nominal+"*"+norekFrom+"^"+norekTo+"%"+nameFrom+"#"+nameTo+"@"+BPD_HASHCODE+"}")BPD_HASHCODE = p91wrswK (dari .env production). Hash code ini kemudian di-encrypt dengan AES sebelum dikirim di body request.
# CLI:
node lpd-crypto.cjs hashcode <fromAcc> <amount> <dateTime> <refNo> <destBank> <destAcc> <destName>
node lpd-crypto.cjs hashcode <fromAcc> <amount> <dateTime> <refNo> <destBank> <destAcc> <destName>
Build Transfer Bank Request (Lengkap)
Full BuilderBuild request lengkap untuk
/api/smart/transfer/bank/check atau /post atau /inquiry. Menghasilkan semua header + body terenkripsi + curl command siap pakai.Login Nasabah
POST /api/smart/access/loginLogin mengirim
MD5(user_name) & MD5(user_pass) sebagai body. Header Authorization (JWT), X-SIGNATURE, X-PARTNER-ID, X-CLIENT-ID dibuat otomatis dari AES CS + private key LPD. Setelah berhasil, sesi aktif untuk Cek Saldo & Transfer. 1. Derive Keys
›
2. Isi Kredensial
›
3. Login
›
4. Status 00
Kunci AES & X-CLIENT-ID
Kredensial Nasabah
# Flow otomatis (sesuai POC sukses):
1. MD5(user_name) → user_name hashed (32 hex)
2. MD5(user_pass) → user_pass hashed (32 hex)
3. createJWT(refNo, tsISO, priv_lpd) → Authorization header
4. generateSignature(jwt, ts, aesCs) → X-SIGNATURE & X-PARTNER-ID
5. POST /api/smart/access/login → status:"00" + account_list
# Catatan: Body TIDAK di-AES-encrypt. Hanya header yang perlu AES CS.
1. MD5(user_name) → user_name hashed (32 hex)
2. MD5(user_pass) → user_pass hashed (32 hex)
3. createJWT(refNo, tsISO, priv_lpd) → Authorization header
4. generateSignature(jwt, ts, aesCs) → X-SIGNATURE & X-PARTNER-ID
5. POST /api/smart/access/login → status:"00" + account_list
# Catatan: Body TIDAK di-AES-encrypt. Hanya header yang perlu AES CS.
Belum login. Silakan Login Nasabah terlebih dahulu untuk mendapatkan token.
Cek Saldo
POST /api/smart/account/balanceNomor rekening akan dienkripsi AES-256-CBC sebelum dikirim. JWT & signature dibuat ulang otomatis dari private key LPD tiap request.
# Endpoint:
POST /api/smart/account/balance
Body: { no_rek: aesEncrypt(norek) }
POST /api/smart/account/balance
Body: { no_rek: aesEncrypt(norek) }
Belum login. Silakan Login Nasabah terlebih dahulu.
Transfer Antar Rekening
Inquiry → Posting 1. Inquiry
›
2. Konfirmasi
›
3. Posting
Inquiry Transfer
Inquiry untuk mengecek ketersediaan rekening tujuan dan nominal. Semua field dienkripsi sebelum dikirim.
# Flow Transfer:
1. POST /api/smart/transfer/inquiry → cek rekening & saldo
2. Konfirmasi data oleh user
3. POST /api/smart/transfer/posting → eksekusi transfer
# Semua field dienkripsi AES-256-CBC, JWT & signature otomatis
1. POST /api/smart/transfer/inquiry → cek rekening & saldo
2. Konfirmasi data oleh user
3. POST /api/smart/transfer/posting → eksekusi transfer
# Semua field dienkripsi AES-256-CBC, JWT & signature otomatis
Referensi Cepat
Konstanta dari .env
BPD_HASHCODE
p91wrswK
CLIENT_SECRET
7vCjkNHs
CLIENT_VA
VA-325
WHITELIST_IP
34.50.74.78
BPD_PREFIX
989191
X-CLIENT-KEY (SNAP)
LPD-SEMINYAK-001
Algoritma Enkripsi per Komponen
Body fields
AES-256-CBC key/iv dari DB atau Gio_CreateKeyAndIv
X-SIGNATURE
HMAC-SHA512 base64(HMAC(token:ts, aes_cs))
X-PARTNER-ID
HMAC-SHA512 sama dengan X-SIGNATURE
hash_code (transfer)
SHA-256 string dengan separators khusus
iOS token sig
RSA-SHA256 sign(SHA256("Seminyak|ts"), priv_lpd)
SNAP token sig
RSA-SHA256 sign(clientKey+"|"+ts, priv_bpd)
AES Key derivation
HMAC-SHA512 key=ts, msg=clientID → 64 bytes → slice
CLI Commands
node lpd-crypto.cjs demo
node lpd-crypto.cjs keygen "clientID" "timestamp"
node lpd-crypto.cjs encrypt "plaintext" "key_b64" "iv_b64"
node lpd-crypto.cjs decrypt "cipher_b64" "key_b64" "iv_b64"
node lpd-crypto.cjs did "X-CLIENT-ID"
node lpd-crypto.cjs jwt "JWT_token"
node lpd-crypto.cjs sig "X-SIGNATURE_b64"
node lpd-crypto.cjs hashcode from amount datetime ref bank acc name
node lpd-crypto.cjs ref SMY
node lpd-crypto.cjs keygen "clientID" "timestamp"
node lpd-crypto.cjs encrypt "plaintext" "key_b64" "iv_b64"
node lpd-crypto.cjs decrypt "cipher_b64" "key_b64" "iv_b64"
node lpd-crypto.cjs did "X-CLIENT-ID"
node lpd-crypto.cjs jwt "JWT_token"
node lpd-crypto.cjs sig "X-SIGNATURE_b64"
node lpd-crypto.cjs hashcode from amount datetime ref bank acc name
node lpd-crypto.cjs ref SMY
File Keys
private_bpd_003.pem
Private key SNAP BPD Bali (untuk X-SIGNATURE SNAP)
private_key_lpd.pem
Private key LPD Seminyak (untuk iOS token sig)
keys/public_key.pem
Public key client (diterima server untuk verifikasi iOS)
public_key_bpd.pem
Public key BPD (untuk verifikasi SNAP token)