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>
Örnek canlı kullanımını buraya tıklayarak deneyebilirsiniz. Bu örneğe ait kaynak kod bu sayfanın devamında verilmiştir.
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.
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.
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 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.
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"
}
]
}
Bilgi veya belgeye ait kaynak bilgilerini belirtir.
Kaynağa ait tekil bilgi. Zorunlu değildir, yanlızca kaynakları bir id numarası ile ayırt etmek için kullanılır.
Kaynağın bulunduğu adres veya base64 kodlu bilgi yada metin. Bu alan içeriğine göre sourceType alanını belirlemeniz gereklidir.
source alanının içeriğinin tipi
Kaynağın ekranda gösterilecek dosya adı. Zorunlu değildir.
Üretilecek imzanın biçimi. Belirtilmediğinde CadesBes kullanılır.
Kullanılacak özet algoritması.
Belge veya bilgi içeriği imza içerisine eklenmeli mi ?
Eğer kaynak imzalanmış ise Base64 kodlanmış imza içeriğini gösterir.
İmza oluşturulduktan sonra imzanın POST metodu ile gönderileceği adres. Belirtilmediğinde gönderim yapılmaz.
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.
İmzalama işlemi için kullanılacak sertifika filtrelerini içerir.
İmza talebine ait bilgileri içerir.
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"
}
}
İmza oluşturulduktan sonra gönderilen cevap bilgilerini içerir.
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
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>
Ü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>