# Ruby and Cryptography

**URL:** <https://rubytalk.org/t/ruby-and-cryptography/36286>\
**Category:** ruby-talk\
**Created:** [20 March 2007 07:22 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286 "2007-03-20T07:22:01Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Amr\_Kamel](https://avatars.discourse-cdn.com/v4/letter/a/8c91f0/32.png) [@Amr\_Kamel](https://rubytalk.org/u/Amr_Kamel)\
**Post date:** [20 March 2007 07:22 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/1 "2007-03-20T07:22:01Z")

</div>

Hello everyone,  
Is there any Ruby packages that provides cryptography "either symmetric  
or asymmetric cryptography"? If so can any one tell me and recommend me  
what to use?  
Thanks in advance.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Harold\_Hausman](https://avatars.discourse-cdn.com/v4/letter/h/ac91a4/32.png) [@Harold\_Hausman](https://rubytalk.org/u/Harold_Hausman)\
**Post date:** [20 March 2007 07:39 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/2 "2007-03-20T07:39:45Z")

</div>

> Hello everyone,  
> Is there any Ruby packages that provides cryptography "either symmetric  
> or asymmetric cryptography"? If so can any one tell me and recommend me  
> what to use?  
> Thanks in advance.

Hi Amr,  
There are lots of good libraries for doing crypto with Ruby. Here is a  
google search on the subject of your message:  
[http://www.google.com/search?q=Ruby+and+Cryptography](http://www.google.com/search?q=Ruby+and+Cryptography)

And here is the first result:  
[http://rubyforge.org/projects/crypt/](http://rubyforge.org/projects/crypt/)

Though, this forum/mailing-list/usenet group was not set up so people  
can do your googling for you. I think here we'd rather discuss the  
relative merits of different crypto libraries, or possible defects in  
them. Even a question like "I tried thing x with the crypt library and  
y didn't happen. Can anyone help?" would be better.

Highest regards,  
-Harold

> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

And to the world in general,

The warning on the ruby-forum posting page which mentions that this  
every message on this mailing list is delivered to thousands of people  
is awesome! I actually visited the page with the intention of telling  
the forum maintainer to add such a warning. I was very pleased to see  
that it's already there.

Now, how to make people notice it? Perhaps a \<blink\> tag is in order. 😉

> **···**
>
> On 3/20/07, Amr Kamel \<amrkamel@gmail.com\> wrote:

---

<div class="post-metadata">

**Author:** ![come](https://avatars.discourse-cdn.com/v4/letter/c/9f8e36/32.png) [@come](https://rubytalk.org/u/come)\
**Post date:** [20 March 2007 08:10 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/3 "2007-03-20T08:10:08Z")

</div>

Hi,

Yes, you have the openssl in the standard ruby library which is a port  
of the great C library of the same name. But it's is poorly  
documented. [http://www.nongnu.org/rubypki/README\](http://www.nongnu.org/rubypki/README%5C).

So you have an easier library which is based on openssl : ezcrypto.  
[http://ezcrypto.rubyforge.org/\](http://ezcrypto.rubyforge.org/%5C).

> **···**
>
> On 20 mar, 08:22, Amr Kamel \<amrka...@gmail.com\> wrote:
> 
> > Hello everyone,  
> > Is there any Ruby packages that provides cryptography "either symmetric  
> > or asymmetric cryptography"? If so can any one tell me and recommend me  
> > what to use?  
> > Thanks in advance.
> > 
> > --  
> > Posted viahttp://www.ruby-forum.com/.

---

<div class="post-metadata">

**Author:** ![Jeremy\_Hinegardner](https://avatars.discourse-cdn.com/v4/letter/j/65b543/32.png) [@Jeremy\_Hinegardner](https://rubytalk.org/u/Jeremy_Hinegardner)\
**Post date:** [20 March 2007 16:43 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/4 "2007-03-20T16:43:38Z")

</div>

Ruby ships with an OpenSSL interface so you can use the encryption  
available in openssl in ruby.

One example of using OpenSSL and Ruby for encryption is :

&nbsp;&nbsp;&nbsp;&nbsp;[http://snippets.dzone.com/posts/show/576](http://snippets.dzone.com/posts/show/576)

It is true that the documentation on using OpenSSL from Ruby is lacking.

There are also the pure ruby encryption cyphers avaialble in  
[http://crypt.rubyforge.org](http://crypt.rubyforge.org). Those can be installed with:

&nbsp;&nbsp;&nbsp;&nbsp;gem insall crypt

The crypt website has good usage examples.

enjoy,

-jeremy

> **···**
>
> On Tue, Mar 20, 2007 at 04:22:01PM +0900, Amr Kamel wrote:
> 
> > Hello everyone,  
> > Is there any Ruby packages that provides cryptography "either symmetric  
> > or asymmetric cryptography"? If so can any one tell me and recommend me  
> > what to use?  
> > Thanks in advance.
> 
> # --
> 
> Jeremy Hinegardner jeremy@hinegardner.org

---

<div class="post-metadata">

**Author:** ![\_Stud](https://avatars.discourse-cdn.com/v4/letter/_/f05b48/32.png) [@\_Stud](https://rubytalk.org/u/_Stud)\
**Post date:** [20 March 2007 16:50 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/5 "2007-03-20T16:50:05Z")

</div>

I like the crypt library that Harold mentioned and have used it  
successfully in several applications. Good luck.

\_studlee2

---

<div class="post-metadata">

**Author:** ![Technorama\_Ltd](https://avatars.discourse-cdn.com/v4/letter/t/eada6e/32.png) [@Technorama\_Ltd](https://rubytalk.org/u/Technorama_Ltd)\
**Post date:** [20 March 2007 19:44 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/6 "2007-03-20T19:44:14Z")

</div>

> Ruby ships with an OpenSSL interface so you can use the encryption  
> available in openssl in ruby.
> 
> One example of using OpenSSL and Ruby for encryption is :
> 
> &nbsp;&nbsp;&nbsp;&nbsp;[http://snippets.dzone.com/posts/show/576](http://snippets.dzone.com/posts/show/576)
> 
> It is true that the documentation on using OpenSSL from Ruby is lacking.

Updated documentation is available at  
[http://technorama.net/~oss/ruby/openssl/doc/](http://technorama.net/~oss/ruby/openssl/doc/)

The documention isn't complete.

Not all classes or methods are documented. Callbacks aren't documented  
at all.  
Few classes or methods have examples on their usage beyond a simple  
method call.

Here's a summary of what classes are or aren't documented.  
Note: "complete" means the method shows up in rdoc, not that there is  
useful documentation on how it works.

90% complete  
OpenSSL::Cipher::Cipher  
OpenSSL::Digest::Digest  
OpenSSL::HMAC  
OpenSSL::SSL::Session (doesn't exist in 1.8 or 1.9 yet)

75% complete  
OpenSSL::PKey::DH  
OpenSSL::PKey::DSA  
OpenSSL::PKey::RSA

No documentation  
ASN1  
BN  
PKCS\*  
Random  
X509\*  
SSL\*

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Amr\_Kamel](https://avatars.discourse-cdn.com/v4/letter/a/8c91f0/32.png) [@Amr\_Kamel](https://rubytalk.org/u/Amr_Kamel)\
**Post date:** [20 March 2007 19:07 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/7 "2007-03-20T19:07:14Z")

</div>

Thanks alot everyone I really your help and patience with me :).  
Thanks again.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Jeremy\_Hinegardner](https://avatars.discourse-cdn.com/v4/letter/j/65b543/32.png) [@Jeremy\_Hinegardner](https://rubytalk.org/u/Jeremy_Hinegardner)\
**Post date:** [21 March 2007 06:35 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/8 "2007-03-21T06:35:01Z")

</div>

This is great. I was looking at the documentation at the ruby-doc.org  
site when I said OpenSSL documentation was lacking. I assume this is  
being commited to the trunk ?

enjoy,

-jeremy

> **···**
>
> On Wed, Mar 21, 2007 at 04:44:14AM +0900, Technorama Ltd. wrote:
> 
> > \> Ruby ships with an OpenSSL interface so you can use the encryption  
> > \> available in openssl in ruby.  
> > \>  
> > \> One example of using OpenSSL and Ruby for encryption is :  
> > \>  
> > \> [http://snippets.dzone.com/posts/show/576](http://snippets.dzone.com/posts/show/576)  
> > \>  
> > \> It is true that the documentation on using OpenSSL from Ruby is lacking.
> > 
> > Updated documentation is available at  
> > [http://technorama.net/~oss/ruby/openssl/doc/](http://technorama.net/~oss/ruby/openssl/doc/)
> 
> # --
> 
> Jeremy Hinegardner jeremy@hinegardner.org

---

<div class="post-metadata">

**Author:** ![David\_x\_Callaway](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@David\_x\_Callaway](https://rubytalk.org/u/David_x_Callaway)\
**Post date:** [23 March 2007 17:27 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/9 "2007-03-23T17:27:24Z")

</div>

> Updated documentation is available at  
> [http://technorama.net/~oss/ruby/openssl/doc/](http://technorama.net/~oss/ruby/openssl/doc/)
> 
> The documention isn't complete.

but it is a \*lot\* better than the standard lib docs ;-).

with aid from the documention above and looking at the c source for ruby  
openssl, I wrote the code below (I left out error checking for brevity  
here) which looks reasonable for encrypting/decrypting from streams. it  
"works", meaning I can encrypt a stream and recover it, and it is quite  
fast, ~1 sec to encrypt a 20MB file vs more than one hour for Crypt to  
do the same.

questions:

1) is pkcs5\_keyivgen() the way to go rather than hashing (password  
string + salt) and then using that as the key with  
OpenSSL::Cipher::Cipher as EzCrypto does?

2) how can I make the encrypted output compatible with what I get from  
using openssl directly, e.g.

&nbsp;&nbsp;&nbsp;&nbsp;openssl aes-128-cbc -e -in xxx.txt -out out.bin \  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-pass pass:aaaabbbbccccdddd -salt -S 6161616161616161 -p

openssl includes the salt string in the encrypted output, so I tried  
-nosalt and other things like providing the key binary directly, but no  
matter what the encrypted file did not match either the output from the  
code below or code using EzCrypto (EzCrypto didn't match openssl  
either), so I could not decrypt openssl output nor could it decrypt  
mine. since the purpose of encryption is to make the content secure I  
would feel a lot warmer and fuzzier if I got interoperable output.

-------- code follows -----------

&nbsp;&nbsp;&nbsp;&nbsp;def process\_stream(action,src,target)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cipher = Cipher.new(@cipher\_name)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if action == :encrypt  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cipher.encrypt.pkcs5\_keyivgen(@password,@salt)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elsif action == :decrypt  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cipher.decrypt.pkcs5\_keyivgen(@password,@salt)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise "programming error: unsupported action \"#{action}\""  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer = src.read(@block\_size) or break  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target \<\< cipher.update(buffer)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target \<\< cipher.final  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue Exception =\> e  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@error = e.to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true  
&nbsp;&nbsp;&nbsp;&nbsp;end

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Amr\_Kamel](https://avatars.discourse-cdn.com/v4/letter/a/8c91f0/32.png) [@Amr\_Kamel](https://rubytalk.org/u/Amr_Kamel)\
**Post date:** [20 March 2007 19:08 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/10 "2007-03-20T19:08:05Z")

</div>

Amr Kamel wrote:

> Thanks alot everyone I really your help and patience with me :).  
> Thanks again.

sorry for typo error "I really appreciate your help ..." 🙂

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Technorama\_Ltd](https://avatars.discourse-cdn.com/v4/letter/t/eada6e/32.png) [@Technorama\_Ltd](https://rubytalk.org/u/Technorama_Ltd)\
**Post date:** [25 March 2007 19:20 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/11 "2007-03-25T19:20:20Z")

</div>

David x Callaway wrote:

> > Updated documentation is available at  
> > [http://technorama.net/~oss/ruby/openssl/doc/](http://technorama.net/~oss/ruby/openssl/doc/)
> > 
> > The documention isn't complete.
> 
> but it is a \*lot\* better than the standard lib docs ;-).
> 
> with aid from the documention above and looking at the c source for ruby  
> openssl, I wrote the code below (I left out error checking for brevity  
> here) which looks reasonable for encrypting/decrypting from streams. it  
> "works", meaning I can encrypt a stream and recover it, and it is quite  
> fast, ~1 sec to encrypt a 20MB file vs more than one hour for Crypt to  
> do the same.
> 
> questions:
> 
> 1) is pkcs5\_keyivgen() the way to go rather than hashing (password  
> string + salt) and then using that as the key with  
> OpenSSL::Cipher::Cipher as EzCrypto does?

Maybe. In most cases the pkcs5\_keyivgen method is not pkcs5 compliant.  
You must be using MD2, MD5, or SHA1 with RC2 or DES. Using any other  
cipher (like AES) will generate your key/iv in an OpenSSL specific  
format.

You probably don't want to use your own key generation method since you  
are fairly likely to make design mistakes.

Ideally you would use PKCS5 v2. Unfortunately the ruby OpenSSL module  
doesn't have a hook into any of the PKCS5 v2 password generating  
functions.

Below is a pure ruby PKCS5 v2 password -\> key method.

Usage:  
&nbsp;&nbsp;cipher = Cipher::Cipher.new('aes-128-cbc')  
&nbsp;&nbsp;cipher.encrypt  
&nbsp;&nbsp;cipher.key = pkcs5\_pbkdf2\_hmac\_sha1(password, salt, iter,  
cipher.key\_len)  
&nbsp;&nbsp;cipher.iv = generate\_your\_own\_iv

Iterations should probably be above 1000. The higher it is the longer  
it takes to generate the key.

Salt should be unique for each unique piece of data.

def pkcs5\_pbkdf2\_hmac\_sha1(pass, salt, iter, len)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret = ''  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i = 0

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digest = OpenSSL::Digest::Digest.new('sha1')

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while len \> 0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i += 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hmac = HMAC.new(pass, digest)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hmac.update(salt)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hmac.update([i].pack('N'))  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digtmp = hmac.digest

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cplen = len \> digtmp.length ? digtmp.length : len

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp = digtmp.dup

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.upto(iter - 1) do |j|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hmac = HMAC.new(pass, digest)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hmac.update(digtmp)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digtmp = hmac.digest  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.upto(cplen - 1) do |k|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp[k] = (tmp[k] ^ digtmp[k]).chr  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp.slice!((cplen)..-1) if (tmp.length \> cplen)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret \<\< tmp  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len -= tmp.length  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret  
end

Notes:  
&nbsp;&nbsp;The above method was written to answer your message and has not been  
&nbsp;&nbsp;thoroughly tested.

&nbsp;&nbsp;The ruby version is 8-9 times slower than the c version.

&nbsp;&nbsp;Patches for the c method will be sent in to ruby at some point when  
they have  
&nbsp;&nbsp;been properly tested.

If you are designing your own encrypted storage format there are a  
number  
of things you should do (this is not an exhaustive list of everything  
you  
should do, just a few pointers).

Include the following in the header:  
&nbsp;&nbsp;magic string  
&nbsp;&nbsp;version number (either a storage format version or a program version)  
&nbsp;&nbsp;key derivation method and parameters (if you have one)  
&nbsp;&nbsp;cipher id  
&nbsp;&nbsp;digest or hmac id

Document the format.

Write unit tests.

Test, test, test, test and test.

There's nothing worse than finding out that you used the wrong variable  
for the key and now everything is encrypted with the same key. Or  
finding out later  
than you didn't store the key properly and can't retrieve anything.

> 2) how can I make the encrypted output compatible with what I get from  
> using openssl directly, e.g.
> 
> &nbsp;&nbsp;&nbsp;&nbsp;openssl aes-128-cbc -e -in xxx.txt -out out.bin \  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-pass pass:aaaabbbbccccdddd -salt -S 6161616161616161 -p
> 
> openssl includes the salt string in the encrypted output, so I tried  
> -nosalt and other things like providing the key binary directly, but no  
> matter what the encrypted file did not match either the output from the  
> code below or code using EzCrypto (EzCrypto didn't match openssl  
> either), so I could not decrypt openssl output nor could it decrypt  
> mine. since the purpose of encryption is to make the content secure I  
> would feel a lot warmer and fuzzier if I got interoperable output.

Here's a quick and dirty bit of code to encrypt/decrypt the openssl  
program output.

require 'openssl'

magic = 'Salted\_\_'  
salt\_len = 8

infile = ""  
outfile = ""  
password = "x"  
cipher = 'aes-128-cbc'

# decrypt: compatible with openssl -e $CIPHER -k $PASS  
file = File.open(infile)  
if (buf = file.read(magic.length)) != magic  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise "unknown file, read #{buf.inspect}"  
end

salt = file.read(salt\_len)

c = OpenSSL::Cipher::Cipher.new(cipher)  
c.decrypt  
c.pkcs5\_keyivgen(password, salt, 1)

buf = c.update(file.read) + c.final

# encrypt: compatible with openssl enc -d $CIPHER -k $PASS  
file = File.new(outfile, "w")  
salt ||= OpenSSL::Random::pseudo\_rand\_bytes(salt\_len)  
c = OpenSSL::Cipher::Cipher.new(cipher)  
c.encrypt  
c.pkcs5\_keyivgen(password, salt, 1)

file.write(magic)  
file.write(salt)  
file.write(c.update(buf) + c.final)

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![David\_x\_Callaway](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@David\_x\_Callaway](https://rubytalk.org/u/David_x_Callaway)\
**Post date:** [26 March 2007 11:44 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/12 "2007-03-26T11:44:02Z")

</div>

thanks, that was very illuminating, see comments below.

... snip ...

> > 1) is pkcs5\_keyivgen() the way to go rather than hashing (password  
> > string + salt) and then using that as the key with  
> > OpenSSL::Cipher::Cipher as EzCrypto does?
> 
> Maybe. In most cases the pkcs5\_keyivgen method is not pkcs5 compliant.

I'm running ruby 1.8.5 and comments pertain to that source.

pkcs5\_keyivgen eventually calls down to EVP\_BytesToKey, passing the  
passphrase, salt (must be exactly 8 bytes if given), iteration count  
(defaults to 2048) and digest; it returns the key and IV.

the man page for EVP\_BytesToKey says:

&nbsp;&nbsp;&nbsp;&nbsp;If the total key and IV length is less than the digest length and  
&nbsp;&nbsp;&nbsp;&nbsp;MD5 is used then the derivation algorithm is compatible with  
&nbsp;&nbsp;&nbsp;&nbsp;PKCS#5 v1.5 otherwise a non standard extension is used to derive  
&nbsp;&nbsp;&nbsp;&nbsp;the extra data.

&nbsp;&nbsp;&nbsp;&nbsp;Newer applications should use more standard algorithms such as  
&nbsp;&nbsp;&nbsp;&nbsp;PKCS#5 v2.0 for key derivation.

however there is no suggestion about how to get v2.0 output.

> You must be using MD2, MD5, or SHA1 with RC2 or DES. Using any other  
> cipher (like AES) will generate your key/iv in an OpenSSL specific  
> format.
> 
> You probably don't want to use your own key generation method since you  
> are fairly likely to make design mistakes.

I definitely \*don't\* want to do this, hence I was trying to figure out  
how to match "enc".

> Ideally you would use PKCS5 v2. Unfortunately the ruby OpenSSL module  
> doesn't have a hook into any of the PKCS5 v2 password generating  
> functions.

right, see comment above.

> Below is a pure ruby PKCS5 v2 password -\> key method.

thanks, but I don't want to get ahead of the ruby openssl library. of  
course this \*does\* raise the question of how it will eventually be  
incorporated. it wouldn't be a nice thing if the addition caused all  
my encrypted files to be inaccessible.

... snip ...

> If you are designing your own encrypted storage format there are a  
> number of things you should do (this is not an exhaustive list of  
> everything you should do, just a few pointers).

right, but I don't want to do this at all ;-).

... snip ...

> Test, test, test, test and test.
> 
> There's nothing worse than finding out that you used the wrong  
> variable for the key and now everything is encrypted with the same  
> key. Or finding out later than you didn't store the key properly  
> and can't retrieve anything.

right, that's precisely why I was attempting to test against openssl  
enc.

... snip ...

> Here's a quick and dirty bit of code to encrypt/decrypt the openssl  
> program output.

the key in the code you provided, besides the obvious biz with the  
header, is the iteration count is 1, something I wouldn't have  
guessed. inspecting the openssl src for "enc" shows the same (I  
should have gone there first).

the other thing I didn't figure out by messing around with "enc" is if  
you don't provide it a salt, and if you don't specify -nosalt, then it  
will do as you did, provide a random salt string when encrypting. I  
understand the idea of salt, but specifying it on the command line  
each time didn't make sense to me, and now I see that's because it  
doesn't make sense ;-).

... snip ...

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![David\_x\_Callaway](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@David\_x\_Callaway](https://rubytalk.org/u/David_x_Callaway)\
**Post date:** [26 March 2007 13:29 UTC](https://rubytalk.org/t/ruby-and-cryptography/36286/13 "2007-03-26T13:29:49Z")

</div>

one more thing, at least on my system:

the call OpenSSL::Random::pseudo\_rand\_bytes(salt\_len)  
should be OpenSSL::Random::pseudo\_bytes(salt\_len), the other doesn't  
exist.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).
