Code Monkey home page Code Monkey logo

slosilo's Introduction

Slosilo

Slosilo is providing a ruby interface to some cryptographic primitives:

  • symmetric encryption,
  • a mixin for easy encryption of object attributes,
  • asymmetric encryption and signing,
  • a keystore in a postgres sequel db -- it allows easy storage and retrieval of keys,
  • a keystore in files.

Installation

Add this line to your application's Gemfile:

gem 'slosilo'

And then execute:

$ bundle

Compatibility

Version 3.0 introduced full transition to Ruby 3. Consumers who use slosilo in Ruby 2 projects, shall use slosilo V2.X.X.

Version 2.0 introduced new symmetric encryption scheme using AES-256-GCM for authenticated encryption. It allows you to provide AAD on all symmetric encryption primitives. It's also NOT COMPATIBLE with CBC used in version <2.

This means you'll have to migrate all your existing data. There's no easy way to do this currently provided; it's recommended to create a database migration and put relevant code fragments in it directly. (This will also have the benefit of making the migration self-contained.)

Since symmetric encryption is used in processing asymetrically encrypted messages, this incompatibility extends to those too.

Usage

Symmetric encryption

sym = Slosilo::Symmetric.new
key = sym.random_key
# additional authenticated data
message_id = "message 001"
ciphertext = sym.encrypt "secret message", key: key, aad: message_id
sym = Slosilo::Symmetric.new
message = sym.decrypt ciphertext, key: key, aad: message_id

Encryption mixin

require 'slosilo'

class Foo
  attr_accessor :foo
  attr_encrypted :foo, aad: :id

  def raw_foo
    @foo
  end

  def id
    "unique record id"
  end
end

Slosilo::encryption_key = Slosilo::Symmetric.new.random_key

obj = Foo.new
obj.foo = "bar"
obj.raw_foo # => "\xC4\xEF\x87\xD3b\xEA\x12\xDF\xD0\xD4hk\xEDJ\v\x1Cr\xF2#\xA3\x11\xA4*k\xB7\x8F\x8F\xC2\xBD\xBB\xFF\xE3"
obj.foo # => "bar"

You can safely use it in ie. ActiveRecord::Base or Sequel::Model subclasses.

Asymmetric encryption and signing

private_key = Slosilo::Key.new
public_key = private_key.public

Key dumping

k = public_key.to_s # => "-----BEGIN PUBLIC KEY----- ...
(Slosilo::Key.new k) == public_key # => true

Encryption

encrypted = public_key.encrypt_message "eagle one sees many clouds"
# => "\xA3\x1A\xD2\xFC\xB0 ...

public_key.decrypt_message encrypted
# => OpenSSL::PKey::RSAError: private key needed.

private_key.decrypt_message encrypted
# => "eagle one sees many clouds"

Signing

token = private_key.signed_token "missile launch not authorized"
# => {"data"=>"missile launch not authorized", "timestamp"=>"2014-10-13 12:41:25 UTC", "signature"=>"bSImk...DzV3o", "key"=>"455f7ac42d2d483f750b4c380761821d"}

public_key.token_valid? token # => true

token["data"] = "missile launch authorized"
public_key.token_valid? token # => false

Keystore

Slosilo::encryption_key = ENV['SLOSILO_KEY']
Slosilo.adapter = Slosilo::Adapters::FileAdapter.new "~/.keys"

Slosilo[:own] = Slosilo::Key.new
Slosilo[:their] = Slosilo::Key.new File.read("foo.pem")

msg = Slosilo[:their].encrypt_message 'bar'
p Slosilo[:own].signed_token msg

Keystore in database

Add a migration to create the necessary table:

require 'slosilo/adapters/sequel_adapter/migration'

Remember to migrate your database

$ rake db:migrate

Then

Slosilo.adapter = Slosilo::Adapters::SequelAdapter.new

Contributing

We welcome contributions of all kinds to this repository. For instructions on how to get started and descriptions of our development workflows, please see our contributing guide.

slosilo's People

Contributors

andytinkham avatar dividedmind avatar dustinmm80 avatar h-artzi avatar jakequilty avatar jjmason avatar jtuttle avatar kgilpin avatar micahlee avatar nahumcohen avatar semyon-estrin avatar ucatu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slosilo's Issues

Recalculate fingerprints in `slosilo_keystore` during migration

