Add support to encrypt the private key used to sign gems. #453

Merged
merged 6 commits into from Apr 4, 2013

Conversation

Projects
None yet
3 participants
Contributor

pietro commented Feb 13, 2013

I'm using 3DES to encrypt the key, but that can be easily changed/ made customizable by users.
I'm using ENV['GEM_PRIVATE_KEY_PASSPHRASE'] as the key passphrase because I couldn't find a way to ask the user when OptionParser is parsing the command line options or to automatically test when OpenSSL asks for it.

@pietro pietro referenced this pull request in rubygems-trust/rubygems.org Feb 13, 2013

Open

Feature: passphrases and key management #12

Not that it really matters, but why 3DES by default?

Contributor

pietro commented Feb 14, 2013

I picked it up semi randomly from the supported ciphers list.

AES is probably a better choice

Owner

drbrain commented Feb 14, 2013

It seems unsafe to allow the passphrase to be stored in ENV, on some OSes this value is available to other users.

I agree we should probably pick a more modern cipher than 3DES, but which AES? I know some of these are "bad":

$ ruby -ropenssl -e 'puts OpenSSL::Cipher.ciphers.grep(/AES/)'
AES-128-CBC
AES-128-CBC-HMAC-SHA1
AES-128-CFB
AES-128-CFB1
AES-128-CFB8
AES-128-CTR
AES-128-ECB
AES-128-OFB
AES-128-XTS
AES-192-CBC
AES-192-CFB
AES-192-CFB1
AES-192-CFB8
AES-192-CTR
AES-192-ECB
AES-192-OFB
AES-256-CBC
AES-256-CBC-HMAC-SHA1
AES-256-CFB
AES-256-CFB1
AES-256-CFB8
AES-256-CTR
AES-256-ECB
AES-256-OFB
AES-256-XTS
AES128
AES192
AES256

AES128, AES192 and AES256 are aliases:

$ ruby -ropenssl -e 'puts OpenSSL::Cipher.new("AES256").name'
AES-256-CBC

While it's always safer to pick an authenticated encryption mode, I don't think most traditional CCA/CPA-style attacks matter here. The only goal here is confidentiality and I don't think an attacker has anything to gain from compromising the integrity of a key which is only stored locally on disk and protected by a passphrase (note: most full disk encryption systems don't use authenticated encryption for this same reason)

I hate to recommend CBC or CFB but they're probably the most portable solutions on that list and for this application I don't think it really matters. CTR is arguably better in many respects but I have not seen it ubiquitously available as it depends on your OpenSSL version.

Owner

drbrain commented Feb 14, 2013

Here's the ciphers Apple Ruby (1.8.7) with Apple OpenSSL (0.9.8r) has:

$ /usr/bin/ruby -v -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION, OpenSSL::Cipher.ciphers.grep(/AES/)'
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]
OpenSSL 0.9.8r 8 Feb 2011
AES-128-CBC
AES-128-CFB
AES-128-CFB1
AES-128-CFB8
AES-128-ECB
AES-128-OFB
AES-192-CBC
AES-192-CFB
AES-192-CFB1
AES-192-CFB8
AES-192-ECB
AES-192-OFB
AES-256-CBC
AES-256-CFB
AES-256-CFB1
AES-256-CFB8
AES-256-ECB
AES-256-OFB
AES128
AES192
AES256

Yeah, no CTR as you can see.

CFB adds a few things over CBC that prevents bitflipping attacks against multi-block messages (i.e. you can attack the first block but it corrupts subsequent blocks), but I really don't really think there's much use in even attempting to perpetrate a bitflipping attack here.

As far as least common denominator solution goes, CFB or CBC are probably the way to go :|

@drbrain drbrain merged commit e941467 into rubygems:master Apr 4, 2013

1 check passed

default The Travis build passed
Details

drbrain added a commit that referenced this pull request Apr 4, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment