WikiStart: idCard.js

File idCard.js, 12.6 KB (added by aaraujo, 9 years ago)

javascript library

Line 
1
2/*
3 * JavaScript library for signing in web browsers - version 0.20
4 *
5 * April 2014 (client library ver 0.20)
6 *              idCard.js       - Changed IdCardPluginHandler methods getCertificate(), sign() and getVersion() API and behaviour - the methods must now be used asynchronously with callback functions. Users of 0.14 version need to make changes in the client code to continue using the library (see also user manual for more information).
7 *                              - Added variable 'libraryVersion' which specifies the idCard.js library's version. It is strongly recommended to write the version information to log file during signature creation - additional information is provided in the documentation.
8 *                              - Added method getType() which returns the signing module's type (asynchronous or synchronous). It is strongly recommended to write the type information to log file during signature creation - additional information is provided in the documentation.
9 *                              - User manual "JavaScript library for Signing in Web Browsers" is now available in English.
10 *              sign.html       - sign.html sample application is now available in English.
11 *                              - changed the DigiDocService web service related steps to 'optional'
12 *                              - added idCard.js library's version to the heading section of the sample.
13 *                              - added the signing module's type information to the heading section of the sample.
14 *                              - added Lithuanian to the language selection dropdown.
15 *
16 *
17 * May 2013 (client library ver 0.14)
18 *              idCard.js - removed support for old plugin-s, default language is English
19 *
20 *
21 * May 2013 (client library ver 0.13)
22 *              idCard.js - old Mac OSX plugin (application/x-idcard-plugin) support removed
23 *
24 *
25 * 16 Mar 2012 (client library ver 0.12)
26 *              idCard.js - java applet support removed
27 *
28 *
29 * 7 Sept 2011 (client library ver 0.11)
30 *              idCard.js - bug fixes, see also header of idCard.js
31 *              sign.html - minor fixes
32 *              documentation - "Veebis signeerimise Javascripti klienditeek.doc" - added error codes and description of inner logic behind idCard.js
33 *
34 *
35 * 10 May 2011 (client library ver 0.10)
36 *              Bug fixes to idCard.js, sign.html, API documentation
37*/     
38
39
40
41/* ------------------------------------ */
42/* --- Variables and data structures --- */
43/* ------------------------------------ */
44
45//  version of the idCard.js library
46var libraryVersion = '0.20'; 
47
48var Certificate = {
49    id: null,
50    cert: null,
51    CN: null,
52    issuerCN: null,
53    keyUsage: null,
54    validFrom: "", // Certificate's "valid from" date, in format dd.mm.yyyy hh:mm:ss (Zulu time-zone)
55    validTo: null // Certificate's "valid to" date, in format dd.mm.yyyy hh:mm:ss (Zulu time-zone)
56}
57
58var getCertificatesResponse = {
59    certificates: [],
60    returnCode: 0
61}
62
63var SignResponse = {
64    signature: null,
65    returnCode: 0
66}
67
68//1..99 are error codes returned by the signing module
69var dictionary = {
70    1:  {est: 'Allkirjastamine katkestati',                     eng: 'Signing was cancelled',                   lit: 'Pasirašymas nutrauktas',                                  rus: 'Подпись была отменена'},
71    2:  {est: 'Sertifikaate ei leitud',                         eng: 'Certificate not found',                   lit: 'Nerastas sertifikatas',                                   rus: 'Сертификат не найден'},
72        9:  {est: 'Vale allkirjastamise PIN',                   eng: 'Incorrect PIN code',                              lit:'Incorrect PIN code',                                               rus: 'Неверный ПИН-код'},
73    12: {est: 'ID-kaardi lugemine ebaõnnestus',         eng: 'Unable to read ID-Card',                  lit: 'Nepavyko perskaityti ID-kortos',                  rus: 'Невозможно считать ИД-карту'},
74        14: {est: 'Tehniline viga',                                             eng: 'Technical error',                                 lit: 'Techninė klaida',                                                 rus: 'Техническая ошибка'},
75        15: {est: 'Vajalik tarkvara on puudu',                  eng: 'Unable to find software',                 lit: 'Nerasta programinės įranga',                              rus: 'Отсутствует необходимое программное обеспечение'},
76        16: {est: 'Vigane sertifikaadi identifikaator', eng: 'Invalid certificate identifier',  lit: 'Neteisingas sertifikato identifikatorius',rus: 'Неверный идентификатор сертификата'},
77        17: {est: 'Vigane räsi',                                                eng: 'Invalid hash',                                    lit: 'Neteisinga santrauka',                                    rus: 'Неверный хеш'},
78        19: {est: 'Veebis allkirjastamise käivitamine on võimalik vaid https aadressilt',               eng: 'Web signing is allowed only from https:// URL',                                   lit: 'Web signing is allowed only from https:// URL',                                   rus: 'Подпись в интернете возможна только с URL-ов, начинающихся с https://'},
79        100: {est: 'Teie arvutist puudub allkirjastamistarkvara või ei ole Teie operatsioonisüsteemi ja brauseri korral veebis allkirjastamine toetatud. Allkirjastamistarkvara saate aadressilt https://installer.id.ee',              eng: 'Web signing module is missing from your computer or web signing is not supported on your operating system and browser platform. Signing software is available from https://installer.id.ee',              lit: 'Web signing module is missing from your computer or web signing is not supported on your operating system and browser platform. Signing software is available from https://installer.id.ee',                              rus: 'На вашем компьютере отстутствует модуль для цифровой подписи в интернете или цифровая подпись в интернете не поддерживается вашей операционной системой и/или браузером. Программное обеспечение доступно здесь: https://installer.id.ee'}
80}
81
82// Variable for internal use in idCard.js
83var loadedPlugin = '';
84
85
86// Exception
87function IdCardException(returnCode, message) {
88    this.returnCode = returnCode;
89
90    this.message = message;
91
92    this.isError = function () {
93        return this.returnCode != 1;
94    }
95
96    this.isCancelled = function () {
97        return this.returnCode == 1;
98    }
99}
100
101// This function is meant for internal use, do not use in client code.
102function isPluginSupported(pluginName) {
103       if (navigator.mimeTypes && navigator.mimeTypes.length) {
104               if (navigator.mimeTypes[pluginName]) {
105                       return true;
106               } else {
107                       return false;
108               }
109       } else {
110               return false;
111       }
112}
113
114// This function is meant for internal use, do not use in client code.
115function checkIfPluginIsLoaded(pluginName, lang)
116{
117        var plugin = document.getElementById('IdCardSigning');
118
119        if (pluginName == "digidocPlugin")
120        {
121                try
122                {
123                        var ver = plugin.version;       
124                        if (ver!==undefined) {
125                                return true;
126                        }
127                }
128                catch (ex)
129                {
130                }
131
132                return false;
133        }
134        else // Other cases, e.g. pluginName == ""
135        {               
136                return false;
137        }
138}
139
140// Loads the signing module to browser
141function loadSigningPlugin(lang, pluginToLoad){
142
143        var pluginHTML = {
144                digidocPlugin:  '<object id="IdCardSigning" type="application/x-digidoc" style="width: 1px; height: 1px; visibility: hidden;"></object>'
145        }
146        var plugin;
147
148        if (!lang || lang == undefined)
149        {
150                lang = 'eng';
151        }
152
153        // It is checked if the connection is https during the signing module loading
154        if (document.location.href.indexOf("https://") == -1)
155        {
156                throw new IdCardException(19, dictionary[19][lang]);
157        }
158
159        if (pluginToLoad != undefined)
160        {
161                if (pluginHTML[pluginToLoad] != undefined) // Signing module with the specified name exists
162                {
163                        document.getElementById('pluginLocation').innerHTML = pluginHTML[pluginToLoad];
164
165                        if (!checkIfPluginIsLoaded(pluginToLoad, lang))
166                        {
167                                throw new IdCardException(100, dictionary[100][lang]);
168                        }
169
170                        loadedPlugin = pluginToLoad;
171                }
172                else
173                {
174                        // Throw exception to return information about incorrect signing module's name
175                        throw new IdCardException(100, dictionary[100][lang]);
176                }
177                return;
178        } else {
179
180                if ( // Special case for Mac+Safari combination, it must be checked if the signing module is installed in the user's system. Otherwise an error is shown to the user.
181                                (!(navigator.userAgent.indexOf('Mac') != -1 && navigator.userAgent.indexOf('Safari') != -1)) ||
182                                isPluginSupported('application/x-digidoc')
183                        )
184                {
185                        document.getElementById('pluginLocation').innerHTML = pluginHTML['digidocPlugin'];
186                        if (checkIfPluginIsLoaded('digidocPlugin', lang))
187                        {
188                                loadedPlugin = "digidocPlugin";
189                                return;
190                        }
191                }
192
193                // The signing module's loading was unsuccessful, throw exception
194                if (loadedPlugin===undefined || loadedPlugin=="")
195                {
196                        throw new IdCardException(100, dictionary[100][lang]);
197                }
198        }
199}
200
201// Returns ISO 639-1 compatible two-letter language code
202function getISO6391Language(lang)
203{
204    var languageMap = {est: 'et', eng: 'en', rus: 'ru', lit: 'lt', et: 'et', en: 'en', ru: 'ru', lt: 'lt'};
205    return languageMap[lang];
206}
207
208// Returns the signing module's type, possible values are 'SYNC' and 'ASYNC' (synchronous or asynchronous).
209function getType() {
210    return 'SYNC';
211}
212
213// This function is meant for internal use by the library
214function digidocPluginHandler(lang)
215{
216        var plugin = document.getElementById('IdCardSigning');
217
218    plugin.pluginLanguage = getISO6391Language(lang);
219
220        this.getCertificate = function () {
221                var TempCert;
222                var response;
223                var tmpErrorMessage;
224
225                try
226                {
227                        TempCert = plugin.getCertificate();
228                }
229                catch (ex)
230                {
231
232                }
233
234                if (plugin.errorCode != "0")
235                {
236
237                        try
238                        {
239                                tmpErrorMessage = dictionary[plugin.errorCode][lang];   // Exception is thrown if there is no respective element in the array
240                        }
241                        catch (ex)
242                        {
243                                tmpErrorMessage = plugin.errorMessage;
244                        }
245
246                        throw new IdCardException(parseInt(plugin.errorCode), tmpErrorMessage);
247                }
248
249                // Workaround for IE - in case the certificate is not returned in HEX format then the value is taken from certificateAsHex field.
250                if ((TempCert.cert==undefined)){
251                                response = '({' +
252                           '    id: "' + TempCert.id + '",' +
253                           '    cert: "'+TempCert.certificateAsHex+'",' +
254                           '    CN: "' + TempCert.CN + '",' +
255                           '    issuerCN: "' + TempCert.issuerCN + '",' +
256                           '    keyUsage: "Non-Repudiation"' +
257//                                 '    validFrom: ' + TempCert.validFrom + ',' +
258//                                 '    validTo: ' + TempCert.validTo +
259                           '})';
260                                response = eval('' + response);
261                                return response;
262                } else {
263                        return TempCert;
264                }
265        }
266
267        this.sign = function (id, hash ) {
268                var response;
269                var tmpErrorMessage;
270
271                try
272                {
273                        response = plugin.sign(id, hash, "");
274                }
275                catch (ex)
276                {}
277
278                if (plugin.errorCode != "0")
279                {
280
281                        try
282                        {
283                                tmpErrorMessage = dictionary[plugin.errorCode][lang];   // Exception is thrown if there is no respective element in the array
284                        }
285                        catch (ex)
286                        {
287                                tmpErrorMessage = plugin.errorMessage;
288                        }
289
290                        throw new IdCardException(parseInt(plugin.errorCode), tmpErrorMessage);
291                }
292
293
294                if (response == null || response == undefined || response == "")
295                {
296                        response = '({' + 'signature: "",' + 'returnCode: 14' + '})';
297                }
298                else
299                {
300                        response = '({' + 'signature: "' + response + '",' + 'returnCode:0' + '})'
301                }
302
303                response = eval('' + response);
304
305                if (response.returnCode != 0) {
306            throw new IdCardException(response.returnCode, dictionary[response.returnCode][lang]);
307        }
308        return response.signature;
309        }
310
311        this.getVersion = function () {
312                return plugin.version;
313        }
314}
315
316// Provides the main functionality for signature creation
317function IdCardPluginHandler(lang)
318{
319        var plugin = document.getElementById('IdCardSigning');
320        var pluginHandler = null;
321        var response = null;
322
323        if (!lang || lang == undefined)
324        {
325                lang = 'eng';
326        }
327
328        this.choosePluginHandler = function () {
329            return new digidocPluginHandler(lang);
330        }
331
332    // Get the signer's certificate from the smart card
333        this.getCertificate = function (successCallback, failureCallback) {
334
335                pluginHandler = this.choosePluginHandler();
336        try {
337                    var result = pluginHandler.getCertificate();
338            successCallback(result);
339        } catch (e) {
340            failureCallback(e);
341        }
342        }
343
344        // Get the signature value from the smart card
345        this.sign = function (id, hash, successCallback, failureCallback) {
346
347                pluginHandler = this.choosePluginHandler();
348        try {
349             var result = pluginHandler.sign(id, hash);
350             successCallback(result);
351        } catch (e) {
352            failureCallback(e);
353        }
354        }
355
356        // Get the signing module's version
357        this.getVersion = function (successCallback, failureCallback) {
358
359                pluginHandler = this.choosePluginHandler();
360        try {
361            var result = pluginHandler.getVersion();
362            successCallback(result);
363        } catch (e) {
364            failureCallback(e);
365        }
366        }
367
368}