Old server-side code samplesΒΆ

Server

@RestController
public class ProcController implements ExternalAuthenticateHandler, MutualAuthenticateHandler {

        /* This is the private key for SCWS environment creation
        * (should correspond to the public key for which the webappcert has been generated)
        * Note: the webappcert is in the javascript code */
        private static final String privateKeyPEM =
                        "-----BEGIN RSA PRIVATE KEY-----\r\n" +
                        "MIIBOgIBAAJBAMPMNNpbZZddeT/GTjU0PWuuN9VEGpxXJTAkmZY02o8238fQ2ynt\r\n" +
                        "N40FVl08YksWBO/74XEjU30mAjuaz/FB2kkCAwEAAQJBALoMlsROSLCWD5q8EqCX\r\n" +
                        "rS1e9IrgFfEtFZczkAWc33lo3FnFeFTXSMVCloNCBWU35od4zTOhdRPAWpQ1Mzxi\r\n" +
                        "aCkCIQD9qjKjNvbDXjUcCNqdiJxPDlPGpa78yzyCCUA/+TNwVwIhAMWZoqZO3eWq\r\n" +
                        "SCBTLelVQsg6CwJh9W7vlezvWxUni+ZfAiAopBAg3jmC66EOsMx12OFSOTVq6jiy\r\n" +
                        "/8zd+KV2mnKHWQIgVpZiLZo1piQeAvwwDCUuZGr61Ap08C3QdsjUEssHhOUCIBee\r\n" +
                        "72JZuJeABcv7lHhAWzsiCddVAkdnZKUo6ubaxw3u\r\n" +
                        "-----END RSA PRIVATE KEY-----";

        /**
        * Entry point for generating the signature, for the initial environment creation.
        * (called by the client between SCWS.findService and SCWS.createEnvironment).
        * @param rnd the challenge to sign (coming from the client-side SCWS).
        * @return the cryptogram that will authorize environment creation.
        */
        @GetMapping("/sign_env_challenge")
        public String signEnvChallenge(String rnd) {
                try {
                        PrivateKey privateKey;
                        try (PEMParser pemParser = new PEMParser(new StringReader(privateKeyPEM))) {
                                JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
                                Object object = pemParser.readObject();
                                KeyPair kp = converter.getKeyPair((PEMKeyPair)object);
                                privateKey = kp.getPrivate();
                        }
                        Signature signer = Signature.getInstance("NONEwithRSA","BC");
                        signer.initSign(privateKey);
                        signer.update(Hex.decode(rnd));
                        byte[] signature = signer.sign();
                        return Hex.toHexString(signature);
                } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e.getMessage(), e);
                }
        }

        /**
        * Create a {@link SCSSSession} object.
        * @return the handle of created {@link SCSSSession} object.
        * @throws SCMException
        * @throws IOException
        */
        @GetMapping("/init_session")
        public String startTest() throws SCMException, IOException {
                final SCSSSession s = new SCSSSession();
                return s.getHandle();
        }

        /**
        * Process session and allow communication between ServerSide SmartCard and ClientSide SmartCard middlewares.
        * @param id the handle of the {@link SCSSSession} object to communicate with.
        * @param body the body of HTTP request
        * @return the result of processed session.
        * @throws SCMException
        * @throws IOException
        */
        @PostMapping("/process_session/{id}")
        public String processSession(@PathVariable String id, @RequestBody String body) throws SCMException, IOException {
                return SCSSSession.process(id, body);
        }

        /**
        * Execute session. Once {@link SCSSSession} object is created and session is managed with {@link SCSSSession#process}, call this to use methods and attributes from
        * {@link Token} object.
        * @param id the handle of {@link SCSSSession} object.
        * @return some result
        * @throws SCMException
        * @throws IOException
        */
        @GetMapping("/exec_session/{id}")
        public String execSession(@PathVariable String id) throws SCMException, IOException {
                SCSSSession s = SCSSSession.getSession(id);

                try {
                        s.init();

                        /* -------------------------------------------------------------------- */
                        // here lies the server-side application logic.
                        // Operations are made by calling Token methods on the `s` object.
                        /* -------------------------------------------------------------------- */

                }
                catch (Exception e){
                        return "Operation failed";
                }
                finally {
                        s.close();
                }
                return "Operation OK";
        }

}

Client

