LabVIEW Web Services Security

Contents

How do I secure my Web services?

When many people think about security, they think in terms of encryption, user IDs, and passwords. User IDs and passwords are used for authorization (telling the target who is making the request). Encryption protects the communications traffic between client and server so that unauthorized individuals cannot intercept and read the sent and received data.

LabVIEW 8.6 does not support built-in encryption, so secured requests sent between clients and LabVIEW Web services are sent unencrypted or "in-the-clear". However, the requests are "digitally-signed", with a secret key intended to be known only by authorized applications. So in LabVIEW Web services, security is accomplished by only accepting and acting on "signed" requests from client applications, and validating the signature to verify the request was created by an application with authorization to access the requested resource such as the Web method VI or static document.

A developer may secure a LabVIEW Web service by checking the Require API Key checkbox in the Mapping Information options group beneath the URL Mappings page in the service's build specification. This setting is individually-specified for each URL mapping, not for the Web service as a whole. You should enable security for every URL map that you want secured.

How does the Web service runtime engine verify a digital signature?


At runtime, the Web services runtime engine inspects every client request as it arrives. When a request matches a secured URL mapping, the runtime looks for the "digital signature" in the request. If this signature is missing or incorrectly formed, the request is rejected. If the signature is present, the runtime looks at the request and calculates what the signature should be for that request. It then compares its calculated signature with the one actually present in the message. If the two do not match, the request is rejected.

When a secured request is rejected, the client receives an HTTP response containing an "HTTP/1.1 403 Forbidden" error, indicating that the request has been rejected because the client was not authorized to make that request.

The algorithm for creating signatures includes the time of day of the request, and the runtime is configured to reject any request containing an "out-of-date" signature. A signature is considered to be out-of-date if it was created more than a configured number of minutes outside a window from the current time. By default this is plus or minus 15 minutes. This is to minimize the likelihood that an unauthorized application could capture a properly-signed request and "replay" it to perform an unauthorized action at a later time.

Note that this means that the clocks on the server and the client must be correctly set. The signature time uses UTC time, which is timezone-independent, so the client and server may be in different timezones.
The digital signature mathematically guarantees that a request has not been altered in transit. Any attempt to change a request after it has been signed automatically invalidates the signature.

The core assumption is that secured Web service requests must be authorized by the presence of a digital signature, and only an application that is authorized has the knowledge to create a proper digital signature.

Digital Signing Overview

The mechanism for "digitally signing" requests uses a custom HTTP scheme based on a keyed-HMAC (Hash Message Authentication Code) for authentication. To form an authenticated request, clients must first concatenate selected elements of the request to form a string. They then use LabVIEW's Access ID and Secret ID to calculate the HMAC of that string. Informally, we call this process "signing the request," and we call the output of the HMAC algorithm the "signature" because it simulates the security properties of a real signature. Once the signature has been made, it is added to the collection of HTTP headers to be sent to the server as part of the request, using the syntax that we describe below.

The LabVIEW Web Services Security Key

Each installation of LabVIEW contains a Web Services Security Key (found in the Web Services: Security page in the Tools>>Options menu). The Security Key consists of an Access ID and a Secret ID. These correspond roughly to a username and password, in that the Access ID is considered to be well-known and the secret ID is considered to be private, known only to an authorized user.

Each installation of the LabVIEW IDE, the LabVIEW Runtime Engine, and all LabVIEW Real-Time targets are installed with a default key (see below). On Windows, it can be changed at any time by using the Web Services: Security page in the Tools>>Options menu, and requires a restart of LabVIEW to activate changes. For RT targets, it is in the Web Services: Security page on the target, and it is necessary to restart the target after changing the Security Key.

LabVIEW's key generation algorithm creates a highly randomized string of printable characters. We strongly recommend allowing LabVIEW to generate new security keys. Once the keys have been chosen for a particular LabVIEW installation, you can copy the key (both parts) to the clipboard by pressing the Copy to Clipboard button in the Security Key dialog, and either paste them into a text document or into another copy of LabVIEW on another machine.

One common use for copying the Security Key to the clipboard is to be able to paste it into a client application's configuration dialog or its source files, so that those clients may invoke secured Web services on your targets. If your clients must talk to multiple Web services targets, it will need the Security Key for each target. Alternatively, you can use the copy/paste feature to past the same Security Key into all your targets and servers and only need to keep track of a single key.

The default Security Key at installation time is:
AccessID = 'PqVr/ifkAQh+lVrdPIykXlFvg12GhhQFR8H9cUhphgg='
SecretID = 'pTe9HRlQuMfJxAG6QCGq7UvoUpJzAzWGKy5SbZ+roSU='

*Note that the single-quotes around the strings above are NOT part of the individual strings.

So how is the key used?

