X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=doc%2Fclasses%2FMCollective%2FSSL.html;fp=doc%2Fclasses%2FMCollective%2FSSL.html;h=678945dba14a2a52b8f642fd9dd79a3540144c88;hb=d1f1649ba43c5cbc43c4beb2380096ba051d646a;hp=0000000000000000000000000000000000000000;hpb=8a3fe7daeecccf43dd71c59371c5005400d35101;p=packages%2Fprecise%2Fmcollective.git diff --git a/doc/classes/MCollective/SSL.html b/doc/classes/MCollective/SSL.html new file mode 100644 index 0000000..678945d --- /dev/null +++ b/doc/classes/MCollective/SSL.html @@ -0,0 +1,886 @@ + + + + + + Class: MCollective::SSL + + + + + + + + + + +
+ + + + + + + + + + + + + + +
ClassMCollective::SSL
In: + + lib/mcollective/ssl.rb + +
+
Parent: + Object +
+
+ + +
+ + + +
+ +
+

+A class that assists in encrypting and decrypting data using a combination +of RSA and AES +

+

+Data will be AES encrypted for speed, the Key used +in # the AES stage will be encrypted using RSA +

+
+  ssl = SSL.new(public_key, private_key, passphrase)
+
+  data = File.read("largefile.dat")
+
+  crypted_data = ssl.encrypt_with_private(data)
+
+  pp crypted_data
+
+

+This will result in a hash of data like: +

+
+  crypted = {:key  => "crd4NHvG....=",
+             :data => "XWXlqN+i...=="}
+
+

+The key and data will all be base 64 encoded already by default you can +pass a 2nd parameter as false to encrypt_with_private and counterparts that will +prevent the base 64 encoding +

+

+You can pass the data hash into ssl.decrypt_with_public which should return +your original data +

+

+There are matching methods for using a public key to encrypt data to be +decrypted using a private key +

+ +
+ + +
+ +
+

Methods

+ + +
+ +
+ + + + +
+ + + + + +
+

Attributes

+ +
+ + + + + + + + + + + + + + + + +
private_key_file [R] 
public_key_file [R] 
ssl_cipher [R] 
+
+
+ + + + +
+

Public Class methods

+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 195
+195:     def self.base64_decode(string)
+196:       Base64.decode64(string)
+197:     end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 186
+186:     def self.base64_encode(string)
+187:       Base64.encode64(string)
+188:     end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 203
+203:     def self.md5(string)
+204:       Digest::MD5.hexdigest(string)
+205:     end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+    # File lib/mcollective/ssl.rb, line 37
+37:     def initialize(pubkey=nil, privkey=nil, passphrase=nil, cipher=nil)
+38:       @public_key_file = pubkey
+39:       @private_key_file = privkey
+40: 
+41:       @public_key  = read_key(:public, pubkey)
+42:       @private_key = read_key(:private, privkey, passphrase)
+43: 
+44:       @ssl_cipher = "aes-256-cbc"
+45:       @ssl_cipher = Config.instance.ssl_cipher if Config.instance.ssl_cipher
+46:       @ssl_cipher = cipher if cipher
+47: 
+48:       raise "The supplied cipher '#{@ssl_cipher}' is not supported" unless OpenSSL::Cipher.ciphers.include?(@ssl_cipher)
+49:     end
+
+
+
+
+ +
+ + + + +
+

+Creates a RFC 4122 version 5 UUID. If string is supplied it will produce +repeatable UUIDs for that string else a random 128bit string will be used +from OpenSSL::BN +

+

+Code used with permission from: +

+
+   https://github.com/kwilczynski/puppet-functions/blob/master/lib/puppet/parser/functions/uuid.rb
+
+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 213
+213:     def self.uuid(string=nil)
+214:       string ||= OpenSSL::Random.random_bytes(16).unpack('H*').shift
+215: 
+216:       uuid_name_space_dns = "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
+217: 
+218:       sha1 = Digest::SHA1.new
+219:       sha1.update(uuid_name_space_dns)
+220:       sha1.update(string)
+221: 
+222:       # first 16 bytes..
+223:       bytes = sha1.digest[0, 16].bytes.to_a
+224: 
+225:       # version 5 adjustments
+226:       bytes[6] &= 0x0f
+227:       bytes[6] |= 0x50
+228: 
+229:       # variant is DCE 1.1
+230:       bytes[8] &= 0x3f
+231:       bytes[8] |= 0x80
+232: 
+233:       bytes = [4, 2, 2, 2, 6].collect do |i|
+234:         bytes.slice!(0, i).pack('C*').unpack('H*')
+235:       end
+236: 
+237:       bytes.join('-')
+238:     end
+
+
+
+
+ +

