使用 PHP 加密和解密文件

问题描述 投票:0回答:1

我想从上传文件中解密扩展名为 .txt .docx .xlsx 和 .pdf 的文件。

加密.php

<?php
  include "koneksi.php";
  function generateKeyPairFromFileName(){
    $config = array(
      "default_md" => "sha512",
      "private_key_bits" => 512,
      "private_key_type" => OPENSSL_KEYTYPE_RSA,
    );

    $keypair = openssl_pkey_new($config);

    if (!$keypair) {
      die("Failed to generate key pair");
    }

    openssl_pkey_export($keypair, $privateKey, null, $config);
    $publicKey = openssl_pkey_get_details($keypair);
    $publicKey = $publicKey['key'];

    return array(
      'publicKey' => $publicKey,
      'privateKey' => $privateKey
    );
  }

  function savePublicKeyToLocal($publicKey, $fileName) {
    $publicKeyPath = $fileName . '_public_key.pem'; // Ganti dengan lokasi penyimpanan kunci publik Anda
    file_put_contents($publicKeyPath, $publicKey);
    return $publicKeyPath;
  }

  // Fungsi untuk menyimpan kunci pribadi ke file lokal
  function savePrivateKeyToLocal($privateKey, $fileName) {
    $privateKeyPath = $fileName . '_private_key.pem'; // Ganti dengan lokasi penyimpanan kunci pribadi Anda
    file_put_contents($privateKeyPath, $privateKey);
    return $privateKeyPath;
  }

// Fungsi untuk mengenkripsi file menggunakan AES
function encryptFile($data, $key) {
  // Buat vektor inisialisasi (IV) acak
  $iv = openssl_random_pseudo_bytes(16);

  // Enkripsi data menggunakan AES-256-CBC dengan kunci dan IV yang diberikan
  $encryptedData = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);

  // Base64 encode hasil enkripsi
  $encryptedDataBase64 = base64_encode($encryptedData);

  // Simpan atau kirim data terenkripsi ke tempat penyimpanan atau penerima
  // echo "Data terenkripsi: " . $encryptedDataBase64;

  return $encryptedDataBase64;
}

  if(isset($_POST['generate'])){
    $uploadedFileName = $_FILES['file']['name'];
    $filetmp = $_FILES['file']['tmp_name'];

    // Membaca isi file
    $fileContent = file_get_contents($filetmp);

    $KeyPair = generateKeyPairFromFileName();
    
    $publicKeyPath = savePublicKeyToLocal($KeyPair['publicKey'], $uploadedFileName);
    $publicKeyPath = savePrivateKeyToLocal($KeyPair['privateKey'], $uploadedFileName);

    $encryptedFileContent = encryptFile($fileContent, $KeyPair['publicKey']);
    // echo $encryptedFileContent;

    $query = "INSERT INTO upload (nama_file, filedata) VALUES ('$uploadedFileName', '$encryptedFileContent')";
    if (mysqli_query($conn, $query)) {
        echo "File berhasil diunggah dan dienkripsi.";
    } else {
        echo "Gagal mengunggah dan menyimpan file ke database: " . mysqli_error($conn);
    }


  }
?>

<form action="" method="post" enctype="multipart/form-data">
        Pilih file untuk diunggah (PDF, DOCX, XLSX, TXT, maks 15 MB):
  <input type="file" name="file">
  <button name="generate" type="submit">Generate</button>
</form>

我将私钥和公钥保存在本地。上面的脚本用于在保存到数据库之前加密数据。

ecnrypt.php

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
include "koneksi.php";

// Fungsi dekripsi
function decryptFile($data, $key) {
  // Decode data terenkripsi dari base64
  $encryptedData = base64_decode($data);

  // Ambil IV dari data terenkripsi
  $iv = openssl_random_pseudo_bytes(16);

  $decryptedData = openssl_decrypt($encryptedData, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);

  // Kembalikan data yang telah didekripsi
  return $decryptedData;
}

if(isset($_GET['nama_file'])){
  // Nama file
  $fileName = $_GET['nama_file'];

  // Membaca kunci privat
  try {
    $privateKeyPath = $fileName . '_private_key.pem';
    if (!file_exists($privateKeyPath)) {
      throw new Exception("File kunci privat tidak ditemukan: " . $privateKeyPath);
    }

    $privateKey = file_get_contents($privateKeyPath);
  } catch (Exception $e) {
    echo "Gagal membaca kunci privat: " . $e->getMessage();
    exit;
  }

  // Mengambil data file terenkripsi dari database
  $query = "SELECT filedata FROM upload WHERE nama_file = '$fileName'";
  $result = mysqli_query($conn, $query);

  if ($result && mysqli_num_rows($result) > 0) {
    $row = mysqli_fetch_assoc($result);

    // Dekripsi data
    $decryptedData = decryptFile($row['filedata'], $privateKey);

    // Tampilkan data yang telah didekripsi
    echo $decryptedData;
  } else {
    echo "File tidak ditemukan!";
  }
}

我要解密的文件是空的。我的意思是在解密的数据上返回空。有人有同样的问题吗?

期待包含解密数据的文件。

php cryptography rsa
1个回答
0
投票

我检查了我的 PHP 脚本,它似乎有效地结合了 RSA 和 AES 加密来进行文件上传。

加密.php

