E-fatura?

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Re: E-fatura?

Mesaj gönderen cengaver » 01 Oca 2017 11:34

Merhaba mkysoft, iyi niyetin için teşekkürler, XE8 ile ilgili örneği inceledim. Ben zaten XE8 ile ilgili projedekiin çoğunu yapıyorum, yukarıdaki iletimde de bahsettiğim gibi, ben zaten ubl-tr 2.1 standardında e-fatura xml dosyası üretebiliyorum. Bu noktada bir sorunum yok. Bunun için sıfırdan bir nesne yazdım.

Benim sorunum .NET api'leri ile imza attığımda matematiksel doğrulama hatası alıyor olmamdan kaynaklanıyor. iletinde bahsetti,ğin konuları inceledim, evet, orjinal xml dosyasını değiştirdiğini fark ettim. Hatta <cbc:UUID> tagındaki GUID verisini de değiştiriyor, bu kısmı anlamak mümkün değil. imza atan C# kodu aşağıda paylaşıyorum, umarım bir çözüm yolu bulabiliriz;

imzayı "createEnvelopedBes" yordamı atıyor, alıcı gözüyle bir inceleyebilir misiniz?

Kod: Tümünü seç

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using NUnit.Framework;
using log4net;
using iaik.pkcs.pkcs11.wrapper;
using tr.gov.tubitak.uekae.esya.api.smartcard.gui;
using tr.gov.tubitak.uekae.esya.api.common.util.bag;
using System.Xml;
using tr.gov.tubitak.uekae.esya.api.common;
using tr.gov.tubitak.uekae.esya.api.xmlsignature;
using tr.gov.tubitak.uekae.esya.api.asn.x509;
using tr.gov.tubitak.uekae.esya.api.cmssignature.example.util;
using tr.gov.tubitak.uekae.esya.api.common.crypto;
using tr.gov.tubitak.uekae.esya.api.smartcard.pkcs11;
using tr.gov.tubitak.uekae.esya.api.common.util;
using tr.gov.tubitak.uekae.esya.api.xmlsignature.config;
using tr.gov.tubitak.uekae.esya.api.xmlsignature.transforms;

using TransformType = tr.gov.tubitak.uekae.esya.api.xmlsignature.TransformType;
using Transform = tr.gov.tubitak.uekae.esya.api.xmlsignature.model.Transform;
using Transforms = tr.gov.tubitak.uekae.esya.api.xmlsignature.model.Transforms;
using tr.gov.tubitak.uekae.esya.api.xmlsignature.document;