Client applications use the Security key as part of the digital signing process for Web service requests by combining elements from the message to be sent with both parts of the Security Key via a mathematical algorithm. The resulting signature is for this one instance of this request. It will not work for any other request. Furthermore, it has an expiration date (15 minutes from the time of creation by default, though this can be modified) so that it can't be intercepted and replayed by an unauthorized user.

Digital signatures can only be created by someone who knows both parts of the Security key.

Creating the Signature In Client Applications

Signing a request requires that you have implementations of the MD5 digest algorithm, as well as the SHA256 cryptographic digest algorithm, able to be called from your client’s programming language. Both of these algorithms are commonly available for most platforms. You also need:

  1. The string for the HTTP method to be used (‘GET’, ‘POST’, ‘PUT’, ‘DELETE’)
  2. The target IP address (or DNS hostname)
  3. The URL requested at that address
  4. An HTTP content body (may be present for ‘PUT’ or ‘POST’ requests)
  5. The current time of day (in UTC time using format ‘YYYY-MM-DD HH:MM:SSZ’)
  6. Both elements of the Security Key (Access ID and Secret ID)

For example, given the following HTTP request:
Method = GET
Time = 2008-07-23 22:41:02Z
URL = /quotes/NATI

  1. The client creates a number of individual string elements that will get concatenated together. These elements are:
    The string for the HTTP method to be used (‘GET’, ‘POST’, ‘PUT’, ‘DELETE’)
    ‘GET’
  2. The URL requested
    '/quotes/NATI'
  3. The current time of day (in UTC time using format ‘YYYY-MM-DD HH:MM:SSZ’)
    ‘2008-07-23 22:41:02Z’
  4. The Access ID portion of the Security Key
    'PqVr/ifkAQh+lVrdPIykXlFvg12GhhQFR8H9cUhphgg='  the default Access ID
  5. The hex-encoded MD5 digest of the Secret ID portion of the Security Key
    Given: 'pTe9HRlQuMfJxAG6QCGq7UvoUpJzAzWGKy5SbZ+roSU='  the default Secret ID
    ‘4ce83e7d608f70375fd1cda0a6f3ae66’  the hex-encoded MD5 digest of the Secret ID string
  6. The hex-encoded MD5 digest of the content-body if there is a content-body for the request (Not applicable for this request because there is no content-body for a GET request).

Appended together, these give us a string of:
‘GET/quotes/NATI2008-07-23
22:41:02ZPqVr/ifkAQh+lVrdPIykXlFvg12GhhQFR8H9cUhphgg=4ce83e7d608f70375fd1cda0a6f3ae66’

We then calculate the SHA256 digest of that string (which gives us an array of binary data) and encode that array in Base64, to give us:
‘xTDFuYyLJpwOLL2bKKlAco59W/0N53BnVwOGNZ0fXl0=’

To form the final signature, we append together:

  1.  ‘NIWS’ (for requests with no content-body, or for requests in which we do not want to include the content-body as part of the signature) or ‘NIWS2’ (for requests with a content body).
  2. A blank space (0x20).
  3. The Access ID
  4. A colon (0x3a)
  5. The Base64-encoded SHA256 digest, as calculated above.

This gives us the signature string:
‘PqVr/ifkAQh+lVrdPIykXlFvg12GhhQFR8H9cUhphgg=:xTDFuYyLJpwOLL2bKKlAco59W/0N53BnVwOGNZ0fX
l0=’

This signature string is added to the HTTP request as a header named: “x-ni-authentication”.

The timestamp string used to create this signature is also attached to the signature as a header named “x-ni-date”.
So a complete signed HTTP request (with ‘\n’ shown to represent the required carriage returns) would look like:

GET /quotes/NATI HTTP/1.1 ‘\n’
x-ni-date: 2008-07-23 22:41:02Z ‘\n’
x-ni-authentication: NIWS PqVr/ifkAQh+lVrdPIykXlFvg12GhhQFR8H9cUhphgg=:xTDFuYyLJpwOLL2bKKlAco59W/0N53BnVwOGNZ0fXl0= ‘\n’
‘\n’

This signature, embedded as HTTP headers, is only for this request. It could only have been
created by someone who knew the algorithm and both parts of the Security Key. Plus, the signature includes an encoded version of the timestamp, so the signature has a built-in expiration time, as configured on the LabVIEW target. Outside of that time window, this signature is automatically invalid, preventing later replays of the request.

Note that the timestamp calculations require that the clock be properly set on both the client and the LabVIEW target. Because the timestamp string is written in UTC time, the client and servers can each be in different time zones, as long as their local clocks and time zones are correctly set.

Example

The accompanying Ruby_Security_Client.zip contains a LabVIEW 8.6 project and Web service, along with a Ruby client program that demonstrates invoking the included Web services from Ruby. The Ruby client contains the logic necessary to digitally sign HTTP requests for invoking secured Web services.

Related LabVIEW Web Services Documents on ni.com

Scripting in LabVIEW Web Services
A guide to ESP scripting using LabVIEW Web services and the LabVIEW Web Server.