مین مواد پر جائیں

HTML فارم کا دستخط

گاہک براؤزر میں ہی فارم کی کوئی بھی فیلڈ بدل سکتا ہے — مثال کے طور پر، کم رقم لکھ سکتا ہے۔ اسی لیے انوائس کی فیلڈز دستخط شدہ کنٹینر میں جاتی ہیں: سروس دستخط کا دوبارہ حساب لگاتی ہے اور اگر وہ مماثل نہ ہو تو انوائس نہیں بناتی۔

اسٹور کا سرور دستخط کا حساب لگاتا ہے۔ براؤزر تک صرف تیار data اور signature کا جوڑا پہنچتا ہے۔

دستخط کس چیز پر ہوتا ہے

data = base64url(json)
signature = HMAC-SHA256(data, formSecret)

HMAC کا حساب data اسٹرنگ پر ہوتا ہے، JSON کے بائٹس پر نہیں۔ وصول کنندہ دستخط کو بھیجی گئی اسٹرنگ سے جوں کا توں جانچتا ہے، اور صرف اس کے بعد اسے ڈی کوڈ کرتا ہے۔

اس سے یہ نتیجہ نکلتا ہے کہ کوئی canonicalization نہیں ہوتی: کلیدوں کی ترتیب، JSON کی انڈینٹیشن اور Unicode escaping کا طریقہ دستخط پر اثر نہیں ڈالتے۔ کوئی بھی معیاری JSON انکوڈر کام کرتا ہے۔

حوالہ جاتی سیٹ

یہ قدریں اپنے کوڈ میں ڈالیں اور نتیجے کا موازنہ کریں۔

مثال کی خفیہ کلید:

dvc3khto5WpjEPojZfYJsbJzFEPPVnRa

رقم اور ادائیگی کی مہلت نمبرز کی صورت میں؛ اسٹرنگز بھی قبول ہیں:

{"projectId":"a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d","amountFiat":10.5,"currencyFiat":"USD","timeToPay":1,"description":"Order #7, delivery","serviceData":"order-7"}

data اسٹرنگ انہی بائٹس کا base64url ہے۔ یہاں پیڈنگ ہٹی ہوئی ہے؛ وصول کنندہ اسے پیڈنگ کے ساتھ بھی قبول کرتا ہے:

eyJwcm9qZWN0SWQiOiJhMWIyYzNkNC01ZTZmLTRhN2ItOGM5ZC0wZTFmMmEzYjRjNWQiLCJhbW91bnRGaWF0IjoxMC41LCJjdXJyZW5jeUZpYXQiOiJVU0QiLCJ0aW1lVG9QYXkiOjEsImRlc2NyaXB0aW9uIjoiT3JkZXIgIzcsIGRlbGl2ZXJ5Iiwic2VydmljZURhdGEiOiJvcmRlci03In0

اوپر والی خفیہ کلید کے ساتھ اس اسٹرنگ کا دستخط:

09628020c47400c9231420450af642adfdb3c246f33e3e12cb8e28f96c2a785e

ان قدروں کے ساتھ نیچے کی مثالیں بالکل یہی data اور دستخط پرنٹ کرتی ہیں۔ یہی JSON، آخر میں "output":"errors" کلید کے ساتھ، ایک مختلف data اسٹرنگ اور مختلف دستخط دیتا ہے۔

اگر JSON ایک جیسا نظر آنے کے باوجود data مماثل نہیں ہے، تو وجہ JSON انکوڈر ہے: کلیدوں کی مختلف ترتیب یا فاصل کے بعد خالی جگہیں۔ وصول کنندہ ایسا کنٹینر قبول کرتا ہے، لیکن وہ حوالے سے حرف بہ حرف مماثل نہیں ہوتا۔

مثالیں

<?php

function signedContainer(array $fields, string $formSecret): array {
$data = rtrim(strtr(base64_encode(json_encode($fields)), '+/', '-_'), '=');

return [
'data' => $data,
'signature' => hash_hmac('sha256', $data, $formSecret),
];
}

// Test values from the reference set. Before going live,
// replace the secret with the form secret from your project settings
$container = signedContainer([
'projectId' => 'a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d',
'amountFiat' => 10.5,
'currencyFiat' => 'USD',
'timeToPay' => 1,
'description' => 'Order #7, delivery',
'serviceData' => 'order-7',
], 'dvc3khto5WpjEPojZfYJsbJzFEPPVnRa');

echo $container['data'], "\n";
echo $container['signature'], "\n";

مثال کی قدریں ASCII ہیں، لیکن کوڈ بغیر کسی تبدیلی کے کسی بھی Unicode کے ساتھ کام کرتا ہے۔ PHP اور Python بطور ڈیفالٹ غیر ASCII حروف کو \uXXXX کی صورت میں escape کرتے ہیں، جبکہ JavaScript خام UTF-8 بھیجتا ہے — وصول کنندہ دونوں قبول کرتا ہے۔

دو عام غلطیاں

کنٹینر کے بجائے JSON پر دستخط ہوتا ہے۔ HMAC کا حساب data اسٹرنگ پر ہوتا ہے، یعنی base64url پر۔ یہ غلطی «سب کچھ مماثل ہے، لیکن دستخط نہیں» جیسی نظر آتی ہے۔

دستخط کے بعد کنٹینر دوبارہ بنایا جاتا ہے۔ اگر data کا ایک بائٹ بھی بدل جائے، تو دستخط غلط ہو جاتا ہے۔ جوڑا اپنے کوڈ میں ایک ہی جگہ بنائیں۔

اگر دستخط مماثل نہ ہو

JSON سے data تک اور data سے دستخط تک کی زنجیر کو مرحلہ وار جانچیں؛ حوالے سے سب سے پہلے الگ ہونے والی کڑی ہی وجہ ہے۔ پہلے data جانچیں: یہ خفیہ کلید پر منحصر نہیں۔