namespace ma3api_xmlsignature_test
{
	[ComVisible(true)]
	public interface arayuz
    {
		void Set_SMART_CARD_PIN(String aSMART_CARD_PIN);
		void createEnvelopedBes(String aLisansYol, String aConfigXmlYol, String aPinNo, bool aNitelik, string aSignatureID, String aXML, string aSignedXmlFilePath);
	}
    public class DelphiComx: arayuz
    {
        protected IBaseSmartCard				bsc;
        protected BaseSigner					mSigner;
        public static string					DETACHED_SIGNATURE_FILENAME = "sig_bes_detached.xsig";
        public const System.String				FILENAME_BES_ENVELOPED_SIGNATURE = "sig_bes_enveloped.xsig";
        public const System.String				FILENAME_BES_ENVELOPED_TRANSFORM_SIGNATURE = "sig_bes_envelopedTransform.xsig";
        public const System.String				FILENAME_BES_ENVELOPING_SIGNATURE = "sig_bes_enveloping.xsig";
        public static string					FILENAME_PARALLEL_DETACHED = "sig_parallel_detached.xsig";
        public static string					FILENAME_PARALLEL_ENVELOPED = "sig_parallel_enveloped.xsig";
        public static string					FILENAME_COUNTER_EXISTING = "sig_detached_counter.xsig";
        public static string					FILENAME_PARALLEL_COUNTER_EXISTING = "sig_parallel_counter.xsig";
        public static string					SIGNATURE_FILENAME_P1 = "profile_p1_bes.xsig";
        public static string					SIGNATURE_FILENAME_P2 = "profile_p2_t.xsig";
        public static string					SIGNATURE_FILENAME_P3 = "profile_p3_xl_crl.xsig";
        public static string					SIGNATURE_FILENAME_P4 = "profile_p4_xl_ocsp.xsig";
        public static string					SIGNATURE_FILENAME_A = "profile_p4_a.xsig";
        public static string					SIGNATURE_FILENAME_AA = "profile_p4_aa.xsig";
        internal static readonly bool			WORK_ONLY_WITH_QUALIFIED_CERTS = false;
        public static String					SMART_CARD_PIN = ""; /* createEnvelopedBes veya Set_SMART_CARD_PIN prosedüründen değerini alacak... */
		public static readonly String			TEST_PROJECT_FOLDER = Application.StartupPath; /* EXE'nin çalıştığı klasör kastediliyor... */
        public static int askOption(Control aParent, Icon aIcon, String[] aSecenekList, String aBaslik, String[] aOptions)
        {
            SlotList      sl     = new SlotList(null, aIcon, aSecenekList, aBaslik);
            DialogResult  result = sl.ShowDialog();
            if (result != DialogResult.OK)
                return -1;
            return sl.getSelectedIndex();
        }
        private ECertificate selectCertificate(bool checkIsQualified, bool checkBeingNonQualified, List<byte[]> aCerts)
        {
            if (aCerts != null && aCerts.Count == 0) throw new ESYAException("Kartta sertifika yok");
            if (checkIsQualified && checkBeingNonQualified) throw new ESYAException("Bir sertifika ya niteliklidir ya da niteliksizdir. Aynı anda hem nitelikli hem de niteliksiz sertifika olmaz");
            List<ECertificate> certs = new List<ECertificate>();
            foreach (byte[] bs in aCerts)
            {
                ECertificate cert = new ECertificate(bs);
                if (checkIsQualified)         { if (cert.isQualifiedCertificate()) certs.Add(cert);  } else
                if (checkBeingNonQualified)   { if (!cert.isQualifiedCertificate()) certs.Add(cert); } else
                { certs.Add(cert); }
            }
            ECertificate selectedCert = null;
            if (certs.Count == 0)
            {
                if (checkIsQualified)       throw new ESYAException("Kartta nitelikli sertifika yok");  else
                if (checkBeingNonQualified) throw new ESYAException("Kartta niteliksiz sertifika yok");
            } else
            if (certs.Count == 1)
            {
                selectedCert = certs[0];
            } else
            {
                String[] optionList = new String[certs.Count];
                for (int i = 0; i < certs.Count; i++) { optionList[i] = certs[i].getSubject().getCommonNameAttribute(); }
                int result = askOption(null, null, optionList, "Sertifika Listesi", new[] { "Tamam" });
                if (result < 0) selectedCert = null; else selectedCert = certs[result];
            }
            return selectedCert;
        }
		private XmlDocument newEnvelope2(String aXML)
		{
			try
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.LoadXml(aXML);
				return xmlDocument;
			}
			catch (System.Exception x)
			{
				SupportClass.WriteStackTrace(x, Console.Error);
			}
			throw new ESYAException("XML verisinde hata var. İmza üretilemedi.");
		}
		public static void EnvelopedSignatureInitialize(string lisansFilePath)
		{
			LicenseUtil.setLicenseXml(new FileStream(lisansFilePath, FileMode.Open));
		}
	public void Set_SMART_CARD_PIN(String aSMART_CARD_PIN)
	{
		SMART_CARD_PIN = aSMART_CARD_PIN;
	}
	[b]public void createEnvelopedBes(String aLisansFile, String aConfigXmlYol, String aPinNo, bool aNitelik, string aSignatureID, String aXML, string aSignedXmlFilePath)
		{
			EnvelopedSignatureInitialize(aLisansFile);
			Set_SMART_CARD_PIN(aPinNo);
			String aConfigXmlFile = aConfigXmlYol + @"xmlsignature-config.xml";

			// here is our custom envelope xml
			XmlDocument envelopeDoc = newEnvelope2(aXML);

			// create context with working dir
			Context context	= new Context(aConfigXmlYol);
			context.Config	= new Config(aConfigXmlFile);
			
			// define where signature belongs to
			context.Document = envelopeDoc;

			// create signature according to context,
			// with default type (XADES_BES)
			XMLSignature signature = new XMLSignature(context, false);
			signature.SigningTime = DateTime.Now;

			// attach signature to envelope
			envelopeDoc.DocumentElement.GetElementsByTagName("ext:ExtensionContent").Item(0).AppendChild(signature.Element); // NORMALDE BU SATIRI KULLANIYORDUK AMA BİZE ARADA BİR YERDE KULLANMAK GEREKİYOR...

			// add document as reference,
			Transforms transforms = new Transforms(context);
			transforms.addTransform(new Transform(context, TransformType.ENVELOPED.Url));

			// add whole document(="") with envelope transform, with SHA256
			// and don't include it into signature(false)
			signature.addDocument("", "text/xml", transforms, DigestMethod.SHA_256, false);

			String[] terminals = SmartOp.getCardTerminals();
			String terminal;
			if (terminals == null || terminals.Length == 0) throw new SmartCardException("Kart takılı bir e-imza/e-mühür kartı yok");

			int index = 0;
			if (terminals.Length == 1) terminal = terminals[index];
			else
			{
				index = askOption(null, null, terminals, "Okuyucu Listesi", new String[] { "Tamam" });
				terminal = terminals[index];
			}
			Pair<long, CardType> slotAndCardType = SmartOp.getSlotAndCardType(terminal);
			bsc = new P11SmartCard(slotAndCardType.getmObj2());
			bsc.openSession(slotAndCardType.getmObj1());
			List<byte[]> allCerts = bsc.getSignatureCertificates();
			ECertificate signingCert = selectCertificate(aNitelik, false, allCerts);
			
			signature.addKeyInfo(signingCert);
			bsc.login(aPinNo);
			mSigner = bsc.getSigner(signingCert, Algorithms.SIGNATURE_RSA_SHA256);

			signature.sign(mSigner);
			envelopeDoc.Save(aSignedXmlFilePath);
			// MessageBox.Show("XML imzası atıldı, dosya (3): " + aSignedXmlFilePath);
		}
	}[/b]
}

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 02 Oca 2017 10:30

İlk dikkatimi çeken XmlDocument.Save yapmanız. Bu komut standart writer'ı kullanır, bir önceki mesajımda bahsettiğim new line karekterinizi değiştirir. bu noktada writer nesnesini kendiniz tanımlayıp kullanmalısınız.

Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Re: E-fatura?

Mesaj gönderen cengaver » 04 Oca 2017 09:48

