25 May 2019 - tsp
Last update 07 Feb 2021
13 mins
The following article provides a short summary (since documentation is hard to find and because of the
XML-heavy nature and complexity of the specification) on how to use the citizen card issed in Austria
to sign actions triggered by users and how to use that for authenticating users. Note that not
all features of the card are available to all users of the service. For example the identity binding
cannot be queried by any instance of the service that’s not using a server side SSL certificate for
a domain under the .gv.at
domain or has an additional government agency usage attribute set
inside their X.509 server certificate.
Rationale: Why would one want to use the card for authentication? Because smartcards provide way better security than passwords or client certificates that are not stored inside an HSM - and of course they provide security lightyears better than using SMS or applications on mobile phones as second factors (see the comparison of TAN mechanisms)
Only the Null operation as well as the basic signing operation will be discussed in this short summary. The API is capable of doing much more but none of these services is required for basic signing and authentication.
The basic infrastructure that’s used is an application running on the users system that is interfacing
the local smartcard reader (or other HSMs) to be capable of signing requests and providing identity
information. I’ve also tried to use the smartcard via the usual well established PKCS#11
interface
supported by many browsers for SSL client authentication - but unfortunately wasn’t able to use it that way.
The application is interfaced with other web applications by providing an local webbrowser
listening on 127.0.0.1:3495
with a single http-security-layer-request
endpoint. Since the
webserver runs locally it is accessed via http (i.e. http://127.0.0.1:3495/http-security-layer-request
).
Requests are sent as POST
requests either via form submission or using an XMLHttpRpcRqeuest
(Ajax).
After a user has issued an request the browser gets issued an redirect to an additionally supplied RedirectURL
.
Note that this happens immediately - even before the requested operation has finished. This redirection is done
by means of HTTP 302 (Found, moved temporarily). The URI supplied by the application on the request is copied
without any modification so it may contain some session information.
Data responses (for example decrypted information, identity information, signatures, etc.) of the application
are not delivered by redirection but by a separate http or https request (many operations require SSL with an
verifyable certificate to be used - and it’s a good idea anyway for sensitive information from an AAA process)
made by the local application to the application server. The address is specified as dataURL
and can contain
additional session information. Note that since the request is not made by the users browser the session
information from URI parameters is the only way to correlate data requests with the original HTTP request whenever
one doesn’t have request information embedded for example in the signed content which is available too.
The following operations are commonly used:
CreateXMLSignatureRequest
)InfoboxReadRequest
). This
is an request that is restricted to certain government agencies and certified applications. For
companies there is an additional method of requesting less information by providing the governmental
issued companies register identifier.InfoboxReadRequest
on the Certificates
store.
This of course only reads public keys, private keys are as usual never exposed by the smartcard (this is
of course not enforced by the application but by the smartcard)There are additional operations that are supported but not commonly used. These are:
All applications are performed by requesting the operating via a well formed XML - responses are contained in XML documents too. The client side security application can perform XSLT transformations on data shown to users as well as data that should be signed - the following article only describes the most basic usage to introduce the way these mechanisms work without getting too XML loaded (which is one of the reasons these mechanisms are not implemented very often).
The following operations are the operations that are interesting to authenticating users
The null operation is simply a no-operation operation that can be used to verify the presence of the client side security application.
It is triggered by sending an POST
request to the http://127.0.0.1:3495/http-security-layer-request
endpoint. This operation requires at least one parameter but is normally called with 3 parameters:
XMLRequest
is the required request that gets parsed by the security layer. It’s described belowDataURL
contains an URI to which the application should send the application - application request (not
using the users browser). These requests are always POST
requests.RedirectURL
is the URL the user gets redirected via a HTTP 302 response. This happens immediately - i.e. it
has no direct timed relation to the data URL request.The XML request is an XML document containing just the NullOperationRequest
:
<?xml version'1.0' encoding='UTF-8'?>
<NullOperationRequest xmlns='http://www.buergerkarte.at/namespaces/securitylayer/1.2#'/>
If one wants to trigger a null operation by an HTML form one could use the following document:
<!DOCTYPE HTML>
<html>
<head>
<title> Do a NULL request </title>
</head>
<body>
<form action="http://127.0.0.1:3495/http-security-layer-request" method="POST">
<input type="hidden" name="XMLRequest" value="<?xml version'1.0' encoding='UTF-8'?> <NullOperationRequest xmlns='http://www.buergerkarte.at/namespaces/securitylayer/1.2#'/>">
<input type="hidden" name="DataURL" value="https://example.com/index?action=null_dataurl">
<input type="hidden" name="RedirectURL" value="https://example.com/index?action=null_redirurl">
<input type="submit" value="NULL request">
</form>
</body>
</html>
One would see that the user gets redirected with an GET request to the redirection URL receives an POST request with URL-encoded payload. This payload contains two fields:
ResponseType
just contains the string HTTPS-Security-Layer-RESPONSE
XMLResponse
contains an XML document describing the response:<?xml version='1.0' encoding='UTF-8'?>
<sl:NullOperationResponse xmlns:sl='http://www.buergerkarte.at/namespaces/securitylayer/1.2#' />
One can use URL parameters to correlate the data request with any user sessions.
Signing requests support signing of full XML documents according to the XML Signature Syntax and Processing Version 1.1 recommendation. This is not required for most simple applications (for example because they want to sign a simple base64 encoded string, a simple unique number or timestamp, etc.). The signature request also supports transforming the signature data via an XSLT request (if the client application supports that) to display them in a rich formatted display. As a more extended method the client also supports a subset of XHTML which is way out of scope for this article. These features are also not presented in the following section.
To request the signature of some data a POST
request is done again to the http://127.0.0.1:3495/http-security-layer-request
endpoint. The same three parameters (XMLRequest
, DataURL
, RedirectURL
) as before are used.
The most basic XML request to sign text/plain
data object contains an CreateXMLSignatureRequest
object
selecting the SecureSignatureKeypair
keypair and supplying the data inside an DataObjectInfo
as the DataObject
inside it’s XMLContent
element. The TransformInfo
is not used for anything else than supplying the MIME type
of the content.
<?xml version="1.0" encoding="UTF-8"?>
<sl:CreateXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
<sl:DataObjectInfo Structure="enveloping">
<sl:DataObject>
<sl:XMLContent>Sample text</sl:XMLContent>
</sl:DataObject>
<sl:TransformsInfo>
<sl:FinalDataMetaInfo>
<sl:MimeType>text/plain</sl:MimeType>
</sl:FinalDataMetaInfo>
</sl:TransformsInfo>
</sl:DataObjectInfo>
</sl:CreateXMLSignatureRequest>
The redirection URI gets set to the landing page that the user gets redirected to (this is the same page in case of successful signature as well as in case of a failed signature - for example when the user aborts the process). The data URI is the URI that receives the signature data (asynchronously).
The signature output (in case of successful signature) contains the signed data (see the dsig:Object Id="signed-data-1-1"
element),
the X509Certificate
certificate used to sign the data (this may be used to identify the user later on in an
sign on system) as well as some certificate information. The digests of all objects are included too - note that a variety
of signature algorithms may be used - at the time of writing SHA256 was the standard algorithm. All hashes as well as
the certificate data are base64 encoded. The base64 encoded hashes are raw binary data, encoded certificates are base64
encoded DER encoded X.509 certificates.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<sl:CreateXMLSignatureResponse xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="signature-1-1">
<dsig:SignedInfo>
<dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
<dsig:Reference Id="reference-1-1" URI="#signed-data-1-1">
<dsig:Transforms>
<dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
<xpf:XPath xmlns:xpf="http://www.w3.org/2002/06/xmldsig-filter2" Filter="intersect">id('signed-data-1-1')/node()</xpf:XPath>
</dsig:Transform>
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<dsig:DigestValue>...=</dsig:DigestValue>
</dsig:Reference>
<dsig:Reference Id="etsi-data-reference-1-1" Type="http://uri.etsi.org/01903#SignedProperties" URI="#etsi-signedproperties-1-1">
<dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<dsig:DigestValue>I...=</dsig:DigestValue>
</dsig:Reference>
</dsig:SignedInfo>
<dsig:SignatureValue Id="signaturevalue-1-1">P4NKWG8G7w6fMbDrdH1Kyc9oB0gdT3Iw9XtIeKOKqu+cZqlOIMyc1rJ3GhYz2WCN35mCTKQzObZ+DFcKUH7xPQ==</dsig:SignatureValue>
<dsig:KeyInfo>
<dsig:X509Data>
<dsig:X509Certificate>MII....==</dsig:X509Certificate>
</dsig:X509Data>
</dsig:KeyInfo>
<dsig:Object Id="signed-data-1-1">Sample text</dsig:Object>
<dsig:Object Id="etsi-signed-1-1">
<etsi:QualifyingProperties xmlns:etsi="http://uri.etsi.org/01903/v1.3.2#" Target="#signature-1-1">
<etsi:SignedProperties Id="etsi-signedproperties-1-1">
<etsi:SignedSignatureProperties>
<etsi:SigningTime>2019-05-24T23:42:14Z</etsi:SigningTime>
<etsi:SigningCertificate>
<etsi:Cert>
<etsi:CertDigest>
<dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<dsig:DigestValue>....=</dsig:DigestValue>
</etsi:CertDigest>
<etsi:IssuerSerial>
<dsig:X509IssuerName>CN=a-sign-Premium-Sig-05,OU=a-sign-Premium-Sig-05,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT</dsig:X509IssuerName>
<dsig:X509SerialNumber>XXXXXXXXXXXXXX</dsig:X509SerialNumber>
</etsi:IssuerSerial>
</etsi:Cert>
</etsi:SigningCertificate>
<etsi:SignaturePolicyIdentifier>
<etsi:SignaturePolicyImplied/>
</etsi:SignaturePolicyIdentifier>
</etsi:SignedSignatureProperties>
<etsi:SignedDataObjectProperties>
<etsi:DataObjectFormat ObjectReference="#reference-1-1">
<etsi:MimeType>text/plain</etsi:MimeType>
</etsi:DataObjectFormat>
</etsi:SignedDataObjectProperties>
</etsi:SignedProperties>
</etsi:QualifyingProperties>
</dsig:Object>
</dsig:Signature>
</sl:CreateXMLSignatureResponse>
To display certificate data for debugging purposes one can use the
openssl x509 -noout -text -inform der -in BINARYDATA.DER
command (in the following output the fields CN (Common Name - the full name of the user), SN (Sure name) and GN have been anonymized as wel as the serial number. Note that this would not really have been required since this certificate only contains publically available data.
Certificate:
Data:
Version: 3 (0x2)
Serial Number: XXXXXXXXXXXXXX (0xXXXXXXXXXXXXXX)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, OU=a-sign-Premium-Sig-05, CN=a-sign-Premium-Sig-05
Validity
Not Before: Jan 11 11:58:14 2017 GMT
Not After : Jan 11 10:58:14 2022 GMT
Subject: C=AT, CN=XXXXXXXXXXXXXX, SN=XXXXXXXXXXXXXX, GN=XXXXXXXXXXXXXX/serialNumber=XXXXXXXXXXXXXX
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:6a:c8:33:21:f6:13:67:65:26:42:eb:a4:87:38:
...
b7:6d:fa:ec:fc
ASN1 OID: prime256v1
X509v3 extensions:
Authority Information Access:
CA Issuers - URI:http://www.a-trust.at/certs/a-sign-Premium-Sig-05.crt
OCSP - URI:http://ocsp.a-trust.at/ocsp
X509v3 Key Usage: critical
Digital Signature, Non Repudiation
qcStatements: critical
0.0......F..0
..+.......
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.a-trust.at/crl/a-sign-premium-sig-05
X509v3 Basic Constraints:
CA:FALSE
X509v3 Certificate Policies:
Policy: 0.4.0.1456.1.1
Policy: 1.2.40.0.17.1.11
CPS: http://www.a-trust.at/docs/cp/a-sign-Premium
X509v3 Authority Key Identifier:
keyid:41:F8:08:39:1B:01:E8:24
X509v3 Subject Key Identifier:
4D:...:11
Signature Algorithm: sha256WithRSAEncryption
84:93:f8:48:08:ad:6d:b4:7e:2c:3d:7b:24:29:b0:e2:37:16:
...
f5:06:d5:48:21:a4:c3:0b
One can use the certificate hash or the certificate itself as an identifier for the user for an authentication system. Note that this certificate of course changes whenever the user exchanges his signature card. One can also just check the subject (which also changes since it includes the serial) if one trust the signature of the issuer.
The basic idea is simple. One can perform a binding between a user and his certificate by issuing a simple signature request against some arbitrary random (guaranteed to be used only once) bunch of data. The response contains a signature as well as the certificate data one can store the certificate data or it’s hash inside an database or directory and link it to the internal user id. The signature has to be verified to prevent spoofed requests. Note that this is not easily preventable during the first registration - one can protect the user against that attacks by attaching an nonce to the data URI that can only be used for a really short time interval for exactly one operation - of by displaying the Subject contained inside the request. This of course does not protect against malware on the users computer during the registration process that might intercept the request and insert it’s own certificate.
After registration a user can log in by simply signing a random only-used-once nonce again. The certificate received with the signature request can be used to identify the user, the signature has to be verified to check that the request really originated from the user and is not replayed from a previous time. One should also include additional information from the session to prevent replaying or intercepting the requests.
This article is tagged:
Dipl.-Ing. Thomas Spielauer, Wien (webcomplains389t48957@tspi.at)
This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/