Signature Process
The main components involved for the signature process are the application server that run the code that manage the signed file and the 4identity client that sign the file. The main functionality of the SMARTENGINE in this process is to maintain the channel lifecycle.
Detailing this process, the application stored on the application server is able to choose the file to sign and to receive the signed file by a POST message from the 4Identity client. The application then store the signed file on a server.
Figura 3 – Signature Process
In the signature process the 4identity client installed on the client machine is able to show the user the certificate to use for the signature:
Figura 4 – Choose the certificate for the signature
Show a preview of the document to sign:
Figura 5 – Document preview
and run the signature functionality. In the case of the document type is not PDF the following window is shown to the user asking a proof for the the document review. After this check the sign button is enabled and the document can be signed.
Figura 6 – Run the signature
Due that the 4Identity client do not need any custom code we will show the code for the application run on application server.
This application is composed of:
- a FORM to enable the user to choose a file to sign;
- a component to read the signed file sent by a post message and redirect he user to the landing page;
- a landing page that give the result to the user and the link for the signed file.
Java code
For an environment using J2EE we will use:
- an application server as.example.com:8080 that expose the custom application on /4identity ;
- the custom application 4identity consist of:
- index.html: containing the form ;
- a servlet called Signing that read the POST data and redirect the session to a landing page called success.jsp;
- a JSP page called success.jsp that show the user the signed file;
INDEX.HTML
See below the code for index.html page.
- <div>
- <form class="bit4id-sign" action="4identity/Signing" method="post">
- <p></p>
- <div class="bit4id-signReq" style="display: none;">
- <div class="bit4id-document">http://as.example.com:8080/4identity/TestData.pdf</div>
- <div class="bit4id-documentName">TEST PDF DOCUMENT</div>
- <div class="bit4id-signatureType">PAdES</div>
- <div class="bit4id-signingAlgorithm">RSASHA256</div>
- <div class="bit4id-certInfo">CN</div>
- </div>
- <div>
- <fieldset>
- <div><h3>Document Signature</h3></div>
- <div><p><strong>Proceeding the document TestData.pdf will be signed, are you sure?</strong></p></div>
- <div id="bit4id-status"></div>
- <div><input type="submit" value="Sign Document" name="cmd" disabled></div>
- </fieldset>
- </div>
- </form>
- <script src="http://fe.example.com:8082/smartengine/bit4id-sign.min.js"></script>
- </div>
This page contain the FORM element with the custom class bit4id-sign, the action configured against our servlet Signing and the method set to POST:
<form class="bit4id-sign" action="4identity/Signing" method="post">
OTHER CODE HERE
</form>
Then we need to build the signature request with the class bit4id-signReq. The request is filled with the information for:
- The document path, in this case is a file (TestData.pdf) stored on the server as.example.com :
<div class="bit4id-document">http://as.example.com:8080/4identity/TestData.pdf</div>
- The file name:
<div class="bit4id-documentName">TestData.pdf</div>
- The signature Type (Pades):
<div class="bit4id-signatureType">PAdES</div>
- The signature Algorithm (RSASHA256) :
<div class="bit4id-signingAlgorithm">RSASHA256</div>
- The certificate’s attribute (CN) shown on the 4identity client:
<div class="bit4id-certInfo">CN</div>
- The channel status information, used normally for debug purpose:
<div id="bit4id-status"></div>
- The submit button to send the post, the name need to be cmd and disabled:
<div><input type="submit" value="Sign Document" name="cmd" disabled></div>
- The script resource on the SMARTENGINE server deployed on the server fe.example.com on the port 8082 :
<script src="http://fe.example.com:8082/smartengine/bit4id-sign.min.js"></script>
For the other information about the signature request, see the chapter 2.1.4.
Signing servlet
See below the code for the Servlet class:
package com.bit4id.identity;
import java.io.IOException;
import java.io.File;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/Signing")
@MultipartConfig(fileSizeThreshold=1024102410,maxFileSize=1024102415,maxRequestSize=1024102430)
public class Signing extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String contentdir = "D:\jboss-as-7.1.1\standalone\deployments\4identity.war\signed";
public Signing() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("SIGNATURE MANAGEMENT SERVLET");
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String signstore ="http://as.example.com:8080/4identity/signed";
for (Part part : request.getParts()) {
part.write(contentdir + File.separator + "FILESIGNED.pdf");
}
response.sendRedirect("success.jsp?link=" + signstore + "//" + "FILESIGNED.pdf");
}
}
As shown above is a Servlet standard that manage a POST message and store the file using the annotation.
The main code is the read of the file in the POST message and save the signed file (FILESIGNED.pdf) in the path written in the variable contentdir with :
for (Part part : request.getParts()) {
part.write(contentdir + File.separator + "FILESIGNED.pdf");
}
After this, the code redirect the session to the landing page sending the link to download the file:
response.sendRedirect("success.jsp?link=" + signstore + "//" + "FILESIGNED.pdf");
success.jsp
See below the code for page success.jsp:
See below the code for page success.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Signature Process</title>
</head>
<body>
<%
if (request.getParameter( "link" ) != null) {
String link = request.getParameter("link");
out.println("<a href=" + link.toString() + ">SIGNED FILE</a>") ;
}
if (request.getParameter( "outprint" ) != null) {
String outprint = request.getParameter("outprint");
out.println("REQUEST PRINT:" + outprint.toString());
}
%>
</body>
</html>
The code above read the link sent :
String link = request.getParameter("link");
And build the link for the file download:
out.println("<a href=" + link.toString() + ">SIGNED FILE</a>")
Java 1.5 example for Signing class
In case of using an old version of Java that do not support the Servlet 3.0 classes, see the code below to read the signed file sent into the post.
The code below works on an application server that run Java 1.5 and Servlet 2.5.
package com.bit4id.identity;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class Signing extends HttpServlet {
private static final long serialVersionUID = 1L;
private int maxFileSize = 50 1024 1024;
private int maxMemSize = 30 * 1024;
public Signing() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("SIGNATURE MANAGEMENT SERVLET");
ServletContext servletContext = getServletContext();
String contentdir = servletContext.getRealPath(File.separator);
String pathServlet = request.getServletPath();
String fullPathServlet = request.getRequestURL().toString();
int resInt = fullPathServlet.length() - pathServlet.length();
String result = fullPathServlet.substring(0, resInt + 1);
out.println("Context path: " + contentdir);
out.println("Full Servlet path: " + fullPathServlet);
out.println("Servlet path: " + pathServlet);
out.println("Server path: " + result);
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
ServletContext servletContext = getServletContext();
String contentdir = servletContext.getRealPath(File.separator) + "signed";
String pathServlet = request.getServletPath();
String fullPathServlet = request.getRequestURL().toString();
int resInt = fullPathServlet.length() - pathServlet.length();
String signstore = fullPathServlet.substring(0, resInt + 1) + "signed";
// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
return;
}
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Sets the size threshold beyond which files are written directly to
// disk.
factory.setSizeThreshold(maxMemSize);
// Sets the directory used to temporarily store files that are larger
// than the configured size threshold. We use temporary directory for
// java
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Set overall request size constraint
upload.setSizeMax(maxFileSize);
try {
// Parse the request
FileItem item = (FileItem)upload.parseRequest(request).iterator().next();
if (!item.isFormField()) {
String fileName = "FILESIGNED.pdf";
String filePath = contentdir + File.separator + fileName;
File uploadedFile = new File(filePath);
System.out.println(filePath);
// saves the file to upload directory
item.write(uploadedFile);
response.sendRedirect("success.jsp?link=" + signstore + "//" + fileName);
}
} catch (FileUploadException ex) {
throw new ServletException(ex);
} catch (Exception ex) {
throw new ServletException(ex);
}
}
}
.NET code
For an environment using .NET Framework, we will use:
- a IIS web server as.example.com:9090 that expose the custom .NET application on /4identity ;
- the custom application 4identity consist of:
- Sign.aspx: containing the form ;
- an aspx page called SignOk.aspx that read the POST data, do some server code elaboration like saving the signed file and finally redirect the session to a landing page called landing.aspx;
- an aspx page called landing.aspx that show to the user the signed file;
Sign.aspx
See below the code for Sign.aspx page.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Sign.aspx.cs" Inherits="SmartEngineDemo.Sign" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>4Identity Authentication</title>
</head>
<body>
<form class="bit4id-sign" method="post" action="/4identity/SignOk.aspx">
<div class="bit4id-signReq" style="display: none;">
<div class="bit4id-localFile">NO</div>
<div class="bit4id-document">http://192.168.161.1:9090/4identity/Documents/test.pdf</div>
<div class="bit4id-documentName">test.pdf</div>
<div class="bit4id-documentID">01</div>
<div class="bit4id-signatureType">PAdES</div>
</div>
<div id="bit4id-status">wait</div>
<input disabled="disabled" type="submit" value="Sign Document" />
</form>
<script type="text/javascript" src="http://192.168.161.60:8082/smartengine/bit4id-sign.min.js"></script>
</body>
</html>
This page contain the FORM element with the custom class bit4id-sign, the action configured against the custom SignOk.aspx and the method set to POST:
<form class="bit4id-sign" method="post" action="/4identity/SignOk.aspx">
OTHER CODE HERE
</form>
Then we need to build the signature request with the class bit4id-signReq. The request is filled with the information for:
- The document path, in this case is a file (test.pdf) stored on the server as.example.com :
<div class="bit4id-document">http://as.example.com:9090/4identity/Documents/test.pdf</div>
- The file name:
<div class="bit4id-documentName">test.pdf</div>
- The signature Type (Pades):
<div class="bit4id-signatureType">PAdES</div>
- The signature Algorithm (RSASHA256) :
<div class="bit4id-signingAlgorithm">RSASHA256</div>
- The certificate’s attribute (CN) shown on the 4identity client:
<div class="bit4id-certInfo">CN</div>
- The channel status information, used normally for debug purpose:
<div id="bit4id-status"></div>
- The submit button disabled, it will be automatically enabled once the connection will be established with the SMARTENGINE:
<input disabled="disabled" type="submit" value="Sign Document" />
- The script resource on the SMARTENGINE server deployed on the server fe.example.com on the port 8082 :
<script type="text/javascript" src="http://fe.example.com:8082/smartengine/bit4id-sign.min.js"></script>
For the other information about the signature request, see the chapter 2.1.4.
SignOK.aspx
The page SignOk.aspx has a frontend and some code to run on the Page_Load event.
Front end Code:
<%@ Page Title="About Us" Language="C#" AutoEventWireup="true" trace="true"
CodeBehind="SignOk.aspx.cs" Inherits="SmartEngineDemo.SignOk" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>process page</title>
</head>
<body>
</body>
</html>>
The behind code:
public partial class SignOk : System.Web.UI.Page
{
public String outError = "not Set";
public String pathOut;
protected void Page_Load(object sender, EventArgs e)
{
foreach (string file in Request.Files)
{
HttpPostedFile postfile = Request.Files[file] as HttpPostedFile;
if (postfile.ContentLength == 0)
{
outError = "File not sent";
}
else
{
outError = "File sent";
string savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "signed", Path.GetFileName(postfile.FileName));
pathOut = postfile.FileName;
postfile.SaveAs(savedFileName);
}
}
Response.Redirect("landing.aspx?SignedFile="+ pathOut);
}
}
The example code above manage the POST message and store the signed file using the HttpPostedFile.
The main code is the file reading in the POST message and save the signed file in the path written in the variable savedFileName with the line:
postfile.SaveAs(savedFileName)
After this, the code redirect the session to the landing page sending the link to download the file:
Response.Redirect("landing.aspx?SignedFile="+ pathOut);
Landing.aspx
The page landing.aspx has a frontend and some code to run on the Page_Load event.
Front end Code:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="landing.aspx.cs" Inherits="SmartEngineDemo.landing" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>4Identity Signature</title>
</head>
<body>
<h2>
Landing Page
</h2>
File correctly Signed and downloadable here: <asp:HyperLink ID="hlSigned" runat="server">Signed File</asp:HyperLink>
<BR />Output: <%=Request.QueryString["out"] %>
</body>
</html>
In the code above is inserted a Hyperlink server object hlSigned that will point to the signed file to be downloaded by the user. This dynamic link will be set by the code behind of the same page.
The behind code:
public partial class landing : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
String wserver = "http://as.example.com:9090/4identity/signed/";
String LinkAddr = wserver + Request.QueryString["SignedFile"];
hlSigned.NavigateUrl = LinkAddr;
}
}
The code above build the link and set the NavigateUrl parameter of the object hlSigned :
hlSigned.NavigateUrl = LinkAddr;
Signature Parameter
Below are detailed the parameter for the signature functionality.
CAdES SIGNATURE API
This section describes the parameters of the signature to be included within the form class: bit4idsignReq to perform a CAdES signature request.
Parameter | Values | Default |
---|---|---|
bit4id-document | Url for the file to be signed | |
bit4id-signatureType | “CAdES” | NO DEFAULT |
bit4id-signingAlgorithm | “RSASHA256”, “RSASHA1”, “RSAMD5” | “RSASHA256” |
bit4id-encoding | “1”, “0” | “0” |
bit4id-issuerFilter | “CN=..., OU=..., T=..., ecc.” | “” |
bit4id-certType | “ANY”, “SIG”, “AUT” | “ANY” |
bit4id-certInfo | “CN, OU, T, ecc.” | NO DEFAULT |
bit4id-bundle | “YES” , “NO” | “NO” |
bit4id-filepath | Absolute path for the file to be signed. | Example : C:\File\example.txt |
bit4id-document: defines the url for the file to be signed . Only for CADES signature it is possible to insert string: or string64: to define the string to be signed. In case of use of string64 it is expected to find a Base64 string.
An example:
<div class="bit4id-document">stringb64:OTE3MDA4ZWYtYjEzZi00YWU3LWEyMTEtYjM4NjQ3NDU5MjQ3</div>
bit4id-signingAlgorithm: Defines the algorithm that will be used to sign.
bit4id-encoding: Defines the encoding of the output signed file. 1 for base64 encoding or 0 for binary encoding.
bit4id-issuerFilter: Defines the signing certificate filter as a sub-string of the certificate issuer distinguished name.
bit4id-certType: Defines the signing certificate filter as a string describing the type of certificate.
bit4id-certInfo: Defines the attribute shown on the 4Identity client.
bit4id-bundle: If this option is set to YES, the file to sign must be a zip archive containing all files to sign. The files contained into the zip archive will be shown on the preview as usual. The signature output will be a zip archive with the signed files inside.
bit4id-filepath: Defines the absolute path for the file to be signed.
- The document path, in this case is a file (TestData.pdf) stored on the server as.example.com :
<div class="bit4id-document">http://as.example.com:8080/4identity/TestData.pdf</div>
- The file name:
<div class="bit4id-documentName">TestData.pdf</div>
PAdES SIGNATURE API
This section describes the parameters of the signature to be included within the form class: bit4idsignReq to perform a PAdES signature request.
Parameter | Values | Default |
---|---|---|
bit4id-signatureType | “PAdES” | NO DEFAULT |
bit4id-page | “0”, “1”..”n” | “0” (Invisible) |
bit4id-position | “[1x, 1y, 2x, 2y]” | “[]” |
bit4id-location | “location string” | “” |
bit4id-reason | “reason string” | “” |
bit4id-signingAlgorithm | “RSASHA256”, “RSASHA1”, “RSAMD5” | “RSASHA256” |
bit4id-level | “LTV” | “” |
bit4id-paragraphFormat | “signature string (on image)” | “” |
bit4id-image | “http://imageurl”, “data:image/png;base64,R0lGODdhMA...” | “” |
bit4id-issuerFilter | “CN=..., OU=..., T=..., .=...” | “” |
bit4id-certType | “ANY”, “SIG”, “AUT” | “ANY” |
bit4id-certInfo | “CN, OU, T, ecc.” | NO DEFAULT |
bit4id-filepath | Absolute path for the file to be signed. | C:\File\example.pdf |
bit4id-page: Defines the pdf document page where the signature will be added. (Only for graphical signature)
bit4id-position: Defines the position, in points, on the pdf document page selected, where the signature will be shown. (Only for graphical signature)
bit4id-location: Defines the location of signing.
bit4id-signingAlgorithm: Defines the algorithm that will be used to sign.
bit4id-paragraphFormat: Defines the text that will be drawn on the graphic signature.
bit4id-image: Defines the url or data-url from where to download the image that will be used for the graphical signature appearance.
bit4id-issuerFilter: Defines the signing certificate filter as a sub-string of the certificate issuer distinguished name.
bit4id-certType: Defines the signing certificate filter as a string describing the type of certificate.
bit4id-certInfo: Defines the attribute shown on the 4Identity client.
bit4id-filepath: Defines the absolute path for the file to be signed.
XAdES SIGNATURE API
This section describes the parameters of the signature to be included within the form class: bit4idsignReq to perform a XAdES signature request.
Parameter | Values | Default |
---|---|---|
bit4id-signatureType | “XADES” | NO DEFAULT |
bit4id-hashAlgorithm | “SHA256”, “SHA1”, “MD5” | “SHA256” |
bit4id-signatureMode | “Enveloping”, “Enveloped”, “InternalDetached”, “Binary” | “Enveloped” |
bit4id-level | “BES”, “T”, “C”, “X”, “XL” | “BES” |
bit4id-binary | 1 or 0 | “0” |
bit4id-xpath | “xpath of node to be signed” | “/*” |
bit4id-signingAlgorithm | “RSASHA256”, “RSASHA1”, “RSAMD5” | “RSASHA256” |
bit4id-issuerFilter | “CN=..., OU=..., T=..., .=...” | “” |
bit4id-certType | “ANY”, “SIG”, “AUT” | “ANY” |
bit4id-certInfo | “CN, OU, T, ecc.” | NO DEFAULT |
bit4id-filepath | Absolute path for the file to be signed. | C:\File\example.txt |
bit4id-hashAlgorithm: Defines the type of hashing algorithm that is used to sign.
bit4id-signatureMode: Defines the type of XAdES signature that will be used.
bit4id-level: Defines the level of XAdES signature that will be used.
bit4id-binary: Set to 1 if you want sign a binary file, or 0 to sign an xml.
bit4id-xpath: Defines the node of the XML document that will be signed as an xpath expression string.
bit4id-issuerFilter: Defines the signing certificate filter as a sub-string of the certificate issuer distinguished name.
bit4id-certType: Defines the signing certificate filter as a string describing the type of certificate.
bit4id-certInfo: Defines the attribute shown on the 4Identity client.
bit4id-filepath: Defines the absolute path for the file to be signed.