Bahsettiğiniz değişikliği yaptım fakat bir gelişme olmadı, bir kaç düzenleme daha yapıp aşağıdaki hale getirdim, tekrar inceleyebilirmisiniz gözden kaçırdığım ne olabilir?

Kod: Tümünü seç

public void createEnvelopedBes  ( string aLisansFile         /* Örnek = C:\Sirius_XADES\lisans\lisans.xml */
                                , string aConfigXmlYol       /* Örnek = C:\Sirius_XADES\config\ */
                                , string aPinNo              /* Örnek = 123456 */
                                , bool aNitelik              /* Örnek = False */
                                , string aSignatureID        /* Örnek = RBC0160000000009 */
                                , string aXML                /* Örnek = C:\Temp\Orjinal.XML */
                                , string aSignedXmlFilePath  /* Örnek = C:\Temp\Yeni.XML */
)
{
  LicenseUtil.setLicenseXml(new FileStream(aLisansFile, FileMode.Open)); // Lisans dosyası yükleniyor
  Set_SMART_CARD_PIN(aPinNo);                                            // NESNEYE kartın pin bilgisi veriliyor

  XmlDocument envelopeDoc = new XmlDocument();
  envelopeDoc.PreserveWhitespace = true;
  envelopeDoc.Load (aXML); /* aXML burada full file path olarak değerlendirilir. */

  string aConfigXmlFile = aConfigXmlYol + @"xmlsignature-config.xml";    // xmlsignature-config.xml dosyasının tam olarak nerede olduğu söyleniyor
  Context context = new Context(aConfigXmlYol);    // çalışma klasörü ile içerik oluşturuluyor
  context.Config = new Config(aConfigXmlFile);     // Config dosyası yükleniyor
  context.Document = envelopeDoc;                  // imzalanacak belge içeriği alınıyor

  XMLSignature signature = new XMLSignature(context, false); // create signature according to context, with default type (XADES_BES)
  signature.SigningTime = DateTime.Now;
  signature.Id = "imzaid_" + aSignatureID;

  envelopeDoc.DocumentElement.GetElementsByTagName("ext:ExtensionContent").Item(0).AppendChild(signature.Element); // attach signature to envelope

  Transforms transforms = new Transforms(context);
  transforms.addTransform(new Transform(context, TransformType.ENVELOPED.Url)); // ENVELOPED kısmını burası ayarlıyor.

  signature.addDocument( "", "text/xml", transforms, DigestMethod.SHA_256, false); // URI'si boş referansı burası üretiyor...
  // signature.SignedInfo.SignatureMethod = SignatureMethod.RSA_SHA256;

  /* Smartkart listesi üretiliyor, birden fazla varsa kullanıcı aralarından birini seçecek... */
  String[] terminals = SmartOp.getCardTerminals();
  String terminal;
  if (terminals == null || terminals.Length == 0) throw new SmartCardException("Kart takılı bir e-imza/e-mühür (USB) aygıtı yok");

  int index = 0;
  if (terminals.Length == 1) terminal = terminals[index];
  else {
    index = askOption(null, null, terminals, "Okuyucu Listesi", new String[] { "Tamam" });
    terminal = terminals[index];
  }
  Pair<long, CardType> slotAndCardType = SmartOp.getSlotAndCardType(terminal);
  
  bsc = new P11SmartCard(slotAndCardType.getmObj2());
  bsc.openSession(slotAndCardType.getmObj1());
  List<byte[]> allCerts = bsc.getSignatureCertificates();
  ECertificate signingCert = selectCertificate(aNitelik, false, allCerts); /* Mali mühür için false, false kombinasyonu gerekiyor...  */

  signature.addKeyInfo(signingCert);
  bsc.login(aPinNo);
  mSigner = bsc.getSigner(signingCert, Algorithms.SIGNATURE_RSA_SHA256);

  // İmzala...
  signature.sign(mSigner);

  // CR+LF kullanacak şekilde ayarla 
  XmlWriterSettings ayarlar = new XmlWriterSettings();
  ayarlar.NewLineChars = "\r\n";
  ayarlar.Indent = true;
  ayarlar.Encoding = Encoding.UTF8;
  XmlWriter yazar = XmlWriter.Create(aSignedXmlFilePath, ayarlar);

  // Yeni dosyaya yaz.
  envelopeDoc.WriteTo(yazar); //envelopeDoc.Save(aSignedXmlFilePath); // .save = eski yöntem
  yazar.Close();
}

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 05 Oca 2017 11:47

Yine bozar aşağıdaki satır nedeniyle:
ayarlar.NewLineChars = "\r\n";
Encoding bom'suz olmalı, direk utf8 yapmayın.
xmlwriter'ı close etmeden önce flush etmeniz gerekiyor diye hatırlıyorum.

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 05 Oca 2017 11:48

cac:Signature içinde bulunan alana referans etmelisiniz, matematiksel doğrulamayı geçtiğinizde bu hatayı alacaksınız.
GİB test portalinden imzalanmış bir fatura alıp incelemenizi tavsiye ederim.

Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Re: E-fatura?

Mesaj gönderen cengaver » 09 Oca 2017 07:38

mkysoft,

Bahsettiğiniz kontrolleri yaptım, kıyaslamalar için de e-fatura portalinde sunulan imzalı efatura örneklerini kullandım, bunların halâ geçerli olup olmadığını da e-belge görüntüleyici ile kontrol ettim.

3) ESYA API'lerinin <ds:X509SubjectName> tagını üretmediğini fark ettim ama bunu nasıl ekleye bileceğimi bulamadım, bir öneriniz var mı?

