Menu

Monday, April 20, 2020

[PHP - Laravel] วิธีการตรวจสอบว่า Private key ที่ผู้ใช้งานใส่เข้ามาตรงกับ Public key ที่ตั้งค่าไว้หรือไม่
[PHP - Laravel] How to Verify Private Key with Existing Public Key

สืบเนื่องจากโพสต์ [Laravel - Model] การเข้ารหัสและถอดรหัสค่าของฟิลด์ใน Laravel Model โดยใช้ SSH Keys ที่ใช้ SSH keys ในการเข้ารหัสข้อมูล โดยที่เราตั้งค่า public key ไว้ในไฟล์ .env แต่เราให้ผู้ใช้งานเป็นผู้กรอก private key เอง แล้วเราจะรู้ได้อย่างไรว่า private key ที่ถูกกรอกเข้ามานั้น เป็นคู่ของ public key ที่เราตั้งค่าไว้จริงๆ

เรามีวิธีตรวจสอบ 2 วิธีดังนี้
  • การตรวจสอบด้วยการ sign และ verify signature
  • การตรวจสอบด้วยการ encrypt และ decrypt ข้อความ

การตรวจสอบด้วยการ sign และ verify signature

ขั้นตอนการตรวจสอบเป็นดังนี้
  1. เลือกข้อความมา 1 ข้อความ ข้อความอะไรก็ได้
  2. sign ข้อความนั้นด้วย private key ที่ผู้ใช้กรอกเข้ามา เพื่อสร้าง signature
  3. verify ข้อความนั้นกับ signature ที่เพิ่ง sign ด้วย public key ในระบบ
  4. ถ้า verify ไม่ผ่านจะเกิด exception ดังนี้

โค้ดตัวอย่างที่ implement ตามขั้นตอนข้างบนเป็นดังนี้
use phpseclib\Crypt\RSA;
use Cache;

...
        $privateKey = "key_from_user";
        $publicKey = env('PUBLIC_KEY');

        $plaintext = 'ThisIsTest';
        $rsa = new RSA();
        $rsa->loadKey($privateKey);
        $signature = $rsa->sign($plaintext);
        $rsa->loadKey($publicKey);

        try {
            $isVerified = $rsa->verify($plaintext, $signature);
            if(!$isVerified) {
                throw new \Exception('Incorrect SSH key')
            }
            Cache::forever('private_key', $privateKey);

        } catch (\Exception $ex) {
            // Handle invalid signature
        }
...
หมายเหตุ การตรวจสอบด้วยวิธีนี้อาจจะเกิด exception ข้างล่างนี้ในบางครั้ง เนื่องจาก signature ที่ได้อาจมีขนาดใหญ่กว่าที่กำหนด

  

การตรวจสอบด้วยการ encrypt และ decrypt ข้อความ

ขั้นตอนการตรวจสอบเป็นดังนี้
  1. เลือกข้อความมา 1 ข้อความ ข้อความอะไรก็ได้
  2. encrypt ข้อความนั้นด้วย public key ในระบบ 
  3. decrypt ข้อความที่ได้จากข้อ 2 ด้วย private key ที่ผู้ใช้กรอกเข้ามา 
  4. ถ้า decrypt ข้อความไม่สำเร็จ จะได้ค่า false
โค้ดตัวอย่างที่ implement ตามขั้นตอนข้างบนเป็นดังนี้
use phpseclib\Crypt\RSA;
use Cache;

...
        $privateKey = "key_from_user";
        $publicKey = env('PUBLIC_KEY');

        $plaintext = 'ThisIsTest';
        $rsa = new RSA();
        $rsa->loadKey($publicKey);
        $ciphertext = $rsa->encrypt($plaintext);

        $rsa->loadKey($privateKey);
        $decryptedText = $rsa->decrypt($ciphertext);

        if($decryptedText && $plaintext == $decryptedText) {
            Cache::forever('private_key', $privateKey);
        }
        else {
            // Handle invalid signature
        }
...

No comments:

Post a Comment