Skip to content

Latest commit

 

History

History
133 lines (101 loc) · 4.54 KB

README.rdoc

File metadata and controls

133 lines (101 loc) · 4.54 KB

RightCert

Secure serialization using X.509 Certificates for digital signatures and encryption

Synopsis

RightCert provides a simple way to create X.509 certificates and use them to sign and/or encrypt data. Signatures can later be verified and encrypted data decrypted. RightCert also provides a secured serializer which can sign and optionally encrypt the serialized data. This serializer expose the standard ‘dump’ and ‘load’ methods and thus can be used in place of the other standard ruby serializers (Marshal, YAML, JSON etc.)

Installation

The latest stable RightCert release is available as a Ruby gem:

sudo gem install rightcert

The latest source code is available on github:

git clone git://github.com/rightscale/rightcert.git

Usage

Sign Data

Digital signatures can be generated from any string as follows:

def sign(data)
  # Certificate issuer distinguished name
  issuer = RightCert::DistinguishedName.new({ 
    'C'  => 'US',
    'ST' => 'California',
    'L'  => 'Santa Barbara',
    'O'  => 'MyOrganization',
    'OU' => 'Certification Services',
    'CN' => 'MyOrganization.com' })

  # Certificate subject distinguished name
  subject = RightCert::DistinguishedName.new({ 
    'C'  => 'US',
    'ST' => 'California',
    'L'  => 'Santa Barbara',
    'O'  => 'RightScale',
    'OU' => 'RightCert',
    'CN' => 'RightCert example' })

  # Create private key and certificate
  key = RightCert::RsaKeyPair.new
  cert = RightCert::Certificate.new(key, issuer, subject)

  # Generate digital signature
  RightCert::Signature.new(data, cert ,key)
end

The signature can then be validated using:

def check_signature(signature, cert)
  sig = Signature.from_data(signature)
  sig.match?(cert)
end

Encrypt Data

Similarly any string can be encrypted using:

def encrypt(data)
  # Generate key and certificate as previously
  # Then create encrypted document
  doc = RightCert::EncryptedDocument.new(data, cert)
  # Encrypted PEM encoded data can be retrieved with
  doc.encrypted_data
end

And decrypted with:

def decrypt(data, cert, key)
  doc = EncryptedDocument.from_data(data)
  doc.decrypted_data(key, cert)
end

Use Secure Serializer

The secure serializer uses certificates and corresponding private keys to sign and optionally encrypt the given payload.

It is important to understand that:

  1. A certificate only includes the public key component of a cryptographic key pair.

  2. Signing requires the use of a certificate and its private key, checking the signature then only requires the certificate (the idea is that only the signer has the secret private key and thus can sign but anyone can check the signature).

  3. Encrypting only requires the certificate but decrypting also requires the private key (anyone can encrypt the data but only the intended recipient can decrypt it).

A signing serializer thus needs access to the signer certificate and private key. An encrypting serializer also needs access to the intended recipients certificates. There needs to be a way to dynamically retrieve the corresponding certificates. This is done using certificate stores.

Certificate stores associate identities with certificates. The identity is associated when the data is serialized and can be keyed off to retrieve the right certificate upon deserialization.

RightCert provides a static store implementation which can be used when the certificates used for serialization are always the same and can be kept in memory. RightCert also provides a certificate store proxy cache which can be associated with any store implementation and will cache the most used certificates.

The serializer should be initialized prior to being used by calling the ‘init’ method:

# Initialize serializer, must be called prior to using it.
#
#  - 'identity':   Identity associated with serialized messages
#  - 'cert':       Certificate used to sign serialized messages and
#                  decrypt encrypted messages
#  - 'key':        Private key corresponding to 'cert'
#  - 'store':      Certificate store. Exposes certificates used for
#                  encryption and signature validation.
#  - 'encrypt':    Whether data should be signed and encrypted ('true')
#                  or just signed ('false'), 'true' by default.
#
def Serializer.init(identity, cert, key, store, encrypt = true)

Once initialized the serializer can be used the same way other serializers are:

data = RightCert::Serializer.dump(obj)
RightCert::Serializer.load(data).should eql(obj)