Poslao: 18 Jun 2017 15:24
|
offline
- return void
- Anti Malware Fighter
Rank 1
- Pridružio: 02 Jan 2008
- Poruke: 2167
|
Pokusavam da napravim portal za razmenu sifrovanih poruka koristeci asimetricno sifrovanje. Citao sam i koliko vidim, OpenSSL dodaci za PHP su jedino dobro resenje.
E sad, problem nastaje jer ja iz nekog razloga ne mogu da generisem kljuceve gledajuci ovaj primer:
//kreiranje privatnog i javnog kljuca za Boba
$key = openssl_pkey_new(array('private_key_bits' => 2048));
$bob_key = openssl_pkey_get_details($key);
$bob_public_key = $bob_key['key'];
//Alisa salje poruku koju sifruje Bobovim javnim kljucem
$alice_msg = "Hi Bob, im sending you a private message";
openssl_public_encrypt($alice_msg, $pvt_msg, $bob_public_key);
//Bob prima Alisinu poruku i koristi svoj privatni kljuc za desifrovanje
openssl_private_decrypt( $pvt_msg, $bob_received_msg, $key);
print $bob_received_msg;
Moje pitanje je, da li je meni potreban SSL sertifikat da bi mogao da generisem privatne i javne kljuceve koristeci kod iznad? Iskoristio bih Let's encrypt recimo, posto je besplatan.
Pokusao sam prvi primer ovde, pa da izgenerisem svoje serftifikate, ali neuspeva :
+ Greska
+ Kod<?php
// Fill in data for the distinguished name to be used in the cert
// You must change the values of these keys to match your name and
// company, or more precisely, the name and company of the person/site
// that you are generating the certificate for.
// For SSL certificates, the commonName is usually the domain name of
// that will be using the certificate, but for S/MIME certificates,
// the commonName will be the name of the individual who will use the
// certificate.
$dn = array(
"countryName" => "UK",
"stateOrProvinceName" => "Somerset",
"localityName" => "Glastonbury",
"organizationName" => "The Brain Room Limited",
"organizationalUnitName" => "PHP Documentation Team",
"commonName" => "Wez Furlong",
"emailAddress" => "wez@example.com"
);
// Generate a new private (and public) key pair
$privkey = openssl_pkey_new();
// Generate a certificate signing request
$csr = openssl_csr_new($dn, $privkey);
// You will usually want to create a self-signed certificate at this
// point until your CA fulfills your request.
// This creates a self-signed cert that is valid for 365 days
$sscert = openssl_csr_sign($csr, null, $privkey, 365);
// Now you will want to preserve your private key, CSR and self-signed
// cert so that they can be installed into your web server, mail server
// or mail client (depending on the intended use of the certificate).
// This example shows how to get those things into variables, but you
// can also store them directly into files.
// Typically, you will send the CSR on to your CA who will then issue
// you with the "real" certificate.
openssl_csr_export($csr, $csrout) and var_dump($csrout);
openssl_x509_export($sscert, $certout) and var_dump($certout);
openssl_pkey_export($privkey, $pkeyout, "mypassword") and var_dump($pkeyout);
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
}
?>
Konkretno mi je namera da se prilikom svake registracije novog korisnika kreira njegov privati i javni kljuc i da se oni odmah upisu u bazu (znam da nije bas najbolja praksa, ali ovo je projekat za vezbu). Nakon toga, ja bih koristio te kljuceve za sifrovanje/desifrovanje poruka izmedju korisnika.
|
|
|
Registruj se da bi učestvovao u diskusiji. Registrovanim korisnicima se NE prikazuju reklame unutar poruka.
|
|
Poslao: 18 Jun 2017 16:38
|
offline
- Peca
- Glavni Administrator
- Predrag Damnjanović
- SysAdmin i programer
- Pridružio: 17 Apr 2003
- Poruke: 23211
- Gde živiš: Niš
|
Napisano: 18 Jun 2017 17:33
Možda je banalan problem - možda PHP na Windowsu nije podešen da radi sa OpenSSL.
Digni Linux na virtuelnoj mašini pa probaj isti taj kod.
Dopuna: 18 Jun 2017 17:38
btw, signed sertifikat ti svakako nije potreban... radio sam sa tim OpenSSL PHP funkcijama sa sertifikatom koji sam sam izgenerisao na Linuxu.
|
|
|
|
Poslao: 18 Jun 2017 16:53
|
offline
- vasa.93
- Moderator foruma
- Pridružio: 17 Dec 2007
- Poruke: 14824
- Gde živiš: Niš
|
Napisano: 18 Jun 2017 17:51
Asinhrono šifrovanje? Misliš asimetrično?
Dopuna: 18 Jun 2017 17:53
I druga stvar, kako bi te poruke između korisnika bile obezbeđene na putu do servera? Kroz HTTPS konekciju?
|
|
|
|
Poslao: 19 Jun 2017 21:52
|
offline
- return void
- Anti Malware Fighter
Rank 1
- Pridružio: 02 Jan 2008
- Poruke: 2167
|
Napisano: 18 Jun 2017 18:53
Peca ::Napisano: 18 Jun 2017 17:33
Možda je banalan problem - možda PHP na Windowsu nije podešen da radi sa OpenSSL.
Digni Linux na virtuelnoj mašini pa probaj isti taj kod.
Dopuna: 18 Jun 2017 17:38
btw, signed sertifikat ti svakako nije potreban... radio sam sa tim OpenSSL PHP funkcijama sa sertifikatom koji sam sam izgenerisao na Linuxu.
U php.ini fajlu sam skinuo ; sa openssl dodatka, tako da je sa te strane u redu. Ne znam da li je jos nesto potrebno podesavati?
Da li je kod sa php.net sajta koji sam gore okacio dovoljan za generisanje potrebnih sertifikata?
Da li bi ja uopste mogao da koristim Let's encrypt SSL sertifikat za OpenSSL? Pitam za slucaj da se spetljam sa Linuxom, jer ce mi onda biti lakse da dobijem vec gotov sertifikat nego da ga sam generisem.
vasa.93 ::Napisano: 18 Jun 2017 17:51
Asinhrono šifrovanje? Misliš asimetrično?
Dopuna: 18 Jun 2017 17:53
I druga stvar, kako bi te poruke između korisnika bile obezbeđene na putu do servera? Kroz HTTPS konekciju?
Lapsus, ispravljeno
Pa da, jer ne vidim drugi nacin za to. Preko HTTPS-a bi izbegao "man-in-the-middle attack" napade. Za to sam svakako planirao Let's encrypt SSL da ubacim...
Dopuna: 19 Jun 2017 21:00
Izgleda da je problem ipak bio jer radim na lokalu. Kad sam kod ispod pokrenuo na shared hostingu, dobio sam odgovor bez greske.
+ Kod<?php
// Fill in data for the distinguished name to be used in the cert
// You must change the values of these keys to match your name and
// company, or more precisely, the name and company of the person/site
// that you are generating the certificate for.
// For SSL certificates, the commonName is usually the domain name of
// that will be using the certificate, but for S/MIME certificates,
// the commonName will be the name of the individual who will use the
// certificate.
$dn = array(
"countryName" => "UK",
"stateOrProvinceName" => "Somerset",
"localityName" => "Glastonbury",
"organizationName" => "The Brain Room Limited",
"organizationalUnitName" => "PHP Documentation Team",
"commonName" => "Wez Furlong",
"emailAddress" => "wez@example.com"
);
// Generate a new private (and public) key pair
$privkey = openssl_pkey_new();
// Generate a certificate signing request
$csr = openssl_csr_new($dn, $privkey);
// You will usually want to create a self-signed certificate at this
// point until your CA fulfills your request.
// This creates a self-signed cert that is valid for 365 days
$sscert = openssl_csr_sign($csr, null, $privkey, 365);
// Now you will want to preserve your private key, CSR and self-signed
// cert so that they can be installed into your web server, mail server
// or mail client (depending on the intended use of the certificate).
// This example shows how to get those things into variables, but you
// can also store them directly into files.
// Typically, you will send the CSR on to your CA who will then issue
// you with the "real" certificate.
openssl_csr_export($csr, $csrout) and var_dump($csrout);
openssl_x509_export($sscert, $certout) and var_dump($certout);
openssl_pkey_export($privkey, $pkeyout, "mypassword") and var_dump($pkeyout);
// Show any errors that occurred here
while (($e = openssl_error_string()) !== false) {
echo $e . "\n";
}
?>
Dopuna: 19 Jun 2017 22:52
Ok, sve sam osposobio i uspesno izgenerisem privatne i javne kljuceve koje potom upisem u bazu koristeci ovaj kod:
+ Kod$key = openssl_pkey_new(array('private_key_bits' => 2048)); //kreiranje privatnog kljuca
// Get private key
openssl_pkey_export($key, $privkey);
// Get public key
$pubkey=openssl_pkey_get_details($key);
$pubkey=$pubkey["key"];
Ipak, sada mi je problem da poruku sifrujem i da je upisem u bazu, posto se u bazi upise prazno polje. Koristim ovaj kod:
<?php
require 'provera_sesije.php';
require 'baza.php';
//Fetching Values from URL
$poruka2=$_POST['poruka1'];
$korisnik_forma2=$_POST['korisnik_forma1'];
$javni_kljuc = '';
$sifrovana_poruka = '';
$sql = "SELECT javni_kljuc FROM bz.kljucevi WHERE korisnik='$korisnik_forma2'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
/*$fff = $row['javni_kljuc'];
$javni_kljuc = openssl_get_publickey($fff);*/
$javni_kljuc = openssl_get_publickey($row['javni_kljuc']);
//pokusao sam i ovo, posto openssl_get_publickey() ocekuje kljuc u PEM formatu
/*
$aaa = openssl_pkey_export($row['javni_kljuc'],$fff);
$javni_kljuc = openssl_get_publickey($fff);*/
}
} else {
echo "Došlo je do greške...";
}
openssl_seal($poruka2, $sifrovana_poruka, $ekeys, array($javni_kljuc));
//Insert query
$stmt = $conn->prepare("INSERT INTO bz.poruke (poslao, primio, poruka) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $_SESSION['email'], $korisnik_forma2, $sifrovana_poruka);
$stmt->execute();
$stmt->close();
$conn->close();
openssl_free_key($javni_kljuc);
?>
Mene konkretno buni treci parametar funkcije openssl_seal() a to je promenljiva $ekeys. Gledam dokumentaciju ali ne vidim odakle je ta promenljiva i sta da joj dodelim kao vrednost... Moze li neko da pomogne?
|
|
|
|
Poslao: 19 Jun 2017 22:09
|
offline
- vasa.93
- Moderator foruma
- Pridružio: 17 Dec 2007
- Poruke: 14824
- Gde živiš: Niš
|
To je 'povratna' vrednost. Drugi i treći parametar se prenose po referenci, pa se oni setuju unutar same funkcije. Dakle, pored šifrovane poruke metoda vraća i niz ključeva kojima je ta poruka šifrovana, a ti ključevi su šifrovani javnim ključevima koji su prosleđeni. Dešifrovanje verovatno ide obrnuto - privatnim ključevima se najpre dešifruju ključevi, a onda se pomoću dešifrovanih ključeva dešifruje poruka. Na osnovu ovoga lako je zaključiti da pored šifrovane poruke moraš da pamtiš i taj niz šifrovanih ključeva.
|
|
|
|
Poslao: 20 Jun 2017 11:08
|
offline
- Peca
- Glavni Administrator
- Predrag Damnjanović
- SysAdmin i programer
- Pridružio: 17 Apr 2003
- Poruke: 23211
- Gde živiš: Niš
|
return void :: Izgleda da je problem ipak bio jer radim na lokalu. Kad sam kod ispod pokrenuo na shared hostingu, dobio sam odgovor bez greske.
Rekoh ja...
|
|
|
|
Poslao: 20 Jun 2017 14:57
|
offline
- return void
- Anti Malware Fighter
Rank 1
- Pridružio: 02 Jan 2008
- Poruke: 2167
|
Na kraju sam odustao od upisivanja kljuceva u bazu jer nikako nisam uspeo da ih izvucem. Zato sam uradio ovako i pamtim ih kao fajlove:
<?php
require 'provera_sesije.php';
require 'baza.php';
//Fetching Values from URL
$poruka2=$_POST['poruka1'];
$korisnik_forma2=$_POST['korisnik_forma1'];
// Compress the data to be sent
$poruka2 = gzcompress($poruka2);
// Get the public Key of the recipient
$publicKey = openssl_pkey_get_public('file://kljucevi/'.$korisnik_forma2.'/public.key');
$a_key = openssl_pkey_get_details($publicKey);
// Encrypt the data in small chunks and then combine and send it.
$chunkSize = ceil($a_key['bits'] / 8) - 11;
$output = '';
while ($poruka2)
{
$chunk = substr($poruka2, 0, $chunkSize);
$poruka2 = substr($poruka2, $chunkSize);
$encrypted = '';
if (!openssl_public_encrypt($chunk, $encrypted, $publicKey))
{
die('Failed to encrypt data');
}
$output .= $encrypted;
}
openssl_free_key($publicKey);
// This is the final encrypted data to be sent to the recipient
$encrypted = $output;
base64_encode($encrypted); //zbog BLOB-a
//Insert query
$stmt = $conn->prepare("INSERT INTO bz.poruke (poslao, primio, poruka) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $_SESSION['email'], $korisnik_forma2, $encrypted);
$stmt->execute();
$stmt->close();
$conn->close();
?>
Ipak, kad sada pokusam da desifrujem poruku, nikako ne uspevam.
Ovo je kod za desifrovanje za korisnika koji poruku prima. Isti kod je i za korisnika koji poruku salje, samo se razlikuju parametri za query:
//$_SESSION['email'] je trenutno ulogovani korisnik tj. onaj ko poruku cita (desifruje)
$sql2 = "SELECT poslao, primio, poruka, vreme FROM bz.poruke WHERE poslao='".$_SESSION['korisnik']."' AND primio='".$_SESSION['email']."' ORDER BY vreme DESC";
$result2 = $conn->query($sql2);
if ($result2->num_rows > 0) {
// output data of each row
while($row2 = $result2->fetch_assoc()) {
// Get the private Key
if (!$privateKey = openssl_pkey_get_private('file://kljucevi/'.$_SESSION['email'].'/private.key'))
{
die('Private Key failed');
}
$a_key = openssl_pkey_get_details($privateKey);
// Decrypt the data in the small chunks
$chunkSize = ceil($a_key['bits'] / 8);
$output = '';
base64_decode($row2['poruka']); //zbog BLOB-a
$sifrovano = $row2['poruka'];
while ($sifrovano)
{
$chunk = substr($sifrovano, 0, $chunkSize);
$sifrovano = substr($sifrovano, $chunkSize);
$decrypted = '';
if (!openssl_private_decrypt($chunk, $decrypted, $privateKey))
{
die('Failed to decrypt data');
}
$output .= $decrypted;
}
openssl_free_key($privateKey);
// Uncompress the unencrypted data.
$output = gzuncompress($output);
echo ''.$output.'';
echo '<br />';
echo '<small class="text-muted">'.$row2['poslao'].' | '.$row2['vreme'].'</small>';
echo '<hr />';
Gde gresim?
|
|
|
|