Skip to content

Instantly share code, notes, and snippets.

@helloworldlab
Last active June 28, 2021 01:06
Show Gist options
  • Select an option

  • Save helloworldlab/8089de03d3578b83bc86a1091417381d to your computer and use it in GitHub Desktop.

Select an option

Save helloworldlab/8089de03d3578b83bc86a1091417381d to your computer and use it in GitHub Desktop.
PHP dan GPG

Pengenalan

Terdapat 2 pihak iaitu pihak A dan pihak B. Pihak A ingin menghantar encrypted data pada pihak B dan pada masa yang sama pihak B juga ingin menghantar encrypted data pada pihak A. Bagi menyelesaikan masalah ini kita boleh menggunakan asymmetric cryptography seperti library GnuPG (GPG).

Di dalam asymmetric cryptography, pihak A dan pihak B perlu mempunyai sepasang kekunci yang dipanggil sebagai Public Key dan Private Key. Public Key dan Private Key ini mempunyai tujuan masing-masing:

  1. Public Key digunakan untuk encrypt data. Jadi, Public Key boleh diberikan kepada siapa-siapa yang diinginkan.
  2. Private Key digunakan untuk decrypt data. Jadi, Private Key perlu disimpan dengan selamat dan tidak boleh diberikan kepada sesiapa.

Untuk pengetahuan anda, Private Key dan Secret Key adalah sama.

GnuPG (GPG)

Pemasangan

  1. Semak kewujudan library GnuPG (GPG) pada komputer dengan arahan baris gpg --version:
gpg --version

gpg (GnuPG) 2.2.27
libgcrypt 1.9.3-unknown
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
  1. Jika tiada, pasang library tersebut dengan taip arahan baris berikut pada terminal mengikut sistem operasi masing-masing:
# Mac OS
brew install gnupg

# Red Hat (Fedora)
sudo dnf install gnupg

# Debian (Ubuntu)
sudo apt install gnupg

Bagi pengguna sistem operasi Windows, anda boleh mendapatkan library GnuPG (GPG) pada pautan ini.

Menjana pasangan kekunci

Berikut merupakan panduan untuk menjana pasangan kekunci Public Key dan juga Private Key:

  1. Jana Public Key dan Private Key dengan taip arahan baris berikut pada terminal:

    gpg --gen-key
    
    • Masukkan nama yang ingin digunakan dan tekan butang Enter.
    • Masukkan emel yang ingin digunakan dan tekan butang Enter.
    • Jika anda ingin kemaskini semua nama atau emel, boleh tekan butang N untuk tukar nama, tekan butang E untuk tukar emel. Jika anda ingin teruskan, tekan butang O dan jika ingin batalkan, tekan butang Q.
  2. Jika anda tekan butang O anda dipaparkan untuk meletakkan passphrase ataupun kata laluan. Anda digalakkan untuk meletakkan passphrase anda.

  3. Maka, pasangan Public Key dan Private Key akan terhasil. Anda boleh menyemaknya dengan taip arahan baris gpg --list-keys pada terminal:

    gpg --list-keys
    
    /home/pihakA/.gnupg/pubring.kbx
    -----------------------------------
    pub   rsa3072 2021-06-23 [SC] [expires: 2023-06-23]
      5FF7D2955056AD37C979488B811AC80AF0E77AC0
    uid           [ultimate] Pihak A <[email protected]>
    sub   rsa3072 2021-06-23 [E] [expires: 2023-06-23]
    
    pub   rsa3072 2021-06-23 [SC] [expires: 2023-06-23]
        879812AF2D0ABB1A0548BE093A88AA2FCCB336E5
    uid           [ultimate] Pihak B <[email protected]>
    sub   rsa3072 2021-06-23 [E] [expires: 2023-06-23]
    

Penggunaan pakej PHP pear/crypt_gpg

Untuk berkomunikasi dengan library GnuPG (GPG) dengan menggunakan PHP, anda boleh memasang pakej PHP pear/crypt_gpg pada projek anda dengan menggunakan Composer. Anda boleh memasangnya pada projek anda dengan menaip arahan baris berikut:

composer require pear/crypt_gpg

Pihak A menghantar encrypted text kepada pihak B

A -----encrypt data dengan menggunakan Public Key pihak B-----> B