When upgrading from a pre-FIPS version to a post-FIPS version of Conjur, the fingerprints of the keys in the table slosilo_keystore need to be updated. This was caused by an update to the hashing algorithm used to calculate them (#15).

Fix: Add a method to slosilo that recaclulate_fingerprints if they exist. This method will be triggered during migrations and potentially other events.

The gem will need to be updated in the appropriate downstream projects

Switch to JWT token encapsulation

Currently tokens are Slosilo-specific, content-agnostic JSON blobs. Since they were first designed JOSE family of standards came into being which specifies formally a design for bearer tokens, as used with Conjur. Since we're considering expanding tokens to support eg. issuer-set expiration time, it's a good time to switch to standards-based format, which already has features like that built-in. It will also make the structure of the tokens themselves reflect the primary (only?) usage, which is to bear authentication certification by a service identified with a keypair.

Note this issue is not about making Slosilo a generic standards-conforming JWT implementation or allowing different crypto algorithms to be used. Instead this is about, in the interest of interoperability and transparency, leveraging immense design work done on JOSE and drift in that direction in lieu of a NIH, not formally specified token format while making it transparent to users (especially Conjur server and clients) where possible.

Note that for Conjur usage this will need further work in conjur-rack and conjur to take advantage of the changes.

Proposed token format

New access tokens mirror old-style Slosilo tokens and use the same algorithm, extending them with extra fields and formatting them in accordance with RFC 7519.

RFC 7519 tokens are composed of three individually base64-encoded parts, which for Slosilo will be, in the first iteration, defined as follows:

  • JWS protected header, a JSON object with keys:
    • typ: document type, value: JWT
    • alg: signature algorithm, value: conjur.org/slosilo/v2
    • kid: key ID (corresponds to key field in old-style Slosilo tokens).
  • JWT (JSON) document payload, with following claims:
    • sub: subject name (aka “username”, “login”). Required. Corresponds to the contents of data field in old-style tokens.
    • iat: date and time of issue (aka “timestamp”) as numeric (“UNIX”) UTC timestamp. Required. Corresponds to the contents of timestamp field in old-style Slosilo tokens.
    • exp expiration date and time as numeric (“UNIX”) UTC timestamp. Optional. By default tokens expire in 8 minutes since iat.
    • cidr list of CIDR restrictions. The token is considered valid if and only if it is presented by an originating IP matching at least one of them. (This restriction should be implemented by Slosilo token consumers, such as conjur-rack. Optional.
  • Signature, using the same algorithm as in old-style tokens (identified by conjur.org/slosilo/v2 in the alg header field. The string to sign is generated as per RFC 7515. This corresponds to the signature field in old-style tokens.

Security considerations

The new tokens are expected to provide the same or stronger security than the old-style ones:

  • Signature algorithm is intentionally kept the same; Slosilo code has received extensive security and crypto review on two separate occasions and to change it would be to lose the assurance brought by that.
  • Intentionally no effort is made to support RFC-mandated algorithms, even REQUIRED. This ensures that security properties are unchanged.
  • String to sign still contains all the fields of the token (Slosilo tokens don't use unprotected JWT headers), but instead of the construction being defined only in code, it's formally specified to be per RFC 7515.
  • Note: for future extensibility care should be taken to define and handle critical fields correctly. This is TBD.

Interoperability considerations

Conjur

For compatibility with existing clients, token issuers may by default issue tokens in JWS JSON serialization (cf. RFC 7515). Tokens so serialized must be base64 encoded before using in a HTTP request header, as with old-style Slosilo tokens; this ensures that from the point of view of the client the format change is transparent, as long as the client treats tokens as opaque (as clients libraries are expected to). Alternatively, issuer can emit JWS compact serialization (perhaps on an endpoint that legacy clients cannot be expected to be able to use anyway, or as indicated by the client with Accept HTTP header), which can be used in requests without any further processing.

Third-party JOSE implementations

Slosilo is not claiming or intended to provide a general-purpose JWT implementation. However standards-conformant clients should be able to parse the tokens and understand common fields. Since non-standard algorithm is used, a generic implementation won't be able to verify the signature out-of-the-box; it can be accomplished by using Slosilo::Keystore#get_by_fingerprint to lookup the key by kid and Slosilo::Key#verify_signature to perform the verification on standard string-to-sign, bypassing Slosilo JWT parsing logic.

Motivation

Beyond moving to a standard token format, two improvements for Conjur should already be apparent from the proposed format:

  • Token expiration can be specified by the signer. This has long been a feature requested by customers in various contexts, not necessarily valid. However there is significant value in providing this functionality, as Conjur authenticators can now specify the expiration time to be proportional to the amount of work and trust put into the authentication process to explicitly express any performance-security tradeoff, which they're in the best position to estimate. (Note consumers can still make their own decisions about how old tokens they want to accept.)
  • CIDR restrictions can be specified as part of the token. This is especially important for environments where the network is (relatively) trusted, as it can provide an additional level of security without the need for a central service to coordinate these restrictions; moreover, they can differ per authentication event to reflect that environment and trust, again putting that control in the place which is best situated to know it.

Future work

  • Define and implement handling of critical fields (cf. Security considerations above).
  • Formally specify the signature algorithm to make it easier to develop third-party implementations.

Jenkins test failure

  1) Slosilo::Adapters::SequelAdapter with old schema supports look up by fingerprint, but issues a warning
     Failure/Error: STDERR.grab do
       expected empty? to return false, got true
     # ./spec/sequel_adapter_spec.rb:109:in `block (3 levels) in <top (required)>'

Consider deprecating `#signed_token`

It's unclear what purpose Key#signed_token serves. It does not produce a valid JWT token, and the only apparent uses of this method are in tests for slosilo and cyberark/conjur.

This is potentially a good candidate for removal to simply the code and reduce the opportunity for mistakes using this library.

# create a new timestamped and signed token carrying data
def signed_token data
token = { "data" => data, "timestamp" => Time.new.utc.to_s }
token["signature"] = Base64::urlsafe_encode64(sign token)
token["key"] = fingerprint
token
end

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.