Kolay Imza Geliştirici Dokümantasyonu

Kolay İmza Nasıl Çalışır ?

Kolay imza “sign:…” adresi ile başlayan bir protokol kullanır. Bu adresi ister web uygulamanız içerisinde isterseniz de desktop uygulama içerisinden çağırarak kolay imzayı başlatabilirsiniz. Sign adresi içerisine imza atılacak belge ve bilgilere ait talebin bilgileri yer alır. Bununla ilgili bilgiler aşağıda detaylı olarak anlatılacaktır ama önce kolay imzayı nasıl başlatacağımıza bakalım.

Web uygulaması içerisinde kolay imzanın başlatılması. HTML içerisinde aşağıdakine benzer bir şekilde bir link yerleştirmeniz yeterlidir.

<a href="sign:XXXX">İmzala</a> 

Nasıl Çalışır ?

UygulamaKolay İmzaİmza talebioluşturulur.İmza talebi sign adresi ile kolay imza'ya gönderilir.İmza isteğiincelenir.Gerekiyorsa imzalanacak belgeler ağ üzerinden indirilir.İmzalama işlemitamamlanır.İsteniyorsa imza içeriği gönderilir.İsteniyor ise toplu imza cevabı gönderilir.UygulamaKolay İmza

Canlı Kullanım

Örnek canlı kullanımını buraya tıklayarak deneyebilirsiniz. Bu örneğe ait kaynak kod bu sayfanın devamında verilmiştir.

İmza Talebi Nasıl Oluşturulur ?

Web tabanlı uygulamalar için imza talebini uygulamanız içerisinde kullanıcının tıklayarak başlatacağı bir adres oluşturarak başlatabilirsiniz. Masaüstü uygulamalar uygulamalar için lütfen Masaüstü Yazılım ve Yerel Dosya Erişimi başlığına bakınız.

İmza talebinini imzalanacak bilgileri içeren adresi belirterek veya imzalanacak bilgileri kodlayarak Kolay İmza’ya gönderebilirsiniz.

Adres ile Başlatma

JSON cevabı gönderecek olan adresi ?xs=<adres> şeklinde belirtebilirsiniz.

<a href="sign://?xs=http://localhost/app/file.aspx?id=123&op=request">İmzala</a>

Bu örnekte file.aspx dosyasının aşağıdakine benzer bir Request tipinde bir JSON geri göndermesi beklenir.

{
    "resources" : [
        {
            "source" : "http://localhost/app/file.aspx?id=123"
        }
    ],
    "responseUrl" : "http://localhost/app/file.aspx?id=123&op=response"
}

resources içerisinde imzalanmasını istediğiniz kaynaklara ait bilgiler yer alır. Birden fazla kaynak belirterek aynı anda birden fazla belgenin imzalanmasını sağlayabilirsiniz. Belge içeriğini örnekte olduğu gibi bir adres vererek veya base64 kodlu şekilde JSON içerisinde gönderebilirsiniz.

Direk Başlatma

Alternatif olarak Request JSON objesini aşağıdaki örnekteki gibi base64 kodlayarak adres içerisinde de gönderebilirsiniz.

<a href="sign://?xsjson=eyJyZXN.....zZSJ9">İmzala</a>

Bu yöntemi tercih ederseniz aşağıdaki gibi bir java script kodu ile adresi üretebilirsiniz.