Untuk menghantar encrypted data dari pihak A kepada pihak B, pihak A perlu encrypt data dengan menggunakan Public Key pihak B. Supaya, apabila pihak B menerima encrypted data dari pihak A, pihak B sahaja yang boleh decrypt encrypted data itu kembali dengan menggunakan Private Key pihak B sendiri.

  1. Pihak A encrypt plaintext dengan menggunakan Public Key Pihak B.

    // Buat satu objek bagi kelas Crypt_GPG
    $gpg = new Crypt_GPG();
    
    // Tetapkan Public Key yang ingin digunakan
    $gpg->addEncryptKey('[email protected]');
    
    // Encrypt plaintext, dan simpan encrypted text pada pembolehubah $encryptedText
    $encryptedText = $gpg->encrypt('data sensitif seperti maklumat bank atau maklumat kad kredit');
    
    // Simpan encrypted text di dalam satu fail bernama encrypted_text
    file_put_contents('encrypted_text', $encryptedText);

    Hasilnya, anda akan menghasilkan encrypted text seperti berikut:

    -----BEGIN PGP MESSAGE-----
    
    hQGMA0N2FxvPoVdoAQwAnjBgxspdXhbev+/wPsMoFs2SHt+AsxUlwXSCGpP8ADI/
    5FjygnwLzSYDDnbGhhHfnSVh2xBXr6Q9O2yHY2/7lvLIDa56dKQT3cILvDKUWYdT
    FsbU+e8lT0wOdFjodjffN8fpMDBbXwUQiKvTtbR3s1TDviFw/nBkTCwpKqSmIU9t
    erbWLOVbFk7NEubSPvOXiRojTfaGFsqzeu6cBXa3zPihAqVJry4zBDyt9YSuPGPr
    hNfRHviZGbqCeM1buoBX1OOOs36Yk/bSF7jK/G1r8Jl4310wURS6uh0nu/EWeEHE
    zuCz42wjHwTLyHZejD2Ag/Rg2JIIjwPPTjjgbSC1zDVyDVP0oSPliofHGvfEjW5V
    aVTVmjR/nFP0K9jTxdtu2vQ5M+eknNalLkXN88adG/Zl2vHAQHYmlHRQKrZgtP7z
    lpzZjIYmiYyKtYvLZwuxqrPcmL0QfCE69rNzVWERSH9Tn7DmFWU4c94UwO5/MYCd
    FCwBSsbIqtoUGQA+RaCI0m0Bg8Ou2iaM3hITZfqFcLkf51djQml6PlkC2Wf5yxvJ
    GQ5HhWZqc/jIYXzNoG80bIsdoRJyxUK/NtVLNM6dmyQb1GATIiIK/pzPmar7fNbE
    xOkygHWEGLDRmG24CuVl5x8w01ChuumaETDOkjWl
    =wXRE
    -----END PGP MESSAGE-----
    
  2. Pihak A menghantar encrypted text kepada pihak B (fail bernama encrypted_text).

  3. Pihak B terima encrypted text (fail bernama encrypted_text) dan decrypt encrypted text tadi dengan menggunakan Private Key pihak B sendiri.

    // Buat satu objek bagi kelas Crypt_GPG
    $gpg = new Crypt_GPG();
    
    // Tetapkan Private Key yang ingin digunakan bersama dengan passphrase (jika ada)
    $gpg->addDecryptKey('[email protected]', 'passphrase');
    
    // Dapatkan encrypted text pada fail bernama encrypted_text.txt
    $encryptedText = file_get_contents('encrypted_text.txt');
    
    // Decrypt encrypted text, dan simpan decrypted text pada pembolehubah $decryptedText
    $decryptedText = $gpg->decrypt($encryptedText);
    
    // Simpan decrypted text di dalam satu fail bernama decrypted_text.txt
    file_put_contents('decrypted_text.txt', $decryptedText);

Perkara yang sama juga berlaku jika pihak B ingin menghantar encrypted text kepada pihak A.

Pihak A menghantar encrypted text bersama digital signature kepada pihak B

Untuk menghantar encrypted data bersama digital signature dari pihak A kepada pihak B, pihak A perlu encrypt data dengan menggunakan Public Key pihak B dan juga menghasilkan digital signature dengan menggunakan Private Key pihak A sendiri.