1) NewLineChars parametresini de kontrol ettim, şu an itibariyle orjinal XML dosyasının hiç bir şekilde bozulmadığını teyit edebiliyorum. Yani orjinal xml ile imzalı xml arasında imza dışında hiç bir değişiklik yok. TextDiff denen ücretsiz bir yazılım var, ayrıca bununla da kontrol ettim birebir aynı

2)

Kod: Tümünü seç

    <cac:DigitalSignatureAttachment>
      <cac:ExternalReference>
        <cbc:URI>#Signature_RBC0170000000001</cbc:URI>
      </cac:ExternalReference>
    </cac:DigitalSignatureAttachment>
  </cac:Signature>
kısmından bahsediyorsunuz, #Signature_RBC0170000000001 değerini aşağıdaki taglara da yazdım;

a)

Kod: Tümünü seç

<ds:Signature Id="Signature_RBC0170000000001">
b)

Kod: Tümünü seç

<xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="#Signature_RBC0170000000001">
C# Kodunun son hali aşağıda yer alıyor;

Kod: Tümünü seç

public void createEnvelopedBes  ( string aLisansFile            /* Misal = C:\Sirius_XADES\lisans\lisans.xml */
                                , string aConfigXmlYol          /* Misal = C:\Sirius_XADES\config\ */
                                , string aPinNo                 /* Misal = 123456 */
                                , bool aNitelik                 /* Misal = False */
                                , string aSignatureID           /* Misal = RBC0160000000009 */
                                , string aXML                   /* Misal = C:\Temp\Orjinal.XML */
                                , string aSignedXmlFilePath     /* Misal = C:\Temp\Yeni.XML */
)
{
    LicenseUtil.setLicenseXml(new FileStream(aLisansFile, FileMode.Open));    // Lisans dosyası yükleniyor
    Set_SMART_CARD_PIN(aPinNo);                                                // NESNEYE kartın pin bilgisi veriliyor
    string aConfigXmlFile = aConfigXmlYol + @"xmlsignature-config.xml";        // xmlsignature-config.xml dosyasının tam olarak nerede olduğu söyleniyor

    XmlDocument envelopeDoc = new XmlDocument();                            // Yeni bir XML nesnesi üretiliyor
    envelopeDoc.PreserveWhitespace = true;                                    // Yükelencek olan belgenin kılına dokunulmayacak demektir...
    envelopeDoc.Load (aXML);                                                // aXML burada full file path olarak değerlendirilir.

    Context context = new Context(aConfigXmlYol);                            //    XML Config klasörü ve içerik oluşturuluyor
    context.Config = new Config(aConfigXmlFile);                            //    Config dosyası yükleniyor
    context.Document = envelopeDoc;                                         //    imzalanacak belge içeriği alınıyor

    string cbc_URI = envelopeDoc.DocumentElement.GetElementsByTagName("cbc:URI").Item(0).InnerText.Trim(); //    ok
    string cbc_URI2 = cbc_URI.Remove(0, 1); // cbc_URI.Substring(2, cbc_URI.Length-1);

    XMLSignature signature = new XMLSignature(context, false);              // Mevcut içeriğe uygun Varsayılan (XADES_BES) türünde bir imza nesnesi üretilir.
    signature.Element.RemoveAttribute("xmlns:ds");
    signature.Element.SetAttribute("Id", cbc_URI2);
    signature.SigningTime = DateTime.Now;
    signature.SignedInfo.SignatureMethod = SignatureMethod.RSA_SHA256;
    signature.SignedInfo.Id = "SignedInfo"; /*1*/

    // add document as reference,
    Transforms transforms = new Transforms(context);
    transforms.addTransform(new Transform(context, TransformType.ENVELOPED.Url)); // ENVELOPED kısmını burası ayarlıyor.
    // Boş ID'li bir referans ekleniyor ( add whole document(="") with envelope transform, with SHA256 ) and don't include it into signature(false)
    signature.addDocument( "", "text/xml", transforms, DigestMethod.SHA_256, false); // URI'si boş referansı burası üretiyor...
    signature.SignedInfo.getReferenceByURI("").Element.RemoveAttribute("Id");

    // xades: SignedDataObjectProperties bu da silinecek...
    //signature.Document.GetElementsByTagName("xades:SignedDataObjectProperties").Item(0).RemoveAll();    BU NOKTADA HATA VERİYOR ?!
    
    // attach signature to envelope structure
    envelopeDoc.DocumentElement.GetElementsByTagName("ext:ExtensionContent").Item(0).AppendChild(signature.Element);
    //add signer role information
    SignerRole rol = new SignerRole(context, new ClaimedRole[] { new ClaimedRole(context, "Tedarikçi") });
    signature.QualifyingProperties.SignedSignatureProperties.SignerRole = rol;

    /* Smartkart listesi üretiliyor, birden fazla varsa kullanıcı aralarından birini seçecek... */
    String[] terminals = SmartOp.getCardTerminals();
    String terminal;
    if (terminals == null || terminals.Length == 0) throw new SmartCardException("Kart takılı bir e-imza/e-mühür (USB) aygıtı yok");
    int index = 0;
    if (terminals.Length == 1) terminal = terminals[index]; else 
    {
        index = askOption(null, null, terminals, "Okuyucu Listesi", new String[] { "Tamam" });
        terminal = terminals[index];
    }
    Pair<long, CardType> slotAndCardType = SmartOp.getSlotAndCardType(terminal);
    bsc = new P11SmartCard(slotAndCardType.getmObj2());
    bsc.openSession(slotAndCardType.getmObj1());
    List<byte[]> allCerts = bsc.getSignatureCertificates();
    ECertificate signingCert = selectCertificate(aNitelik, false, allCerts);

    signature.QualifyingProperties.Target = cbc_URI; // ŞART
    signature.QualifyingProperties.SignedSignatureProperties.SigningTime = signature.SigningTime; // ŞART

    //signingCert.isMaliMuhurCertificate(); // sertifina Dongılı bir mali mühür ise TRUE sonucunu veriyor...

    X509Certificate2 x509 = signingCert.asX509Certificate2();// Bu satır olmayacaksa alttaki satırın alternatifini kulan - 
    AsymmetricAlgorithm aKey = x509.PublicKey.Key; // ALTERNATİFİ = AsymmetricAlgorithm aKey = signingCert.asX509Certificate2().PublicKey.Key;
    signature.addKeyInfo(aKey);
    signature.addKeyInfo(signingCert);

    EName x509SN = signingCert.getSubject(); 
    MessageBox.Show("EKLENECEK : ...<ds:X509SubjectName>" + x509SN.stringValue() + " </ds:X509SubjectName>");
    //signature.KeyInfo.resolveCertificate();
    //signature.KeyInfo.resolvePublicKey();
    //signature.KeyInfo.Element.GetElementsByTagName("ds:X509Data").Item(0).PrependChild(new XmlNode("aa","www"));// AppendChild(aSubjectName);

    bsc.login(aPinNo);
    mSigner = bsc.getSigner(signingCert, Algorithms.SIGNATURE_RSA_SHA256);
    // ValidationResult Verifikasyon = signature.verify( signingCert); // SERTİFİKA

    /* İMZALA *************************************************************************************************************************/
    signature.sign(mSigner);
    // Satır sonlarını CR+LF kullanacak şekilde ayarla 
    XmlWriterSettings ayarlar = new XmlWriterSettings();
    ayarlar.NewLineChars = "\r\n";
    ayarlar.Indent = true;
    ayarlar.Encoding = Encoding.UTF8;
    XmlWriter yazar = XmlWriter.Create(aSignedXmlFilePath, ayarlar);

    // Yeni dosyaya yaz.
    envelopeDoc.WriteTo(yazar); //envelopeDoc.Save(aSignedXmlFilePath); // .save = eski yöntem
    yazar.Close();
    MessageBox.Show("Its Done !");
}

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 09 Oca 2017 08:59