$(document).ready(function() {
    var link = btoa(JSON.stringify({
        "resources" : [
            {
                "source" : "http://localhost/app/file.aspx?id=123"
            }
        ],
        "responseUrl" : "http://localhost/app/file.aspx?id=123&op=response"
    }));    
    // $('a.imzala').attr('src', link);
}

Bir çok internet gezgininde btoa fonksiyonu türkçe karakterler ile ilgili problem çıkardığı için gerekiyor ise alternatif bir base64 çevirici kullanmanızı öneririz.

İmza Geri Nasıl Alınır

İmza talebi oluşturulurken aşağıdaki örnekte olduğu gibi resource objesi üzerinde targetUrl belirttiyseniz imzalı bilgi yada belge standart dosya upload yöntemine benzer şekilde POST yöntemi ile belirttiğiniz adrese gönderilecektir. Bu adresin imzalı bilgiyi veri tabanına kaydetmesi beklenir.

{
    "resources" : [
        {
            "source" : "http://localhost/app/file.aspx?id=123",
            "targetUrl" : "http://localhost/app/file.aspx?id=123",
            "format" : "CadesBes"
        }
    ]
}

Bunun dışında imza talebi içerisinde responseUrl belirtilmiş ise tüm imza detayları bu adrese JSON formatında aşağıdaki şekilde gönderilecektir.

{
    "certificate": "MIIG+zCCBe....BYsjR1L384",
    "certificateIssuer": "Nitelikli Elektronik Sertifika Hizmetleri",
    "certificateName": "SELAHATTİN BOSTANCI",
    "certificateSerialNumber": "4.......2",
    "createdAt": "2016-02-10T14:19:19.5071679+03:00",
    "resources": [
        {
            "attachSource": true,
            "digest": "Sha256",
            "signature": "MIAGCSqGSI....AAAAAA",
            "source": "http://localhost/app/file.aspx?id=123",
        }
    ]
}

Request objesi üzerindeki responseUrl ve Resource üzerindeki targetUrl adreslerinin her ikisi de zorunlu değildir. İkisini de aynı anda kullanabilir veya herhangi birisini belirleyebilirsiniz. İkisi de belirtilmediğinde imza oluşturulur ancak gönderim yapılacak bir yer olmayacağından uygulama otomatik kapanacaktır.

Masaüstü Yazılım ve Yerel Dosya Erişimi

1.7 Versiyonundan itibaren internet tarayıcılar dışındaki masaüstü yazılımlarda kolay imzayı başlatmak üzere aşağıdaki şekilde imza talebini argüman olarak belirterek başlatabilirsiniz.

C:\Program Files (x86)\KolayImza\AltiKare.KolayImza.exe c:\imza.json

Parametre olarak “Imza.json” dosyası imza talebi olan Request modeli ile aynı tiptedir.

Imza talebi içerisindeki url içerisinde yerel dosya yolunu belirtilebilirsiniz. Ancak yerel dosya erişimi söz konusu olduğunda kullanıcı bu işlem ile ilgili bir uyarı mesajı alacaktır. Kullanıcının işleme izin vermesi ile ancak imzalama işlemi tamamlanır.

{
    "resources" : [
        {
            "source" : "c:\\dizin\\dosya.pdf",
            "targetUrl" : "c:\\dizin\\imzalidosya.pdf",
            "format" : "PadesBes"
        }
    ]
}

JSON Modelleri

Resource

Bilgi veya belgeye ait kaynak bilgilerini belirtir.

id: string

Kaynağa ait tekil bilgi. Zorunlu değildir, yanlızca kaynakları bir id numarası ile ayırt etmek için kullanılır.

source: string

Kaynağın bulunduğu adres veya base64 kodlu bilgi yada metin. Bu alan içeriğine göre sourceType alanını belirlemeniz gereklidir.

sourceType: string ∈ { Binary, PlainText, Url }

source alanının içeriğinin tipi

sourceName: string

Kaynağın ekranda gösterilecek dosya adı. Zorunlu değildir.

format: string ∈ { CadesBes, CadesT, CadesX, CadesA, PadesBes, PadesT, SMime }

Üretilecek imzanın biçimi. Belirtilmediğinde CadesBes kullanılır.

digest: string ∈ { Sha1, Sha256, Sha384, Sha512 }

Kullanılacak özet algoritması.

attachSource: boolean

Belge veya bilgi içeriği imza içerisine eklenmeli mi ?

signature: string

Eğer kaynak imzalanmış ise Base64 kodlanmış imza içeriğini gösterir.

targetUrl: string

İmza oluşturulduktan sonra imzanın POST metodu ile gönderileceği adres. Belirtilmediğinde gönderim yapılmaz.

pdfOptions: object

PDF dosyaları için yerleştirilecek imza görüntüsünün özelliklerini belirler. Belirtilmediğinde imza kutusu görünür olmayacaktır.

signatureName: string

PDF içerisinde görüntülenecek imza adı.

reason: string

İmza nedeni

location: string

İmzanın atıldığı yer.

x: integer

İmza kutusunun yerleştirileceği X pozisyonu.

y: integer

İmza kutusunun yerleştirileceği Y pozisyonu.

width: integer

İmza kutusunun genişliği.

height: integer

İmza kutusunun yüksekliği.

CertificateFilter

İmzalama işlemi için kullanılacak sertifika filtrelerini içerir.

serialNumber: string
Sertifika içerisindeki TC Kimlik No. Belirtilmediğinde tümü kullanılır.

Request

İmza talebine ait bilgileri içerir.

id: string
Yapılan istek için belirlenecek tekil numara.
resources: Resource[]
İmzalanması istenen kaynakların listesi. Birden fazla belirtilerek aynı anda birden fazla imza atılması mümkündür.
timestamp: object
Zaman damgası kullanılacak ise erişim bilgilerini içerir. Belirtilmediğinde kullanıcı seçeneklerinde belirtilen zaman damgası kullanılacaktır.
url: string
Zaman damgası sunucusunun adresi.
user: string
Zaman damgası sunucusuna gönderilecek kullanıcı adı.
password: string
Zaman damngası sunucusuna gönderilecek kullanıcının şifresi.
createdAt: string (dateTime)
İmza talebinin oluşturulduğu tarih ve saat.
responseUrl: string
İmza oluşturulduğunda cevabın geri gönderileceği adres.
certificateFilter: CertificateFilter
Kullanılması istenen sertifika filtresi.

İmza Talebi Örneği

Aşağıda request objesinin bir örneğini bulabilirsiniz.

{
    "resources" : [
		{
			"id" : "Imza1",
			"source" : "İmzalanacak metin",
			"sourceType" : "PlainText",
			"digest" : "Sha256",
			"targetUrl" : "http://myserver/imza.php"
		},
		{
			"id" : "Imza2",
			"source" : "http://myserver/dosyadownload.php",
			"targetUrl" : "http//myserver/dosyaupload.php"
		},
		{
			"id" : "Imza3",
			"source" : "http://myserver/dosya.pdf",
			"targetUrl" : "http://myserver/imzalidosya.pdf",
			"format" : "PadesBes"
		}
	],
	"certificateFilter" : {
		 "serialNumber" : "1234567890"
	}
}

Response

İmza oluşturulduktan sonra gönderilen cevap bilgilerini içerir.

id: string
Yapılan isteğe ait tekil numara.
resources: Resource[]
İmzalanan belge ve bilgilerin arrayi
certificate: string
İmzayı oluşturan Base64 kodlanmış sertifika bilgisi.
certificateName: string
İmzayı oluşturan sertifikanın adı.
certificateIssuer: string
İmzayı oluşturan sertifikayı çıkaran yer adı.
certificateSerialNumber: string
İmzayı oluşturan sertifikanın seri numarası. Nitelikli olmayan sertifikalar için bu alan boştur.
createdAt: string (dateTime)
İmzanın oluşturulduğu tarih ve saat.

Konsol Penceresi

Uygulama içerisindeki yapılan işlemlerin kaydına ve detaylı hata bilgilerine ulaşmak istiyorsanız, konsol penceresinin görüntülenmesini sağlayabilirsiniz.

Kurulum sonrasında HKEY_CLASSES_ROOT\sign\shell\open\command kütük kaydına /console parametresinin eklenmesi yeterlidir. Alternatif olarak aşağıdaki bilgileri .reg dosyası olarak kaydedip, çift tıklayarak kaydın yapılmasını sağlayabilirsiniz.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\sign\shell\open\command]
@="\"C:\\Program Files (x86)\\KolayImza\\AltiKare.KolayImza.exe\" \"%1\" /console

