Client Side Encryption

#63 Client Side Encryption
1/15/2017

Summary

Add an extra level of security to your application with client side encryption. Even over an SSL connection, there are attacks which could expose your users' sensitive information. Using JSEncrypt, learn how to encrypt on the client side and decrypt on the server side.
8
rails security javascript encryption 10:31 min

Summary

Copy https://github.com/travist/jsencrypt/blob/master/bin/jsencrypt.js to your vendor/assets/javascripts folder

Terminalopenssl genrsa -out rsa_1024_priv.pem 1024
openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem

You will want to avoid storing the public and private keys in application.rb. Instead, you should have them in your secrets.yml, environment variable, parameter store or elsewhere secure.

application.rbPUBLIC_KEY = <PUBLIC KEY DATA>
PRIVATE_KEY = <PUBLIC KEY DATA>
application.js//= require jsencrypt
application.js$(document).on('turbolinks:load', function(){
  $('form').submit(function( event ) {
    var encrypt = new JSEncrypt();
    $('[data-encrypt]').each(function(){
      unencrypted = $(this);
      encrypt.setKey($('#public_key').val());
      encrypted = encrypt.encrypt(unencrypted.val());
      if (encrypted != false) {
        unencrypted.val(encrypted);
      }  
    })
    // event.preventDefault();
  });
});
users/sessions_controller.rbclass Users::SessionsController < Devise::SessionsController
# before_action :configure_sign_in_params, only: [:create]

  # POST /resource/sign_in
  def create
    # self.resource = warden.authenticate!(auth_options)
    resource = User.find_by(email: params[:user][:email])
    if resource&.valid_password?(authenticate_encryptor)
      set_flash_message!(:notice, :signed_in)
      sign_in(resource_name, resource)
      yield resource if block_given?
      respond_with resource, location: after_sign_in_path_for(resource)
    else
      redirect_to new_user_session_path, alert: 'Bad email or password.'
    end
  end

  private

  def authenticate_encryptor
    private_key = OpenSSL::PKey::RSA.new(PRIVATE_KEY)
    password = params[:user][:password]
    private_key.private_decrypt(Base64.decode64(password))
  end
end
views/devise/sessions/new.html.erb<%= f.password_field :password, autocomplete: "off", placeholder: 'Password', class: 'form-control', data: { encrypt: true } %>


2652674?v=3&s=64
emars said 9 months ago:

You mentioned man-in-the-middle attacks as an example of how client-side encryption can protect a users data.

Doesn't SSL already protect against this kind of attack?

Namely, I thought SSL guaranteed the authenticity of whoever you are communicating with. Is this not the case? 

635114?v=3&s=64
kobaltz said 9 months ago:

SSL Doesn't really protect against a MitMA. In hindsight, this method really doesn't either. However, this method does provide some level of obscurity to your password which is good, but in no means does it replace the need for SSL certs.

A VPN tunnel or something similar would be a much safer bet. I really should have made the episode more around the ability to have a secure communicate between two users or something. Yes, a  trusted Certificate Authority does issue SSL certificates to someone when they can verify a level of ownership to a domain.

Login to Comment