window.webappcert = "4SyF8E6?J4{SVYI)psu*Xb0t#E=1oJdCH}B[Y8){oDbd%GP-L&ZI*KtJl@P?<:t$Tvv[NPS9>6Mqkpnmg^O1Zkn[Zo#czsNjEe:ASWVef!l-I$=e02=*YAmCkmvm1iifG])b[EFTe2>-:Hmk.KPTX9S0CQPVV41h3>S0>QyDEq/Bb?u#Zc^i7v]JDE@jgy@*bbc=59z!woxg6nRpqTxix&o8>5J8D6lzoLkuw=Q8MreUlGfHfBt(&q8!8Eh>BBL.6A)S.&IBkyKcR%$V@Zb$.!0aJjM1<iEMzoN)2!j^GtkU:d>A/Rx=u*@Q7W6$kk[zM";

window.connections = [];
window.connecting = false;

/* boilerplate function for performing a ajax request */
function req(method, url, contents) {
        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("App server request failed"));
                        }
                };
                req.open(method, url, true);
                req.send(contents);
        });
}

function reqGet(url) {
        return req("GET", url);
}

function reqPost(url, contents) {
        return req("POST", url, contents);
}

/* connects to the SCWS, then tries to find smart cards in readers and connect to them */
function init() {
        /* connecting to SCWS */
        console.log("Connecting to SCWS...");
        SCWS.findService(window.webappcert).then(function(challenge) {
                console.log("Connection to SCWS succeeded");
                return reqGet("sign_env_challenge?rnd=" + challenge)
                .then(function(signature) {
                        return SCWS.createEnvironment(signature);
                });
        }).then(function() {
                console.log("SCWS environment created successfully");
                /* check all readers already connected */
                var readers = SCWS.readers;
                if (readers.length == 0) {
                        console.log("No readers found");
                }
                else {
                        for (var i = 0; i < readers.length; i++)
                                checkReader(readers[i]);
                }
                document.getElementById("initbtn").style.display = "none";
                updateStatus();
                /* register event callbacks for checking readers changes */
                SCWS.onreaderadded = function(reader) {
                        console.log("Reader inserted: '" + reader.name + "'");
                        checkReader(reader);
                }
                SCWS.onreaderremoved = function(reader) {
                        console.log("Reader removed: '" + reader.name + "'");
                        checkReader(reader);
                }
                SCWS.onreaderstatechanged = function(reader) {
                        console.log("Reader state changed: '" + reader.name + "'");
                        checkReader(reader);
                }
        }).catch(function(err) {
                console.log("ERROR: " + err.message);
        });
}

function updateStatus()
{
        // update GUI elements to show connection state
}

/**
* Called when a reader needs to be scanned for objects.
*/
function checkReader(reader) {
        /* trying to find reader from existing connections */
        for (var connidx = 0; connidx < window.connections.length; connidx++) {
                if (window.connections[connidx].reader == reader)
                        break;
        }
        if (connidx == window.connections.length) {
                if (reader.status == "ok" && reader.cardPresent) {
                        /* reader not found in existing connections, and reader contains card: connecting */
                        console.log("Connecting to reader '" + reader.name + "'...");
                        var connection = { reader: reader };
                        window.connections.push(connection);
                        window.connecting = true;
                        updateStatus();
                        reader.connect().then(function(token) {
                                connection.token = token;
                                connection.items = [];
                                console.log("Getting objects from reader '" + reader.name + "'...");
                                return token.getObjects();
                        }).then(function(items) {
                                connection.items = items;
                                window.connecting = false;
                                updateStatus();
                        }).catch(function(err) {
                                console.log("ERROR: " + err.message);
                                window.connecting = false;
                                updateStatus();
                        });
                }
        }
        else {
                var conn = connections[connidx];
                if (reader.status != "ok" || !reader.cardPresent) {
                        /* reader found in existing connections, but contains no card: removing */
                        if (conn.token) {
                                console.log("Disconnecting from reader '" + reader.name + "'.");
                                conn.token.disconnect();
                        }
                        window.connections.splice(connidx, 1);
                        updateStatus();
                }
        }
}

function showError(err) {
        document.getElementById("errmsg").textContent = err.message || err;
}

/* Function that actually opens the server session */
function test() {
        /* first, create the SCSSSession instance on the server */
        reqGet("init_session").then(function(sessHandle) {
                /* process the session (session handle is used in the URL) */
                window.connections[0].token.processServerSession("process_session/" + sessHandle).then(function() {
                        console.log("OK");
                        /* at that point, the session is fully completed */
                }, function() {
                        console.log("error");
                });
                /* concurrently with the processServerSession call, the REST entry point that actually performs the operation is called, also giving the session handle */
                reqGet("exec_session/" + sessHandle).then(function(result) {
                        console.log(result);
                        /* although the REST operation is completed, the session may not be yet finished at that point */
                });
        });
}