C# Kullanım Örneği

Bu örnekte yukarıda anlatılan tüm işlemlerin bütününü içeren file.aspx adlı bir sayfa görmektesiniz. Bu sayfa aracılığı ile imzalanacak bilgileri ve imzalandıktan sonra yapılacak işlemleri kendi taleplerinize göre uyarlayabilirsiniz.

<%@ Page Title="" Language="C#" %>
<%@ Import Namespace="System.Threading" %>

<script runat="server" language="c#">

    private string GetUrl(string query)
    {
        return Request.Url.GetLeftPart(UriPartial.Authority) + this.ResolveUrl("~/file.aspx?" + query);
    }

    class EventData
    {
        public EventData()
        {
            this.SignatureReceived = new ManualResetEvent(false);
        }

        public ManualResetEvent SignatureReceived { get; set; }

        public string Data { get; set; }
    }

    static Dictionary<string, EventData> events = new Dictionary<string, EventData>();

    protected override void OnLoad(EventArgs e)
    {
        var url = this.Request.Url;
        var operation = this.Request["op"] ?? "";
        var id = this.Request["id"] ?? "";

        switch (operation)
        {
            case "wait":
                {
                    EventData eventData;

                    this.Response.Write("İmza bekleniyor");
                    this.Response.Write("<scri" + "pt type=\"text/javascript\">");
                    this.Response.Flush();

                    if (events.TryGetValue(id, out eventData))
                    {
                        if (eventData.SignatureReceived.WaitOne(TimeSpan.FromSeconds(3)))
                        {
                            this.Response.Write("alert('");
                            this.Response.Write(eventData.Data);
                            this.Response.Write("');");
                        }
                        else
                        {
                            // refresh page
                            this.Response.Write("window.location = '" + url + "';");
                        }
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(3000);
                    }

                    this.Response.Write("</scri" + "pt>");
                    this.Response.End();

                    break;
                }
            case "request":
                {
                    var request = "{" +
                    "   \"id\":\"" + id + "\"," +
                    "   \"resources\": [" +
                    "       { " +
                    "         \"source\" : \"" + GetUrl("id=" + id + "&op=content") + "\", " +
                    "         \"sourceName\" : \"sample.txt\", " +
                             "\"format\": \"CadesX\"" +
                    "       }" +
                    "   ]," +
                    "   \"responseUrl\": \"" + GetUrl("id=" + id + "&op=response") + "\"" +
                    "}";

                    if (!events.ContainsKey(id))
                    {
                        events[id] = new EventData();
                    }

                    this.Response.ContentType = "application/json";
                    this.Response.Write(request);
                    this.Response.End();
                    break;
                }

            case "content":
                {
                    this.Response.ContentType = "application/octet-stream";
                    this.Response.Write("hello");
                    this.Response.End();
                    //this.Response.TransmitFile(filePath);
                    break;
                }

            case "response":
                {
                    EventData data;

                    if (events.TryGetValue(id, out data))
                    {
                        using (var textReader = new System.IO.StreamReader(this.Request.InputStream))
                        {
                            data.Data = textReader.ReadToEnd();
                        }

                        data.SignatureReceived.Set();
                    }

                    this.Response.End();
                    break;
                }
        }

    }