Sertifika adı zorunlu değil diye hatırlıyorum, eklemesende sorun olmaz. yinede eklemek istersen aşağıdaki gibi yapabilirsin.

Kod: Tümünü seç

var keyInfo = signature.createOrGetKeyInfo();
for (int i = 0; i < keyInfo.ElementCount; i++)
{
  if (keyInfo.get(i).GetType().IsAssignableFrom(typeof(keyinfo.X509Data)))
  {
    var x509Data = (keyinfo.X509Data)keyInfo.get(i);
    x509Data.add(new keyinfo.x509.X509SubjectName(context, signingCert.getSubject().stringValue()));
    break;
  }
}

Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Re: E-fatura?

Mesaj gönderen cengaver » 10 Oca 2017 02:13

mkysoft,

İmzalanan XML dosyalarını İmzager ile kontrol ettiğimde
"Sertifika Zinciri Sorunlu. Güvendiğiniz bir sertifika zinciri oluşturulamadı. Sertifikanın kök sertifikası güvenilir Sertifikalarınızdan biri olmayabilir." uyarısını veriyor,

KamuSM'nin mali mühürünü kullanıyoruz, sertifika da bu mali mühürün içinde zaten, acaba xml-signature-config.xml dosyasında bir ayar mı yapmak gerekir?

http://i.hizliresim.com/zaO2A7.jpg
Resim

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 11 Oca 2017 03:31

İmzager'de doğrulama yapabilmek için bazı ayarlar yapmalısınız. Sertifika deposu içinden alt kök sertifikaları yüklemeniz gerekiyor zincir problemini çözmek için. Nasıl yapılacağını anlatan bir sayfa vardı kamusm üzerinde, şimdi bulamadım. Bulursam paylaşayım.

Önceki mesajmda bahsettiğim referans hatası alıyorsunuz. Yanlış referans kullanıyorsunuz. İmzalı xml'i yüklerseniz bakalım.

Kullanıcı avatarı
cengaver
Üye
Mesajlar: 111
Kayıt: 01 Nis 2014 04:02
Konum: İstanbul

Re: E-fatura?

Mesaj gönderen cengaver » 12 Oca 2017 02:02

mkysoft,

Karşılaştırma yapabilmeniz için İmzayı atan kısım aşağıda yer alıyor, eğer imza atan projenin tamamını isterseniz onu da ekleyebilirim,

Bunun dışında istediğiniz orijinal ve İmzalı XML örneklerini de ekte bulabilirsiniz,

