The Incommon Federation wiki has moved.

Please visit the new InCommon Federation Library wiki for updated content. Remember to update your bookmarks.

Click in the link above if you are not automatically redirected in 15 seconds.



You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 30 Next »

Handling of Private Keys

This topic discusses the proper handling of the IdP's private signing key. The corresponding public key is bound to an X.509 certificate in IdP metadata. Note that a signing key is used for more than just signing, as discussed in the Key Usage topic.

Protect your private keys!

Positive control of your private keys must be maintained at all times. This includes the private keys used for browser-facing TLS, XML Signature, and XML Encryption.

This topic focuses on the keys used for XML Signature. See the TLS Server Certificates topic regarding keys and certificates used for browser-facing TLS.

Key Generation

The security of your IdP deployment depends on the security of the private key used to sign SAML messages. Develop a strategy for securing your private key before you generate it. For instance, the following strategy is highly recommended:

  1. Start with a secure system for your IdP…and keep it that way!
  2. Generate the private signing key directly on the secure IdP system
  3. Prevent the private signing key from ever leaving the secure system
  4. Ensure ongoing access to the private signing key is strictly controlled

If you generate the private signing key on any other system, then that system must also be secure. Indeed, every system the private key comes in contact with must be secure—at least as secure as the target system—or the private key must be encrypted at rest. Moreover, the private key must be encrypted while in transit to the secure system. All in all, that is much more work (and error-prone), so the best advice is don't do it. Generate your private keys on the target IdP in the first place.

Here's another way to state these basic security requirements:

  • Until the private key is securely stored on the target IdP (or SP) infrastructure, it needs to be encrypted, both at rest and in transit.
  • Under no circumstances should an unencrypted private key come to rest on an insecure system or transit the network over an unprotected channel.

It is easy to generate a private key and a corresponding long-lived, self-signed certificate with OpenSSL. On a linux system, type:

$ /usr/bin/openssl req -new -x509 -newkey rsa:2048 -keyout key.pem \
    -days 3650 -subj "/CN=hostname.example.org" -out cert.pem

The above command will store the private key in file key.pem and the corresponding public key certificate in file cert.pem. The latter is ultimately added to your IdP's metadata.

Test your OpenSSL software installation

OpenSSL is a subtly complicated tool having many versions with various capabilities (and bugs). It is recommended that all OpenSSL commands be tested in advance to ensure that the tool is functioning as expected.

When you issue the above OpenSSL command, you will be prompted to enter a pass phrase for the purpose of decrypting an encrypted private key. If you're generating the private key directly on the IdP, it is not necessary to encrypt the private key since it is assumed your host system is secure. Simply press return when prompted to enter a pass phrase or use the -nodes option in the command above to issue an unencrypted private key straightaway.

If, however, you're generating the private key on any other host, you must encrypt the private key as stipulated earlier. Once the private key has been secured on the target IdP, it may be decrypted in situ with the following OpenSSL command:

$ /usr/bin/openssl rsa -in key.pem -out key.pem

Simply press return when prompted to enter a new pass phrase.

The IdP Signing Key

In the case of the IdP, the private key is used to sign SAML assertions transmitted to the SP. (The corresponding certificate in metadata contains the public key that is used by the SP to verify the signature on the assertion.) If the private key is lost or stolen, the holder has the power to issue arbitrary assertions to any SP. This is the absolute worst thing that can happen in a federated context.

The IdP's private signing key is necessarily an online key, that is, it must be available to the IdP software at runtime. An online key may be encrypted, but the password or passphrase used to decrypt the key generally has to be available in an unencrypted file so that the IdP service can be restarted in unattended fashion. Therefore an online key is considerably more vulnerable than an offline key, and must be protected accordingly.

If the signing key is stored in the file system as an ordinary file, it should have strict permissions to prevent unauthorized copying of the private key. For stronger protection, the signing key may be stored in a hardware security module (HSM) that prevents export of the private key.

Key Audit

You need to go back to day one of the total lifetime of each of your private keys and ask the following question: Has this key been under my positive control at all times? If the answer to that question is anything other than yes, the key should be considered compromised. This requires you to securely generate a new private key and to systematically migrate the corresponding public key certificate out of metadata. See the Certificate Migration topic for safe instructions how to do this.

If there is reason to believe that the IdP's signing key has fallen into the wrong hands, it should be replaced immediately. In this case, there can be no orderly migration of the corresponding public key certificate in metadata, which should be replaced immediately as well. This will break interoperability with SPs until such time as they have refreshed metadata (which is why regular, automated metadata refresh is important), so replace the IdP's signing key only under the most serious circumstances.

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))
  • No labels