Public Instance methods

+ +
+ + + + +
+

+decrypts a string given key, iv and data +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 158
+158:     def aes_decrypt(key, crypt_string)
+159:       cipher = OpenSSL::Cipher::Cipher.new(ssl_cipher)
+160: 
+161:       cipher.decrypt
+162:       cipher.key = key
+163:       cipher.pkcs5_keyivgen(key)
+164:       decrypted_data = cipher.update(crypt_string) + cipher.final
+165:     end
+
+
+
+
+ +
+ + + + +
+

+encrypts a string, returns a hash of key, iv and data +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 144
+144:     def aes_encrypt(plain_string)
+145:       cipher = OpenSSL::Cipher::Cipher.new(ssl_cipher)
+146:       cipher.encrypt
+147: 
+148:       key = cipher.random_key
+149: 
+150:       cipher.key = key
+151:       cipher.pkcs5_keyivgen(key)
+152:       encrypted_data = cipher.update(plain_string) + cipher.final
+153: 
+154:       {:key => key, :data => encrypted_data}
+155:     end
+
+
+
+
+ +
+ + + + +
+

+base 64 decode a string +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 191
+191:     def base64_decode(string)
+192:       SSL.base64_decode(string)
+193:     end
+
+
+
+
+ +
+ + + + +
+

+base 64 encode a string +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 182
+182:     def base64_encode(string)
+183:       SSL.base64_encode(string)
+184:     end
+
+
+
+
+ +
+ + + + +
+

+Decrypts data, expects a hash as create with crypt_with_public +

+

[Source]

+
+
+    # File lib/mcollective/ssl.rb, line 88
+88:     def decrypt_with_private(crypted, base64=true)
+89:       raise "Crypted data should include a key" unless crypted.include?(:key)
+90:       raise "Crypted data should include data" unless crypted.include?(:data)
+91: 
+92:       if base64
+93:         key = rsa_decrypt_with_private(base64_decode(crypted[:key]))
+94:         aes_decrypt(key, base64_decode(crypted[:data]))
+95:       else
+96:         key = rsa_decrypt_with_private(crypted[:key])
+97:         aes_decrypt(key, crypted[:data])
+98:       end
+99:     end
+
+
+
+
+ +
+ + + + +
+

+Decrypts data, expects a hash as create with crypt_with_private +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 102
+102:     def decrypt_with_public(crypted, base64=true)
+103:       raise "Crypted data should include a key" unless crypted.include?(:key)
+104:       raise "Crypted data should include data" unless crypted.include?(:data)
+105: 
+106:       if base64
+107:         key = rsa_decrypt_with_public(base64_decode(crypted[:key]))
+108:         aes_decrypt(key, base64_decode(crypted[:data]))
+109:       else
+110:         key = rsa_decrypt_with_public(crypted[:key])
+111:         aes_decrypt(key, crypted[:data])
+112:       end
+113:     end
+
+
+
+
+ +
+ + + + +
+

+Encrypts supplied data using AES and then encrypts using RSA the key and IV +

+

+Return a hash with everything optionally base 64 encoded +

+

[Source]

+
+
+    # File lib/mcollective/ssl.rb, line 73
+73:     def encrypt_with_private(plain_text, base64=true)
+74:       crypted = aes_encrypt(plain_text)
+75: 
+76:       if base64
+77:         key = base64_encode(rsa_encrypt_with_private(crypted[:key]))
+78:         data = base64_encode(crypted[:data])
+79:       else
+80:         key = rsa_encrypt_with_private(crypted[:key])
+81:         data = crypted[:data]
+82:       end
+83: 
+84:       {:key => key, :data => data}
+85:     end
+
+
+
+
+ +
+ + + + +
+

+Encrypts supplied data using AES and then encrypts using RSA the key and IV +

+

+Return a hash with everything optionally base 64 encoded +

+

[Source]