Supaya, apabila pihak B menerima encrypted data dari pihak A, pihak B boleh decrypt encrypted data itu kembali dengan menggunakan Private Key pihak B sendiri di samping dapat melihat kesahihan data yang dihantar dengan menyemak maklumat penghantar iaitu maklumat pihak A.

  1. Pihak A encrypt plaintext dengan menggunakan Public Key Pihak B.

    // Buat satu objek bagi kelas Crypt_GPG
    $gpg = new Crypt_GPG();
    
    // Tetapkan Public Key yang ingin digunakan untuk encrypt data
    $gpg->addEncryptKey('[email protected]');
    
    // Tetapkan Private Key yang ingin digunakan untuk menghasilkan Digital Signature
    $gpg->addSignKey('[email protected]', 'passphrase');
    
    // Encrypt plaintext, dan simpan encrypted text pada pembolehubah $encryptedText
    $encryptedText = $gpg->encryptAndSign('data sensitif seperti maklumat bank atau maklumat kad kredit');
    
    // Simpan encrypted text di dalam satu fail bernama encrypted_text
    file_put_contents('encrypted_text', $encryptedText);

    Hasilnya, anda akan menghasilkan encrypted text bersama digital signature seperti berikut:

    -----BEGIN PGP MESSAGE-----
    
    hQGMA1TIaFdiUENRAQv/fwhQexdPXKtO8VnuB8h5HiPUuMyT2D6LoK3B4x63ZQp1
    yIJeDw7wlv9Uj3DNjt04zv8NAekcCoZbKXcmQrZBU1juocc+dxLHq9Ftf3hbw4R4
    xTZt+Ue5cq/ugDKSzgykP92Xb+fEflbYWLDI8etWEz0eF7QWui19JIBLK4M58gKi
    q1wCPPjUbkuHtcIfOFdQcTft5tZ7n7rBacHOkwCgy0Xxl/JiPG4TDbMNtE4vF+lC
    tjNE1/zewl63J310U8B+IxgEtevdK9lXd2ZZmib0KA7yxg0t2UJY0LngcTL6LApE
    4OOqnozRfq0wnNCWHgEsGIVmi1cVhXvz/UC96gqN2HDt8Zo0J4hxWr71ET50vv9g
    CMwagDDiibM5Z9pMugQ5AdTOdcnkMe96yhNU1hxVRuQF64sX7GOuDPgb+7CTacT6
    4aB9EaBXT2Kg+FkKYIfsfbbuh7ef2CIIAMPl7i1PczAjHScIUMHcUbnAYymabvwM
    QuO2Z4gSBTNb5w7WO2Xu0ukBuV9CHK2pmeVynnJgLpHZkNZ30NDWwfFgVvNB7olw
    X9Yj5rditEzZLazvKnU0oJcrIXkVLYN6UGtwSO0Kf7wQ39MsReugpyZ1GfKIjWT9
    Jpk/llR34I+ZxV8UzyDyahjabHP7Z3LUMsvMIHDV+jCpOaARpwkF5MPTFcuK1kRk
    /Z1r3SJwf23EP9NPdO+41QOcbzlxRcayGNB6VB6F4hEnJKrf8hcmEassVAkurkdU
    pD3l05BuHlgRRhA2z5L4/WYMBvjeMjHGPF2VBw6z9oixjKiIqnMVVPuleGZsks35
    30ONzx+UFii7UPGYeMg7BfetUHbHf5C7w4G63cXS0fuGHEnGa+XTNYeXutYHfCxU
    YEvsSlRa5HkQCHoVKdHln/yM7R/1mP0P/M2KGUdI7cvwkKy+XE3Bnks/MuObIpnD
    wra6uq0Y3U63eA75EPg2HhFn0BmggCB1m7GEInLTNaAmDoBQ6hOKSx546JlVT8/0
    mZLkgytELxV50Riy2vKkDk9R2/toPlokbqg8n6wnWwf6WW2gJbZQ1RWbKPkNUufV
    bgv1zCkEIyF+EQSlESfPYFIyLFtHHXIbFjVdxIbyg6sdmktQYG5e2lAcwT6dRMEp
    ryipK3/PQm+58vjIb96itYXHEz35jrHbI907YJiW5gltfSiL8vN+Cwk30tdooaCJ
    bz3XJZ9EsRpg78Zl6ahIarokIBnMt9Fq1r4ge4N1fLIweISsP0ZrakxM+z6kBzlp
    mNCynmQbAXltr42bsrPS
    =xNDO
    -----END PGP MESSAGE-----
    
  2. Pihak A menghantar encrypted text kepada pihak B (fail bernama encrypted_text).

  3. Pihak B terima encrypted text (fail bernama encrypted_text) dan decrypt encrypted text tadi dengan menggunakan Private Key pihak B sendiri.

    // Buat satu objek bagi kelas Crypt_GPG
    $gpg = new Crypt_GPG();
    
    // Tetapkan Private Key yang ingin digunakan bersama dengan passphrase (jika ada)
    $gpg->addDecryptKey('[email protected]', 'password');
    
    // Dapatkan encrypted text pada fail bernama encrypted_text.txt
    $encryptedText = file_get_contents('encrypted_text.txt');
    
    // Decrypt encrypted text, dan simpan decrypted text pada pembolehubah $decryptedTextAndDigitalSignature
    $decryptedTextAndDigitalSignature = $gpg->decryptAndVerify($encryptedText);
    
    // Ambil decrypted text pada array dengan kekunci data dan simpan pada pembolehubah $decryptedText
    $decryptedText = $decryptedTextAndDigitalSignature['data'] ?? null;
    
    // Ambil digital signatures pada array dengan menggunakan kekunci signatures dan simpan pada pembolehubah $digitalSignatures
    $digitalSignatures = $decryptedTextAndDigitalSignature['signatures'] ?? null;
    
    // Semak jika digital signatures bukan null dan mestilah jenis data array
    if (! is_null($digitalSignatures) && is_array($digitalSignatures)) {
        // Semak jika digital signature adalah sah, simpan decrypted text pada fail bernama decrypted_text.txt
        // Jika tidak sah, tidak perlu buat apa-apa
        if ($digitalSignatures[0]->isValid()) {
            file_put_contents('decrypted_text.txt', $decryptedText);
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment