Skip to content

Session Encryption

Jay Tuley edited this page Nov 18, 2013 · 12 revisions

Because Public Key Cryptography is a slow and expensive and better suited to small amounts of data. Keyczar has a built in API that mixes asymmetric and symmetric encryption. It requires an asymmetric key set as show in Keyczar Public/Private Encryption and uses that the public key to encrypt a random AES key and random HMAC key stored as SessionMaterial and then encrypts your plaintext with that AES key, so that if you provide that SessionMaterial with the private key you can decrypt the plaintext.

So for encryption and creating the session

WebBase64 sessionMaterial;
WebBase64 cipherText;
using(var encrypter = new Encrypter("path_to_public_key_set"))
using(var sessionCrypter = new SessionCrypter(encrypter))
{
  sessionMaterial =sessionCrypter.SessionMaterial;
  cipherText = sessionCrypter.Encrypt(plaintext);
}

Note: If you are wondering what a WebBase64 is, it's a static type for a web safe base64 encoded string.

Then to decrypt from a session

using(var crypter = new Crypter("path_to_private_key_set"))
using(var sessionCrypter = new SessionCrypter(crypter, sessionMaterial))
{
   return sessionCrypter.Decrypt(cipherText);
}

However, if you don't close the sessionCrypter, you can actually encrypt/decrypt from the session starter or the session recipient.

Signing the session is also available to authenticate the sender, however the encryption/decryption then becomes one way. The sender can only encrypt and the recipient can only decrypt.

Sender

WebBase64 sessionMaterial;
WebBase64 cipherText;
using(var encrypter = new Encrypter("path_to_public_crypt_key_set"))
using(var signer = new AttachedSigner("path_to_private_sign_key_set"))
using(var sessionCrypter = new SessionCrypter(encrypter, signer))
{
  sessionMaterial =sessionCrypter.SessionMaterial;
  cipherText = sessionCrypter.Encrypt(plaintext);
}

Then to decrypt from a session

using(var crypter = new Crypter("path_to_private_crypt_key_set"))
using(var verifier = new AttachedVerifier("path_to_public_sign_key_set"))
using(var sessionCrypter = new SessionCrypter(crypter, sessionMaterial, verifier))
{
   return sessionCrypter.Decrypt(cipherText);
}

Note: This is compatible with the SignedSessionEncrypter/SignedSessionDecrypter of the Java/Python/C++ versions.

The C# api also has an alternative format for packing the symmetric key that makes the key type flexible.

So for encryption and creating the session

WebBase64 sessionMaterial;
WebBase64 cipherText;
using(var encrypter = new Encrypter("path_to_public_key_set"))
using(var sessionCrypter = new SessionCrypter(encrypter, symmetricKeyType: KeyType.AES_AEAD, keyPacker: new BsonSessionKeyPacker()))
{
  sessionMaterial =sessionCrypter.SessionMaterial;
  cipherText = sessionCrypter.Encrypt(plaintext);
}

Then to decrypt from a session

using(var crypter = new Crypter("path_to_private_key_set"))
using(var sessionCrypter = new SessionCrypter(crypter, sessionMaterial, keyPacker: new BsonSessionKeyPacker()))
{
   return sessionCrypter.Decrypt(cipherText);
}

Note: you can also add a signer and verifier to a session using a BsonSessionKeyPacker, it provides an extra security measure of signing the session material in addition to the cipher text, but this is only compatible with the C# version of Keyczar.