Kod: Tümünü seç

		public void createEnvelopedBes(string aLisansFile            // Örnek = C:\XADES\lisans\lisans.xml   > KamuSM'nin lisans dosyası
										, string aConfigXmlYol          // Örnek = C:\XADES\config\             > xmlsignature-config.xml dosyasının pathi.
										, string aPinNo                 // Örnek = 123456                              > SmartKarttaki pin 
										, bool aNitelik                 // Örnek = False                               > Smartkarttaki sertifikanın nitelik durumu (Mali mühürde false oluyor )
										, string aSignatureID           // Örnek = RBC0160000000009                    > Fatura No
										, string aXML                   // Örnek = C:\Temp\Orjinal.XML                 
										, string aSignedXmlFilePath     // Örnek = C:\Temp\Yeni.XML                    
		)
		{
			LicenseUtil.setLicenseXml(new FileStream(aLisansFile, FileMode.Open));  // Lisans dosyası yükleniyor
			Set_SMART_CARD_PIN(aPinNo);                                             // NESNEYE kartın pin bilgisi veriliyor

			/* Smartkart listesi üretiliyor, birden fazla varsa kullanıcı aralarından birini seçecek... */
			String[] terminals = SmartOp.getCardTerminals();
			String terminal;
			if (terminals == null || terminals.Length == 0) throw new SmartCardException("Kart takılı bir e-imza/e-mühür (USB) aygıtı yok");
			int index = 0;
			if (terminals.Length == 1) terminal = terminals[index];
			else
			{
				index = askOption(null, null, terminals, "Okuyucu Listesi", new String[] { "Tamam" });
				terminal = terminals[index];
			}
			Pair<long, CardType> slotAndCardType = SmartOp.getSlotAndCardType(terminal);
			bsc = new P11SmartCard(slotAndCardType.getmObj2());
			bsc.openSession(slotAndCardType.getmObj1());
			List<byte[]> allCerts = bsc.getSignatureCertificates();
			ECertificate signingCert = selectCertificate(aNitelik, false, allCerts);

			XmlDocument envelopeDoc = new XmlDocument();                            // Yeni bir XML nesnesi üretiliyor
			envelopeDoc.PreserveWhitespace = true;                                  // Yükelencek olan belge olduğu gibi duracak, boşluk ve tab düzeltmesi yapılmayacak demektir...
			envelopeDoc.Load(aXML);                                                // Orjinal XML dosyası yükleniyor.

			string aConfigXmlFile = aConfigXmlYol + @"xmlsignature-config.xml";     // xmlsignature-config.xml dosyasının tam olarak nerede olduğu söyleniyor
			Context context = new Context(aConfigXmlYol);                           // XML Config klasörü ve içerik oluşturuluyor
			context.Config = new Config(aConfigXmlFile);                            // Config dosyası yükleniyor
			context.Document = envelopeDoc;                                         // imzalanacak belge içeriği alınıyor

			XMLSignature signature = new XMLSignature(context, false);              // Mevcut içeriğe uygun Varsayılan (XADES_BES) türünde bir imza nesnesi üretilir.
																					// attach signature to envelope structure
			XmlElement extContent = (XmlElement)envelopeDoc.DocumentElement.GetElementsByTagName("ext:ExtensionContent").Item(0);
			extContent.AppendChild(signature.Element);

			Transforms transforms = new Transforms(context);                              // add document as reference,
			transforms.addTransform(new Transform(context, TransformType.ENVELOPED.Url)); // ENVELOPED kısmını burası ayarlıyor.

			signature.addDocument("", "text/xml", transforms, DigestMethod.SHA_256, false); // Boş ID'li bir referans ekleniyor ( add whole document(="") with envelope transform, with SHA256 ) and don't include it into signature(false)

			//add signer role information
			SignerRole rol = new SignerRole(context, new ClaimedRole[] { new ClaimedRole(context, "Tedarikçi") }); // ileride parametrik olacak...
			signature.QualifyingProperties.SignedSignatureProperties.SignerRole = rol;

			X509Certificate2 x509 = signingCert.asX509Certificate2();  // Bu satır olmayacaksa alttaki satırın alternatifini kulan
			AsymmetricAlgorithm aKey = x509.PublicKey.Key;             // ALTERNATİFİ = AsymmetricAlgorithm aKey = signingCert.asX509Certificate2().PublicKey.Key;
			signature.addKeyInfo(aKey);
			signature.addKeyInfo(signingCert);

			var keyInfo = signature.createOrGetKeyInfo();
			for (int i = 0; i < keyInfo.ElementCount; i++)
			{
				if (keyInfo.get(i).GetType().IsAssignableFrom(typeof(tr.gov.tubitak.uekae.esya.api.xmlsignature.model.keyinfo.X509Data)))
				{
					var x509Data = (tr.gov.tubitak.uekae.esya.api.xmlsignature.model.keyinfo.X509Data)keyInfo.get(i);
					x509Data.add(new tr.gov.tubitak.uekae.esya.api.xmlsignature.model.keyinfo.x509.X509SubjectName(context, signingCert.getSubject().stringValue()));
					break;
				}
			}

			signature.QualifyingProperties.SignedSignatureProperties.SigningTime = DateTime.Now; // signature.SigningTime; // ŞART

			string cbc_URI = envelopeDoc.DocumentElement.GetElementsByTagName("cbc:URI").Item(0).InnerText.Trim(); //	ok
			string cbc_URI2 = cbc_URI.Remove(0, 1); // Baştaki # karakterini siliyor sadece...

			signature.Element.SetAttribute("Id", cbc_URI2);
			signature.QualifyingProperties.Target = cbc_URI; // ŞART

			bsc.login(aPinNo);
			mSigner = bsc.getSigner(signingCert, Algorithms.SIGNATURE_RSA_SHA256);

			signature.sign(mSigner); // İMZALA

			XmlWriterSettings ayarlar = new XmlWriterSettings();
			ayarlar.Indent = true;
			XmlWriter yazar = XmlWriter.Create(aSignedXmlFilePath, ayarlar);

			// Yeni dosyaya yaz.
			envelopeDoc.WriteTo(yazar);
			yazar.Close();
			MessageBox.Show("İmzalandı");

			/*
			ValidationResult Verifikasyon = signature.verify(signingCert);
			__(Verifikasyon.getCheckResult());

			ValidationSystem vs = CertificateValidation.createValidationSystem(tr.gov.tubitak.uekae.esya.api.certificate.validation.policy);
			vs.setBaseValidationTime(DateTime.UtcNow);
			CertificateStatusInfo csi = CertificateValidation.validateCertificate (vs, signingCert);
			*/

			/*			
			signature.Element.RemoveAttribute("xmlns:ds");
			signature.Element.SetAttribute("Id", cbc_URI2);
			signature.SigningTime = DateTime.Now;
			signature.SignedInfo.SignatureMethod = SignatureMethod.RSA_SHA256;
			signature.SignedInfo.Id = "SignedInfo"; //1

			// xades: SignedDataObjectProperties bu da silinecek...
			//signature.Document.GetElementsByTagName("xades:SignedDataObjectProperties").Item(0).RemoveAll();	BU NOKTADA HATA VERİYOR ?!
			//*signature.KeyInfo.add(new KeyValue(context, cert.asX509Certificate2().PublicKey.Key));
			//signingCert.isMaliMuhurCertificate(); // sertifina Dongılı bir mali mühür ise TRUE sonucunu veriyor...
			
			//ValidationResult Verifikasyon = signature.verify( signingCert); // SERTİFİKA

			//ayarlar.NewLineChars = "\r\n";
			//ayarlar.Encoding = Encoding.UTF8;

			*/
		}
