function imzaBul($objVeri, $bul, $konum=0, $ns='http://www.w3.org/2000/09/xmldsig#')
{
if ($objVeri instanceof DOMDocument) $veri = $objVeri;
else $veri = $objVeri->ownerDocument;
if ($veri)
{
$xpath = new DOMXPath($veri);
$xpath->registerNamespace('ntgimza', $ns);
$bulunan = $xpath->query($bul, $objVeri);
if(is_null($konum)) $imzaXml = $bulunan;
else $imzaXml = $bulunan->item($konum);
return $imzaXml;
}
return null;
}
function tagOlustur($isim, $deger=null, $ns=false)
{
$XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#';
$imzveri = new DOMDocument();;
if($ns == true)
{
if (! is_null($deger)) {
$sonuc = $imzveri->createElementNS($XMLDSIGNS, $isim, $deger);
} else {
$sonuc = $imzveri->createElementNS($XMLDSIGNS, $isim);
}
}
else
{
if (! is_null($deger)) {
$sonuc = $imzveri->createElement($isim, $deger);
} else {
$sonuc = $imzveri->createElement($isim);
}
}
return $sonuc;
}
/* Anahtar Okuma Fonksiyonu */
function AnahtarYukle($anahtar, $tur = 'private', $sifre='')
{
switch ($tur)
{
case 'private':
if (!$anhtr = openssl_get_privatekey($anahtar, $sifre)) die('Anahtar çıkarılamıyor');
break;
default:
if (!$anhtr = openssl_get_publickey($anahtar)) die('Anahtar çıkarılamıyor');
break;
}
return $anhtr;
}
/* PFX İle E-Fatura İmzalama */
function Imzala()
{
$ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature';
$ANA_TEMA = '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"></Signature>';
$URI_ETSI_V132 = 'http://uri.etsi.org/01903/v1.3.2#';
$SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256';
$SIGNED_PROP = 'http://uri.etsi.org/01903#SignedProperties';
$RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
$C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments';
$onek = 'ds';
$bul = array("<S", "</S", "xmlns=");
$deg = array("<$onek:S", "</$onek:S", "xmlns:$onek=");
$ANA_TEMA = str_replace($bul, $deg, $ANA_TEMA);
$sertifika_dosya = 'sertifika.pfx';
$sertifika_sifre = '123456';
if (is_file($sertifika_dosya) and !empty($sertifika_sifre))
{
if (openssl_pkcs12_read(file_get_contents($sertifika_dosya), $sertifikaSonuc, $sertifika_sifre))
else exit('Sertifika Hatalı !');
}
else exit('Sertifika Bulunamadı !');
$FaturaNo = "NTG2017000000001";
$ana_id = 'Signature_'.$FaturaNo;
$SHA_256 = 'sha256';
$dosya_adi = 'TemelFatura.xml';
$dom = new DOMDocument();
$dom->loadXML($ANA_TEMA);
$imzaXml = $dom->documentElement;
$veri = new DOMDocument();
$veri->load($dosya_adi);
$veriPath = new DOMXPath($veri);
$imzaXml->setAttribute('Id', $ana_id);
/* SignedInfo Oluşturuluyor */
$SignedInfo = tagOlustur('ds:SignedInfo', null, true);
$SignedInfo->setAttribute('Id', 'SignedInfo');
$imzaXml->appendChild($SignedInfo);
$CanonicalizationMethod = tagOlustur('ds:CanonicalizationMethod');
$CanonicalizationMethod->setAttribute('Algorithm', $C14N_COMMENTS);
$SignedInfo->appendChild($CanonicalizationMethod);
$SignatureMethod = tagOlustur('ds:SignatureMethod');
$SignatureMethod->setAttribute('Algorithm', $RSA_SHA256);
$SignedInfo->appendChild($SignatureMethod);
/* Referans 1 Alanı */
$Reference1 = tagOlustur('ds:Reference', null, true);
$Reference1->setAttribute('URI', '');
$Reference1_Transforms1 = tagOlustur('ds:Transforms');
$Reference1_Transforms2 = tagOlustur('ds:Transform');
$Reference1_Transforms2->setAttribute('Algorithm', $ENVELOPED);
$Reference1_Transforms1->appendChild($Reference1_Transforms2);
$Reference1->appendChild($Reference1_Transforms1);
$Reference1_DigestMethod = tagOlustur('ds:DigestMethod');
$Reference1_DigestMethod->setAttribute('Algorithm', $SHA256);
$Reference1->appendChild($Reference1_DigestMethod);
$Reference1_DigestValue = tagOlustur('ds:DigestValue', base64_encode(hash($SHA_256, $veri->C14N(false, true, null, null), true))); /* Referans 1 Değeri Atanıyor */
$Reference1->appendChild($Reference1_DigestValue);
$SignedInfo->appendChild($Reference1);
/* Referans 2 Alanı */
$Reference2 = tagOlustur('ds:Reference', null, true);
$Reference2->setAttribute('Id', 'SignedProperties-Reference');
$Reference2->setAttribute('Type', $SIGNED_PROP);
$Reference2->setAttribute('URI', '#SignedProperties');
$Reference2_DigestMethod = tagOlustur('ds:DigestMethod');
$Reference2_DigestMethod->setAttribute('Algorithm', $SHA256);
$Reference2->appendChild($Reference2_DigestMethod);
$Reference2_DigestValue = tagOlustur('ds:DigestValue', null, true);
$Reference2->appendChild($Reference2_DigestValue);
$SignedInfo->appendChild($Reference2);
$SignatureValue = tagOlustur('ds:SignatureValue');
$SignatureValue->setAttribute('Id', 'id1');
$imzaXml->appendChild($SignatureValue);
$key = AnahtarYukle($sertifikaSonuc['pkey']);
$privateKey = openssl_pkey_get_details($key);
$KeyInfo = tagOlustur('ds:KeyInfo');
/* RSA Key Alanı */
$KeyValue = tagOlustur('ds:KeyValue');
$RSAKeyValue = tagOlustur('ds:RSAKeyValue');
$Modulus = tagOlustur('ds:Modulus', chunk_split(base64_encode($privateKey['rsa']['n']), 64, ""));
$Exponent = tagOlustur('ds:Exponent', chunk_split(base64_encode($privateKey['rsa']['e']), 64, ""));
$RSAKeyValue->appendChild($Modulus);
$RSAKeyValue->appendChild($Exponent);
$KeyValue->appendChild($RSAKeyValue);
$KeyInfo->appendChild($KeyValue);
/* Sertifika X509 */
$X509Data = tagOlustur('ds:X509Data');
$X509SubjectName = tagOlustur('ds:X509SubjectName');
$X509Certificate = tagOlustur('ds:X509Certificate');
$X509Data->appendChild($X509SubjectName);
$X509Data->appendChild($X509Certificate);
$KeyInfo->appendChild($X509Data);
$KeyInfo->appendChild($X509Data);
$imzaXml->appendChild($KeyInfo);
/* Object Alanı */
$objectNode = tagOlustur('ds:Object');
$imzaXml->appendChild($objectNode);
$QualifyingProperties = tagOlustur('xades:QualifyingProperties');
$QualifyingProperties->setAttribute('xmlns:xades', $URI_ETSI_V132);
$QualifyingProperties->setAttribute('Target', $ana_id);
$objectNode->appendChild($QualifyingProperties);
$SignedProperties = tagOlustur('xades:SignedProperties');
$SignedProperties->setAttribute('Id', 'SignedProperties');
$QualifyingProperties->appendChild($SignedProperties);
$SignedSignatureProperties = tagOlustur('xades:SignedSignatureProperties');
$SignedProperties->appendChild($SignedSignatureProperties);
$SigningTime = tagOlustur('xades:SigningTime', gmdate(DATE_ATOM));
$SignedSignatureProperties->appendChild($SigningTime);
$SigningCertificate = tagOlustur('xades:SigningCertificate');
$SignedSignatureProperties->appendChild($SigningCertificate);
$Cert = tagOlustur('xades:Cert');
$SigningCertificate->appendChild($Cert);
$CertDigest = tagOlustur('xades:CertDigest');
$Cert->appendChild($CertDigest);
$DigestMethod = tagOlustur('ds:DigestMethod');
$DigestMethodAttrAlgorithm = $imzaXmlOwn->createAttribute('Algorithm'); $DigestMethodAttrAlgorithm->value = $SHA256;
$DigestMethod->appendChild($DigestMethodAttrAlgorithm);
$CertDigest->appendChild($DigestMethod);
/* Object Digest Atanıyor */
$arr = explode("\n", $sertifikaSonuc['cert']);
array_shift($arr); array_pop($arr);
$data = base64_decode(implode(PHP_EOL, $arr));
$DigestValue = tagOlustur('ds:DigestValue', base64_encode(hash('sha256', $data, true)));
$CertDigest->appendChild($DigestValue);
/* Sertifika Getir */
$sertifikalar = $sertifikaSonuc509($sertifikaSonuc['cert'], true);
$AdDegeri = '';
$X509SrtfkDegeri = '';
/* Public Sertifika Ayarlanıyor */
foreach ($sertifikalar as $X509Srtfk)
{
if ($sertifikaVerisi = openssl_x509_parse("-----BEGIN CERTIFICATE-----\n".chunk_split($X509Srtfk, 64, "\n")."-----END CERTIFICATE-----\n"))
{
if (! empty($sertifikaVerisi['subject']))
{
if (is_array($sertifikaVerisi['subject']))
{
$parcalar = array();
foreach ($sertifikaVerisi['subject'] AS $anahtar => $deger)
{
if (is_array($deger))
{
foreach ($deger as $degerElm)
array_unshift($parcalar, "$anahtar=$degerElm");
}
else array_unshift($parcalar, "$anahtar=$deger");
}
$AdDegeri = implode(',', $parcalar);
}
else $AdDegeri = $sertifikaVerisi['issuer'];
}
if (! empty($sertifikaVerisi['issuer']) && ! empty($sertifikaVerisi['serialNumber']))
{
if (is_array($sertifikaVerisi['issuer']))
{
$parcalar = array();
foreach ($sertifikaVerisi['issuer'] AS $anahtar => $deger)
array_unshift($parcalar, "$anahtar=$deger");
$issuerDegeri = implode(', ', $parcalar);
}
else $issuerDegeri = $sertifikaVerisi['issuer'];
$IssuerSerial = tagOlustur('xades:IssuerSerial');
$Cert->appendChild($IssuerSerial);
$x509Node = tagOlustur('ds:X509IssuerName', $issuerDegeri);
$IssuerSerial->appendChild($x509Node);
$x509Node = tagOlustur('ds:X509SerialNumber', $sertifikaVerisi['serialNumber']);
$IssuerSerial->appendChild($x509Node);
}
}
$X509SrtfkDegeri = $X509Srtfk;
}
/* Public Sertifika Atanıyor */
$X509SubjectName->nodeValue = $AdDegeri;
$X509Certificate->nodeValue = $X509SrtfkDegeri;
$SignerRole = tagOlustur('xades:SignerRole', '');
$SignedSignatureProperties->appendChild($SignerRole);
$SignerCalimedRoles = tagOlustur('xades:ClaimedRoles', '');
$SignerRole->appendChild($SignerCalimedRoles);
$SignerCalimedRole = tagOlustur('xades:ClaimedRole', 'Tedarikçi');
$SignerCalimedRoles->appendChild($SignerCalimedRole);
/* XML ExtensionContent Alanına İmza Ekleniyor */
$ExtensionContent = $veriPath->query("//ext:ExtensionContent")->item(0);
$document = $ExtensionContent->ownerDocument;
$signatureElement = $document->importNode($imzaXml, true);
$ExtensionContent->insertBefore($signatureElement);
$veriXML = $veri->saveXML();
/* İmza Eklendikten Sonra Veriler Tekrar Okunuyor */
$yeniVeri = new DOMDocument();
$yeniVeri->loadXML($veriXML);
$Reference2_DigestValue = imzaBul($yeniVeri, '//ntgimza:Reference/ntgimza:DigestValue', 1);
$SignedPropertiesX = imzaBul($yeniVeri, '//ntgimza:SignedProperties', 0, $URI_ETSI_V132);
/* Referans 2 Alanı Verisi Atanıyor */
$Reference2_DigestValue->nodeValue = base64_encode(hash($SHA_256, $SignedPropertiesX->C14N(false, true, null, null), true));
/* SignedInfo Okunuyor */
$SignedInfoX = imzaBul($yeniVeri, '//ntgimza:SignedInfo', 0);
/* SignedInfo İmzalanıyor */
if (! openssl_sign($SignedInfoX->C14N(false, true, null, null), $imzaSonuc, $key, $SHA_256)) {
die('Veri İmzalama Hatası: ' . openssl_error_string() . ' - '.$SHA_256);
}
/* SignatureValue Alanına SignedInfo Verisi Atanıyor */
$SignatureValueX = imzaBul($yeniVeri, '//ntgimza:SignatureValue', 0);
$SignatureValueX->nodeValue = base64_encode($imzaSonuc);
/* XML Kaydediliyor */
if (file_exists($dosya_adi)) unlink($dosya_adi);
$yeniVeri->save($dosya_adi);
return true;
}
/* PFX İle E-Fatura İmzalama */