REBOL/Services Security, Authentication, Encryption
The level of security for REBOL/Services depends on the needs of each service provider. Some services may be totally open, allowing everyone access to all information. For example, you might be publishing free documents, sources, or images for download to all users. Other services may be completely closed, denying access to all users except those who possess valid credentials. An example would be a service that allows access to corporate financial documents or patient medical information.
The range of security allowed for REBOL/Services is more than just on or off. There are several layers to the the security model that can be enabled. They include:
- IP address filtering
- Private key encryption
- Dynamic session key encryption
- User authentication
- Service certification
- Command permissions
This document will cover each of these security features in the sections below.
IP Address Filtering
IP address filtering lets you explicitly allow or deny connections to a server based on the address of the client. For example, if you want to restrict access to specific addresses or a range of client addresses, you can specify that. Or, you can also invert the logic and specify addresses that are denied access to your server.
To setup IP filtering, you can provide the addresses and masks for the clients or networks that you want to allow or deny. See the examples section below.
This is a fairly common method of security that is used on many types of servers; however, it is not entirely foolproof. It is known to be possible for a client to spoof its IP address to bypass this type of security. For high security applications, use this method only in conjunction with one or more of the other methods listed below.
Several types of encryption are supported by REBOL/Services. By default, all REBOL/Service packets are encrypted, but a service has control over the strength of encryption. The combinations are listed here:
- Cloak method with REBOL public key (default)
- Cloak method with shared private key
- Cloak method with unique session key
- AES method with shared private key
- AES method with unique session key
- RSA method with private/public key pairs
Note that REBOL/Services does not supply an unencrypted mode of operation.
Cloak is a high-speed but low strength encryption method that is provided in all versions of REBOL. It has three modes of operation:
|Public||When used with the REBOL public key (#1 in above list), it provides a simple means of data hiding as packets transfer over the network.|
|Private||You can restrict access to your service requiring all clients to encrypt packets using a private key (a "shared secret"). Each side must use the same private key. The key length can be any size (any number of bits). In theory, the more bits, the stronger the encryption.|
|Session||When a client provides account information that is authenticated by a server, a new private key is generated for all subsequent packets. This session key is separately generated by both the server and the client and is produced from the hashed combination of private keys and the account password challenge. The new session key is never sent over the network. If the client does not possess the necessary private keys and account password, access is not allowed. The session key can be regenerated at any time during the session by sending a special command request to the service.|
AES is the advanced encryption standard. This is a high-strength cryptographic cipher based on the Rijndael algorithm. AES allows encryption in one pass instead of the three passes used by the DES method. This is an optional encryption method available only in REBOL/Command and REBOL/SDK. Two modes of operation are supported:
|Private||Restricts access to your service requiring all clients to encrypt packets using an AES private key (a "shared secret"). Each side must use the same AES private key and up to 256 bits are allowed (in non-restricted countries based on export laws).|
|Session||Same as cloak method above, but using the AES key.|
RSA Encryption and Server Certification
RSA is a highly secure cryptography method that consists of a private key and a public key. This is an optional encryption method available in REBOL/Command and REBOL/SDK. Two modes are used:
|Private||The RSA private key is only known to the server and each client has a copy of the public key. In this mode, server certification (validation that server is authentic) occurs because only the server has access to the private key. Until client authentication, all packets sent from the server are signed with the private key (providing certification), and all packets sent form the client are encrypted with the public key.|
|Session||Once authentication (login) takes place, a new session private key is generated and the encryption mode is upgraded to AES. (The RSA method is no longer necessary, because the server has been certified.) A new session key can be regenerated at any time upon request of the client.|
User authentication is performed via a 160 bit private key (hashed password) challenge method. The user's password is never sent over the network.
The authentication method has been streamlined by the login-service function provided in REBOL/Services. It is also possible to perform the authentication sequence manually by sending a login command to the server.
Here is a summary of the authentication sequence:
- Client sends to server a login request with an account name.
- Server computes a password challenge based on a SHA1 hashing method and the known password (or a one-way hashed version of the password).
- Server sends client the challenge along with a salt value that was used to compute the one-way hash of the original password. (The challenge uses a sequencing method that assures that it is always different, preventing the recording and playback of the logon packet sequence by a man-in-the-middle.)
- Client and server compute a session private encryption key based on shared-secrets and the challenge. Only an authentic client will produce the correct encryption key. Failure to provide the correct encryption will cause the server to close the session before access can proceed.
On the server, passwords are stored as SHA1 hashed strings, never as clear-text strings. The hash salt value (unique hashing randomizer) is stored along with the hashed password in order to provide it for client hashing. This also ensures that the password hash is always different, even when generated from the same text password.
The client application can either require that passwords be provided each time by the user, or optionally (for ease of access) the application can store the password using the same SHA1 hashing method as used on the server. Note that if the password is to be stored on the client it is important that it be stored as the SHA1 hash. Never store the clear text password to disk at any time because people often use the same password for many other purposes (never advised, but in reality this is a frequent occurance).
Additional protection for client authenticity can be accomplished by using the private key methods described above or ultimately with a physical memory card, keycard, or fingerprint methods that generate the required private keys.
If a password (or its hash equivalent) is stored on the client's disk, it is always possible in some way to obtain it. Without storage on media that is external to the client (such as a memory card), it is not possible to provide complete protection.
If it is absolutely necessary to store passwords (or their hashes) on the client, you can help protect them with additional levels of local encryption and by protecting or hiding the required encryption key in some other location (other than the local disk).
Packet Sequencing Protection
REBOL/Services provides further protection from man-in-the-middle packet playback attacks by encrypting a packet sequence number within the packets body.
In the unlikely event that a man-in-the-middle intercepts a packet and replays it during the same session and valid session key window, the packet will still be rejected due to its incorrect sequence number.
Securing Public Services
REBOL/Services allows you to operate a server that allows both public and private access. This is necessary if you want to allow allow some but not all of your services to be public. For example, you can create a service that allows people to openly download files, but not upload, delete, or change files.
If you plan to publish your service using the publish-service function, you must allow public access to the default service context (the info service) to allow the directory service to request the required information for publication (such as the server title, description, etc.) If your server requires private key access for the info service, your services cannot be published in the directory.
The public/private mode of operation is the default. In this mode, for public commands (like the info service) the server uses only the Cloak REBOL Public Key method described above. To access other services, the user must login and authenticate before access is allowed.
Once a user has been authenticated, the permission tags in the user's account become active. These tags provide a simple mechanism of allowing or denying access to selected services or commands on the same server.
For example, REBOL/Services allows administrators to remotely manage their servers. They can update the server's source code, modify user accounts, and even shutdown or restart the server. The required user account permission for this type of action is admin.
More information on account permissions will be covered in a separate document on user administration.
These examples show how to configure your server and clients to provide the above security methods.
To setup IP filtering, you can provide the addresses and masks for the clients or networks that you want to allow or deny. These are part of the server config object that is optionally provided to the open-service function.
Here are some examples:
ip-allow: [18.104.22.168 22.214.171.124 mask 255.255.0.0] ip-deny: [126.96.36.199 mask 255.0.0.0]
The first example only allows access to the 188.8.131.52 client and to any clients in the 198.50 subnet range. The second example denies all clients in the 100 subnet range.
Private Encryption Keys
Generate your encryption key as a binary string:
save %key.r copy/part checksum/secure mold now/precise 16
The above line generates and stores a unique 128 bit key.
To start your server with cloak private-key encryption enabled:
start-service/options tcp://:1234 compose [ private-key: (load %key.r) encode: pe-priv-cloak ]
Then, to use each client you will need:
rs-port: open-service/options tcp://host:1234 compose [ private-key: (load %key.r) encode: pe-priv-cloak ]
To start the server with AES encryption enabled:
start-service/options tcp://:1234 compose [ private-key: (load %key.r) encode: pe-priv-aes ]
Then, each client will need:
rs-port: open-service/options tcp://host:1234 compose [ private-key: (load %key.r) encode: pe-priv-aes ]
Closed Server Keys
To close a server (not allowing access to any open services, even the default info service), generate a key similar to the above, then start the server like this:
start-service/options tcp://:1234 compose [ open-key: (load %key.r) ]
Now all clients need the key, even to access normally open services:
rs-port: open-service/options tcp://host:1234 compose [ open-key: (load %key.r) ]
You can also use the open-key in conjunction with the private-key as shown above. If a private-key is provided, the session key will be generated from it. If no private-key is provided, the session key will be based on the open-key.
RSA Encryption Key Pairs
First, you will need to generate an RSA key pair:
rsa-key: rsa-make-key rsa-generate-key rsa-key 1024 3
Now, you can save the private key for use on the server:
save %rsa-server.r third rsa-key
and the public key for use on your clients:
save %rsa-client.r rsa-key/n
To start the server with RSA-encryption enabled:
start-service/options tcp://:1234 compose [ rsa-key: (context load %rsa-server.r) ]
Then, to use each client you will need:
rs-port: open-service/options tcp://host:1234 compose [ rsa-key: (load %rsa-client.r) ]
Notice that the client does not need the full RSA object, only the public key binary part of it.
Client Hashed Password Storage
Here is how to obtain the properly hashed password (in case you decide to store it somewhere to make login easier for users -- but see above warnings):
pass: request-pass ; returns password string port: login-service tcp://host:1234 "user" pass if port [ session: session-service? port pass-hash: make-pass pass session/challenge/2 ; now store it, whatever... ]
The second item in the challenge block is the salt needed to create the correct password hash.