Dosya ekleri
Ornek_XML.rar
(194.82 KiB) 59 kere indirildi

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 12 Oca 2017 09:19

satır sonu karakteri probleminiz düzelmemiş görünüyor:
Resim

Esya Signature alanını \n oluşturuyor normalde. Elimle düzelttim ancak yine de geçmedi doğrulamadan. Sonra aşağıdaki satırı farkettim, bu satır imzalanmış xml'i hizalayacağı için bozacaktır.
ayarlar.Indent = true;
Onun dışında gözüme çarpan birşey yok.

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 12 Oca 2017 10:05

Aşağıdaki kodları kullanarak kaydedin xml'i.

Kod: Tümünü seç

XmlWriterSettings ayarlar = new XmlWriterSettings();
ayarlar.Encoding = new System.Text.UTF8Encoding(false);
ayarlar.NewLineHandling = NewLineHandling.None;
XmlWriter yazar = XmlWriter.Create(aSignedXmlFilePath, ayarlar);

uparlayan
Üye
Mesajlar: 28
Kayıt: 09 Oca 2009 05:48

Re: E-fatura?

Mesaj gönderen uparlayan » 16 Oca 2017 02:34

Kodların tamamını biraz daha elden geçirip sadeleştirdim, Mustafa Kerim YILMAZ ve Müslüm ÖZTÜRK'ten de teorik yardım aldım ve sonuç olarak mali mühür kullanarak e-fatura imzası atan sade bir prosedür geliştirebildik. Müslüm beyin gönderdiği örnekler e-defter ile ilgili idi fakat benzer bir yapıya sahipti o nedenle Müslüm ÖZTÜRK'e özellikle teşekkür etmek isterim. Denemelerimde mali mühür ve XML'i doğrulayabildim, e-belge görüntüleyici ile görüntüleyip oradan da doğrulamasını yapabildim. Gönül isterdi ki nitelikli bir sertifika ile de denemeler yapabilelim, elimizde nitelikli bir sertifika olmadığı için bu denemeyi yapamadım fakat büyük ihtimalle o notada da çalışacaktır.

Projenin tamamı KamuSM'nin örnek CSHARP projesinden devşirilmiştir ve ilgili siteden çekilebilir(, eski postlarda link vardı), dolayısıyla Bu prosedürü o projeye yamarsanız sonuç elde edebilirsiniz; Parametrelerin örnekleri de size neyi nereye koyacağınız konusunda bir ip ucu veriyor.

Hayırlı olsun, İşte (Allahın cezası, beyin yakan) ilgili Kod;

Kod: Tümünü seç

