E-İmza İle PDF İmzalama | C#

Merhaba, geçenlerde bir ihtiyaç üzerine Kamu Sertifikasyon Merkezi (https://yazilim.kamusm.gov.tr) tarafından sunulan e-imza kütüphanesi ile tanıştım.
Burada hem C#, hem de Java örnek kodları vardı.
Örneği ayağa kaldırmaktansa, onu referans alarak basit bir uygulama yazdım.
Hem oradaki gibi .p7s dosyası oluşturabildim, hem de bir PDF belgesini imzalayabildim.
İhtiyacı olanlar için de buraya çalışan halini koyuyorum.

  • Öncelikle KamuSm’den indirdiğim örnek projenin içerisindeki BENİOKU.txt içerisinde verilen yönergeleri uyguladım.
    http://depo.kamusm.gov.tr/depo/SertifikaDeposu.svt adresinden “SertifikaDeposu.svt” dosyasını,
    http://depo.kamusm.gov.tr/depo/SertifikaDeposu.xml adresinden “SertifikaDeposu.xml” dosyasını indirebilirsiniz.
    Bu dosyaları c:\Users\zamkinos\.sertifikadeposu\ dizini altına kopyalamalısınız.
  • “lib” dizini altında kullanmanız gereken dll dosyaları bulunmaktadır. Onların hepsini projenin altında lib dizini içine koydum.
  • Ben C altına EImza diye bir dizin açtım. İşlemleri orada yaptım.
  • Aldığım hatalar neticesinde certval-policy.xml dosyasına aşağıdaki satırları ekledim.
  • Örnekle uyumlu olması açısından .net FrameWork 3.5 ile yazdım ben de.
  • Örneklerde PDF dosyasını imzalama yoktu. Onu da internette bir arkadaşın örneğinden faydalanarak hallettim.

Örnek projeyi de buraya bırakıyorum. Belki birilerinin işine yarar.

https://www.zamkinos.net/KonsolEImza.rar

Selamlar.

Kaynaklar:

https://github.com/mfarkan/E-Imza-iTextSharp-ESYA-Api

https://yazilim.kamusm.gov.tr/?q=/node/14

31 thoughts on “E-İmza İle PDF İmzalama | C#

  1. Merhaba,

    Öncelikle çözümünüz için teşekkür ederim. Bir projem için e-imza okumam gerekiyor. Projenizi faydalanabileceğimi düşündüm ve lokalime indirip çalıştırdım. Ancak bir noktada hata almaktayım.

    SmartCardManager.cs sınıfı, 155. satırda SmartOp.getSlotAndCardType() metodu Unhandled Exception atmakta.

    Detaylı hata açıklaması:
    “Net.Pkcs11Interop.Common.UnmanagedException: ‘Unable to load library. Error code: 0x0000007E. Error detail: The specified module could not be found'”

    Çözüme dair bir fikriniz var ise, paylaşırsanız sevinirim.

    İyi çalışmalar.

  2. Merhaba, karşılaştığım bir hata değil. Ancak aşağıdakiler kontrol edilebilir:
    * ma3api-pkcs11-interop.dll’in referanslarda olduğu teyit edilebilir.
    * e-imza dongle’ına ait yazılımın doğru bir şekilde yüklendiğine emin olmak lazım.
    * https://docs.microsoft.com/tr-TR/cpp/windows/latest-supported-vc-redist adresinden Microsoft Visual C++ Yeniden Dağıtılabilir paketini indirip kurmayı deneyebilirsin.

    Bütün bunları denemene rağmen olmazsa da, uzaktan bağlanıp bakabilirim müsait bir zamanda.

    Selamlar.

    1. Cevabınız için teşekkür ederim. Başka bir bilgisayarda denedim, bu sefer çalıştı. Sanırım Smart Card Reader sürücüleri doğru şekilde yüklenmemişti.

      Şu an geldiğim noktada terminalleri okuyup, e-imza üzerinden verileri doğru şekilde alabiliyorum.

      Ancak imzalaBasitIcerik() içinde assert yaparken sdvr.getSDStatus() metodu NOT_ALL_VALID döndürüyor (Program.cs, satır: 149).

      sdvr.getSDValidationResults() metodu ile değerleri incelediğimde, “(-) Signature Checker Signature crypto verification is unsuccessful” mesajını görüyorum. Mesajın tamamı aşağıdaki gibidir;

      “{Pre-verification is done. Signature Checker Results: (-) Signature Checker Signature crypto verification is unsuccessful. (+) Message Digest Attribute Checker Message digest check is successful. (+) Signing Certificate V2 Attribute Checker Signing certificate attribute check is successful. (+) Certificate Validation Checker Certificate validation is successful (+) Content Type Attribute Checker Content Type attribute check is successful. }”

      Ben ACS Smart Card Reader üzerinden e-imza yüklü e-kimlik okuyorum. Sanırım sizin projeniz dongle okumak için tasarlanmış. Bende terminallerin ve e-imza verilerinin alınmasında bir problem oluşmadı ama belki bununla ilgili olabilir. Önerileriniz olursa dönüşlerinizi bekliyorum.

      Teşekkürler.

      1. Merhaba, öncelikle imzalaBasitIcerik() metodunu KamuSm’den aldığım örneği çalıştırabilecek miyim diye koymuştum oraya. Onun da çalıştığını teyit etmek için.
        Ancak PDF imzalamak için ona ihtiyacımız yok. Eğer sen PDF imzalayabiliyorsan o metodu es geçebilirsin. Bende ACS Smart Card Reader olmadığından deneyemiyorum, o yüzden sebebi ile ilgili net bir cevap veremiyorum, kusura bakma.

        Selamlar.

  3. Merhaba, paylaşımınız için çok teşekkür ederim, çalışan bir örnek bulmak gerçekten çok zor. Ben e-imzayı .pdf dosyası üzerinde bir alanda (koordinat belirterek) kullanmak istiyorum, adobe reader ‘da imzalama yaparken bir alan taradığımızda oraya imza yerleştiriyor. Amacım bir yazı oluşturduğumda isim soyisim göstererek imzalamak ve mouse ile üstüne gelince eimzayı göstermesi. Sizin örneğinizde nasıl bir değişiklik yapmam gerekli yada böyle bir çalışmanız var ise paylaşmanız mümkün mü? Umarım ne demek istediğimi anlatabilmişimdir.
    Tekrar teşekkürler.

    1. Merhaba, PdfSigner class’ında SignPDF metoduna şu iki satırı eklersen sanırım istediğin olacak. Rectangle nesnesinin parametreleri ile de koordinatlarını ayarlayabilirsin. Ben örnek bir PDF’te denedim ve görüntüleyebildim.
      ......
      PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;

      signatureAppearance.SetVisibleSignature(new Rectangle(150, 1100, 500, 50), 1, "Signature");
      signatureAppearance.Reason = "Keyfimden...";

      crlList = new List();
      ........

      Selamlar

      1. Cevabın için teşekkür ederim, şu an şehir dışındayım deneme imkanım olmadı. Bu sanırım console uygulaması, msdos (siyah) ekranda açılıyor , ben windows form uygulaması yapmak istiyorum, yani imzalanacak dokümanı openfiledialog ile seçip, imza sonrası hangi klasöre atacak, eimza şifresi textbox ile girilecek, hatta 2 kişi imzalayacak gibi. Kodlar program.cs sınıfında başlangıç yapıyor, ben kodları form içindeki butondan çalıştırmak için denemeler yaptım, hatta program.cs’de sadece form1 açılsın dedim ama yine dos ekranı arkada açılıyor, bunun nedeni console application olmasından kaynaknalıyor olabilir mi? kodları windowsform uygulamasına taşımak için kolay bir yöntem varmı. Yardımcı olursan çok sevinirim. Teşekkürler kolay gelsin.

        1. Merhaba, form uygulamasına çevirmek kısmında e-imza ile ilgili hiç bir şey düşünme bence. Bahsettiğin şekilde bir Form Uygulaması yaz. Sadece dosya seçilsin. Bir butona basınca InputBox çıksın şifre alsın kullanıcıdan. Bir butona basınca imzaladım diye mesaj çıksın. Ama hiç bir işlem yapmasın. Yani uygulamanın iskeletini e-imza kodları olmaksızın yazarsan, butonun arkasında e-imza ile ilgili kısımları eklemek çok basit. Çünkü konsol da olsa, form da olsa aynı kod çalışacak. O noktada buradaki kodu kullanabilirsin. Ama önce içi boş bir form uygulaması oluşturman lazım.

          Selamlar.

  4. Merhaba,
    Kodları denedim, sorunsuz çalıştı eline sağlık. Şimdi form uygulaması kısmına başladım, ,imza kısmında tarih ve başka bilgilerde gözüküyor, sadece ad soyad gözükmesi için ne yapabilirim, bir kaç gündür araştırıyorum ama çözemedim, bir de kafamda imzalanacak pdf ‘deki koordinatları alan tarayarak belirlemek var, yani pdf açılacak ve orada bir alanı taradığımda koordinatları textbox’a yazıp imzalayacak. Bu konuda nasıl bir yol izlemeliyim. Uygulamayı tamamladıktan sonra dilersen sana göndereyim yayınlayabilirsin, ihtiyacı olanlara faydası dokunur. Bu konuda maalesef kimse yardımcı olmuyor, paylaşımın kendim için hazırladığım uygulamada can kurtardı.

    1. Merhaba, Adobe Acrobat Reader DC ile imza atıldığında da benzer bir şekilde tarih gözüküyor. Sadece ad-soyad gözükmesini istemenin özel bir nedeni var mı? Nasıl olacağı ile ilgili bir fikrim yok açıkcası.
      Koordinatları nasıl alacağın ile ilgili de aklıma bir fikir gelmedi. Ama ben yapıyor olsaydım PDF dokümanının sabit olarak sağ alt veya üst köşesine yerleştirirdim herhalde. Hayati öneme sahip bir konuysa ben de araştırayım ama.

      Selamlar.

  5. Tekrar merhaba, istediğim gibi form üzerinden dosya seçerek ve şifre girerek imzalama yapabiliyorum, fakat daha önce imzalanmış bir .pdf dosyasını farklı bir kişi ikinci imza atamıyorum, bu konuda programda nasıl bir değişiklik yapmam gerekli, yardımcı olabilirmisin. Aynı dokümanı bir hazırlayan imzalayacak bir de onaylayan olacak. Ayrıca imza sonrası program yine döngüye girip tekrar imzalama yapıyor, uygulama akışını nasıl duraklatabilirim yada durdurabilir, tekrar imzala butonuna basana kadar programın beklemesi gibi. Teşekkürler.

    1. Merhaba, aslında örnek kod ile imzalı bir PDF ikinci kez imzalanabiliyor.
      Yani kendisine gelen PDF imzalı mı diye bakmıyor, direkt imzalıyor.
      PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', null, true);
      Bu satırdaki sondaki “true” bu işe yarıyor sanırım. Varolanın üzerine ekliyor.
      Bu noktada nasıl bir hata alıyorsun? Belki biraz daha detay verirsen yardımcı olabilirim.

      Bahsettiğin döngüyü hiç anlamadım. Belki kodundan bir kısmını paylaşırsan bir fikir yürütebilirim.

      Selamlar.

  6. Merhaba, PdfSigner class’ında SignPDF metoduna aşağıdaki Rectange komutunu ekleyince, imzalı bir dosyayı 2. kere imzalarken hata veriyor.
    Döngüden kastım, imzalama bitince tekrar ,imzalanacak dosyanın adresini soruyor. Ben form uygulaması yaptım, imzala diye bir butona basınca imza atıyor fakat senin komutları direkt kullandım, bu nedenle tekrar imzalanacak dosya soruyor gibi davranıyor, dosyayı tekrar imzalamaya kalkıyor. Bu arada desteğin için tekrar teşekkür ederim.
    ……
    PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;

    signatureAppearance.SetVisibleSignature(new Rectangle(150, 1100, 500, 50), 1, “Signature”);
    crlList = new List();
    ……..

    1. Hocam merhaba, ben sorunu çözdüm, belki basit bir bilgi eksikliği (amatör olarak kod yazıyorum) ama hata imza için gerekli alanların isimlerinin aynı olmasından kaynaklanmış. 2 imza için ayrı ayrı tanımlama yapınca sorunsuz çalıştı.
      PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
      signatureAppearance.SetVisibleSignature(new Rectangle(150, 1100, 500, 50), 1, “Signature”);

      ve
      PdfSignatureAppearance signatureAppearance1 = pdfStamper.SignatureAppearance;
      signatureAppearance1.SetVisibleSignature(new Rectangle(150, 1100, 500, 50), 1, “Signature1”);

      İlgin ve desteğin için tekrar çok teşekkür ederim.
      Bu arada fikrine ihtiyacım var, amacım Rectangle ile imza koordinatlarını kodun içine gömmek yerine kullanıcıya bırakmak istiyorum, şöyle .pdf dokümanı açılsın, kullanıcı imzalamak isteği alanı mouse ile tarasın ve imzala butonuna basınca imzalasın,Adobe’de ki yani. bu seneryo için nasıl bir izlemem gerekli,

      1. Merhaba, biraz araştırdım da, iTextSharp kütüphanesinde böyle bir event göremedim. Yani OnSelection, OnMouseSelect,..vs gibi bir event bulamadım.
        PdfPageEventHelper class’ına baktım, mevcut eventler işini görmez.
        PDF’ten ve itextSharp’tan bağımsız farenin koordinatlarını alarak belki ilerlenebilir ama bu durumda açık olan PDF belgesinin doğru alanına denk getirmek için belki takla atman lazım. O iş de pek kafama yatmadı.
        Acrobat Reader nasıl yapıyor diye düşünülebilir. Buradaki durum Acrobat Reader’dan şöyle farklı; Orada Acrobat Reader senin form uygulaman gibi düşün. Kendi form uygulamanda farenin pozisyonunu, çizilen bir dikdörtgenin koordinatlarını alabilirsin. Ama burada senin form uygulaman bir dosyayı harici bir yerde açıyor. Yani bir nevi misafir pozisyonundasın. Diğerinde dosya da sensin, açan da sensin gibi.
        Bilmiyorum anlatabildim mi?
        Belki de bir yolu vardır fakat ben bulamadım açıkcası.

        Selamlar.

        1. Merhaba, KamuSm’den alınan bilgilerle bir türlü imzalayamadım.
          Ücretsiz TimeStamp sunucuları varmış, internette ararken buldum:https://stackoverflow.com/questions/25052925/does-anyone-know-a-freetrial-timestamp-server-service
          Onlardan birini kullandım ve zaman damgası ile imzalayabildim.
          SignDetached metodu TimeStamp server parametresi de alıyor.

          public string SignPDF(PdfRequestDTO req)
          {
          string sonuc = "";
          MemoryStream stream = new MemoryStream();
          try
          {
          ITSAClient tsaClient = new TSAClientBouncyCastle("http://timestamp.sectigo.com");

          X509Certificate2 signingCertificate;
          IExternalSignature externalSignature;
          this.SelectSignature(req, out signingCertificate, out externalSignature);
          X509Certificate2[] chain = generateCertificateChain(signingCertificate);
          ICollection Bouncychain = chainToBouncyCastle(chain);
          ocsp = new OcspClientBouncyCastle();
          crl = new merged.iTextSharp.text.pdf.security.CrlClientOnline(Bouncychain);
          PdfReader pdfReader = new PdfReader(req.KaynakPdfYolu);
          FileStream signedPdf = new FileStream(req.HedefPdfYolu, FileMode.Create); //the output pdf file
          PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', null, true);
          PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
          crlList = new List();
          crlList.Add(crl);
          lock (lockSign)
          {
          MakeSignature.SignDetached(signatureAppearance, externalSignature, Bouncychain, crlList, ocsp, tsaClient, 0, CryptoStandard.CMS);
          //MakeSignature.SignDetached(signatureAppearance, externalSignature, Bouncychain, crlList, ocsp, null, 0, CryptoStandard.CMS);
          }
          }
          catch (Exception ex)
          {
          GenelIslemler.LogaYaz(" HATA: " + ex.Message);
          }
          return sonuc;
          }

          TimeStamp

          TimeStamp

          Selamlar.

  7. Merhaba,

    E-imza ile pdf imzalama yapmışsınız. .Net üzerinde Tübitak Api si ile ITextSharp kütüphanelerini birleştirmişsiniz. Peki bu yöntemi kullanarak mobil imza ile pdf imzalama yapılabilir mi? Konu ile ilgili destek olabilir misiniz?

    Saygılarımla,
    Onur

    1. Merhaba Onur, mobil imza ile ilgili bir fikrim yok.
      Ama araştıracağım.
      Sen de genel mantığıyla ilgili bildiklerini paylaşırsan faydası olabilir.
      Bir gelişme olursa da buradan mutlaka paylaşacağım.

      Selamlar.

  8. Merhaba,
    c:\Users\zamkinos.sertifikadeposu\ Buradaki ayarı nereden yapıyoruz ? Kod içerisinde aradığımda bulamadım da.

    1. Merhaba, sanırım ona bizim bu örnekte ihtiyaç yok. KamuSm’den indirdiğimiz dokümanda vardı. Ben de çok sorgulamadan bahsedilen dosyaları kopyaladım ilgili dizinlere. Ancak bizim örneğimizde kullanılmıyor benim de gördüğüm kadarıyla.

      Selamlar.

  9. Merhaba,
    SmartOp Class ‘ ında getSlotAndCardType metodundan kart tipi dönmüyor. Kart türlerine göre enum olarak kart tipini mi eklememiz lazım ?

    1. Merhaba hocam, açıkcası o DLL’in içerisindeki metotlara müdahale etmeyi gerektiren bir hata ile karşılaşmadım.
      Kullandığın e-imzanın işlemcisi nedir?
      E-devlete giriş yapabiliyor musun? Ya da Acrobat DC ile PDF imzalayabiliyor musun?

      Selamlar.

  10. Merhaba,
    SmarCardManager’ da aşağıdaki metod çalışınca
    “Özel durum bir çağırma hedefi tarafından oluşturuldu” hatası basıyor. İmza terminali gemalto. kurumda e imza ile belge imzalayabiliyorum.
    Pair slotAndCardType = SmartOp.getSlotAndCardType(terminal);

  11. Merhaba hocam, doğrusu bir fikrim yok.
    Uzaktan bağlanıp bakabilirim ama çözebileceğime emin değilim.
    GmailChat üzerinden yazabilirsin akşam 21’den sonra, eğer bağlanıp bakalım dersen.

    Selamlar.

  12. Merhaba,
    MA3 E-IMZA KÜTÜPHANESI .NET (CADES + XADES) örnek kodlarını indirdim ve gerekli düzenlemeleri yaptım fakat uygulamayı çalıştırdığım zaman SmartCardManager sınıfında 59. satırda hata alıyorum. Aldığım hata şu şekilde: System.TypeInitializationException: ‘The type initializer for ‘tr.gov.tubitak.uekae.esya.api.smartcard.winscard.Smart’ threw an exception.’
    Inner Exception
    Exception: Unable to establish smart card context

    Örnek kodların çalışabilmesi için de akıllı kart kullanmak zorunda mıyım? elimde test için kullanabileceğim akıllı kart yok, eğer test için de akıllı kart kullanmak gerekiyorsa nasıl temin ederim bilginiz var mı acaba?

Leave a Reply

Your email address will not be published. Required fields are marked *