+
+
+    # File lib/mcollective/ssl.rb, line 55
+55:     def encrypt_with_public(plain_text, base64=true)
+56:       crypted = aes_encrypt(plain_text)
+57: 
+58:       if base64
+59:         key = base64_encode(rsa_encrypt_with_public(crypted[:key]))
+60:         data = base64_encode(crypted[:data])
+61:       else
+62:         key = rsa_encrypt_with_public(crypted[:key])
+63:         data = crypted[:data]
+64:       end
+65: 
+66:       {:key => key, :data => data}
+67:     end
+
+
+
+
+ +
+ + + + +
+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 199
+199:     def md5(string)
+200:       SSL.md5(string)
+201:     end
+
+
+
+
+ +
+ + + + +
+

+Reads either a :public or :private key from disk, uses an optional +passphrase to read the private key +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 242
+242:     def read_key(type, key=nil, passphrase=nil)
+243:       return key if key.nil?
+244: 
+245:       raise "Could not find key #{key}" unless File.exist?(key)
+246:       raise "#{type} key file '#{key}' is empty" if File.zero?(key)
+247: 
+248:       if type == :public
+249:         begin
+250:           key = OpenSSL::PKey::RSA.new(File.read(key))
+251:         rescue OpenSSL::PKey::RSAError
+252:           key = OpenSSL::X509::Certificate.new(File.read(key)).public_key
+253:         end
+254: 
+255:         # Ruby < 1.9.3 had a bug where it does not correctly clear the
+256:         # queue of errors while reading a key.  It tries various ways
+257:         # to read the key and each failing attempt pushes an error onto
+258:         # the queue.  With pubkeys only the 3rd attempt pass leaving 2
+259:         # stale errors on the error queue.
+260:         #
+261:         # In 1.9.3 they fixed this by simply discarding the errors after
+262:         # every attempt.  So we simulate this fix here for older rubies
+263:         # as without it we get SSL_read errors from the Stomp+TLS sessions
+264:         #
+265:         # We do this only on 1.8 relying on 1.9.3 to do the right thing
+266:         # and we do not support 1.9 less than 1.9.3
+267:         #
+268:         # See  http://bugs.ruby-lang.org/issues/4550
+269:         OpenSSL.errors if Util.ruby_version =~ /^1.8/
+270: 
+271:         return key
+272:       elsif type == :private
+273:         return OpenSSL::PKey::RSA.new(File.read(key), passphrase)
+274:       else
+275:         raise "Can only load :public or :private keys"
+276:       end
+277:     end
+
+
+
+
+ +
+ + + + +
+

+Use the private key to RSA decrypt data +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 123
+123:     def rsa_decrypt_with_private(crypt_string)
+124:       raise "No private key set" unless @private_key
+125: 
+126:       @private_key.private_decrypt(crypt_string)
+127:     end
+
+
+
+
+ +
+ + + + +
+

+Use the public key to RSA decrypt data +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 137
+137:     def rsa_decrypt_with_public(crypt_string)
+138:       raise "No public key set" unless @public_key
+139: 
+140:       @public_key.public_decrypt(crypt_string)
+141:     end
+
+
+
+
+ +
+ + + + +
+

+Use the private key to RSA encrypt data +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 130
+130:     def rsa_encrypt_with_private(plain_string)
+131:       raise "No private key set" unless @private_key
+132: 
+133:       @private_key.private_encrypt(plain_string)
+134:     end
+
+
+
+
+ +
+ + + + +
+

+Use the public key to RSA encrypt data +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 116
+116:     def rsa_encrypt_with_public(plain_string)
+117:       raise "No public key set" unless @public_key
+118: 
+119:       @public_key.public_encrypt(plain_string)
+120:     end
+
+
+
+
+ +
+ + + + +
+

+Signs a string using the private key +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 168
+168:     def sign(string, base64=false)
+169:       sig = @private_key.sign(OpenSSL::Digest::SHA1.new, string)
+170: 
+171:       base64 ? base64_encode(sig) : sig
+172:     end
+
+
+
+
+ +
+ + + + +
+

+Using the public key verifies that a string was signed using the private +key +

+

[Source]

+
+
+     # File lib/mcollective/ssl.rb, line 175
+175:     def verify_signature(signature, string, base64=false)
+176:       signature = base64_decode(signature) if base64
+177: 
+178:       @public_key.verify(OpenSSL::Digest::SHA1.new, signature, string)
+179:     end
+
+
+
+
+ + +
+ + +
+ + +
+

[Validate]

+
+ + + \ No newline at end of file