public void createEnvelopedBes  ( string aLisansFile         // Örnek = C:\Sirius_XADES\lisans\lisans.xml   > KamuSM'nin lisans dosyası
                                , string aConfigXmlYol       // Örnek = C:\Sirius_XADES\config\             > xmlsignature-config.xml dosyasının pathi.
                                , string aPinNo              // Örnek = 123456                              > SmartKarttaki pin 
                                , bool aNitelik              // Örnek = False                               > Smartkarttaki sertifikanın nitelik durumu (Mali mühürde false oluyor )
                                , string aSignerRol          // Örnek = Tedarikçi
                                , string aXML                // Örnek = C:\Temp\Orjinal.XML                 
                                , string aSignedXmlFilePath  // Örnek = C:\Temp\Yeni.XML                    
)
{
   /* Uğur PARLAYAN */
    LoadLicense(aLisansFile);
    Set_SMART_CARD_PIN(aPinNo);

    XmlDocument envelopeDoc = NewEnvelopeFromFilePath(aXML);
    string cbc_URI = envelopeDoc.DocumentElement.GetElementsByTagName("cbc:URI").Item(0).InnerText.Trim();
    string cbc_URI2 = cbc_URI.Remove(0, 1); // Sadece baştaki # karakterini siliyor...

    // imza nesnesi üretiliyor
    var context = CreateContext(aConfigXmlYol);
    if (context == null)
    {
        MessageBox.Show(string.Format("Context nesnesi oluşturulamadı: {0}", aConfigXmlYol));
        return;
    }
    context.Document = envelopeDoc;
    XMLSignature signature = new XMLSignature(context, false);
    if (envelopeDoc.DocumentElement != null)
    {
        envelopeDoc.DocumentElement.GetElementsByTagName("ext:ExtensionContent").Item(0).AppendChild(signature.Element);
    }
    else { MessageBox.Show("imza dosyaya eklenemedi!"); }

    Transforms transforms = new Transforms(context);
    transforms.addTransform(new Transform(context, TransformType.ENVELOPED.Url));

    signature.addDocument("", ""/*bu da boş kalacak, "text/xml" yazılmayacak...*/, transforms, DigestMethod.SHA_256, false);
    signature.SignedInfo.SignatureMethod = SignatureMethod.RSA_SHA256;
    signature.SignedInfo.CanonicalizationMethod = C14nMethod.INCLUSIVE_WITH_COMMENTS;

    signature.QualifyingProperties.SignedSignatureProperties.SigningTime = DateTime.Now;

    signature.Element.SetAttribute("Id", cbc_URI2);
    signature.QualifyingProperties.Target = cbc_URI; // ŞART

    SignerRole rol = new SignerRole(context, new ClaimedRole[] { new ClaimedRole(context, aSignerRol) });
    signature.QualifyingProperties.SignedSignatureProperties.SignerRole = rol;

    ECertificate cert = SmartCardManager.getInstance().getSignatureCertificate(aNitelik, false);
    signature.addKeyInfo(cert);
    var signer = SmartCardManager.getInstance().getSigner(aPinNo, cert);
    if (signer == null)
    {
        MessageBox.Show("İmza signer için Sertifika dosyası bulunamadı:");
        return;
    }

    KeyValue keyValue = new KeyValue(context, cert.asX509Certificate2().PublicKey.Key);
    signature.KeyInfo.add(keyValue);
    var keyInfo = signature.createOrGetKeyInfo();
    for (int i = 0; i < keyInfo.ElementCount; i++)
    {
        if (keyInfo.get(i).GetType().IsAssignableFrom(typeof(tr.gov.tubitak.uekae.esya.api.xmlsignature.model.keyinfo.X509Data)))
        {
            var x509Data = (tr.gov.tubitak.uekae.esya.api.xmlsignature.model.keyinfo.X509Data)keyInfo.get(i);
            x509Data.add(new tr.gov.tubitak.uekae.esya.api.xmlsignature.model.keyinfo.x509.X509SubjectName(context, cert.getSubject().stringValue()));
            break;
        }
    }
    signature.SigningTime = DateTime.Now;
    signature.sign(signer);

    XmlWriterSettings settings = new XmlWriterSettings { NewLineChars = "\r\n", Indent = true };
    XmlWriter writer = XmlWriter.Create(aSignedXmlFilePath, settings);

    envelopeDoc.WriteTo(writer);
    writer.Close();
}
En son uparlayan tarafından 16 Oca 2017 04:49 tarihinde düzenlendi, toplamda 1 kere düzenlendi.

mkysoft
Kıdemli Üye
Mesajlar: 3006
Kayıt: 25 Ağu 2003 11:35
Konum: İstanbul
İletişim:

Re: E-fatura?

Mesaj gönderen mkysoft » 16 Oca 2017 03:29

@uparlayan yanlış kodu paylaşmış olabillir misiniz? Writer new line'ları değiştiriyor gibi görünüyor, sorun olabilir.

uparlayan
Üye
Mesajlar: 28
Kayıt: 09 Oca 2009 05:48

Re: E-fatura?

Mesaj gönderen uparlayan » 16 Oca 2017 04:24

@mkysoft, kod doğru, test etmek için bahsettiğin satırı şu şekilde değiştirdiğimde de doğrulamayı başardım;

Kod: Tümünü seç

XmlWriterSettings settings = new XmlWriterSettings { NewLineChars = "\n", Indent = true };
Sanırım burada asıl sorun dosyayı yazarken değil, okurken ortaya çıkıyor. Yani eskisinde ben bunu bir text dosya gibi düşünüyordum ve özel bir işlemden geçirmiyordum, o noktada aşağıdaki prosedür ile sorunu çözmüş olduk. Bu noktadan sonra da nasıl kaydettiğin pek fark etmiyor, ki zaten doğrusu da öyle olmalıydı. Yani demek istediğim, mantıken dosyanın BOM'lu olup olmadığının veya UTF-8 ile kodlanıp kodlanmadığının bir öneminin olmaması gerekirdi. Aşağıdaki kod ile bunu halletmiş olduk;

Kod: Tümünü seç

public XmlDocument NewEnvelopeFromFilePath(string path)
{
	if (File.Exists(path))
	{
		byte[] bytes = File.ReadAllBytes(path);
		MemoryStream ms = new MemoryStream(bytes);
		XmlDocument doc = new XmlDocument { PreserveWhitespace = true };
		XmlReader reader = XmlReader.Create(ms);
		doc.Load(reader);
		return doc;
	}
	return null;
}
Resim

Cevapla