<?php
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
    include "koneksi.php";
    
    // Enkripsi
    if(isset($_POST['generate'])){
        // Mendapatkan informasi file yang diunggah
        $uploadedFileName = $_FILES['file']['name'];
        $uploadedFileSize = $_FILES['file']['size'];
        $uploadedFileType = strtolower(pathinfo($uploadedFileName, PATHINFO_EXTENSION));
    
        $sql = "SELECT nama_file FROM upload WHERE nama_file='$uploadedFileName'";
        $query = mysqli_query($conn, $sql);
        $rows = mysqli_num_rows($query);
    
        if( $rows > 0) {
            return header('location:./home.php?message=error');
        }
    
        // Batasi jenis file yang diperbolehkan dan ukuran file
        $allowedTypes = array('txt', 'docx', 'pdf', 'xlsx');
        $maxFileSize = 15 * 1024 * 1024; // 15 MB dalam bytes
    
        if (in_array($uploadedFileType, $allowedTypes) && $uploadedFileSize <= $maxFileSize) {
            // Menghasilkan pasangan kunci RSA
            $rsaKey = openssl_pkey_new(array(
                'private_key_bits' => 2048,
                'private_key_type' => OPENSSL_KEYTYPE_RSA
            ));
    
            // Mendapatkan kunci privat
            openssl_pkey_export($rsaKey, $privateKey);
    
            // Mendapatkan kunci publik
            $publicKey = openssl_pkey_get_details($rsaKey)['key'];
    
            // Menyimpan kunci dengan awalan nama file yang diunggah
            $privateKeyFileName = pathinfo($uploadedFileName, PATHINFO_FILENAME) . "_private_key.pem";
            $publicKeyFileName = pathinfo($uploadedFileName, PATHINFO_FILENAME) . "_public_key.pem";
    
            // echo $privateKeyFileName;
            file_put_contents('./keys/'. $privateKeyFileName, $privateKey);
            file_put_contents('./keys/'. $publicKeyFileName, $publicKey);
    
            // Menghasilkan kunci AES acak
            $aesKey = openssl_random_pseudo_bytes(16);
    
            // Mengenkripsi kunci AES menggunakan kunci publik RSA
            openssl_public_encrypt($aesKey, $encAesKey, $publicKey);
    
            // Unggah file
            $uploadedFile = $_FILES['file']['tmp_name'];
    
            // Mengenkripsi data menggunakan AES
            $iv = openssl_random_pseudo_bytes(16);
            $ciphertext = openssl_encrypt(file_get_contents($uploadedFile), 'aes-128-cbc', $aesKey, 0, $iv);
    
            // Menyimpan data terenkripsi ke sebuah variabel
            $encryptedFileContent = $iv . $ciphertext;
    
            // Menyimpan kunci AES terenkripsi ke sebuah file dengan awalan nama file yang diunggah
            $encryptedAesKeyFileName = pathinfo($uploadedFileName, PATHINFO_FILENAME) . "_encrypted_aes_key.bin";
            file_put_contents('./keys/'. $encryptedAesKeyFileName, $encAesKey);
    
            // Memasukkan data file terenkripsi ke dalam database
            $query = "INSERT INTO upload (nama_file, filedata, mimetype) 
                      VALUES ('$uploadedFileName', '$encryptedFileContent', '$uploadedFileType')";
            if (mysqli_query($conn, $query)) {
                echo "File berhasil diunggah dan dienkripsi.";
                header('location:./home.php?message=success');
            } else {
                echo "Gagal mengunggah dan menyimpan file ke database: " . mysqli_error($conn);
            }
        } else {
            echo "Jenis file yang diunggah tidak diperbolehkan atau ukuran file melebihi batas maksimum.";
        }
    }
    ?>

解密.php

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
include "koneksi.php";

if(isset($_GET['dekripsi'])) {
    $id = $_GET['dekripsi'];
    $query = "SELECT nama_file, filedata FROM upload WHERE id_file='$id'";
    $result = mysqli_query($conn, $query);
    $row = mysqli_fetch_assoc($result);

    $uploadedFileName = $row['nama_file'];

    // Load RSA private key
    $privateKeyFileName = pathinfo($uploadedFileName, PATHINFO_FILENAME) . "_private_key.pem";
    $privateKey = file_get_contents('./keys/'. $privateKeyFileName);

    // Decrypt AES key using RSA private key
    $encryptedAesKeyFileName = pathinfo($uploadedFileName, PATHINFO_FILENAME) . "_encrypted_aes_key.bin";
    $encAesKey = file_get_contents('./keys/'. $encryptedAesKeyFileName);
    openssl_private_decrypt($encAesKey, $decAesKey, $privateKey);

    // Load encrypted data from the database (Assuming you have a function to retrieve data from the database)
    
    $encryptedData = $row['filedata'];

    // Decrypt data using AES
    $iv = substr($encryptedData, 0, 16);
    $ciphertext = substr($encryptedData, 16);
    $plaintext = openssl_decrypt($ciphertext, 'aes-128-cbc', $decAesKey, 0, $iv);

    // Prepare file for download
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . basename($uploadedFileName));
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . strlen($plaintext));
    ob_clean();
    flush();
    echo $plaintext;
    // exit;
} else {
    echo "File name not provided.";
}
?>
© www.soinside.com 2019 - 2024. All rights reserved.