</script>
<html>
<head>
    <script src="https://code.jquery.com/jquery-git.min.js" type="text/javascript"></script>
</head>
<body>
    <a href="#" class="imzala">İmzala</a>
    <script type="text/javascript">
        $(document).ready(function() {
            $('a.imzala').on('click', function () {
                $('<iframe></iframe>').appendTo('body').attr('src', 'sign://?xs=<%=GetUrl(HttpUtility.UrlEncode("id=123&op=request"))%>');
                window.location.href = '<%=GetUrl("id=123&op=wait")%>';
            });
        });
    </script>
</body>
</html>

PHP Kullanım Örneği

Üstteki C# örneğine benzer şekilde aşağıda benzer işlemleri yapan bir PHP örneğini bulabilirsiniz. PHP ortamının doğası gereği imza cevabı hafızada tutulamadığından geçici olarak sig.json isimli bir dosyaya kaydedilmektedir.

<?php
function getUrl($query)
{
    return 'http://' . $_SERVER["HTTP_HOST"] . '/api/file.php?' . $query;
}

$op = isset($_GET['op']) ? $_GET['op'] : '';
$id = isset($_GET['id']) ? $_GET['id'] : '';

switch ($op) {
case '':
    if (file_exists('./sig.json'))
      unlink('./sig.json');
    break;
case 'wait':
    ob_start();
    echo '<html>';
    echo '<body>';    
    if (file_exists('./sig.json')) {
      echo 'imza alındı';
      echo '<script>';
      echo "alert('" . file_get_contents('./sig.json') . "');";
      echo "window.location = '" . getUrl('') ."';";
      echo '</script>';
    } else {
      echo 'imza bekleniyor';
      sleep(3);
      flush();
      echo '<script>';      
      echo "window.location = 'http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]';";
      echo '</script>';
    }    
    echo '</body></html>';
    return;
    break;
case 'request':
    header('Content-type: application/json');
    echo '{';
    echo '  "id":' . $id . ',';
    echo '  "resources": [';
    echo '    {';
    echo '    "source" : "' . getUrl("id=" . $id . "&op=content") . '",';
    echo '    "sourceName" : "sample.txt"';
    echo '    }';
    echo '  ],';
    echo '  "responseUrl": "' . getUrl("id=" . $id . "&op=response") . '"';
    echo '}';
    return;
    break;
case 'content':
    header('Content-type: application/octet-stream');
    echo "hello";
    return;
    break;
case 'response':
    $data = file_get_contents('php://input');
    json_decode($data); // ensure json
    file_put_contents('./sig.json', $data);
    return;
    break;
}

?>
<html>
<head>
    <script src="https://code.jquery.com/jquery-git.min.js" type="text/javascript"></script>
</head>
<body>
    <a href="#" class="imzala">İmzala</a>
    <script type="text/javascript">
        $(document).ready(function() {
            $('a.imzala').on('click', function () {
                $('<iframe></iframe>').appendTo('body').attr('src', 'sign://?xs=<?=getUrl(urlencode("id=123&op=request"))?>');
                window.location.href = '<?=getUrl("id=123&op=wait")?>';
            });
        });
    </script>
</body>
</html>