Cryptographic operations sample¶
This full sample code demonstrates how to monitor reader events, populate a list from the certificates found in smart cards, verify a PIN, and perform signature, verification, encryption and decryption operations. Note that, for the operations made on the public key (verification and encryption), the public key is extracted from the certificate data and the cryptographic operation is computed in pure JavaScript, using the BSD-licensed Forge library.
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Titre de la page</title>
<script src="libs/forge.min.js"></script>
<script src="libs/promise-polyfill.js"></script>
<script src="../src/scwsapi.js"></script>
<script>
var privateKeys = {};
window.webappcert = "3WKVAuegUKJv}6.5vrlH2yJKIDd@n{fvTh{3B8#hpvR^OCB8LVjBz>@azy^qVx>Ir{zEWZjAc9TxCYkY0fF$QugbyTod}ryfwO#PYwi8y}xMOuniXJcvfFkare?]7kf/7NCf!$KwenfcEA5]T9f!+jnh7*Qre?]mwiX-xCg+rrZBz%n]fekjve?![ie?]ywgby:rxMOuniXJcviwJiwhAirzhzu:rf/IcFgby=8zl.77]a3uEmc@vMWs#=I-EbPF*EX14Y?t3CHGEgPU>q$!DZ*37zk-VBWplV.EQkEqWNo=%UyaK)6DHS2BM:6Ahf^Fp[Qj0W^a/1P]pG5#4=:P8lt@W&5L:itH<kVH5NKs*i&qbr@lBo[pPj0fvW0*]}NEm^NI?QxI.&!XJ)AKCE6E&$vfabiIlIn5am4t$r?GOIl[JoAU#.{1kF89-vG4}O=9J]egOW7Jw:>oq@fVKpmJaExQ2uU:Ah:)C=*9iC)5}.MyC?V<0KBec::^n?q%nnwb9i-XijWRH?sS:D>QIkWLJUDLYpT&5(VfJ6tc&*+H*U4hhuFHUQX4PS5<2YND^tFT9#R(=eA]>OM^9b-wPJ(YAg}-av%&ir*K/.h|MIIE5jCCAs6gAwIBAgIBADANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJGUjEdMBsGA1UEAwwUSWRvcHRlIFdlYkFwcENlcnQgQ0ExDzANBgNVBAoMBklkb3B0ZTAgFw0yNDA3MTUwOTU4MjFaGA8yMDUyMTIzMTIyNTkwMFowMTESMBAGA1UEAxMJTWF4aW1lRGV2MQ8wDQYDVQQKEwZJZG9wdGUxCjAIBgNVBAsTATAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDbbHFzPMOgflE7NLWtYXK0MV8xCLbSZ7qvUug0YdYSwiw9XDXe5uODG2ok9C1YrlSVuQ0O73CC07RqSys2XFsx6hW82JuwN+gEqJ+v+BKW3YQgT7NOzIRrvhucSo4UWrAZV6YXhd/1GZyYyyI1x3K1e1y/1p3Zw8nKAGeIP8vSQvSA7da124DOx860AXvF3eRUyonMEZagnPyueVVy0wodO1u1WRMjVN+f91FUhtbRf+u5am0vU+IZCE5Lv/ALghr0r3QqLAvHMlhe4uw9BmPCWQH7d/fdIbcZf7eDxWizei2dfl/dMh95f2RTGzE/Hnt56IVYvOT4kR5AU95gwCHAgMBAAGjgfowgfcwCQYDVR0TBAIwADAXBgNVHSUEEDAOBgwrBgEEAYHYJAECAgEwXgYDVR0gBFcwVTAPBg0rBgEEAYHYJAECAQEBMA8GDSsGAQQBgdgkAQIBAQMwDwYNKwYBBAGB2CQBAgEBBDAPBg0rBgEEAYHYJAECAQEGMA8GDSsGAQQBgdgkAQIBAQcwcQYDVR0RBGowaIYYaHR0cDovLzEwLjI1LjExLjEzMjoxMjM0hhhodHRwOi8vMTAuMjUuMTEuMTY1OjEyMzSGFWh0dHA6Ly8xMjcuMC4wLjE6MTIzNIYbaHR0cDovLzE5Mi4xNjguMTYwLjExNzoxMjM0MA0GCSqGSIb3DQEBCwUAA4ICAQA5hyRPrhPV8OhYfOxa5+mQoBi0n/m42nWotehg5QJmzUzDTDnZLgEV7t/9dVsNX8uh1t88Kgkbb98vAmgWHpslH++5P1jp9WQfNG9gzASpSglcTXF2BHblKH7oDJ5LMhXtGikUR13TuoK4iPvZxSweIeK5JZ7kMydOgFbj5xlk+rLSqqP+tebS6bOMSzUWKGwgaBQbS3sZ8B6IOhROGxbXxVQZ2vJ94meqmTG/qSoJa3vhf9kOxJLSdxCNdeuLlkIDHEqnHMMQHfnZztJ3dVt/rybr99Qx0IvW248jgRMoD39EeFYVya1sNB2LkAAeqnoVeUlotCW9F8JA3gVo/BFzoy46/vUDrrFUMvGQXWkdHga7PYwf8NHFjLO+o9R2ehATCHNykfmgbE6u+RuKJx3vqoM3MGaVa/OI1P9Jrha8/wGt5hkIMuEW0/n5w5UBs2NuUbMia+9abUy2EQxWJ2Nd4fJfmpvcsf/I1I9J0RuuBKNRcElnidBlK8tkGCw+gMv8T4H0njRoSSmo6dku8PEl71sLiorGdJddA9VRKorj2md3SW6IbeszPZM2/b/EVM4p0HPR6OV/PJruLcSqte8KaBwfsu9/s0e6FrNfhpkqnk+8asXPWSteCi3w3lo0578XQsHuIDHG8P6Dqhv4AtC+GUrhXdaFGWSZcmO9CyqU0w==";
//window.webappcert = "4gM?:G)lz^:r^BM:=BP.0{6YMM2.Vg{fOpeIjyU4cFud+E@>=ZFNFL]oK$eUW]/F?^z1gFmHj(KdQ15QEa(Vo/j*t3+b3Qnz/744vSt6UNj(Wt^R/ba5m#I/{U@)]HzXNcH:Nf}nR=)ansje.px01U1I8zGTx>O7zT}QieR7gwYPjITMoxtu799.8!LEGF?MhB$o&Ygz{<5dHkifW(9FJ6icJvxKbm<+xG1Qa%p>-J@6Q%czJ-/h@.b(XWkFA/1&u(7&=LvUB%tliH/kd3<5rcfryG]]+WZ&<^&[I[{l<xucJUM8fQHb]:cEeB*xbMzn+";
// http://127.0.0.1:1234,http://10.25.11.150:1234
window.password = "yyoussef";
window.p12 = "30820A5E02010330820A2406092A864886F70D010701A0820A1504820A1130820A0D3082049F06092A864886F70D010706A08204903082048C0201003082048506092A864886F70D010701301C060A2A864886F70D010C0106300E0408EB8314818F8957E202020800808204584FD52765C18CF4EB7EE6F030C0D07EFECF901115D923DA104E80457E39AB58ED6D075F59EB02165DF36D6E674B80F313777F4675DA0F7E767F441D0B327AE13D347C54019BF3EEDFEDF574D2FFCDBFF09ABF66C70834E67053C57722DBEB9D37CC4E1A0624197BA8453BC7269AF210F27DFB290B16FD375DDDD36140506811412BFBAD8D3C70D1A8D3CC56BE973870B0E5D8A656E05777155A424E2E6147C66DD56EC2B844ACC8C1CBDAAEFF49FB991EBB4114422893D181ED52A1BE59B499AF0E7A2F8DE49C3C1DC4F96B4C93E342F8232D9A51949D6E2FB4B1F63D0D19196771E43B8CB0B3D849CF32DEEB62521D71318C3E35275FE00B269FE0F61768C7100D7C42DFC5E2E3CF64E56CA223CC2979EB3F9AA6B18216778F30368F06601790C7E162C8888C5FE0E29DB0DBCBE647487515A578462360DCC084C005B482EE6AF26A0B16AE61E293626D9000B370B682C3DB3514A8060600FD5AB3BE9A46C507CF69F972BA55CFF3AF6B11AFB120B7B1D917A8FB724AB3A15E799BCAF3A8DE493C141D20E7598645C3F8DA624F71C1EFC9CBE38C25666F469DA55DE4E397E76328EA2A1EA66F7C04877688C740CB68FEA034BE852300B40528E3161B7059FA2B2744846E95FED4D11474D769276FBAF61798D5B9468C48E21B5908076A80687ACB2A794F5180A2C4EE3B08E7A4C68BC58E2CC4A701B8FF0686385552A568B727998E0DFCD656DD8D5DA147A88AF0F72A3C92A08E3D03AEE504BCFA514D047A496C3E23211DFB54C2802C060202E9D10B06A929280061728D89612CE88563129669630B188D28193CE351B2544EC6155BD9EBA706804325C37972DEAFD99716E16AEA8EFE8B37DAA419E38C09515EF01C773B0BCD890CA3646FAF7B208B16033ADFBE91DCB7903EDA3C4A91D2DD210EBA5D434091F7189176A83730892CC70D35D3DF14EF0C6E7D8C45D0FFC6A409D9BD5A37A3F6EC8EAC0E56C30EAA2D276FBBB3382430908F8AEE21C9BC190DA25A7B5CDA3877C0FD7E14DCF2EF52991F87A3C805AE989EFAD89EFB76C17ED76E8416CC0089887794EDC2757D93EE81C70F7A79F705128CB487598F0C59CA1017A4F38F1270A2BB219BC26DB91DBE566720BF81D591FEC6F8166FAFBD6C8A3EF85D70AAE768908EE00A3C3053AD9C5FF57F09E70D14D33B934C946399FEBBB35096208B396B1D5526C038E704F670F804B095BC41D6EE6AB189A2C559170ED016E9FFA4BA2E153FA8635B17CE079342672CBDD7960B47527C2D3AB01916A82F86DF0CDBE8B0F123A5FE85812037450F9A5180D102B147EE6FD3A814D1872E060AA7D197FB0E07E874F92D34EE21416C0EA759C366FBBDE9E32209F72AEEBD7630C4FBA02C5F5DC7D908085C1C9B71DF34F072C95BAF2052808C7ADCC55162DE757AD53DE29EDE16EF009C3B836FC60251A5D49A075D86F86A2164F38CFE983FE571B6541B7B8B6A5C4CC09E64F4B19A829F3D67B9838779D1DF813A248ED21011610137C89272881E0D2F048B98DADF823F33DCB5EDBC5994EFBDB628341EFB1B2B699D8CEB77FDEE94773082056606092A864886F70D010701A0820557048205533082054F3082054B060B2A864886F70D010C0A0102A08204EE308204EA301C060A2A864886F70D010C0103300E0408FF988A81108A8C1602020800048204C88549F8E681336AF34A8822F0921A55FA2A718DBCB5D2B5A0733EEC24A757218DA1DA64BC73810C0217F58C6AEB8A2D5C5FB75BB0629153155A60C339734E00665D88229F96DD084D28F98BCA63E9B9353FA8F48751D164A12296DFCB38435A914EF90D1AC95E482636320FC71E8FAFD60227E8C07BB2B56D0444CF1548A87E80E315D644BE7462781E1E909C5D08D9730B4F26D2AAE68B7F8F0BFEB0CEAC08A0894B751AD52F0BCAE13FCAF2E3EF38F1C0931BADF3502D0BB0B8D803F8BC11134724B3A7320ED43BBEEF2800DFE699B677A188E12CFDD020FFFBA5751C16E779D03F99847CB3635AE9BF55BB50BBC81608D5B3E55E5C3F8686335604B24B861CCED7E02723052692A864897AB07342D6699A3938535F46833276B441B20B03BA546D6682C70A000DBE9AC208B23462BC91956BEBA7BB8A6A8F7737445B77E9D797237D9AFF31445ABD7F7A7DDE013E1EF23200137A826C3328341AFB362EBE18E0F2A2CB5DA294AD75A671E410D46BB3863501038A93CD4C254ADE0EC911D9E0EEFFFD16072BC4E1D2F881A7E1B449C18AEDC339BE1054EEC874F47B21CB2D0E27A6B9D00517468DAF209CD85A2A15F1E020FE3464D133CECF173F8075A3407BF3CCB5C5BAE26756338893A406A3EA4F09993D62C1A8495F74FAEF373B1CBEF5341324C7098E28F9FDF9824A357AEF67367C9676F228342D1DC9EC63AB9B73246BD0A770D4A64590043D055C41B718EE443E612AF2DCE5B0223AF5E9B6D9AD2BD1DCA2DBC6FE63BD6BAD2EBCC9E6F6605C8EFAF92CD92D08F1D0CD960EA517618C00B90E72879CB950BB0739091DB180308C66BA360899D457558877776A8CA375615CEAFB7DB8A7FDAC94AB52544FC87535129D42015F8E379B24F44D3D1C8629C0FDBED8A5F06EAFBDF386F60D0DA566EABE8B7F4B39C1A8E54ED285452EDA410E7719548A45A6024A221C698B306A55047F6837B0D2E35669F4A8705256757276F7BBFF8DC5CEFFDEB8E05BF019581D18FC788C0D1BB1418A978C654D7950E8ADB9D394F0360A54824862D809E3ADC5EAF7C7602F65A40758EAFCDFC6EF7824E8DC6DE40BBB4269F8E3578FF7157FA5F1BD19B0205BB50ADA7CCCF2D3AE631F5EF25F5E86B4BDB25F9A068613A1CAA76B3788F2A35BC5CD8D072105D7168EC533ABA1859CEA2904CAAA02C2719B7F1832E0AA52819492E3464BCA2260DB34650E1B2421F0D1C885CA9981A6D1BA5BE87E85CF02F6102485B7D672019931A7A7E58B33C81E0E8D139ACF0957765BCC90B147A77E3AF3E680A7DF6006FF3DD5EBCBE1C6F762A661594DDD8F012C1F8B907DF6511E41A98AABE1D93437B2C1DF09387C09B97840D1B6FCCE60096D942485BEBB2D525AD96108636AA18732B24DA59C6271690ABAD068305B8DA33974171B70F359199ACE68C140273DD7C5B98D54258D7232DC18DAE6389564A1C9E8515E57BDF05531697C8A5547AF868B24F67832A96EAA71395739651B727533EAAB53794AEAFE7EF0E89E4C8FF1C9DB3CBA3F68881B8F0B7857F2A226BFD8403ABD03ACF2FCFC18D545E47A84E846645B0B0F608D251A890B6ECCD6E8634FDF7F01E2C1145841D2A089C63B588DC6900E60DD359382AF53FD302579DD9733885D76BAF339565B52A28BEF147E4D2BEFA3668A6B99B7FC034FFA07BFAC6844CF1AD743F875B6CD9E47F6612A9AF7B0C051C568B82F41BD7130CD314A302306092A864886F70D01091431161E140079006F00750073007300650066005F00760033302306092A864886F70D01091531160414E7D7343D5B87A9E7F4B6D87353270FD8B3A89B0630313021300906052B0E03021A05000414EB2034DB2BE189DBF87422063FB6EBF5C46C4057040886C2012A3342832A02020800";
window.certificate = "-----BEGIN CERTIFICATE-----\n MIIDNDCCAhwCCQDWfPjiGAVE3DANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJGcjEPMA0GA1UECAwGVmllbm5lMQ8wDQYDVQQHDAZWaWVubmUxDzANBgNVBAoMBklkb3B0ZTAeFw0xODA1MzExMDIxNTNaFw0yMjA1MzExMDIxNTNaMHgxCzAJBgNVBAYTAkZyMQ8wDQYDVQQIDAZWaWVubmUxDzANBgNVBAcMBlZpZW5uZTEPMA0GA1UECgwGSWRvcHRlMQ4wDAYDVQQDDAVaSVRBTjEmMCQGCSqGSIb3DQEJARYXeW91c3NlZi56aXRhbkBpZG9wdGUuZnIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqPMenM1biCZbzAiaOt9rIoc7sHVEXGwex1yehBVfZi+P3B4bMY3h1i6k7YwfM2wdRRn/7vDbEwiT4tPc7MHnkWoFmrpIEVcSQzgNwBVY8yPNDxtVu3wtemCcnk7MT6c4F68cCnSsE9b2Jl2YzHOB3Ls+LSYRCscmCQTzLfIq3woW+PSgRBNiNDUZWiY1QyQWARqmyND0eD9hMeeEa/pvofZgEgiZPuCJT8QJSSOIp04Wok8wofZULc0GRImlV2QJiwogcJoExCpiVSBY+V0nC3JmITIXYzLZ+ojhTOCEETCnlmjPodQk0tiZM3NdgRA/zTCBCTqVu220/9Ik+LMnXAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBACqfHAhEQr988fVxksK5weg744wwYXoVZBCT9aIjEwjoTkP1EJEoUr8WHBvOJ9yXa6JSqRaaLzPE4E3Og62wIln39DIfAYf4OKo0noJ1Y4pT4b+nz3Hk+t3wIaUO53bnNxGaB8R5jWcMBv/sniPCAJ60/UO5NF6+D1yqCuR8fjL/WXpftSmL0Q1IFQJ/d0Xn+5VNEW4FB1/uIjZEXoAOxnsOOWUpoFKoePO6vvchE9cyL6T+1Ww36gOELT8k7g/WrnldPbc8sg4gW1UsW12kjLP9Pa3jzkRt31WZUISuTg1SSJO/QfshCY2luJNMNtSFkPcQ2tDoRNahA8xsXq8MKJI=\n-----END CERTIFICATE-----";
function log(msg) {
window.infodiv.insertAdjacentHTML('beforeend', msg + '<br>');
window.infodiv.scrollTop += 1000;
}
window.certlistObject = [];
window.onload = function() {
window.infodiv = document.getElementById("infodiv");
window.certlist = document.getElementById("certificatelist");
window.scandlg = document.getElementById("scandlg");
window.scanfield = document.getElementById("scanfield");
window.scandlg.style.visibility = "hidden";
var promise = new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200){
resolve(req.responseText);
}
else
reject(new Error("Challenge generation failed"));
}
};
req.open("GET", "generatechallenge.php", true);
req.send();
}).then(function(challenge) {
/* connecting to SCWS */
log("Connecting to SCWS...");
SCWS.findService(window.webappcert, challenge).then(function(findServiceData) {
log("Connection to SCWS succeeded");
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200)
resolve(req.responseText);
else
reject(new Error("Cryptogram verification failed"));
}
};
req.open("GET", "verifycryptogramsignchallenge.php?keyID=" + findServiceData.keyID + "&cryptogram=" + findServiceData.cryptogram + "&rnd=" + findServiceData.challenge, true);
req.send();
}).then(function(signature) {
log("create environment...");
return SCWS.createEnvironment(signature);
});
}).then(function() {
log("SCWS environment created successfully");
SCWS.onserviceunresponsive = function() {
log("Service became unresponsive");
}
}).catch(function(err){
log("ERROR: " + err.message);
window.certlist.clearChildren();
});
}).catch(function(err) {
log("ERROR: " + err.message);
window.certlist.clearChildren();
});
}
if( typeof Element.prototype.clearChildren === 'undefined' ) {
Object.defineProperty(Element.prototype, 'clearChildren', {
configurable: true,
enumerable: false,
value: function() {
while(this.firstChild) this.removeChild(this.lastChild);
}
});
}
function requestCertificates() {
log("request certificates...");
let options = {
};
let enableSoftToken = getEnableSoftToken();
if (enableSoftToken != "default")
options["enableSoftToken"] = enableSoftToken;
let scanDialogMode = getScanDialogMode();
if (scanDialogMode == "synchronous") {
options["showScanDlg"] = showScanDlg;
options["closeScanDlg"] = closeScanDlg;
options["setScanDlgMsg"] = setScanDlgMsg;
}
else if (scanDialogMode == "asynchronous") {
options["showScanDlg"] = showScanDlgAsynchronous;
options["closeScanDlg"] = closeScanDlgAsynchronous;
options["setScanDlgMsg"] = setScanDlgMsgAsynchronous;
}
if (getScanMessageMode() == "customized") {
options["waitingMsg"] = "Veuillez insérer une carte.";
options["connectingMsg"] = "Connexion à la carte.";
options["readingMsg"] = "Lecture de la carte";
}
return SCWS.requestCertificates(function(certificates) {
log("update list of certificates...");
window.certlist.clearChildren();
for (let i = 0; i < certificates.length; i++) {
let certificate = certificates[i];
let elt = document.createElement("option");
elt.id = window.certlistObject.length;
window.certlistObject.push(certificate);
let readerName = "soft token";
if (certificate.parent.reader)
readerName = certificate.parent.reader.name;
elt.textContent = certificate.subject + " (" + certificate.issuer + ") - " + readerName ;
window.certlist.appendChild(elt);
}
log("Found " + certificates.length + " certificates");
return certificates;
}, options).then(function(certificates){
log("requestCertificates finished");
log("Found " + certificates.length + " certificates");
log("");
}).catch(function(err) {
log("ERROR on request certificates: " + err.message);
window.certlist.clearChildren();
log("");
});
}
function getEnableSoftToken()
{
var elt = document.querySelector('input[name="softToken"]:checked');
if (!elt || !elt.value)
return "default";
return elt.value;
}
function getScanDialogMode()
{
var elt = document.querySelector('input[name="scandlg"]:checked');
if (!elt || !elt.value)
return "asynchronous";
return elt.value;
}
function getScanMessageMode()
{
var elt = document.querySelector('input[name="scanMessage"]:checked');
if (!elt || !elt.value)
return "asynchronous";
return elt.value;
}
function showScanDlg() {
window.scandlg.style.visibility = "visible";
}
function closeScanDlg(message) {
window.scanfield.value = getCloseScanMessage(message);
window.scandlg.style.visibility = "hidden";
}
function getCloseScanMessage(message) {
if (message)
return message;
else if (getScanMessageMode() == "nominal")
return "The operation is finished with success.";
else
return "L'opération s'est terminée avec succés.";
}
function setScanDlgMsg(message) {
window.scanfield.value = message;
}
function showScanDlgAsynchronous() {
return new Promise(function(resolve, reject) {
window.scandlg.style.visibility = "visible";
resolve();
});
}
function closeScanDlgAsynchronous(message) {
return new Promise(function(resolve, reject) {
window.scanfield.value = getCloseScanMessage(message);
return setTimeout(function() {
window.scandlg.style.visibility = "hidden";
resolve();
}, 2000);
});
}
function setScanDlgMsgAsynchronous(message) {
return new Promise(function(resolve, reject) {
window.scanfield.value = message;
resolve();
});
}
function reconnectCertificate(certificate)
{
return new Promise(function(resolve, reject){
let reader = SCWS.getReader(certificate.parent.reader.name);
if(!reader)
reject("reader not found");
reader.connect().then(function(token) {
token.getObjects().then(function(objects){
for (let i = 0; i < objects.length; ++i) {
let object = objects[i];
if(object.type === "certificate" && object.ckId === certificate.ckId)
resolve([certificate,token]);
}
}).catch(reject)
}).catch(reject)
});
}
function chooseCert()
{
/* get selected certificate element */
var elt = window.certlist.options[window.certlist.selectedIndex];
/* enumerate through connections and certificate items to retrieved corresponding certificate object */
var conn = null;
var certificate = window.certlistObject[elt.id];
/* remember selected elements */
window.choosenCertificate = certificate;
if (certificate) {
/* updating pin name label */
document.getElementById("pinname").textContent = certificate.parent.pins[certificate.pinNumber].label || "(Default PIN)";
/* updating certificate value */
certificate.getValue().then(function(value) {
document.getElementById("certificatevalue").textContent = value;
/* build software certificate and public key using forge library */
window.forgeCert = forge.pki.certificateFromPem(value);
window.forgePubKey = window.forgeCert.publicKey;
})
}
}
function getGlobalPin()
{
return new Promise(function (resolve, reject) {
if (!window.choosenCertificate)
throw "no certificate selected";
reconnectCertificate(window.choosenCertificate).then(function(res) {
window.connection = res[1];
resolve(res[1].pins[res[0].pinNumber]);
});
});
}
function getGlobalToken()
{
return new Promise(function (resolve, reject) {
if (!window.choosenCertificate)
throw "no certificate selected";
reconnectCertificate(window.choosenCertificate).then(function(res) {
window.connection = res[1];
resolve(window.connection);
});
});
}
function disconnectAll()
{
if(window.connection)
return window.connection.disconnect();
else
return Promise.resolve();
}
function startAutoLogin()
{
getGlobalPin().then(function(pin) {
log("startAutoLogin ...");
pin.startAutoLogin(document.getElementById("auto-login-counter").value).then(function() {
disconnectAll().then(function() {
log("startAutoLogin successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR: " + err.message);
});
});
});
}
function stopAutoLogin()
{
getGlobalPin().then(function(pin) {
log("stopAutoLogin ...");
pin.stopAutoLogin().then(function() {
disconnectAll().then(function() {
log("stopAutoLogin successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR: " + err.message);
});
});
});
}
function login()
{
getGlobalPin().then(function(pin) {
log("Login...");
pin.login(document.getElementById("pin").value).then(function() {
disconnectAll().then(function() {
log("Login successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR: " + err.message);
});
});
});
}
function loginWithPinDialog()
{
getGlobalPin().then(function(pin) {
log("Login...");
pin.login(false).then(function() {
disconnectAll().then(function() {
log("Login successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR: " + err.message);
});
});
});
}
function loginWithPinPad()
{
getGlobalPin().then(function(pin) {
log("Login...");
pin.login().then(function() {
disconnectAll().then(function() {
log("Login successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR: " + err.message);
});
});
});
}
function GetCredential()
{
getGlobalPin().then(function(pin) {
var state = pin.initSubmissionsState;
log("Login...");
pin.requestCredential(
pin.credentialProperties,
state,
pin.token.reader.name,
pin.token.label).then(function(credential) {
if (credential) {
pin.login(credential).then(function() {
disconnectAll().then(function() {
log("Login successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR: " + err.message);
});
});
}
else {
disconnectAll().then(function() {
log("Canceled by the user.");
});
}
}, function(err) {
disconnectAll().then(function() {
log("ERROR requestCredential: " + err.message);
});
}
);
});
}
function initPin()
{
getGlobalPin().then(function(pin) {
log("Login...");
pin.login("000000000000000000000000000000000000000000000000", true).then(function() {
log("login so successful");
pin.init("0000").then(function() {
disconnectAll().then(function() {
log("initPin successful");
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR initPin: " + err.message);
});
});
}, function(err) {
disconnectAll().then(function() {
log("ERROR loginso: " + err.message);
});
});
});
}
function getHashAlg()
{
var elt = document.querySelector('input[name="hashalg"]:checked');
if (!elt || !elt.value)
return null;
return elt.value;
}
function sign()
{
/* sign the input data using the selected hash algorithm */
log("request private key...")
let options = {
};
let enableSoftToken = getEnableSoftToken();
if (enableSoftToken != "default")
options["enableSoftToken"] = enableSoftToken;
let scanDialogMode = getScanDialogMode();
if (scanDialogMode == "synchronous") {
options["showScanDlg"] = showScanDlg;
options["closeScanDlg"] = closeScanDlg;
options["setScanDlgMsg"] = setScanDlgMsg;
}
else if (scanDialogMode == "asynchronous") {
options["showScanDlg"] = showScanDlgAsynchronous;
options["closeScanDlg"] = closeScanDlgAsynchronous;
options["setScanDlgMsg"] = setScanDlgMsgAsynchronous;
}
if (getScanMessageMode() == "customized") {
options["waitingMsg"] = "Veuillez insérer une carte.";
options["connectingMsg"] = "Connexion à la carte.";
options["readingMsg"] = "Lecture de la carte";
}
SCWS.requestPrivateKey(window.choosenCertificate, false, function(pkey){
log("Signature...");
try {
var data = document.getElementById("datafield").value;
var hashAlg = getHashAlg();
if (hashAlg) {
return pkey.hashAndSign(data, hashAlg).then(function(data) {
data = SCWS.toHexString(data);
log("Signature done:<br> " + data);
window.lastRet = forge.util.hexToBytes(data);
});
}
else {
return pkey.sign(SCWS.fromHexString(data)).then(function(data) {
data = SCWS.toHexString(data);
disconnectAll().then(function() {
log("Signature done:<br> " + data);
window.lastRet = forge.util.hexToBytes(data);
});
});
}
}
catch(err) {
log("ERROR: " + err.message);
throw err;
}
}, options).then(function() {
log("request private key succeeded.");
log("");
}).catch(function(error) {
log("request private key failed: " + error.message);
log("");
});
}
function verify()
{
/* verify the previously generated signature, using the input data and hash algorithm */
var r;
try {
var hash, scheme;
var data = document.getElementById("datafield").value;
var hashAlg = getHashAlg();
if (hashAlg) {
hash = forge.md[hashAlg].create();
hash.update(data);
hash = hash.digest().bytes();
scheme = "RSASSA-PKCS1-V1_5";
}
else {
hash = forge.util.hexToBytes(data);
scheme = null;
}
log("Recovered data:<br> " + forge.util.bytesToHex(forge.rsa.decrypt(window.lastRet, window.forgePubKey, true, true)));
r = window.forgePubKey.verify(hash, window.lastRet, scheme) ? "OK" : "failed";
}
catch (ex) {
r = "failed (" + ex + ")";
}
log("Verification " + r);
}
function encrypt()
{
/* encrypt the input data */
var data = document.getElementById("datafield").value;
var r = window.forgePubKey.encrypt(forge.util.hexToBytes(data));
window.lastRet = r;
r = forge.util.bytesToHex(r);
log("Encryption done:<br> " + r);
}
function decrypt()
{
/* decrypt the result of the last encryption */
getGlobalToken().then(function(token) {
SCWS.requestPrivateKey(window.choosenCertificate, false, function(pkey){
try {
log("Decryption...");
return pkey.decrypt(forge.util.binary.raw.decode(window.lastRet)).then(function(data) {
data = SCWS.toHexString(data);
log("Decryption done:<br> " + data);
});
}
catch(err) {
log("ERROR: " + err.message);
}
});
});
}
function loadFile(file, callback)
{
var xobj = new XMLHttpRequest();
xobj.open('GET', file, true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText);
}
};
xobj.send(null);
}
loadFile('rootCA.crt', function(file) {
window.caCert = forge.pki.certificateFromPem(file);
});
loadFile('rootCA.key', function(file) {
window.caKey = forge.pki.privateKeyFromPem(file);
});
function changePage()
{
localStorage.setItem("arr", JSON.stringify(SCWS.saveEnvironment()));
window.location.href = "restore_environment.html";
}
function signCSR(csrPath)
{
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200)
resolve(req.responseText);
else
reject(new Error("read file failed"));
}
};
req.open("GET", csrPath, true);
req.send();
}).then(function(csrPem) {
var csr = forge.pki.certificationRequestFromPem(csrPem);
var certificate = forge.pki.createCertificate();
certificate.serialNumber = '01';
certificate.validity.notBefore = new Date();
certificate.validity.notAfter = new Date();
certificate.validity.notAfter.setFullYear(certificate.validity.notBefore.getFullYear() + 1);
certificate.setSubject(csr.subject.attributes);
certificate.setIssuer(window.caCert.subject.attributes);
certificate.setExtensions([{
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true
}]);
certificate.publicKey = csr.publicKey;
// sign certificate with CA key
certificate.sign(window.caKey);
return certificate;
});
}
function softtoken()
{
return new Promise(function(resolve, reject) {
SCWS.getSoftToken().then(function(token) {
var attributes = {"label": "test"};
var data = {"subjectName":{"CN":"Test Sign","OU":"Dev","O":"Idopte","L":"Vienne","ST":"Isere","C":"FR", "emailAddress":"test@idopte.fr"}};
var formData = new FormData()
var byteArray = new Uint8Array(window.p12.match(/.{2}/g).map(function(e) { return parseInt(e, 16);}));
var blob = new Blob([byteArray], {type: "application/octet-stream"});
formData.append("file", blob);
formData.append("password", window.password);
token.import(formData, attributes).then(function(objects) {
var promises = [];
promises.push(SCWS.destroyObjects(objects.privateKey));
promises.push(SCWS.destroyObjects(objects.publicKey));
promises.push(SCWS.destroyObjects(objects.certificate));
Promise.allSettled(promises).then(function() {
resolve();
});
});
});
});
}
function callbackChipAuth(pubKey) {
return pubKey;
}
// SignEncrypt functions
/* Download file content from a blob */
function downloadBlobLocal(blob, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
/* Get PDF from local storage as a Blob */
function getBlobFromLocal(inputID) {
var selectedFile = document.getElementById(inputID).files[0];
return selectedFile;
}
function getDownloadExtension(format) {
if (format == "PADES"){
return ".pdf";
}
else if (format == "CADES_ATTACHED" || format == "CADES_DETACHED") {
return ".p7s";
}
else if (format == "XADES_DETACHED") {
return ".xml";
}
}
function signDoc() {
var blob = getBlobFromLocal("inputFile");
var options = {format: document.querySelector('input[name="signEncryptFormat"]:checked').value, hashAlgorithm: document.querySelector('input[name="signEncryptHashAlg"]:checked').value};
if (options.format == "XADES_DETACHED")
Object.assign(options, {fileName: "fileName"});
SCWS.requestCertificates(function(certificates) {
return certificates;
}).then(function(certificates) {
SCWS.requestPrivateKey(certificates[0], false, function(pKey, cert) {
return SCWS.signDocument(blob, pKey, cert, options).then(function(signedBlob) {
log("Signature has succeeded.");
downloadBlobLocal(signedBlob, "Test_signed" + getDownloadExtension(options.format));
}, function(err) {log(err);});
});
});
}
function encryptDoc() {
var blob = document.getElementById("inputFile").files[0];
SCWS.requestCertificates(function(certificates) {
return SCWS.encryptDocument(blob, certificates).then(function(signedBlob) {
log("Encryption has succeeded.");
downloadBlobLocal(signedBlob, "Test_encrypted.p7");
}, function(err) {log(err);});
return certificates;
});
}
function signEncryptDoc() {
var blob = document.getElementById("inputFile").files[0];
var options = {hashAlgorithm: document.querySelector('input[name="signEncryptHashAlg"]:checked').value};
// var x509_raw = "308206B73082059FA003020102021211212643A594608C44C30238006F117D6796300D06092A864886F70D01010B0500306D310B300906035504061302465231123010060355040A13094B45594E4543544953310C300A060355040B130349435331173015060355040B130E3030303220343738323137333138312330210603550403131A4B45594E454354495320494353205155414C4946494544204341301E170D3230303531343131343832385A170D3233303531343131343832385A3081B9310B300906035504061302465231123010060355040A0C09484153484C4F4749433118301606035504610C0F4E545246522D34323134353731383531293027060355040C0C20496E646570656E64616E74732064697665727320707265737461746169726573311730150603550405130E4F543030303852335044303030383111300F060355042A0C085068696C69707065310D300B06035504040C04445241593116301406035504030C0D5068696C69707065204452415930820122300D06092A864886F70D01010105000382010F003082010A0282010100C12BDF410EFC5CF770AEAC60380661326F0032D7BD4A49A63F9478FF3711D69056A2D19D5D0930747EAF24DF2F6CBBDB7EC21BC4350B2B2F0ABEE5F161408C6153B0D52AB93B7265FCD5E975A7F7B475EC253C5C3BA9810E7812185A7D2C27FE6EC8BC2BF6CFA4D83822F12D17D77DC95286AA0B434074B2918A3DE06F66DC710B71D480E097A09C63FC63518478EB98A4D75B7C24B707174039E8F17C51D6148415403C9A5C0B73F359BBCF2D6FA29430DFB20DCB7C74C89C2A9B5A8586108DBD6CFC138486E6511B366B2BFDCF24FFF13E5E14D4E1F26B04D6E6D421383C523BE39DB3640F44E1356B3F9F6CBD9BD105F6162EA9D4EA6C309D47EE92F16DAB0203010001A3820302308202FE300E0603551D0F0101FF0404030206C03013060A2A864886F72F0101090204053003020101302A0603551D2504233021060A2B0601040182370A030C06092A864886F72F01010506082B0601050507030230650603551D20045E305C305A060C2B0601040181AD5A0209030F304A304806082B06010505070201163C68747470733A2F2F7777772E646F63757369676E2E66722F736F63696574652F706F6C697469717565732D64652D63657274696669636174696F6E73300C0603551D130101FF0402300030600603551D1F045930573055A053A051864F687474703A2F2F747275737463656E7465722D63726C2E63657274696669636174322E636F6D2F4B65796E65637469732F4B45594E45435449535F4943535F5155414C49464945445F43412E63726C30819306082B06010505070101048186308183303C06082B060105050730018630687474703A2F2F6F6373702D69642E6473662E646F63757369676E2E6E65742F6963735F7175616C69666965645F6361304306082B060105050730028637687474703A2F2F6372742E6473662E646F63757369676E2E6E65742F6B65796E65637469736963737175616C696669656463612E70376330260603551D11041F301D811B5048494C495050452E4452415940484153484C4F4749432E434F4D3037060A2A864886F72F01010901042930270201018622687474703A2F2F7473732E6473662E646F63757369676E2E6E65742F63657274696430819C06082B0601050507010304818F30818C3008060604008E4601013008060604008E460104304A060604008E4601053040303E163868747470733A2F2F7064732E6473662E646F63757369676E2E6E65742F6B65796E65637469736963737175616C696669656463612E7064661302454E3013060604008E4601063009060704008E46010601301506082B06010505070B023009060704008BEC490102301D0603551D0E041604140F90E2B99C6875B0AB1A4384293866149603D6E5301F0603551D23041830168014549745C1EA00C545A8CDDB82F87DCBF59041A078300D06092A864886F70D01010B050003820101004BCE22A1A19B2CA0D520B41B7B78C6CBAA9E79CA60D7C9C3EE3E78750189BCCAEB6C385F3891A8D6A7323D1482634D70886F6A7C2AA7E7B263B6875F390E45F5DEA486ACEC3F429F45B3BDF63EFDE406DF6929104AAC05D4CC66D5C9D8FDE3F4C44EE796AD64A8AE3C035F8721FEA558B0A3BF73A17CF2E88D204CC92066EB815F06A51852E4C5ADAC7328E830E2B48BF1880D39A4C58461CFB6490F047044ABB8D026E7789F70A5DF07CFC70D7A57A8C249E53F73161374448B3140F8F5C30E8FA6224FF69F159AFA2DB98D83674DDDD9E467E528FBDD667995CF0E4F7B90FDD40E26BEEC8963B31E538B8FFF44DEF6ABA09AB3962AE85D322CEDBB5479C749";
// var byteArray = new Uint8Array(x509_raw.match(/.{2}/g).map(e => parseInt(e, 16)));
// var blobCert = new Blob([byteArray], {type: "application/octet-stream"});
// SCWS.createCertificate(blobCert).then(function(certificate) {
// console.log(certificate);
// });
SCWS.requestCertificates(function(certificates) {
return certificates;
}).then(function(certificates) {
SCWS.requestPrivateKey(certificates[0], false, function(pKey, cert) {
return SCWS.signEncryptDocument(blob, pKey, cert, cert, options).then(function(signEncryptedBlob) {
log("SignEncryption has succeeded.");
downloadBlobLocal(signEncryptedBlob, "Test_signEncrypted.p7");
}, function(err) {log(err);});
});
});
}
function verifyDoc() {
var blob = document.getElementById("inputFile").files[0];
var originalBlob = undefined;
var originalBlobCallback = undefined;
var options = {format: document.querySelector('input[name="signEncryptFormat"]:checked').value};
if (options.format == "CADES_DETACHED" || options.format == "XADES_DETACHED") {
originalBlob = document.getElementById("originalFile").files[0];
}
if (options.format == "CADES_ATTACHED" || options.format == "PKCS7") {
originalBlobCallback = downloadBlobLocal;
}
SCWS.verifyDocument(blob, options, originalBlob, originalBlobCallback).then(function(verifResult){
log("");
log("Verification has succeeded.");
log("globalSignatureValidity: " + verifResult.globalSignatureValidity);
for (let i = 0; i < verifResult.signatories.length; i++) {
log("");
log("\nSignatory " + i + ":");
log("Name: " + verifResult.signatories[i].certificate._subjectName);
log("Certificate handle: " + verifResult.signatories[i].certificate._handle);
log("signatureValidity: " + verifResult.signatories[i].signatureValidity);
log("signerTrust: " + verifResult.signatories[i].signerTrust);
log("cadesBESCompliance: " + verifResult.signatories[i].cadesBESCompliance);
}
}, function(err) {log(err);});
}
function decryptDoc() {
var blob = document.getElementById("inputFile").files[0];
function callbackDecrypt(recipientsList, decryptWith) {
SCWS.requestCertificates(function(certificates) {
return SCWS.matchIssuerAndSerialsWithCerts(recipientsList, certificates).then(function(result) {
for (let i = 0; i < certificates.length; i++) {
const index = result.indexOf(certificates[i]._handle);
if (index != -1)
return certificates[i];
}
});
}).then(function(certificate) {
return SCWS.requestPrivateKey(certificate, false, function(pKey, cert) {
return decryptWith(pKey, cert);
});
});
}
SCWS.decryptDocument(blob, callbackDecrypt).then(function(blob){
log("Decryption has succeeded.");
downloadBlobLocal(blob, "Test_decrypted");
}, function(err) {log(err);});
}
function decryptVerifyDoc() {
var blob = document.getElementById("inputFile").files[0];
function callbackDecrypt(recipientsList, decryptWith) {
SCWS.requestCertificates(function(certificates) {
return SCWS.matchIssuerAndSerialsWithCerts(recipientsList, certificates).then(function(result) {
for (let i = 0; i < certificates.length; i++) {
const index = result.indexOf(certificates[i]._handle);
if (index != -1)
return certificates[i];
}
});
}).then(function(certificate) {
return SCWS.requestPrivateKey(certificate, false, function(pKey, cert) {
return decryptWith(pKey, cert);
});
});
}
SCWS.decryptVerifyDocument(blob, callbackDecrypt, downloadBlobLocal).then(function(verifResult){
log("");
log("DecryptVerification has succeeded.");
log("globalSignatureValidity: " + verifResult.globalSignatureValidity);
for (let i = 0; i < verifResult.signatories.length; i++) {
log("");
log("\nSignatory " + i + ":");
log("Name: " + verifResult.signatories[i].certificate._subjectName);
log("Certificate handle: " + verifResult.signatories[i].certificate._handle);
log("signatureValidity: " + verifResult.signatories[i].signatureValidity);
log("signerTrust: " + verifResult.signatories[i].signerTrust);
log("cadesBESCompliance: " + verifResult.signatories[i].cadesBESCompliance);
}
}, function(err) {log(err);});
}
</script>
</head>
<body>
<table>
<tr>
<td>
<form id="certificateform">
<table>
<tr>
<td>
Enable soft token:<br>
<label><input type="radio" name="softToken" value="default" checked="checked">default</label><br>
<label><input type="radio" name="softToken" value="true">true</label><br>
<label><input type="radio" name="softToken" value="false">false</label><br/>
</td>
<td>
Scan dialog:<br>
<label><input type="radio" name="scandlg" value="nominal">nominal</label><br>
<label><input type="radio" name="scandlg" value="synchronous">synchronous</label><br>
<label><input type="radio" name="scandlg" value="asynchronous" checked="checked">asynchronous</label><br/>
</td>
<td>
message:<br>
<label><input type="radio" name="scanMessage" value="nominal" checked="checked">nominal</label><br>
<label><input type="radio" name="scanMessage" value="customized">customized</label><br/>
</td>
<td id="scandlg">
Scan dialog:<br/>
<form id="scanform">
<textarea id="scanfield" name="scan" cols="40" rows="4"></textarea><br>
</form>
</td>
</tr>
</table>
<input type="button" onclick="requestCertificates()" value="request certificates"/><br/>
Certificate to use:<br>
<div style="display:inline-block;vertical-align:top;">
<select style="height:8rem;" size="4" id="certificatelist" onchange="chooseCert()">
</select>
</div>
<div id="certificatevalue" style="white-space:pre;display:inline-block;vertical-align:top;width:20em;height:8rem;overflow:auto;border:1px solid gray;">
</div>
</form>
<p><form id="dataform">
Input data:<br>
<textarea id="datafield" name="data" cols="40" rows="8"></textarea><br>
</form></p>
<p><form id="loginform">
Counter (0 or less equals infinity) :<input id="auto-login-counter" type="number"/>
<input type="button" onclick="startAutoLogin()" value="startAutoLogin"/>
<input type="button" onclick="stopAutoLogin()" value="stopAutoLogin"/><br/>
Pin <span id="pinname"></span>:<br>
<input id="pin" type="password" />
<input type="button" onclick="login()" value="Login"/>
<input type="button" onclick="loginWithPinDialog()" value="LoginWithPinDialog"/>
<input type="button" onclick="loginWithPinPad()" value="LoginWithPinPad"/>
<input type="button" onclick="GetCredential()" value="GetCredential"/>
</form></p>
<p>
<div style="display:inline-block;text-align:center;margin:0.5em 2em;">
<input type="button" onclick="sign()" value="Sign"/><br>
<input type="button" onclick="verify()" value="Verify"/><br>
<input type="button" onclick="encrypt()" value="Encrypt"/><br>
<input type="button" onclick="decrypt()" value="Decrypt"/>
<input type="button" onclick="softtoken()" value="SoftToken"/>
<input type="button" onclick="initPin()" value="initPin"/>
<input type="button" onclick="changePage()" value="ChangePage"/>
</div>
<div style="display:inline-block"><form id="hashcfgform">
Hashing algorithm:<br>
<label><input type="radio" name="hashalg" value="" checked="checked">None (hex block as input)</label><br>
<label><input type="radio" name="hashalg" value="sha1">SHA-1</label><br>
<label><input type="radio" name="hashalg" value="sha256">SHA-256</label>
</form></div>
</p>
</td>
<td>
<p>Information logs:</p>
<div id="infodiv" style="display:inline-block;vertical-align:top;width:100%;height:30rem;overflow:auto;border:1px solid gray;"></div>
</td>
</tr>
</table>
<h3>
SignEncrypt high level entry points
</h3>
<p>
<div style="display:inline-block">
Input file(s) :<br>
<label for="inputFile">Input file</label><br>
<input type="file" id="inputFile" name="inputFile"/><br>
<label for="originalFile">Original file (for detached verification)</label><br>
<input type="file" id="originalFile" name="originalFile"/>
</div>
<div style="display:inline-block">
Format:<br>
<label><input type="radio" name="signEncryptFormat" value="PKCS7">PKCS7</label><br>
<label><input type="radio" name="signEncryptFormat" value="CADES_ATTACHED">Attached CADES</label><br>
<label><input type="radio" name="signEncryptFormat" value="CADES_DETACHED">Detached CADES</label><br>
<label><input type="radio" name="signEncryptFormat" value="PADES">PADES</label><br>
<label><input type="radio" name="signEncryptFormat" value="XADES_DETACHED">Detached XADES</label>
</div>
<div style="display:inline-block">
Hashing algorithm:<br>
<label><input type="radio" name="signEncryptHashAlg" value="sha1">SHA-1</label><br>
<label><input type="radio" name="signEncryptHashAlg" value="sha256">SHA-256</label><br>
<label><input type="radio" name="signEncryptHashAlg" value="sha384">SHA-384</label><br>
<label><input type="radio" name="signEncryptHashAlg" value="sha512">SHA-512</label>
</div>
<div style="display:inline-block;text-align:center;margin:0.5em 2em;">
<input type="button" onclick="signDoc()" value="SignDocument"/><br>
<input type="button" onclick="encryptDoc()" value="EncryptDocument"/><br>
<input type="button" onclick="signEncryptDoc()" value="SignEncryptDocument"/><br>
<input type="button" onclick="verifyDoc()" value="VerifyDocument"/><br>
<input type="button" onclick="decryptDoc()" value="DecryptDocument"/>
<input type="button" onclick="decryptVerifyDoc()" value="DecryptVerifyDocument"/>
</div>
</p>
</body>
</html>