6

I want to use two key pairs to implement secure messaging with non-repudiation between two communicating systems. I have generated and stored two sets of key pairs using:

sys1_key = OpenSSL::PKey::RSA.generate( 2048 )
sys2_key = OpenSSL::PKey::RSA.generate( 2048 )

Both of these key pairs have had their separate public and private keys saved out to files:

  • sys1.pub.pem
  • sys1.priv.pem
  • sys2.pub.pem
  • sys2.priv.pem

System 1 has its own public and private keys as well as the public key of System 2. System 2 has its own public and private keys as well as the public key of System 1.

On System 1, I want to take the message "Hello world" and encrypt it using System 1's private key and System 2's public key. This message can only be decrypted by System 2 using its own private key and System 1's public key.

We currently effect a similar process using GPG but I want to automate the process -- any help appreciated. We're on Ruby 1.9.2.

davegson
  • 8,205
  • 4
  • 51
  • 71
Michael
  • 4,597
  • 2
  • 17
  • 16
  • Have you looked at GPG public key servers? – irfn Sep 30 '12 at 16:40
  • irfn -- I haven't -- I'm not worried about public key distribution -- I am interested in ruby code that uses OpenSSL to encrypt with multiple keys. – Michael Sep 30 '12 at 20:15

2 Answers2

8

Private keys are for Decryptions and Public keys are for Encryption.

So If System 1 intends to send an encrypted text to System 2.

System 1 should get hold of public key of System 2 and encrypt the text using System 2's Public key. System 2 can receive the text and use its own Private key to decrypt. On sending Side you can use code like this.

#!/usr/bin/env ruby

require 'openssl'
require 'base64'

public_key_file = 'server2_public.pem';
string = 'Secret!';

public_key =
OpenSSL::PKey::RSA.new(File.read(public_key_file))
encrypted_string = Base64.encode64(public_key.public_encrypt(string))
print encrypted_string, "\n"

Base 64 encoding is just an optional step, depending on whether you want to send binary data over the wire etc.

On the receiving side

#!/usr/bin/env ruby

require 'openssl'
require 'base64'

key = 'my_private_key.pem';

private_key = OpenSSL::PKey::RSA.new(File.read(key),'password')
data = private_key.private_decrypt(Base64.decode64(encrypted_data_received))

puts data

If you have n number of systems you should use conventions to lookup public key names. Such as public key name can be same name as target machine name of the message and it can be looked up from the key server. private keys should be present only on corresponding system.

Purpose of Asymmetric Encryption is Twofold.

1) If you Encrypt Using a Public Key. Only the person who has the corresponding Private Key can Decrypt. This achieves message security. 2) If you Sign using a private Key, Public Key can be used to verify authenticity. Everyone who has access to the Public key can verify message authenticity. It proves the point that only you could have encrypted it. This is called a Signature.

adamkonrad
  • 6,794
  • 1
  • 34
  • 41
irfn
  • 560
  • 3
  • 11
  • irfn - many thanks for the detailed explanation -- the remaining issue I have is how server2 can be certain that the originator of the message is deinitely server1. Is it as simple as server1 encrypting the output of the first encryption (i.e. encrypted_string) with server1's private key? And then, server2 decrypting first with server2's copy of server1's public key before decrypting with its own private key? – Michael Oct 01 '12 at 16:57
  • To Prove that You are who you claim you are, You have to create a digital signature. That is usually done by Signing part of the message, Say a Header. You would need a Certification Authority. Look at This Thread for detail http://stackoverflow.com/questions/1999096/digital-signature-verification-with-openssl – irfn Oct 05 '12 at 02:05
2

There is a pretty useful library I wrote a few months ago that serves as a very easy to use wrapper of OpenSSL that supports RSA. The interface is pretty readable and easy to understand.

public_key, private_key = Encryption::Keypair.generate( 2048 )
plaintext = 'some secret data'
securetext = public_key.encrypt( plaintext )
private_key.decrypt( securetext ) == plaintext # true

It's called encryption:
encryption on GitHub.
encryption on Rubygems.
Documentation

Itay Grudev
  • 7,055
  • 4
  • 54
  • 86